From f5ebc47bbe58ff6e522dee0b8679f7b3b64912c4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fabian=20Gr=C3=BCnbichler?= Date: Fri, 3 Mar 2017 15:08:02 +0100 Subject: [PATCH] drop already applied patches these were all cherry-picks on top of the previous 4.4 kernel which are no longer needed. --- ...y-reset-dest_map-vector-when-restori.patch | 68 -- ...-ACS-vs-device-specific-ACS-enabling.patch | 110 --- ...-PCH-root-port-ACS-for-Sunrise-Point.patch | 123 --- ...g-skb-too-early-for-IPV6_RECVPKTINFO.patch | 58 -- ...e-IB-LL-address-into-the-hard-header.patch | 365 --------- Makefile | 11 - ..._head_lost-to-check-skb-len-before-f.patch | 77 -- mei_bus-whitelist-watchdog-client.patch | 74 -- mei_drop-watchdog-code.patch | 754 ------------------ watchdog_implement-mei-iamt-driver.patch | 514 ------------ 10 files changed, 2154 deletions(-) delete mode 100644 0001-kvm-x86-correctly-reset-dest_map-vector-when-restori.patch delete mode 100644 981-1-PCI-Reverse-standard-ACS-vs-device-specific-ACS-enabling.patch delete mode 100644 981-2-PCI-Quirk-PCH-root-port-ACS-for-Sunrise-Point.patch delete mode 100644 CVE-2017-6074-dccp-fix-freeing-skb-too-early-for-IPV6_RECVPKTINFO.patch delete mode 100644 IB-ipoib-move-back-the-IB-LL-address-into-the-hard-header.patch delete mode 100644 bug-950-tcp-fix-tcp_mark_head_lost-to-check-skb-len-before-f.patch delete mode 100644 mei_bus-whitelist-watchdog-client.patch delete mode 100644 mei_drop-watchdog-code.patch delete mode 100644 watchdog_implement-mei-iamt-driver.patch diff --git a/0001-kvm-x86-correctly-reset-dest_map-vector-when-restori.patch b/0001-kvm-x86-correctly-reset-dest_map-vector-when-restori.patch deleted file mode 100644 index da9f4f8..0000000 --- a/0001-kvm-x86-correctly-reset-dest_map-vector-when-restori.patch +++ /dev/null @@ -1,68 +0,0 @@ -From b0eaf4506f5f95d15d6731d72c0ddf4a2179eefa Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Wed, 14 Sep 2016 23:39:12 +0200 -Subject: [PATCH] kvm: x86: correctly reset dest_map->vector when restoring - LAPIC state -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When userspace sends KVM_SET_LAPIC, KVM schedules a check between -the vCPU's IRR and ISR and the IOAPIC redirection table, in order -to re-establish the IOAPIC's dest_map (the list of CPUs servicing -the real-time clock interrupt with the corresponding vectors). - -However, __rtc_irq_eoi_tracking_restore_one was forgetting to -set dest_map->vectors. Because of this, the IOAPIC did not process -the real-time clock interrupt EOI, ioapic->rtc_status.pending_eoi -got stuck at a non-zero value, and further RTC interrupts were -reported to userspace as coalesced. - -Fixes: 9e4aabe2bb3454c83dac8139cf9974503ee044db -Fixes: 4d99ba898dd0c521ca6cdfdde55c9b58aea3cb3d -Cc: stable@vger.kernel.org -Cc: Joerg Roedel -Cc: David Gilbert -Reviewed-by: Radim Krčmář -Signed-off-by: Paolo Bonzini -Signed-off-by: Fabian Grünbichler ---- - arch/x86/kvm/ioapic.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c -index 5f42d03..c7220ba 100644 ---- a/arch/x86/kvm/ioapic.c -+++ b/arch/x86/kvm/ioapic.c -@@ -109,6 +109,7 @@ static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu) - { - bool new_val, old_val; - struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic; -+ struct dest_map *dest_map = &ioapic->rtc_status.dest_map; - union kvm_ioapic_redirect_entry *e; - - e = &ioapic->redirtbl[RTC_GSI]; -@@ -117,16 +118,17 @@ static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu) - return; - - new_val = kvm_apic_pending_eoi(vcpu, e->fields.vector); -- old_val = test_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map.map); -+ old_val = test_bit(vcpu->vcpu_id, dest_map->map); - - if (new_val == old_val) - return; - - if (new_val) { -- __set_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map.map); -+ __set_bit(vcpu->vcpu_id, dest_map->map); -+ dest_map->vectors[vcpu->vcpu_id] = e->fields.vector; - ioapic->rtc_status.pending_eoi++; - } else { -- __clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map.map); -+ __clear_bit(vcpu->vcpu_id, dest_map->map); - ioapic->rtc_status.pending_eoi--; - rtc_status_pending_eoi_check_valid(ioapic); - } --- -2.1.4 - diff --git a/981-1-PCI-Reverse-standard-ACS-vs-device-specific-ACS-enabling.patch b/981-1-PCI-Reverse-standard-ACS-vs-device-specific-ACS-enabling.patch deleted file mode 100644 index 8543bc3..0000000 --- a/981-1-PCI-Reverse-standard-ACS-vs-device-specific-ACS-enabling.patch +++ /dev/null @@ -1,110 +0,0 @@ -From: Alex Williamson -Subject: [PATCH 1/2] PCI: Reverse standard ACS vs device specific ACS enabling - -The original thought was that if a device implemented ACS, then surely -we want to use that... well, it turns out that devices can make an ACS -capability so broken that we still need to fall back to quirks. -Reverse the order of ACS enabling to give quirks first shot at it. - -Signed-off-by: Alex Williamson ---- - drivers/pci/pci.c | 10 ++++------ - drivers/pci/quirks.c | 6 ++++-- - include/linux/pci.h | 7 +++++-- - 3 files changed, 13 insertions(+), 10 deletions(-) - -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index 25e0327..c98c4e2 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -2548,7 +2548,7 @@ void pci_request_acs(void) - * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites - * @dev: the PCI device - */ --static int pci_std_enable_acs(struct pci_dev *dev) -+static void pci_std_enable_acs(struct pci_dev *dev) - { - int pos; - u16 cap; -@@ -2556,7 +2556,7 @@ static int pci_std_enable_acs(struct pci_dev *dev) - - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); - if (!pos) -- return -ENODEV; -+ return; - - pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); - pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); -@@ -2574,8 +2574,6 @@ static int pci_std_enable_acs(struct pci_dev *dev) - ctrl |= (cap & PCI_ACS_UF); - - pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); -- -- return 0; - } - - /** -@@ -2585,10 +2585,10 @@ void pci_enable_acs(struct pci_dev *dev) - if (!pci_acs_enable) - return; - -- if (!pci_std_enable_acs(dev)) -+ if (!pci_dev_specific_enable_acs(dev)) - return; - -- pci_dev_specific_enable_acs(dev); -+ pci_std_enable_acs(dev); - } - - static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) -diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c -index 8e67802..701fad6 100644 ---- a/drivers/pci/quirks.c -+++ b/drivers/pci/quirks.c -@@ -4224,7 +4224,7 @@ static const struct pci_dev_enable_acs { - { 0 } - }; - --void pci_dev_specific_enable_acs(struct pci_dev *dev) -+int pci_dev_specific_enable_acs(struct pci_dev *dev) - { - const struct pci_dev_enable_acs *i; - int ret; -@@ -4236,9 +4236,11 @@ void pci_dev_specific_enable_acs(struct pci_dev *dev) - i->device == (u16)PCI_ANY_ID)) { - ret = i->enable_acs(dev); - if (ret >= 0) -- return; -+ return ret; - } - } -+ -+ return -ENOTTY; - } - - /* -diff --git a/include/linux/pci.h b/include/linux/pci.h -index 004b813..aaec79a 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -1657,7 +1657,7 @@ enum pci_fixup_pass { - #ifdef CONFIG_PCI_QUIRKS - void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); - int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); --void pci_dev_specific_enable_acs(struct pci_dev *dev); -+int pci_dev_specific_enable_acs(struct pci_dev *dev); - #else - static inline void pci_fixup_device(enum pci_fixup_pass pass, - struct pci_dev *dev) { } -@@ -1666,7 +1666,10 @@ static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, - { - return -ENOTTY; - } --static inline void pci_dev_specific_enable_acs(struct pci_dev *dev) { } -+static inline int pci_dev_specific_enable_acs(struct pci_dev *dev) -+{ -+ return -ENOTTY; -+} - #endif - - void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); diff --git a/981-2-PCI-Quirk-PCH-root-port-ACS-for-Sunrise-Point.patch b/981-2-PCI-Quirk-PCH-root-port-ACS-for-Sunrise-Point.patch deleted file mode 100644 index 9c3dd24..0000000 --- a/981-2-PCI-Quirk-PCH-root-port-ACS-for-Sunrise-Point.patch +++ /dev/null @@ -1,123 +0,0 @@ -From: Alex Williamson -Subject: [PATCH 2/2] PCI: Quirk PCH root port ACS for Sunrise Point - -As noted in the comments, these root ports attempted to implement ACS -but used dwords for the capability and control registers, putting the -control register at the wrong offset. We use quirks to enable and -test ACS for these devices, which match the standard functions modulo -the broken control register offset. - -Signed-off-by: Alex Williamson ---- - drivers/pci/quirks.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 78 insertions(+) - -diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c -index 701fad6..d6606e4 100644 ---- a/drivers/pci/quirks.c -+++ b/drivers/pci/quirks.c -@@ -3992,6 +3992,55 @@ static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags) - return acs_flags & ~flags ? 0 : 1; - } - -+/* -+ * Sunrise Point PCH root ports implement ACS, but unfortunately as shown in -+ * the datasheet (Intel 100 Series Chipset Family PCH Datasheet, Vol. 2, -+ * 12.1.46, 12.1.47)[1] this chipset uses dwords for the ACS capability and -+ * control registers whereas the PCIe spec packs them into words (Rev 3.0, -+ * 7.16 ACS Extended Capability). The bit definitions are correct, but the -+ * control register is at offset 8 instead of 6 and we should probably use -+ * dword accesses to them. This applies to the following PCI Device IDs, as -+ * found in volume 1 of the datasheet[2]: -+ * -+ * 0xa110-0xa11f Sunrise Point-H PCI Express Root Port #{0-16} -+ * 0xa167-0xa16a Sunrise Point-H PCI Express Root Port #{17-20} -+ * -+ * NB. This doesn't fix what lspci shows. -+ * -+ * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html -+ * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html -+ */ -+static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) -+{ -+ return pci_is_pcie(dev) && -+ pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT && -+ ((dev->device & ~0xf) == 0xa110 || -+ (dev->device >= 0xa167 && dev->device <= 0xa16a)); -+} -+ -+#define INTEL_SPT_ACS_CTRL (PCI_ACS_CAP + 4) -+ -+static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u16 acs_flags) -+{ -+ int pos; -+ u32 cap, ctrl; -+ -+ if (!pci_quirk_intel_spt_pch_acs_match(dev)) -+ return -ENOTTY; -+ -+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); -+ if (!pos) -+ return -ENOTTY; -+ -+ /* see pci_acs_flags_enabled() */ -+ pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap); -+ acs_flags &= (cap | PCI_ACS_EC); -+ -+ pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl); -+ -+ return acs_flags & ~ctrl ? 0 : 1; -+} -+ - static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags) - { - /* -@@ -4024,6 +4073,7 @@ static const struct pci_dev_acs_enabled { - { PCI_VENDOR_ID_INTEL, 0x15b8, pci_quirk_mf_endpoint_acs }, - /* Intel PCH root ports */ - { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs }, -+ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_spt_pch_acs }, - { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */ - { 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */ - /* Cavium ThunderX */ -@@ -4159,12 +4209,40 @@ static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev) - return 0; - } - -+static int pci_quirk_enable_intel_spt_pch_acs(struct pci_dev *dev) -+{ -+ int pos; -+ u32 cap, ctrl; -+ -+ if (!pci_quirk_intel_spt_pch_acs_match(dev)) -+ return -ENOTTY; -+ -+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); -+ if (!pos) -+ return -ENOTTY; -+ -+ pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap); -+ pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl); -+ -+ ctrl |= (cap & PCI_ACS_SV); -+ ctrl |= (cap & PCI_ACS_RR); -+ ctrl |= (cap & PCI_ACS_CR); -+ ctrl |= (cap & PCI_ACS_UF); -+ -+ pci_write_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, ctrl); -+ -+ dev_info(&dev->dev, "Intel SPT PCH root port ACS workaround enabled\n"); -+ -+ return 0; -+} -+ - static const struct pci_dev_enable_acs { - u16 vendor; - u16 device; - int (*enable_acs)(struct pci_dev *dev); - } pci_dev_enable_acs[] = { - { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs }, -+ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_spt_pch_acs }, - { 0 } - }; - diff --git a/CVE-2017-6074-dccp-fix-freeing-skb-too-early-for-IPV6_RECVPKTINFO.patch b/CVE-2017-6074-dccp-fix-freeing-skb-too-early-for-IPV6_RECVPKTINFO.patch deleted file mode 100644 index 202aa59..0000000 --- a/CVE-2017-6074-dccp-fix-freeing-skb-too-early-for-IPV6_RECVPKTINFO.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 4feb04ade2a559e0e76a0215d259c5673e5b1cbd Mon Sep 17 00:00:00 2001 -From: Andrey Konovalov -Date: Thu, 16 Feb 2017 17:22:46 +0100 -Subject: [PATCH] dccp: fix freeing skb too early for IPV6_RECVPKTINFO -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In the current DCCP implementation an skb for a DCCP_PKT_REQUEST packet -is forcibly freed via __kfree_skb in dccp_rcv_state_process if -dccp_v6_conn_request successfully returns. - -However, if IPV6_RECVPKTINFO is set on a socket, the address of the skb -is saved to ireq->pktopts and the ref count for skb is incremented in -dccp_v6_conn_request, so skb is still in use. Nevertheless, it gets freed -in dccp_rcv_state_process. - -Fix by calling consume_skb instead of doing goto discard and therefore -calling __kfree_skb. - -Similar fixes for TCP: - -fb7e2399ec17f1004c0e0ccfd17439f8759ede01 [TCP]: skb is unexpectedly freed. -0aea76d35c9651d55bbaf746e7914e5f9ae5a25d tcp: SYN packets are now -simply consumed - -Signed-off-by: Andrey Konovalov -Acked-by: Eric Dumazet -Signed-off-by: David S. Miller - -CVE-2017-6074 -BugLink: http://bugs.launchpad.net/bugs/1665935 - -(cherry-picked from 5edabca9d4cff7f1f2b68f0bac55ef99d9798ba4 davem) -Signed-off-by: Stefan Bader - -Signed-off-by: Fabian Grünbichler ---- - net/dccp/input.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/net/dccp/input.c b/net/dccp/input.c -index 3bd14e8..dbe2573 100644 ---- a/net/dccp/input.c -+++ b/net/dccp/input.c -@@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, - if (inet_csk(sk)->icsk_af_ops->conn_request(sk, - skb) < 0) - return 1; -- goto discard; -+ consume_skb(skb); -+ return 0; - } - if (dh->dccph_type == DCCP_PKT_RESET) - goto discard; --- -2.1.4 - diff --git a/IB-ipoib-move-back-the-IB-LL-address-into-the-hard-header.patch b/IB-ipoib-move-back-the-IB-LL-address-into-the-hard-header.patch deleted file mode 100644 index 5b58edd..0000000 --- a/IB-ipoib-move-back-the-IB-LL-address-into-the-hard-header.patch +++ /dev/null @@ -1,365 +0,0 @@ -From patchwork Wed Oct 12 14:30:30 2016 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v2] IB/ipoib: move back IB LL address into the hard header -From: Paolo Abeni -X-Patchwork-Id: 681344 -X-Patchwork-Delegate: davem@davemloft.net -Message-Id: <60efcf739ce3d45a01a7127dbaf7fe366e5ddce4.1476264804.git.pabeni@redhat.com> -To: linux-rdma@vger.kernel.org -Cc: Doug Ledford , Sean Hefty , - Hal Rosenstock , - Jason Gunthorpe , netdev@vger.kernel.org -Date: Wed, 12 Oct 2016 16:30:30 +0200 - -After the commit 9207f9d45b0a ("net: preserve IP control block -during GSO segmentation"), the GSO CB and the IPoIB CB conflict. -That destroy the IPoIB address information cached there, -causing a severe performance regression, as better described here: - -http://marc.info/?l=linux-kernel&m=146787279825501&w=2 - -This change moves the data cached by the IPoIB driver from the -skb control lock into the IPoIB hard header, as done before -the commit 936d7de3d736 ("IPoIB: Stop lying about hard_header_len -and use skb->cb to stash LL addresses"). -In order to avoid GRO issue, on packet reception, the IPoIB driver -stash into the skb a dummy pseudo header, so that the received -packets have actually a hard header matching the declared length. -To avoid changing the connected mode maximum mtu, the allocated -head buffer size is increased by the pseudo header length. - -After this commit, IPoIB performances are back to pre-regression -value. - -v1 -> v2: avoid changing the max mtu, increasing the head buf size - -Fixes: 9207f9d45b0a ("net: preserve IP control block during GSO segmentation") -Signed-off-by: Paolo Abeni ---- - drivers/infiniband/ulp/ipoib/ipoib.h | 20 +++++++--- - drivers/infiniband/ulp/ipoib/ipoib_cm.c | 15 +++---- - drivers/infiniband/ulp/ipoib/ipoib_ib.c | 12 +++--- - drivers/infiniband/ulp/ipoib/ipoib_main.c | 54 ++++++++++++++++---------- - drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 6 ++- - 5 files changed, 64 insertions(+), 43 deletions(-) - -diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h -index 9dbfcc0..5ff64af 100644 ---- a/drivers/infiniband/ulp/ipoib/ipoib.h -+++ b/drivers/infiniband/ulp/ipoib/ipoib.h -@@ -63,6 +63,8 @@ enum ipoib_flush_level { - - enum { - IPOIB_ENCAP_LEN = 4, -+ IPOIB_PSEUDO_LEN = 20, -+ IPOIB_HARD_LEN = IPOIB_ENCAP_LEN + IPOIB_PSEUDO_LEN, - - IPOIB_UD_HEAD_SIZE = IB_GRH_BYTES + IPOIB_ENCAP_LEN, - IPOIB_UD_RX_SG = 2, /* max buffer needed for 4K mtu */ -@@ -134,15 +136,21 @@ struct ipoib_header { - u16 reserved; - }; - --struct ipoib_cb { -- struct qdisc_skb_cb qdisc_cb; -- u8 hwaddr[INFINIBAND_ALEN]; -+struct ipoib_pseudo_header { -+ u8 hwaddr[INFINIBAND_ALEN]; - }; - --static inline struct ipoib_cb *ipoib_skb_cb(const struct sk_buff *skb) -+static inline void skb_add_pseudo_hdr(struct sk_buff *skb) - { -- BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct ipoib_cb)); -- return (struct ipoib_cb *)skb->cb; -+ char *data = skb_push(skb, IPOIB_PSEUDO_LEN); -+ -+ /* -+ * only the ipoib header is present now, make room for a dummy -+ * pseudo header and set skb field accordingly -+ */ -+ memset(data, 0, IPOIB_PSEUDO_LEN); -+ skb_reset_mac_header(skb); -+ skb_pull(skb, IPOIB_HARD_LEN); - } - - /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ -diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c -index 4ad297d..339a1ee 100644 ---- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c -+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c -@@ -63,6 +63,8 @@ MODULE_PARM_DESC(cm_data_debug_level, - #define IPOIB_CM_RX_DELAY (3 * 256 * HZ) - #define IPOIB_CM_RX_UPDATE_MASK (0x3) - -+#define IPOIB_CM_RX_RESERVE (ALIGN(IPOIB_HARD_LEN, 16) - IPOIB_ENCAP_LEN) -+ - static struct ib_qp_attr ipoib_cm_err_attr = { - .qp_state = IB_QPS_ERR - }; -@@ -146,15 +148,15 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev, - struct sk_buff *skb; - int i; - -- skb = dev_alloc_skb(IPOIB_CM_HEAD_SIZE + 12); -+ skb = dev_alloc_skb(ALIGN(IPOIB_CM_HEAD_SIZE + IPOIB_PSEUDO_LEN, 16)); - if (unlikely(!skb)) - return NULL; - - /* -- * IPoIB adds a 4 byte header. So we need 12 more bytes to align the -+ * IPoIB adds a IPOIB_ENCAP_LEN byte header, this will align the - * IP header to a multiple of 16. - */ -- skb_reserve(skb, 12); -+ skb_reserve(skb, IPOIB_CM_RX_RESERVE); - - mapping[0] = ib_dma_map_single(priv->ca, skb->data, IPOIB_CM_HEAD_SIZE, - DMA_FROM_DEVICE); -@@ -624,9 +626,9 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) - if (wc->byte_len < IPOIB_CM_COPYBREAK) { - int dlen = wc->byte_len; - -- small_skb = dev_alloc_skb(dlen + 12); -+ small_skb = dev_alloc_skb(dlen + IPOIB_CM_RX_RESERVE); - if (small_skb) { -- skb_reserve(small_skb, 12); -+ skb_reserve(small_skb, IPOIB_CM_RX_RESERVE); - ib_dma_sync_single_for_cpu(priv->ca, rx_ring[wr_id].mapping[0], - dlen, DMA_FROM_DEVICE); - skb_copy_from_linear_data(skb, small_skb->data, dlen); -@@ -663,8 +665,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) - - copied: - skb->protocol = ((struct ipoib_header *) skb->data)->proto; -- skb_reset_mac_header(skb); -- skb_pull(skb, IPOIB_ENCAP_LEN); -+ skb_add_pseudo_hdr(skb); - - ++dev->stats.rx_packets; - dev->stats.rx_bytes += skb->len; -diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c -index be11d5d..830fecb 100644 ---- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c -+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c -@@ -128,16 +128,15 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id) - - buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu); - -- skb = dev_alloc_skb(buf_size + IPOIB_ENCAP_LEN); -+ skb = dev_alloc_skb(buf_size + IPOIB_HARD_LEN); - if (unlikely(!skb)) - return NULL; - - /* -- * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte -- * header. So we need 4 more bytes to get to 48 and align the -- * IP header to a multiple of 16. -+ * the IP header will be at IPOIP_HARD_LEN + IB_GRH_BYTES, that is -+ * 64 bytes aligned - */ -- skb_reserve(skb, 4); -+ skb_reserve(skb, sizeof(struct ipoib_pseudo_header)); - - mapping = priv->rx_ring[id].mapping; - mapping[0] = ib_dma_map_single(priv->ca, skb->data, buf_size, -@@ -253,8 +252,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) - skb_pull(skb, IB_GRH_BYTES); - - skb->protocol = ((struct ipoib_header *) skb->data)->proto; -- skb_reset_mac_header(skb); -- skb_pull(skb, IPOIB_ENCAP_LEN); -+ skb_add_pseudo_hdr(skb); - - ++dev->stats.rx_packets; - dev->stats.rx_bytes += skb->len; -diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c -index cc1c1b0..823a528 100644 ---- a/drivers/infiniband/ulp/ipoib/ipoib_main.c -+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c -@@ -925,9 +925,12 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr, - ipoib_neigh_free(neigh); - goto err_drop; - } -- if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) -+ if (skb_queue_len(&neigh->queue) < -+ IPOIB_MAX_PATH_REC_QUEUE) { -+ /* put pseudoheader back on for next time */ -+ skb_push(skb, IPOIB_PSEUDO_LEN); - __skb_queue_tail(&neigh->queue, skb); -- else { -+ } else { - ipoib_warn(priv, "queue length limit %d. Packet drop.\n", - skb_queue_len(&neigh->queue)); - goto err_drop; -@@ -964,7 +967,7 @@ err_drop: - } - - static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, -- struct ipoib_cb *cb) -+ struct ipoib_pseudo_header *phdr) - { - struct ipoib_dev_priv *priv = netdev_priv(dev); - struct ipoib_path *path; -@@ -972,16 +975,18 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, - - spin_lock_irqsave(&priv->lock, flags); - -- path = __path_find(dev, cb->hwaddr + 4); -+ path = __path_find(dev, phdr->hwaddr + 4); - if (!path || !path->valid) { - int new_path = 0; - - if (!path) { -- path = path_rec_create(dev, cb->hwaddr + 4); -+ path = path_rec_create(dev, phdr->hwaddr + 4); - new_path = 1; - } - if (path) { - if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { -+ /* put pseudoheader back on for next time */ -+ skb_push(skb, IPOIB_PSEUDO_LEN); - __skb_queue_tail(&path->queue, skb); - } else { - ++dev->stats.tx_dropped; -@@ -1009,10 +1014,12 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, - be16_to_cpu(path->pathrec.dlid)); - - spin_unlock_irqrestore(&priv->lock, flags); -- ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr)); -+ ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); - return; - } else if ((path->query || !path_rec_start(dev, path)) && - skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { -+ /* put pseudoheader back on for next time */ -+ skb_push(skb, IPOIB_PSEUDO_LEN); - __skb_queue_tail(&path->queue, skb); - } else { - ++dev->stats.tx_dropped; -@@ -1026,13 +1033,15 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) - { - struct ipoib_dev_priv *priv = netdev_priv(dev); - struct ipoib_neigh *neigh; -- struct ipoib_cb *cb = ipoib_skb_cb(skb); -+ struct ipoib_pseudo_header *phdr; - struct ipoib_header *header; - unsigned long flags; - -+ phdr = (struct ipoib_pseudo_header *) skb->data; -+ skb_pull(skb, sizeof(*phdr)); - header = (struct ipoib_header *) skb->data; - -- if (unlikely(cb->hwaddr[4] == 0xff)) { -+ if (unlikely(phdr->hwaddr[4] == 0xff)) { - /* multicast, arrange "if" according to probability */ - if ((header->proto != htons(ETH_P_IP)) && - (header->proto != htons(ETH_P_IPV6)) && -@@ -1045,13 +1054,13 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) - return NETDEV_TX_OK; - } - /* Add in the P_Key for multicast*/ -- cb->hwaddr[8] = (priv->pkey >> 8) & 0xff; -- cb->hwaddr[9] = priv->pkey & 0xff; -+ phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff; -+ phdr->hwaddr[9] = priv->pkey & 0xff; - -- neigh = ipoib_neigh_get(dev, cb->hwaddr); -+ neigh = ipoib_neigh_get(dev, phdr->hwaddr); - if (likely(neigh)) - goto send_using_neigh; -- ipoib_mcast_send(dev, cb->hwaddr, skb); -+ ipoib_mcast_send(dev, phdr->hwaddr, skb); - return NETDEV_TX_OK; - } - -@@ -1060,16 +1069,16 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) - case htons(ETH_P_IP): - case htons(ETH_P_IPV6): - case htons(ETH_P_TIPC): -- neigh = ipoib_neigh_get(dev, cb->hwaddr); -+ neigh = ipoib_neigh_get(dev, phdr->hwaddr); - if (unlikely(!neigh)) { -- neigh_add_path(skb, cb->hwaddr, dev); -+ neigh_add_path(skb, phdr->hwaddr, dev); - return NETDEV_TX_OK; - } - break; - case htons(ETH_P_ARP): - case htons(ETH_P_RARP): - /* for unicast ARP and RARP should always perform path find */ -- unicast_arp_send(skb, dev, cb); -+ unicast_arp_send(skb, dev, phdr); - return NETDEV_TX_OK; - default: - /* ethertype not supported by IPoIB */ -@@ -1086,11 +1095,13 @@ send_using_neigh: - goto unref; - } - } else if (neigh->ah) { -- ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(cb->hwaddr)); -+ ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(phdr->hwaddr)); - goto unref; - } - - if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { -+ /* put pseudoheader back on for next time */ -+ skb_push(skb, sizeof(*phdr)); - spin_lock_irqsave(&priv->lock, flags); - __skb_queue_tail(&neigh->queue, skb); - spin_unlock_irqrestore(&priv->lock, flags); -@@ -1122,8 +1133,8 @@ static int ipoib_hard_header(struct sk_buff *skb, - unsigned short type, - const void *daddr, const void *saddr, unsigned len) - { -+ struct ipoib_pseudo_header *phdr; - struct ipoib_header *header; -- struct ipoib_cb *cb = ipoib_skb_cb(skb); - - header = (struct ipoib_header *) skb_push(skb, sizeof *header); - -@@ -1132,12 +1143,13 @@ static int ipoib_hard_header(struct sk_buff *skb, - - /* - * we don't rely on dst_entry structure, always stuff the -- * destination address into skb->cb so we can figure out where -+ * destination address into skb hard header so we can figure out where - * to send the packet later. - */ -- memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN); -+ phdr = (struct ipoib_pseudo_header *) skb_push(skb, sizeof(*phdr)); -+ memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); - -- return sizeof *header; -+ return IPOIB_HARD_LEN; - } - - static void ipoib_set_mcast_list(struct net_device *dev) -@@ -1759,7 +1771,7 @@ void ipoib_setup(struct net_device *dev) - - dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - -- dev->hard_header_len = IPOIB_ENCAP_LEN; -+ dev->hard_header_len = IPOIB_HARD_LEN; - dev->addr_len = INFINIBAND_ALEN; - dev->type = ARPHRD_INFINIBAND; - dev->tx_queue_len = ipoib_sendq_size * 2; -diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c -index d3394b6..1909dd2 100644 ---- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c -+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c -@@ -796,9 +796,11 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb) - __ipoib_mcast_add(dev, mcast); - list_add_tail(&mcast->list, &priv->multicast_list); - } -- if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) -+ if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) { -+ /* put pseudoheader back on for next time */ -+ skb_push(skb, sizeof(struct ipoib_pseudo_header)); - skb_queue_tail(&mcast->pkt_queue, skb); -- else { -+ } else { - ++dev->stats.tx_dropped; - dev_kfree_skb_any(skb); - } diff --git a/Makefile b/Makefile index 0712745..2b6c819 100644 --- a/Makefile +++ b/Makefile @@ -254,20 +254,9 @@ ${KERNEL_SRC}/README ${KERNEL_CFG_ORG}: ${KERNELSRCTAR} #cd ${KERNEL_SRC}; patch -p1 <../add-empty-ndo_poll_controller-to-veth.patch cd ${KERNEL_SRC}; patch -p1 <../override_for_missing_acs_capabilities.patch #cd ${KERNEL_SRC}; patch -p1 <../vhost-net-extend-device-allocation-to-vmalloc.patch - cd ${KERNEL_SRC}; patch -p1 <../bug-950-tcp-fix-tcp_mark_head_lost-to-check-skb-len-before-f.patch - cd ${KERNEL_SRC}; patch -p1 < ../981-1-PCI-Reverse-standard-ACS-vs-device-specific-ACS-enabling.patch - cd ${KERNEL_SRC}; patch -p1 < ../981-2-PCI-Quirk-PCH-root-port-ACS-for-Sunrise-Point.patch cd ${KERNEL_SRC}; patch -p1 < ../kvm-dynamic-halt-polling-disable-default.patch - # avoid iAMT watchdog problems (not a real watchdog, because does not reset the host) - cd ${KERNEL_SRC}; patch -p1 < ../watchdog_implement-mei-iamt-driver.patch - cd ${KERNEL_SRC}; patch -p1 < ../mei_drop-watchdog-code.patch - cd ${KERNEL_SRC}; patch -p1 < ../mei_bus-whitelist-watchdog-client.patch - # IPoIB performance regression fix - cd ${KERNEL_SRC}; patch -p1 < ../IB-ipoib-move-back-the-IB-LL-address-into-the-hard-header.patch cd ${KERNEL_SRC}; patch -p1 < ../cgroup-cpuset-add-cpuset.remap_cpus.patch - cd ${KERNEL_SRC}; patch -p1 < ../0001-kvm-x86-correctly-reset-dest_map-vector-when-restori.patch cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-2596-kvm-page-reference-leakage-in-handle_vmon.patch - cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-6074-dccp-fix-freeing-skb-too-early-for-IPV6_RECVPKTINFO.patch cd ${KERNEL_SRC}; patch -p1 < ../Revert-intel_idle-Add-CPU-model-54-Atom-N2000-series.patch sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/' touch $@ diff --git a/bug-950-tcp-fix-tcp_mark_head_lost-to-check-skb-len-before-f.patch b/bug-950-tcp-fix-tcp_mark_head_lost-to-check-skb-len-before-f.patch deleted file mode 100644 index 2d9bebd..0000000 --- a/bug-950-tcp-fix-tcp_mark_head_lost-to-check-skb-len-before-f.patch +++ /dev/null @@ -1,77 +0,0 @@ -From d88270eef4b56bd7973841dd1fed387ccfa83709 Mon Sep 17 00:00:00 2001 -From: Neal Cardwell -Date: Mon, 25 Jan 2016 14:01:53 -0800 -Subject: [PATCH] tcp: fix tcp_mark_head_lost to check skb len before - fragmenting - -This commit fixes a corner case in tcp_mark_head_lost() which was -causing the WARN_ON(len > skb->len) in tcp_fragment() to fire. - -tcp_mark_head_lost() was assuming that if a packet has -tcp_skb_pcount(skb) of N, then it's safe to fragment off a prefix of -M*mss bytes, for any M < N. But with the tricky way TCP pcounts are -maintained, this is not always true. - -For example, suppose the sender sends 4 1-byte packets and have the -last 3 packet sacked. It will merge the last 3 packets in the write -queue into an skb with pcount = 3 and len = 3 bytes. If another -recovery happens after a sack reneging event, tcp_mark_head_lost() -may attempt to split the skb assuming it has more than 2*MSS bytes. - -This sounds very counterintuitive, but as the commit description for -the related commit c0638c247f55 ("tcp: don't fragment SACKed skbs in -tcp_mark_head_lost()") notes, this is because tcp_shifted_skb() -coalesces adjacent regions of SACKed skbs, and when doing this it -preserves the sum of their packet counts in order to reflect the -real-world dynamics on the wire. The c0638c247f55 commit tried to -avoid problems by not fragmenting SACKed skbs, since SACKed skbs are -where the non-proportionality between pcount and skb->len/mss is known -to be possible. However, that commit did not handle the case where -during a reneging event one of these weird SACKed skbs becomes an -un-SACKed skb, which tcp_mark_head_lost() can then try to fragment. - -The fix is to simply mark the entire skb lost when this happens. -This makes the recovery slightly more aggressive in such corner -cases before we detect reordering. But once we detect reordering -this code path is by-passed because FACK is disabled. - -Signed-off-by: Neal Cardwell -Signed-off-by: Yuchung Cheng -Signed-off-by: Eric Dumazet -Signed-off-by: David S. Miller -Cherry-picked-by: Fabian Grünbichler ---- - net/ipv4/tcp_input.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 0003d40..d2ad433 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -2164,8 +2164,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) - { - struct tcp_sock *tp = tcp_sk(sk); - struct sk_buff *skb; -- int cnt, oldcnt; -- int err; -+ int cnt, oldcnt, lost; - unsigned int mss; - /* Use SACK to deduce losses of new sequences sent during recovery */ - const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq; -@@ -2205,9 +2204,10 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) - break; - - mss = tcp_skb_mss(skb); -- err = tcp_fragment(sk, skb, (packets - oldcnt) * mss, -- mss, GFP_ATOMIC); -- if (err < 0) -+ /* If needed, chop off the prefix to mark as lost. */ -+ lost = (packets - oldcnt) * mss; -+ if (lost < skb->len && -+ tcp_fragment(sk, skb, lost, mss, GFP_ATOMIC) < 0) - break; - cnt = packets; - } --- -2.1.4 - diff --git a/mei_bus-whitelist-watchdog-client.patch b/mei_bus-whitelist-watchdog-client.patch deleted file mode 100644 index 5870e51..0000000 --- a/mei_bus-whitelist-watchdog-client.patch +++ /dev/null @@ -1,74 +0,0 @@ -From e97cdb303c04bfe60283094bdced68a0d363bd5d Mon Sep 17 00:00:00 2001 -From: Tomas Winkler -Date: Fri, 8 Jan 2016 00:49:24 +0200 -Subject: mei: bus: whitelist the watchdog client - -The iAMT WD client has to be whitelisted sice it has two connections -and is filtered out by number_of_connections fixup. -Also the API has changed for BDW and SKL but firmware haven't updated -the protocol version. - -Signed-off-by: Tomas Winkler -Signed-off-by: Alexander Usyskin -Signed-off-by: Greg Kroah-Hartman ---- - drivers/misc/mei/bus-fixup.c | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c -index b2d2a6e..b87323f 100644 ---- a/drivers/misc/mei/bus-fixup.c -+++ b/drivers/misc/mei/bus-fixup.c -@@ -35,6 +35,9 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO; - #define MEI_UUID_NFC_HCI UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, \ - 0x94, 0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c) - -+#define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \ -+ 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) -+ - #define MEI_UUID_ANY NULL_UUID_LE - - /** -@@ -66,6 +69,31 @@ static void blacklist(struct mei_cl_device *cldev) - cldev->do_match = 0; - } - -+/** -+ * mei_wd - wd client on the bus, change protocol version -+ * as the API has changed. -+ * -+ * @cldev: me clients device -+ */ -+#if IS_ENABLED(CONFIG_INTEL_MEI_ME) -+#include -+#include "hw-me-regs.h" -+static void mei_wd(struct mei_cl_device *cldev) -+{ -+ struct pci_dev *pdev = to_pci_dev(cldev->dev.parent); -+ -+ dev_dbg(&cldev->dev, "running hook %s\n", __func__); -+ if (pdev->device == MEI_DEV_ID_WPT_LP || -+ pdev->device == MEI_DEV_ID_SPT || -+ pdev->device == MEI_DEV_ID_SPT_H) -+ cldev->me_cl->props.protocol_version = 0x2; -+ -+ cldev->do_match = 1; -+} -+#else -+static inline void mei_wd(struct mei_cl_device *cldev) {} -+#endif /* CONFIG_INTEL_MEI_ME */ -+ - struct mei_nfc_cmd { - u8 command; - u8 status; -@@ -280,6 +308,7 @@ static struct mei_fixup { - MEI_FIXUP(MEI_UUID_ANY, number_of_connections), - MEI_FIXUP(MEI_UUID_NFC_INFO, blacklist), - MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc), -+ MEI_FIXUP(MEI_UUID_WD, mei_wd), - }; - - /** --- -cgit v0.12 - diff --git a/mei_drop-watchdog-code.patch b/mei_drop-watchdog-code.patch deleted file mode 100644 index f33aad2..0000000 --- a/mei_drop-watchdog-code.patch +++ /dev/null @@ -1,754 +0,0 @@ -From fdd9b8655933c3eb3154fe1ed351c17b654258bd Mon Sep 17 00:00:00 2001 -From: Alexander Usyskin -Date: Fri, 8 Jan 2016 00:49:21 +0200 -Subject: mei: wd: drop the watchdog code from the core mei driver - -Instead of integrating the iAMT watchdog in the mei core driver -we will create a watchdog device on the mei client bus and -create a driver for it. - -This patch removes the watchdog code from the mei core driver. - -Signed-off-by: Alexander Usyskin -Signed-off-by: Tomas Winkler -Signed-off-by: Greg Kroah-Hartman ---- - drivers/misc/mei/Kconfig | 6 +- - drivers/misc/mei/Makefile | 1 - - drivers/misc/mei/client.c | 12 +- - drivers/misc/mei/client.h | 4 - - drivers/misc/mei/init.c | 10 +- - drivers/misc/mei/interrupt.c | 15 -- - drivers/misc/mei/mei_dev.h | 61 +------ - drivers/misc/mei/wd.c | 391 ------------------------------------------- - 8 files changed, 9 insertions(+), 491 deletions(-) - delete mode 100644 drivers/misc/mei/wd.c - -diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig -index d23384d..c49e1d2 100644 ---- a/drivers/misc/mei/Kconfig -+++ b/drivers/misc/mei/Kconfig -@@ -1,6 +1,6 @@ - config INTEL_MEI - tristate "Intel Management Engine Interface" -- depends on X86 && PCI && WATCHDOG_CORE -+ depends on X86 && PCI - help - The Intel Management Engine (Intel ME) provides Manageability, - Security and Media services for system containing Intel chipsets. -@@ -12,7 +12,7 @@ config INTEL_MEI - config INTEL_MEI_ME - tristate "ME Enabled Intel Chipsets" - select INTEL_MEI -- depends on X86 && PCI && WATCHDOG_CORE -+ depends on X86 && PCI - help - MEI support for ME Enabled Intel chipsets. - -@@ -37,7 +37,7 @@ config INTEL_MEI_ME - config INTEL_MEI_TXE - tristate "Intel Trusted Execution Environment with ME Interface" - select INTEL_MEI -- depends on X86 && PCI && WATCHDOG_CORE -+ depends on X86 && PCI - help - MEI Support for Trusted Execution Environment device on Intel SoCs - -diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile -index 01447ca..59e6b0a 100644 ---- a/drivers/misc/mei/Makefile -+++ b/drivers/misc/mei/Makefile -@@ -9,7 +9,6 @@ mei-objs += interrupt.o - mei-objs += client.o - mei-objs += main.o - mei-objs += amthif.o --mei-objs += wd.o - mei-objs += bus.o - mei-objs += bus-fixup.o - mei-$(CONFIG_DEBUG_FS) += debugfs.o -diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c -index 72e3261..e069fca 100644 ---- a/drivers/misc/mei/client.c -+++ b/drivers/misc/mei/client.c -@@ -648,7 +648,7 @@ int mei_cl_unlink(struct mei_cl *cl) - if (!cl) - return 0; - -- /* wd and amthif might not be initialized */ -+ /* amthif might not be initialized */ - if (!cl->dev) - return 0; - -@@ -679,17 +679,11 @@ void mei_host_client_init(struct work_struct *work) - - mutex_lock(&dev->device_lock); - -- - me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid); - if (me_cl) - mei_amthif_host_init(dev, me_cl); - mei_me_cl_put(me_cl); - -- me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid); -- if (me_cl) -- mei_wd_host_init(dev, me_cl); -- mei_me_cl_put(me_cl); -- - dev->dev_state = MEI_DEV_ENABLED; - dev->reset_count = 0; - mutex_unlock(&dev->device_lock); -@@ -1153,7 +1147,7 @@ err: - * - * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise. - */ --int mei_cl_flow_ctrl_creds(struct mei_cl *cl) -+static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) - { - int rets; - -@@ -1186,7 +1180,7 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl) - * 0 on success - * -EINVAL when ctrl credits are <= 0 - */ --int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) -+static int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) - { - if (WARN_ON(!cl || !cl->me_cl)) - return -EINVAL; -diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h -index 04e1aa3..2e90a25 100644 ---- a/drivers/misc/mei/client.h -+++ b/drivers/misc/mei/client.h -@@ -18,7 +18,6 @@ - #define _MEI_CLIENT_H_ - - #include --#include - #include - #include - -@@ -120,9 +119,6 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, - enum mei_cb_file_ops type, struct file *fp); - int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); - --int mei_cl_flow_ctrl_creds(struct mei_cl *cl); -- --int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); - /* - * MEI input output function prototype - */ -diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c -index 3edafc8..46a4302 100644 ---- a/drivers/misc/mei/init.c -+++ b/drivers/misc/mei/init.c -@@ -156,8 +156,7 @@ int mei_reset(struct mei_device *dev) - mei_cl_all_wakeup(dev); - - /* remove entry if already in list */ -- dev_dbg(dev->dev, "remove iamthif and wd from the file list.\n"); -- mei_cl_unlink(&dev->wd_cl); -+ dev_dbg(dev->dev, "remove iamthif from the file list.\n"); - mei_cl_unlink(&dev->iamthif_cl); - mei_amthif_reset_params(dev); - } -@@ -165,7 +164,6 @@ int mei_reset(struct mei_device *dev) - mei_hbm_reset(dev); - - dev->rd_msg_hdr = 0; -- dev->wd_pending = false; - - if (ret) { - dev_err(dev->dev, "hw_reset failed ret = %d\n", ret); -@@ -335,16 +333,12 @@ void mei_stop(struct mei_device *dev) - - mutex_lock(&dev->device_lock); - -- mei_wd_stop(dev); -- - dev->dev_state = MEI_DEV_POWER_DOWN; - mei_reset(dev); - /* move device to disabled state unconditionally */ - dev->dev_state = MEI_DEV_DISABLED; - - mutex_unlock(&dev->device_lock); -- -- mei_watchdog_unregister(dev); - } - EXPORT_SYMBOL_GPL(mei_stop); - -@@ -394,7 +388,6 @@ void mei_device_init(struct mei_device *dev, - init_waitqueue_head(&dev->wait_hw_ready); - init_waitqueue_head(&dev->wait_pg); - init_waitqueue_head(&dev->wait_hbm_start); -- init_waitqueue_head(&dev->wait_stop_wd); - dev->dev_state = MEI_DEV_INITIALIZING; - dev->reset_count = 0; - -@@ -407,7 +400,6 @@ void mei_device_init(struct mei_device *dev, - INIT_WORK(&dev->init_work, mei_host_client_init); - INIT_WORK(&dev->reset_work, mei_reset_work); - -- INIT_LIST_HEAD(&dev->wd_cl.link); - INIT_LIST_HEAD(&dev->iamthif_cl.link); - mei_io_list_init(&dev->amthif_cmd_list); - mei_io_list_init(&dev->amthif_rd_complete_list); -diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c -index 64b568a..6340dee 100644 ---- a/drivers/misc/mei/interrupt.c -+++ b/drivers/misc/mei/interrupt.c -@@ -360,21 +360,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) - list_move_tail(&cb->list, &cmpl_list->list); - } - -- if (dev->wd_state == MEI_WD_STOPPING) { -- dev->wd_state = MEI_WD_IDLE; -- wake_up(&dev->wait_stop_wd); -- } -- -- if (mei_cl_is_connected(&dev->wd_cl)) { -- if (dev->wd_pending && -- mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { -- ret = mei_wd_send(dev); -- if (ret) -- return ret; -- dev->wd_pending = false; -- } -- } -- - /* complete control write list CB */ - dev_dbg(dev->dev, "complete control write list cb.\n"); - list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) { -diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h -index b54d9d9..da61326 100644 ---- a/drivers/misc/mei/mei_dev.h -+++ b/drivers/misc/mei/mei_dev.h -@@ -18,7 +18,7 @@ - #define _MEI_DEV_H_ - - #include --#include -+#include - #include - #include - #include -@@ -26,33 +26,13 @@ - #include "hw.h" - #include "hbm.h" - --/* -- * watch dog definition -- */ --#define MEI_WD_HDR_SIZE 4 --#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE --#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16) -- --#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */ --#define MEI_WD_MIN_TIMEOUT 120 /* seconds */ --#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ -- --#define MEI_WD_STOP_TIMEOUT 10 /* msecs */ -- --#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) -- --#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) -- - - /* - * AMTHI Client UUID - */ - extern const uuid_le mei_amthif_guid; - --/* -- * Watchdog Client UUID -- */ --extern const uuid_le mei_wd_guid; -+#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) - - /* - * Number of Maximum MEI Clients -@@ -78,7 +58,6 @@ extern const uuid_le mei_wd_guid; - */ - #define MEI_HOST_CLIENT_ID_ANY (-1) - #define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ --#define MEI_WD_HOST_CLIENT_ID 1 - #define MEI_IAMTHIF_HOST_CLIENT_ID 2 - - -@@ -123,12 +102,6 @@ enum mei_file_transaction_states { - MEI_READ_COMPLETE - }; - --enum mei_wd_states { -- MEI_WD_IDLE, -- MEI_WD_RUNNING, -- MEI_WD_STOPPING, --}; -- - /** - * enum mei_cb_file_ops - file operation associated with the callback - * @MEI_FOP_READ: read -@@ -404,7 +377,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); - * @wait_hw_ready : wait queue for receive HW ready message form FW - * @wait_pg : wait queue for receive PG message from FW - * @wait_hbm_start : wait queue for receive HBM start message from FW -- * @wait_stop_wd : wait queue for receive WD stop message from FW - * - * @reset_count : number of consecutive resets - * @dev_state : device state -@@ -435,12 +407,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); - * - * @allow_fixed_address: allow user space to connect a fixed client - * -- * @wd_cl : watchdog client -- * @wd_state : watchdog client state -- * @wd_pending : watchdog command is pending -- * @wd_timeout : watchdog expiration timeout -- * @wd_data : watchdog message buffer -- * - * @amthif_cmd_list : amthif list for cmd waiting - * @amthif_rd_complete_list : amthif list for reading completed cmd data - * @iamthif_file_object : file for current amthif operation -@@ -486,7 +452,6 @@ struct mei_device { - wait_queue_head_t wait_hw_ready; - wait_queue_head_t wait_pg; - wait_queue_head_t wait_hbm_start; -- wait_queue_head_t wait_stop_wd; - - /* - * mei device states -@@ -531,13 +496,6 @@ struct mei_device { - - bool allow_fixed_address; - -- struct mei_cl wd_cl; -- enum mei_wd_states wd_state; -- bool wd_pending; -- u16 wd_timeout; -- unsigned char wd_data[MEI_WD_START_MSG_SIZE]; -- -- - /* amthif list for cmd waiting */ - struct mei_cl_cb amthif_cmd_list; - /* driver managed amthif list for reading completed amthif cmd data */ -@@ -649,21 +607,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, - struct mei_cl_cb *complete_list); - int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); - --int mei_wd_send(struct mei_device *dev); --int mei_wd_stop(struct mei_device *dev); --int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl); --/* -- * mei_watchdog_register - Registering watchdog interface -- * once we got connection to the WD Client -- * @dev: mei device -- */ --int mei_watchdog_register(struct mei_device *dev); --/* -- * mei_watchdog_unregister - Unregistering watchdog interface -- * @dev: mei device -- */ --void mei_watchdog_unregister(struct mei_device *dev); -- - /* - * Register Access Function - */ -diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c -deleted file mode 100644 -index b346638..0000000 ---- a/drivers/misc/mei/wd.c -+++ /dev/null -@@ -1,391 +0,0 @@ --/* -- * -- * Intel Management Engine Interface (Intel MEI) Linux driver -- * Copyright (c) 2003-2012, Intel Corporation. -- * -- * This program is free software; you can redistribute it and/or modify it -- * under the terms and conditions of the GNU General Public License, -- * version 2, as published by the Free Software Foundation. -- * -- * This program is distributed in the hope it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- * more details. -- * -- */ --#include --#include --#include --#include --#include --#include -- --#include -- --#include "mei_dev.h" --#include "hbm.h" --#include "client.h" -- --static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; --static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; -- --/* -- * AMT Watchdog Device -- */ --#define INTEL_AMT_WATCHDOG_ID "INTCAMT" -- --/* UUIDs for AMT F/W clients */ --const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, -- 0x9D, 0xA9, 0x15, 0x14, 0xCB, -- 0x32, 0xAB); -- --static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) --{ -- dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); -- memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); -- memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); --} -- --/** -- * mei_wd_host_init - connect to the watchdog client -- * -- * @dev: the device structure -- * @me_cl: me client -- * -- * Return: -ENOTTY if wd client cannot be found -- * -EIO if write has failed -- * 0 on success -- */ --int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) --{ -- struct mei_cl *cl = &dev->wd_cl; -- int ret; -- -- mei_cl_init(cl, dev); -- -- dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; -- dev->wd_state = MEI_WD_IDLE; -- -- ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); -- if (ret < 0) { -- dev_info(dev->dev, "wd: failed link client\n"); -- return ret; -- } -- -- ret = mei_cl_connect(cl, me_cl, NULL); -- if (ret) { -- dev_err(dev->dev, "wd: failed to connect = %d\n", ret); -- mei_cl_unlink(cl); -- return ret; -- } -- -- ret = mei_watchdog_register(dev); -- if (ret) { -- mei_cl_disconnect(cl); -- mei_cl_unlink(cl); -- } -- return ret; --} -- --/** -- * mei_wd_send - sends watch dog message to fw. -- * -- * @dev: the device structure -- * -- * Return: 0 if success, -- * -EIO when message send fails -- * -EINVAL when invalid message is to be sent -- * -ENODEV on flow control failure -- */ --int mei_wd_send(struct mei_device *dev) --{ -- struct mei_cl *cl = &dev->wd_cl; -- struct mei_msg_hdr hdr; -- int ret; -- -- hdr.host_addr = cl->host_client_id; -- hdr.me_addr = mei_cl_me_id(cl); -- hdr.msg_complete = 1; -- hdr.reserved = 0; -- hdr.internal = 0; -- -- if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) -- hdr.length = MEI_WD_START_MSG_SIZE; -- else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) -- hdr.length = MEI_WD_STOP_MSG_SIZE; -- else { -- dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); -- return -EINVAL; -- } -- -- ret = mei_write_message(dev, &hdr, dev->wd_data); -- if (ret) { -- dev_err(dev->dev, "wd: write message failed\n"); -- return ret; -- } -- -- ret = mei_cl_flow_ctrl_reduce(cl); -- if (ret) { -- dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); -- return ret; -- } -- -- return 0; --} -- --/** -- * mei_wd_stop - sends watchdog stop message to fw. -- * -- * @dev: the device structure -- * -- * Return: 0 if success -- * on error: -- * -EIO when message send fails -- * -EINVAL when invalid message is to be sent -- * -ETIME on message timeout -- */ --int mei_wd_stop(struct mei_device *dev) --{ -- struct mei_cl *cl = &dev->wd_cl; -- int ret; -- -- if (!mei_cl_is_connected(cl) || -- dev->wd_state != MEI_WD_RUNNING) -- return 0; -- -- memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); -- -- dev->wd_state = MEI_WD_STOPPING; -- -- ret = mei_cl_flow_ctrl_creds(cl); -- if (ret < 0) -- goto err; -- -- if (ret && mei_hbuf_acquire(dev)) { -- ret = mei_wd_send(dev); -- if (ret) -- goto err; -- dev->wd_pending = false; -- } else { -- dev->wd_pending = true; -- } -- -- mutex_unlock(&dev->device_lock); -- -- ret = wait_event_timeout(dev->wait_stop_wd, -- dev->wd_state == MEI_WD_IDLE, -- msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); -- mutex_lock(&dev->device_lock); -- if (dev->wd_state != MEI_WD_IDLE) { -- /* timeout */ -- ret = -ETIME; -- dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); -- goto err; -- } -- dev_dbg(dev->dev, "wd: stop completed after %u msec\n", -- MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); -- return 0; --err: -- return ret; --} -- --/** -- * mei_wd_ops_start - wd start command from the watchdog core. -- * -- * @wd_dev: watchdog device struct -- * -- * Return: 0 if success, negative errno code for failure -- */ --static int mei_wd_ops_start(struct watchdog_device *wd_dev) --{ -- struct mei_device *dev; -- struct mei_cl *cl; -- int err = -ENODEV; -- -- dev = watchdog_get_drvdata(wd_dev); -- if (!dev) -- return -ENODEV; -- -- cl = &dev->wd_cl; -- -- mutex_lock(&dev->device_lock); -- -- if (dev->dev_state != MEI_DEV_ENABLED) { -- dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", -- mei_dev_state_str(dev->dev_state)); -- goto end_unlock; -- } -- -- if (!mei_cl_is_connected(cl)) { -- cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); -- goto end_unlock; -- } -- -- mei_wd_set_start_timeout(dev, dev->wd_timeout); -- -- err = 0; --end_unlock: -- mutex_unlock(&dev->device_lock); -- return err; --} -- --/** -- * mei_wd_ops_stop - wd stop command from the watchdog core. -- * -- * @wd_dev: watchdog device struct -- * -- * Return: 0 if success, negative errno code for failure -- */ --static int mei_wd_ops_stop(struct watchdog_device *wd_dev) --{ -- struct mei_device *dev; -- -- dev = watchdog_get_drvdata(wd_dev); -- if (!dev) -- return -ENODEV; -- -- mutex_lock(&dev->device_lock); -- mei_wd_stop(dev); -- mutex_unlock(&dev->device_lock); -- -- return 0; --} -- --/** -- * mei_wd_ops_ping - wd ping command from the watchdog core. -- * -- * @wd_dev: watchdog device struct -- * -- * Return: 0 if success, negative errno code for failure -- */ --static int mei_wd_ops_ping(struct watchdog_device *wd_dev) --{ -- struct mei_device *dev; -- struct mei_cl *cl; -- int ret; -- -- dev = watchdog_get_drvdata(wd_dev); -- if (!dev) -- return -ENODEV; -- -- cl = &dev->wd_cl; -- -- mutex_lock(&dev->device_lock); -- -- if (!mei_cl_is_connected(cl)) { -- cl_err(dev, cl, "wd: not connected.\n"); -- ret = -ENODEV; -- goto end; -- } -- -- dev->wd_state = MEI_WD_RUNNING; -- -- ret = mei_cl_flow_ctrl_creds(cl); -- if (ret < 0) -- goto end; -- -- /* Check if we can send the ping to HW*/ -- if (ret && mei_hbuf_acquire(dev)) { -- dev_dbg(dev->dev, "wd: sending ping\n"); -- -- ret = mei_wd_send(dev); -- if (ret) -- goto end; -- dev->wd_pending = false; -- } else { -- dev->wd_pending = true; -- } -- --end: -- mutex_unlock(&dev->device_lock); -- return ret; --} -- --/** -- * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. -- * -- * @wd_dev: watchdog device struct -- * @timeout: timeout value to set -- * -- * Return: 0 if success, negative errno code for failure -- */ --static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, -- unsigned int timeout) --{ -- struct mei_device *dev; -- -- dev = watchdog_get_drvdata(wd_dev); -- if (!dev) -- return -ENODEV; -- -- /* Check Timeout value */ -- if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) -- return -EINVAL; -- -- mutex_lock(&dev->device_lock); -- -- dev->wd_timeout = timeout; -- wd_dev->timeout = timeout; -- mei_wd_set_start_timeout(dev, dev->wd_timeout); -- -- mutex_unlock(&dev->device_lock); -- -- return 0; --} -- --/* -- * Watchdog Device structs -- */ --static const struct watchdog_ops wd_ops = { -- .owner = THIS_MODULE, -- .start = mei_wd_ops_start, -- .stop = mei_wd_ops_stop, -- .ping = mei_wd_ops_ping, -- .set_timeout = mei_wd_ops_set_timeout, --}; --static const struct watchdog_info wd_info = { -- .identity = INTEL_AMT_WATCHDOG_ID, -- .options = WDIOF_KEEPALIVEPING | -- WDIOF_SETTIMEOUT | -- WDIOF_ALARMONLY, --}; -- --static struct watchdog_device amt_wd_dev = { -- .info = &wd_info, -- .ops = &wd_ops, -- .timeout = MEI_WD_DEFAULT_TIMEOUT, -- .min_timeout = MEI_WD_MIN_TIMEOUT, -- .max_timeout = MEI_WD_MAX_TIMEOUT, --}; -- -- --int mei_watchdog_register(struct mei_device *dev) --{ -- -- int ret; -- -- amt_wd_dev.parent = dev->dev; -- /* unlock to perserve correct locking order */ -- mutex_unlock(&dev->device_lock); -- ret = watchdog_register_device(&amt_wd_dev); -- mutex_lock(&dev->device_lock); -- if (ret) { -- dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n", -- ret); -- return ret; -- } -- -- dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); -- watchdog_set_drvdata(&amt_wd_dev, dev); -- return 0; --} -- --void mei_watchdog_unregister(struct mei_device *dev) --{ -- if (watchdog_get_drvdata(&amt_wd_dev) == NULL) -- return; -- -- watchdog_set_drvdata(&amt_wd_dev, NULL); -- watchdog_unregister_device(&amt_wd_dev); --} -- --- -cgit v0.12 - diff --git a/watchdog_implement-mei-iamt-driver.patch b/watchdog_implement-mei-iamt-driver.patch deleted file mode 100644 index dc7834c..0000000 --- a/watchdog_implement-mei-iamt-driver.patch +++ /dev/null @@ -1,514 +0,0 @@ -From 222818c3d84c1f3190767f5f09f2b9b9a0e0ca7f Mon Sep 17 00:00:00 2001 -From: Tomas Winkler -Date: Fri, 8 Jan 2016 00:49:22 +0200 -Subject: watchdog: mei_wdt: implement MEI iAMT watchdog driver - -Create a driver with the generic watchdog interface -for the MEI iAMT watchdog device. - -Signed-off-by: Alexander Usyskin -Signed-off-by: Tomas Winkler -Signed-off-by: Greg Kroah-Hartman - -PVE NOTES: the old code always enables this watchdog, but we do not -want to use this watchdog because it does not reboot the host, and min -timeout is 120 seconds. With this patch, we can simply blacklist mei_wdt. - ---- - Documentation/misc-devices/mei/mei.txt | 12 +- - MAINTAINERS | 1 + - drivers/watchdog/Kconfig | 15 ++ - drivers/watchdog/Makefile | 1 + - drivers/watchdog/mei_wdt.c | 404 +++++++++++++++++++++++++++++++++ - 5 files changed, 427 insertions(+), 6 deletions(-) - create mode 100644 drivers/watchdog/mei_wdt.c - -diff --git a/Documentation/misc-devices/mei/mei.txt b/Documentation/misc-devices/mei/mei.txt -index 91c1fa3..2b80a0c 100644 ---- a/Documentation/misc-devices/mei/mei.txt -+++ b/Documentation/misc-devices/mei/mei.txt -@@ -231,15 +231,15 @@ IT knows when a platform crashes even when there is a hard failure on the host. - The Intel AMT Watchdog is composed of two parts: - 1) Firmware feature - receives the heartbeats - and sends an event when the heartbeats stop. -- 2) Intel MEI driver - connects to the watchdog feature, configures the -- watchdog and sends the heartbeats. -+ 2) Intel MEI iAMT watchdog driver - connects to the watchdog feature, -+ configures the watchdog and sends the heartbeats. - --The Intel MEI driver uses the kernel watchdog API to configure the Intel AMT --Watchdog and to send heartbeats to it. The default timeout of the -+The Intel iAMT watchdog MEI driver uses the kernel watchdog API to configure -+the Intel AMT Watchdog and to send heartbeats to it. The default timeout of the - watchdog is 120 seconds. - --If the Intel AMT Watchdog feature does not exist (i.e. the connection failed), --the Intel MEI driver will disable the sending of heartbeats. -+If the Intel AMT is not enabled in the firmware then the watchdog client won't enumerate -+on the me client bus and watchdog devices won't be exposed. - - - Supported Chipsets -diff --git a/MAINTAINERS b/MAINTAINERS -index 30aca4a..d63b3c7 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -5751,6 +5751,7 @@ S: Supported - F: include/uapi/linux/mei.h - F: include/linux/mei_cl_bus.h - F: drivers/misc/mei/* -+F: drivers/watchdog/mei_wdt.c - F: Documentation/misc-devices/mei/* - - INTEL MIC DRIVERS (mic) -diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index 4f0e7be..57f8721 100644 ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -1212,6 +1212,21 @@ config SBC_EPX_C3_WATCHDOG - To compile this driver as a module, choose M here: the - module will be called sbc_epx_c3. - -+config INTEL_MEI_WDT -+ tristate "Intel MEI iAMT Watchdog" -+ depends on INTEL_MEI && X86 -+ select WATCHDOG_CORE -+ ---help--- -+ A device driver for the Intel MEI iAMT watchdog. -+ -+ The Intel AMT Watchdog is an OS Health (Hang/Crash) watchdog. -+ Whenever the OS hangs or crashes, iAMT will send an event -+ to any subscriber to this event. The watchdog doesn't reset the -+ the platform. -+ -+ To compile this driver as a module, choose M here: -+ the module will be called mei_wdt. -+ - # M32R Architecture - - # M68K Architecture -diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile -index f566753..efc4f78 100644 ---- a/drivers/watchdog/Makefile -+++ b/drivers/watchdog/Makefile -@@ -126,6 +126,7 @@ obj-$(CONFIG_MACHZ_WDT) += machzwd.o - obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o - obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o - obj-$(CONFIG_INTEL_MID_WATCHDOG) += intel-mid_wdt.o -+obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o - - # M32R Architecture - -diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c -new file mode 100644 -index 0000000..32e3e1d ---- /dev/null -+++ b/drivers/watchdog/mei_wdt.c -@@ -0,0 +1,404 @@ -+/* -+ * Intel Management Engine Interface (Intel MEI) Linux driver -+ * Copyright (c) 2015, Intel Corporation. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* -+ * iAMT Watchdog Device -+ */ -+#define INTEL_AMT_WATCHDOG_ID "iamt_wdt" -+ -+#define MEI_WDT_DEFAULT_TIMEOUT 120 /* seconds */ -+#define MEI_WDT_MIN_TIMEOUT 120 /* seconds */ -+#define MEI_WDT_MAX_TIMEOUT 65535 /* seconds */ -+ -+/* Commands */ -+#define MEI_MANAGEMENT_CONTROL 0x02 -+ -+/* MEI Management Control version number */ -+#define MEI_MC_VERSION_NUMBER 0x10 -+ -+/* Sub Commands */ -+#define MEI_MC_START_WD_TIMER_REQ 0x13 -+#define MEI_MC_STOP_WD_TIMER_REQ 0x14 -+ -+/** -+ * enum mei_wdt_state - internal watchdog state -+ * -+ * @MEI_WDT_IDLE: wd is idle and not opened -+ * @MEI_WDT_START: wd was opened, start was called -+ * @MEI_WDT_RUNNING: wd is expecting keep alive pings -+ * @MEI_WDT_STOPPING: wd is stopping and will move to IDLE -+ */ -+enum mei_wdt_state { -+ MEI_WDT_IDLE, -+ MEI_WDT_START, -+ MEI_WDT_RUNNING, -+ MEI_WDT_STOPPING, -+}; -+ -+/** -+ * struct mei_wdt - mei watchdog driver -+ * @wdd: watchdog device -+ * -+ * @cldev: mei watchdog client device -+ * @state: watchdog internal state -+ * @timeout: watchdog current timeout -+ */ -+struct mei_wdt { -+ struct watchdog_device wdd; -+ -+ struct mei_cl_device *cldev; -+ enum mei_wdt_state state; -+ u16 timeout; -+}; -+ -+/* -+ * struct mei_mc_hdr - Management Control Command Header -+ * -+ * @command: Management Control (0x2) -+ * @bytecount: Number of bytes in the message beyond this byte -+ * @subcommand: Management Control Subcommand -+ * @versionnumber: Management Control Version (0x10) -+ */ -+struct mei_mc_hdr { -+ u8 command; -+ u8 bytecount; -+ u8 subcommand; -+ u8 versionnumber; -+}; -+ -+/** -+ * struct mei_wdt_start_request watchdog start/ping -+ * -+ * @hdr: Management Control Command Header -+ * @timeout: timeout value -+ * @reserved: reserved (legacy) -+ */ -+struct mei_wdt_start_request { -+ struct mei_mc_hdr hdr; -+ u16 timeout; -+ u8 reserved[17]; -+} __packed; -+ -+/** -+ * struct mei_wdt_stop_request - watchdog stop -+ * -+ * @hdr: Management Control Command Header -+ */ -+struct mei_wdt_stop_request { -+ struct mei_mc_hdr hdr; -+} __packed; -+ -+/** -+ * mei_wdt_ping - send wd start/ping command -+ * -+ * @wdt: mei watchdog device -+ * -+ * Return: 0 on success, -+ * negative errno code on failure -+ */ -+static int mei_wdt_ping(struct mei_wdt *wdt) -+{ -+ struct mei_wdt_start_request req; -+ const size_t req_len = sizeof(req); -+ int ret; -+ -+ memset(&req, 0, req_len); -+ req.hdr.command = MEI_MANAGEMENT_CONTROL; -+ req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); -+ req.hdr.subcommand = MEI_MC_START_WD_TIMER_REQ; -+ req.hdr.versionnumber = MEI_MC_VERSION_NUMBER; -+ req.timeout = wdt->timeout; -+ -+ ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+/** -+ * mei_wdt_stop - send wd stop command -+ * -+ * @wdt: mei watchdog device -+ * -+ * Return: 0 on success, -+ * negative errno code on failure -+ */ -+static int mei_wdt_stop(struct mei_wdt *wdt) -+{ -+ struct mei_wdt_stop_request req; -+ const size_t req_len = sizeof(req); -+ int ret; -+ -+ memset(&req, 0, req_len); -+ req.hdr.command = MEI_MANAGEMENT_CONTROL; -+ req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); -+ req.hdr.subcommand = MEI_MC_STOP_WD_TIMER_REQ; -+ req.hdr.versionnumber = MEI_MC_VERSION_NUMBER; -+ -+ ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+/** -+ * mei_wdt_ops_start - wd start command from the watchdog core. -+ * -+ * @wdd: watchdog device -+ * -+ * Return: 0 on success or -ENODEV; -+ */ -+static int mei_wdt_ops_start(struct watchdog_device *wdd) -+{ -+ struct mei_wdt *wdt = watchdog_get_drvdata(wdd); -+ -+ wdt->state = MEI_WDT_START; -+ wdd->timeout = wdt->timeout; -+ return 0; -+} -+ -+/** -+ * mei_wdt_ops_stop - wd stop command from the watchdog core. -+ * -+ * @wdd: watchdog device -+ * -+ * Return: 0 if success, negative errno code for failure -+ */ -+static int mei_wdt_ops_stop(struct watchdog_device *wdd) -+{ -+ struct mei_wdt *wdt = watchdog_get_drvdata(wdd); -+ int ret; -+ -+ if (wdt->state != MEI_WDT_RUNNING) -+ return 0; -+ -+ wdt->state = MEI_WDT_STOPPING; -+ -+ ret = mei_wdt_stop(wdt); -+ if (ret) -+ return ret; -+ -+ wdt->state = MEI_WDT_IDLE; -+ -+ return 0; -+} -+ -+/** -+ * mei_wdt_ops_ping - wd ping command from the watchdog core. -+ * -+ * @wdd: watchdog device -+ * -+ * Return: 0 if success, negative errno code on failure -+ */ -+static int mei_wdt_ops_ping(struct watchdog_device *wdd) -+{ -+ struct mei_wdt *wdt = watchdog_get_drvdata(wdd); -+ int ret; -+ -+ if (wdt->state != MEI_WDT_START && wdt->state != MEI_WDT_RUNNING) -+ return 0; -+ -+ ret = mei_wdt_ping(wdt); -+ if (ret) -+ return ret; -+ -+ wdt->state = MEI_WDT_RUNNING; -+ -+ return 0; -+} -+ -+/** -+ * mei_wdt_ops_set_timeout - wd set timeout command from the watchdog core. -+ * -+ * @wdd: watchdog device -+ * @timeout: timeout value to set -+ * -+ * Return: 0 if success, negative errno code for failure -+ */ -+static int mei_wdt_ops_set_timeout(struct watchdog_device *wdd, -+ unsigned int timeout) -+{ -+ -+ struct mei_wdt *wdt = watchdog_get_drvdata(wdd); -+ -+ /* valid value is already checked by the caller */ -+ wdt->timeout = timeout; -+ wdd->timeout = timeout; -+ -+ return 0; -+} -+ -+static const struct watchdog_ops wd_ops = { -+ .owner = THIS_MODULE, -+ .start = mei_wdt_ops_start, -+ .stop = mei_wdt_ops_stop, -+ .ping = mei_wdt_ops_ping, -+ .set_timeout = mei_wdt_ops_set_timeout, -+}; -+ -+/* not const as the firmware_version field need to be retrieved */ -+static struct watchdog_info wd_info = { -+ .identity = INTEL_AMT_WATCHDOG_ID, -+ .options = WDIOF_KEEPALIVEPING | -+ WDIOF_SETTIMEOUT | -+ WDIOF_ALARMONLY, -+}; -+ -+/** -+ * mei_wdt_unregister - unregister from the watchdog subsystem -+ * -+ * @wdt: mei watchdog device -+ */ -+static void mei_wdt_unregister(struct mei_wdt *wdt) -+{ -+ watchdog_unregister_device(&wdt->wdd); -+ watchdog_set_drvdata(&wdt->wdd, NULL); -+} -+ -+/** -+ * mei_wdt_register - register with the watchdog subsystem -+ * -+ * @wdt: mei watchdog device -+ * -+ * Return: 0 if success, negative errno code for failure -+ */ -+static int mei_wdt_register(struct mei_wdt *wdt) -+{ -+ struct device *dev; -+ int ret; -+ -+ if (!wdt || !wdt->cldev) -+ return -EINVAL; -+ -+ dev = &wdt->cldev->dev; -+ -+ wdt->wdd.info = &wd_info; -+ wdt->wdd.ops = &wd_ops; -+ wdt->wdd.parent = dev; -+ wdt->wdd.timeout = MEI_WDT_DEFAULT_TIMEOUT; -+ wdt->wdd.min_timeout = MEI_WDT_MIN_TIMEOUT; -+ wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT; -+ -+ watchdog_set_drvdata(&wdt->wdd, wdt); -+ ret = watchdog_register_device(&wdt->wdd); -+ if (ret) { -+ dev_err(dev, "unable to register watchdog device = %d.\n", ret); -+ watchdog_set_drvdata(&wdt->wdd, NULL); -+ } -+ -+ return ret; -+} -+ -+static int mei_wdt_probe(struct mei_cl_device *cldev, -+ const struct mei_cl_device_id *id) -+{ -+ struct mei_wdt *wdt; -+ int ret; -+ -+ wdt = kzalloc(sizeof(struct mei_wdt), GFP_KERNEL); -+ if (!wdt) -+ return -ENOMEM; -+ -+ wdt->timeout = MEI_WDT_DEFAULT_TIMEOUT; -+ wdt->state = MEI_WDT_IDLE; -+ wdt->cldev = cldev; -+ mei_cldev_set_drvdata(cldev, wdt); -+ -+ ret = mei_cldev_enable(cldev); -+ if (ret < 0) { -+ dev_err(&cldev->dev, "Could not enable cl device\n"); -+ goto err_out; -+ } -+ -+ wd_info.firmware_version = mei_cldev_ver(cldev); -+ -+ ret = mei_wdt_register(wdt); -+ if (ret) -+ goto err_disable; -+ -+ return 0; -+ -+err_disable: -+ mei_cldev_disable(cldev); -+ -+err_out: -+ kfree(wdt); -+ -+ return ret; -+} -+ -+static int mei_wdt_remove(struct mei_cl_device *cldev) -+{ -+ struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); -+ -+ mei_wdt_unregister(wdt); -+ -+ mei_cldev_disable(cldev); -+ -+ kfree(wdt); -+ -+ return 0; -+} -+ -+#define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \ -+ 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) -+ -+static struct mei_cl_device_id mei_wdt_tbl[] = { -+ { .uuid = MEI_UUID_WD, .version = 0x1}, -+ /* required last entry */ -+ { } -+}; -+MODULE_DEVICE_TABLE(mei, mei_wdt_tbl); -+ -+static struct mei_cl_driver mei_wdt_driver = { -+ .id_table = mei_wdt_tbl, -+ .name = KBUILD_MODNAME, -+ -+ .probe = mei_wdt_probe, -+ .remove = mei_wdt_remove, -+}; -+ -+static int __init mei_wdt_init(void) -+{ -+ int ret; -+ -+ ret = mei_cldev_driver_register(&mei_wdt_driver); -+ if (ret) { -+ pr_err(KBUILD_MODNAME ": module registration failed\n"); -+ return ret; -+ } -+ return 0; -+} -+ -+static void __exit mei_wdt_exit(void) -+{ -+ mei_cldev_driver_unregister(&mei_wdt_driver); -+} -+ -+module_init(mei_wdt_init); -+module_exit(mei_wdt_exit); -+ -+MODULE_AUTHOR("Intel Corporation"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Device driver for Intel MEI iAMT watchdog"); --- -cgit v0.12 - -- 2.39.2