]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.17-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jul 2018 09:27:15 +0000 (11:27 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jul 2018 09:27:15 +0000 (11:27 +0200)
added patches:
acpica-aml-parser-ignore-dispatcher-error-status-during-table-load.patch
can-m_can-fix-runtime-resume-call.patch
can-m_can.c-fix-setup-of-cccr-register-clear-cccr-niso-bit-before-checking-can.ctrlmode.patch
can-peak_canfd-fix-firmware-v3.3.0-limit-allocation-to-32-bit-dma-addr-only.patch
can-xilinx_can-fix-device-dropping-off-bus-on-rx-overrun.patch
can-xilinx_can-fix-incorrect-clear-of-non-processed-interrupts.patch
can-xilinx_can-fix-power-management-handling.patch
can-xilinx_can-fix-recovery-from-error-states-not-being-propagated.patch
can-xilinx_can-fix-rx-loop-if-rxnemp-is-asserted-without-rxok.patch
can-xilinx_can-fix-rx-overflow-interrupt-not-being-enabled.patch
can-xilinx_can-keep-only-1-2-frames-in-tx-fifo-to-fix-tx-accounting.patch
driver-core-partially-revert-driver-core-correct-device-s-shutdown-order.patch
revert-staging-r8188eu-use-lib80211-to-support-tkip.patch
staging-speakup-fix-wraparound-in-uaccess-length-check.patch
usb-cdc_acm-add-quirk-for-castles-vega3000.patch
usb-core-handle-hub-c_port_over_current-condition.patch
usb-dwc2-fix-dma-alignment-to-start-at-allocated-boundary.patch
usb-gadget-f_fs-only-return-delayed-status-when-len-is-0.patch
usb-gadget-fix-os-descriptors-support.patch
usb-xhci-fix-memory-leak-in-xhci_endpoint_reset.patch

21 files changed:
queue-4.17/acpica-aml-parser-ignore-dispatcher-error-status-during-table-load.patch [new file with mode: 0644]
queue-4.17/can-m_can-fix-runtime-resume-call.patch [new file with mode: 0644]
queue-4.17/can-m_can.c-fix-setup-of-cccr-register-clear-cccr-niso-bit-before-checking-can.ctrlmode.patch [new file with mode: 0644]
queue-4.17/can-peak_canfd-fix-firmware-v3.3.0-limit-allocation-to-32-bit-dma-addr-only.patch [new file with mode: 0644]
queue-4.17/can-xilinx_can-fix-device-dropping-off-bus-on-rx-overrun.patch [new file with mode: 0644]
queue-4.17/can-xilinx_can-fix-incorrect-clear-of-non-processed-interrupts.patch [new file with mode: 0644]
queue-4.17/can-xilinx_can-fix-power-management-handling.patch [new file with mode: 0644]
queue-4.17/can-xilinx_can-fix-recovery-from-error-states-not-being-propagated.patch [new file with mode: 0644]
queue-4.17/can-xilinx_can-fix-rx-loop-if-rxnemp-is-asserted-without-rxok.patch [new file with mode: 0644]
queue-4.17/can-xilinx_can-fix-rx-overflow-interrupt-not-being-enabled.patch [new file with mode: 0644]
queue-4.17/can-xilinx_can-keep-only-1-2-frames-in-tx-fifo-to-fix-tx-accounting.patch [new file with mode: 0644]
queue-4.17/driver-core-partially-revert-driver-core-correct-device-s-shutdown-order.patch [new file with mode: 0644]
queue-4.17/revert-staging-r8188eu-use-lib80211-to-support-tkip.patch [new file with mode: 0644]
queue-4.17/series
queue-4.17/staging-speakup-fix-wraparound-in-uaccess-length-check.patch [new file with mode: 0644]
queue-4.17/usb-cdc_acm-add-quirk-for-castles-vega3000.patch [new file with mode: 0644]
queue-4.17/usb-core-handle-hub-c_port_over_current-condition.patch [new file with mode: 0644]
queue-4.17/usb-dwc2-fix-dma-alignment-to-start-at-allocated-boundary.patch [new file with mode: 0644]
queue-4.17/usb-gadget-f_fs-only-return-delayed-status-when-len-is-0.patch [new file with mode: 0644]
queue-4.17/usb-gadget-fix-os-descriptors-support.patch [new file with mode: 0644]
queue-4.17/usb-xhci-fix-memory-leak-in-xhci_endpoint_reset.patch [new file with mode: 0644]

diff --git a/queue-4.17/acpica-aml-parser-ignore-dispatcher-error-status-during-table-load.patch b/queue-4.17/acpica-aml-parser-ignore-dispatcher-error-status-during-table-load.patch
new file mode 100644 (file)
index 0000000..24fc688
--- /dev/null
@@ -0,0 +1,90 @@
+From 73c2a01c52b657f4a0ead6c95f64c5279efbd000 Mon Sep 17 00:00:00 2001
+From: "Schmauss, Erik" <erik.schmauss@intel.com>
+Date: Thu, 19 Jul 2018 16:33:00 -0700
+Subject: ACPICA: AML Parser: ignore dispatcher error status during table load
+
+From: Schmauss, Erik <erik.schmauss@intel.com>
+
+commit 73c2a01c52b657f4a0ead6c95f64c5279efbd000 upstream.
+
+The dispatcher and the executer process the parse nodes During table
+load. Error status from the evaluation confuses the AML parser. This
+results in the parser failing to complete parsing of the current
+scope op which becomes problematic. For the incorrect AML below, _ADR
+never gets created.
+
+definition_block(...)
+{
+   Scope (\_SB)
+   {
+     Device (PCI0){...}
+     Name (OBJ1, 0x0)
+     OBJ1 = PCI0 + 5 // Results in an operand error.
+   } // \_SB not closed
+
+   // parser looks for \_SB._SB.PCI0, results in AE_NOT_FOUND error
+   // Entire scope block gets skipped.
+   Scope (\_SB.PCI0)
+   {
+       Name (_ADR, 0x0)
+   }
+}
+
+Fix the above error by properly completing the initial \_SB scope
+after an error by clearing errors that occur during table load. In
+the above case, this means that OBJ1 = PIC0 + 5 is skipped.
+
+Fixes: 5088814a6e93 (ACPICA: AML parser: attempt to continue loading table after error)
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=200363
+Tested-by: Bastien Nocera <hadess@hadess.net>
+Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
+Cc: 4.17+ <stable@vger.kernel.org> # 4.17+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/acpica/psloop.c |   26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+--- a/drivers/acpi/acpica/psloop.c
++++ b/drivers/acpi/acpica/psloop.c
+@@ -497,6 +497,18 @@ acpi_status acpi_ps_parse_loop(struct ac
+                       status =
+                           acpi_ps_create_op(walk_state, aml_op_start, &op);
+                       if (ACPI_FAILURE(status)) {
++                              /*
++                               * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by
++                               * executing it as a control method. However, if we encounter
++                               * an error while loading the table, we need to keep trying to
++                               * load the table rather than aborting the table load. Set the
++                               * status to AE_OK to proceed with the table load.
++                               */
++                              if ((walk_state->
++                                   parse_flags & ACPI_PARSE_MODULE_LEVEL)
++                                  && status == AE_ALREADY_EXISTS) {
++                                      status = AE_OK;
++                              }
+                               if (status == AE_CTRL_PARSE_CONTINUE) {
+                                       continue;
+                               }
+@@ -694,6 +706,20 @@ acpi_status acpi_ps_parse_loop(struct ac
+                           acpi_ps_next_parse_state(walk_state, op, status);
+                       if (status == AE_CTRL_PENDING) {
+                               status = AE_OK;
++                      } else
++                          if ((walk_state->
++                               parse_flags & ACPI_PARSE_MODULE_LEVEL)
++                              && ACPI_FAILURE(status)) {
++                              /*
++                               * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by
++                               * executing it as a control method. However, if we encounter
++                               * an error while loading the table, we need to keep trying to
++                               * load the table rather than aborting the table load. Set the
++                               * status to AE_OK to proceed with the table load. If we get a
++                               * failure at this point, it means that the dispatcher got an
++                               * error while processing Op (most likely an AML operand error.
++                               */
++                              status = AE_OK;
+                       }
+               }
diff --git a/queue-4.17/can-m_can-fix-runtime-resume-call.patch b/queue-4.17/can-m_can-fix-runtime-resume-call.patch
new file mode 100644 (file)
index 0000000..fa0ad55
--- /dev/null
@@ -0,0 +1,53 @@
+From 1675bee3e732c2449e792feed9caff804f3bd42c Mon Sep 17 00:00:00 2001
+From: Faiz Abbas <faiz_abbas@ti.com>
+Date: Tue, 3 Jul 2018 16:41:02 +0530
+Subject: can: m_can: Fix runtime resume call
+
+From: Faiz Abbas <faiz_abbas@ti.com>
+
+commit 1675bee3e732c2449e792feed9caff804f3bd42c upstream.
+
+pm_runtime_get_sync() returns a 1 if the state of the device is already
+'active'. This is not a failure case and should return a success.
+
+Therefore fix error handling for pm_runtime_get_sync() call such that
+it returns success when the value is 1.
+
+Also cleanup the TODO for using runtime PM for sleep mode as that is
+implemented.
+
+Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
+Cc: <stable@vger.kernel.org
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/m_can/m_can.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/can/m_can/m_can.c
++++ b/drivers/net/can/m_can/m_can.c
+@@ -634,10 +634,12 @@ static int m_can_clk_start(struct m_can_
+       int err;
+       err = pm_runtime_get_sync(priv->device);
+-      if (err)
++      if (err < 0) {
+               pm_runtime_put_noidle(priv->device);
++              return err;
++      }
+-      return err;
++      return 0;
+ }
+ static void m_can_clk_stop(struct m_can_priv *priv)
+@@ -1687,8 +1689,6 @@ failed_ret:
+       return ret;
+ }
+-/* TODO: runtime PM with power down or sleep mode  */
+-
+ static __maybe_unused int m_can_suspend(struct device *dev)
+ {
+       struct net_device *ndev = dev_get_drvdata(dev);
diff --git a/queue-4.17/can-m_can.c-fix-setup-of-cccr-register-clear-cccr-niso-bit-before-checking-can.ctrlmode.patch b/queue-4.17/can-m_can.c-fix-setup-of-cccr-register-clear-cccr-niso-bit-before-checking-can.ctrlmode.patch
new file mode 100644 (file)
index 0000000..0771097
--- /dev/null
@@ -0,0 +1,41 @@
+From 393753b217f05474e714aea36c37501546ed1202 Mon Sep 17 00:00:00 2001
+From: Roman Fietze <roman.fietze@telemotive.de>
+Date: Wed, 11 Jul 2018 15:36:14 +0200
+Subject: can: m_can.c: fix setup of CCCR register: clear CCCR NISO bit before checking can.ctrlmode
+
+From: Roman Fietze <roman.fietze@telemotive.de>
+
+commit 393753b217f05474e714aea36c37501546ed1202 upstream.
+
+Inside m_can_chip_config(), when setting up the new value of the CCCR,
+the CCCR_NISO bit is not cleared like the others, CCCR_TEST, CCCR_MON,
+CCCR_BRSE and CCCR_FDOE, before checking the can.ctrlmode bits for
+CAN_CTRLMODE_FD_NON_ISO.
+
+This way once the controller was configured for CAN_CTRLMODE_FD_NON_ISO,
+this mode could never be cleared again.
+
+This fix is only relevant for controllers with version 3.1.x or 3.2.x.
+Older versions do not support NISO.
+
+Signed-off-by: Roman Fietze <roman.fietze@telemotive.de>
+Cc: linux-stable <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/m_can/m_can.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/can/m_can/m_can.c
++++ b/drivers/net/can/m_can/m_can.c
+@@ -1111,7 +1111,8 @@ static void m_can_chip_config(struct net
+       } else {
+       /* Version 3.1.x or 3.2.x */
+-              cccr &= ~(CCCR_TEST | CCCR_MON | CCCR_BRSE | CCCR_FDOE);
++              cccr &= ~(CCCR_TEST | CCCR_MON | CCCR_BRSE | CCCR_FDOE |
++                        CCCR_NISO);
+               /* Only 3.2.x has NISO Bit implemented */
+               if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)
diff --git a/queue-4.17/can-peak_canfd-fix-firmware-v3.3.0-limit-allocation-to-32-bit-dma-addr-only.patch b/queue-4.17/can-peak_canfd-fix-firmware-v3.3.0-limit-allocation-to-32-bit-dma-addr-only.patch
new file mode 100644 (file)
index 0000000..5d00774
--- /dev/null
@@ -0,0 +1,64 @@
+From 5d4c94ed9f564224d7b37dbee13f7c5d4a8a01ac Mon Sep 17 00:00:00 2001
+From: Stephane Grosjean <s.grosjean@peak-system.com>
+Date: Thu, 21 Jun 2018 15:23:31 +0200
+Subject: can: peak_canfd: fix firmware < v3.3.0: limit allocation to 32-bit DMA addr only
+
+From: Stephane Grosjean <s.grosjean@peak-system.com>
+
+commit 5d4c94ed9f564224d7b37dbee13f7c5d4a8a01ac upstream.
+
+The DMA logic in firmwares < v3.3.0 embedded in the PCAN-PCIe FD cards
+family is not capable of handling a mix of 32-bit and 64-bit logical
+addresses. If the board is equipped with 2 or 4 CAN ports, then such a
+situation might lead to a PCIe Bus Error "Malformed TLP" packet
+as well as "irq xx: nobody cared" issue.
+
+This patch adds a workaround that requests only 32-bit DMA addresses
+when these might be allocated outside of the 4 GB area.
+
+This issue has been fixed in firmware v3.3.0 and next.
+
+Signed-off-by: Stephane Grosjean <s.grosjean@peak-system.com>
+Cc: linux-stable <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/peak_canfd/peak_pciefd_main.c |   19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+--- a/drivers/net/can/peak_canfd/peak_pciefd_main.c
++++ b/drivers/net/can/peak_canfd/peak_pciefd_main.c
+@@ -58,6 +58,10 @@ MODULE_LICENSE("GPL v2");
+ #define PCIEFD_REG_SYS_VER1           0x0040  /* version reg #1 */
+ #define PCIEFD_REG_SYS_VER2           0x0044  /* version reg #2 */
++#define PCIEFD_FW_VERSION(x, y, z)    (((u32)(x) << 24) | \
++                                       ((u32)(y) << 16) | \
++                                       ((u32)(z) << 8))
++
+ /* System Control Registers Bits */
+ #define PCIEFD_SYS_CTL_TS_RST         0x00000001      /* timestamp clock */
+ #define PCIEFD_SYS_CTL_CLK_EN         0x00000002      /* system clock */
+@@ -783,6 +787,21 @@ static int peak_pciefd_probe(struct pci_
+                "%ux CAN-FD PCAN-PCIe FPGA v%u.%u.%u:\n", can_count,
+                hw_ver_major, hw_ver_minor, hw_ver_sub);
++#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
++      /* FW < v3.3.0 DMA logic doesn't handle correctly the mix of 32-bit and
++       * 64-bit logical addresses: this workaround forces usage of 32-bit
++       * DMA addresses only when such a fw is detected.
++       */
++      if (PCIEFD_FW_VERSION(hw_ver_major, hw_ver_minor, hw_ver_sub) <
++          PCIEFD_FW_VERSION(3, 3, 0)) {
++              err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
++              if (err)
++                      dev_warn(&pdev->dev,
++                               "warning: can't set DMA mask %llxh (err %d)\n",
++                               DMA_BIT_MASK(32), err);
++      }
++#endif
++
+       /* stop system clock */
+       pciefd_sys_writereg(pciefd, PCIEFD_SYS_CTL_CLK_EN,
+                           PCIEFD_REG_SYS_CTL_CLR);
diff --git a/queue-4.17/can-xilinx_can-fix-device-dropping-off-bus-on-rx-overrun.patch b/queue-4.17/can-xilinx_can-fix-device-dropping-off-bus-on-rx-overrun.patch
new file mode 100644 (file)
index 0000000..e5971db
--- /dev/null
@@ -0,0 +1,41 @@
+From 2574fe54515ed3487405de329e4e9f13d7098c10 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Tue, 7 Feb 2017 13:23:04 +0200
+Subject: can: xilinx_can: fix device dropping off bus on RX overrun
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+commit 2574fe54515ed3487405de329e4e9f13d7098c10 upstream.
+
+The xilinx_can driver performs a software reset when an RX overrun is
+detected. This causes the device to enter Configuration mode where no
+messages are received or transmitted.
+
+The documentation does not mention any need to perform a reset on an RX
+overrun, and testing by inducing an RX overflow also indicated that the
+device continues to work just fine without a reset.
+
+Remove the software reset.
+
+Tested with the integrated CAN on Zynq-7000 SoC.
+
+Fixes: b1201e44f50b ("can: xilinx CAN controller support")
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/xilinx_can.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/net/can/xilinx_can.c
++++ b/drivers/net/can/xilinx_can.c
+@@ -696,7 +696,6 @@ static void xcan_err_interrupt(struct ne
+       if (isr & XCAN_IXR_RXOFLW_MASK) {
+               stats->rx_over_errors++;
+               stats->rx_errors++;
+-              priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
+               if (skb) {
+                       cf->can_id |= CAN_ERR_CRTL;
+                       cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
diff --git a/queue-4.17/can-xilinx_can-fix-incorrect-clear-of-non-processed-interrupts.patch b/queue-4.17/can-xilinx_can-fix-incorrect-clear-of-non-processed-interrupts.patch
new file mode 100644 (file)
index 0000000..f6fd191
--- /dev/null
@@ -0,0 +1,54 @@
+From 2f4f0f338cf453bfcdbcf089e177c16f35f023c8 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Mon, 26 Feb 2018 14:39:59 +0200
+Subject: can: xilinx_can: fix incorrect clear of non-processed interrupts
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+commit 2f4f0f338cf453bfcdbcf089e177c16f35f023c8 upstream.
+
+xcan_interrupt() clears ERROR|RXOFLV|BSOFF|ARBLST interrupts if any of
+them is asserted. This does not take into account that some of them
+could have been asserted between interrupt status read and interrupt
+clear, therefore clearing them without handling them.
+
+Fix the code to only clear those interrupts that it knows are asserted
+and therefore going to be processed in xcan_err_interrupt().
+
+Fixes: b1201e44f50b ("can: xilinx CAN controller support")
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Cc: Michal Simek <michal.simek@xilinx.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/xilinx_can.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/can/xilinx_can.c
++++ b/drivers/net/can/xilinx_can.c
+@@ -938,6 +938,7 @@ static irqreturn_t xcan_interrupt(int ir
+       struct net_device *ndev = (struct net_device *)dev_id;
+       struct xcan_priv *priv = netdev_priv(ndev);
+       u32 isr, ier;
++      u32 isr_errors;
+       /* Get the interrupt status from Xilinx CAN */
+       isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+@@ -956,11 +957,10 @@ static irqreturn_t xcan_interrupt(int ir
+               xcan_tx_interrupt(ndev, isr);
+       /* Check for the type of error interrupt and Processing it */
+-      if (isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK |
+-                      XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK)) {
+-              priv->write_reg(priv, XCAN_ICR_OFFSET, (XCAN_IXR_ERROR_MASK |
+-                              XCAN_IXR_RXOFLW_MASK | XCAN_IXR_BSOFF_MASK |
+-                              XCAN_IXR_ARBLST_MASK));
++      isr_errors = isr & (XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK |
++                          XCAN_IXR_BSOFF_MASK | XCAN_IXR_ARBLST_MASK);
++      if (isr_errors) {
++              priv->write_reg(priv, XCAN_ICR_OFFSET, isr_errors);
+               xcan_err_interrupt(ndev, isr);
+       }
diff --git a/queue-4.17/can-xilinx_can-fix-power-management-handling.patch b/queue-4.17/can-xilinx_can-fix-power-management-handling.patch
new file mode 100644 (file)
index 0000000..e26106e
--- /dev/null
@@ -0,0 +1,178 @@
+From 8ebd83bdb027f29870d96649dba18b91581ea829 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Thu, 17 May 2018 15:41:19 +0300
+Subject: can: xilinx_can: fix power management handling
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+commit 8ebd83bdb027f29870d96649dba18b91581ea829 upstream.
+
+There are several issues with the suspend/resume handling code of the
+driver:
+
+- The device is attached and detached in the runtime_suspend() and
+  runtime_resume() callbacks if the interface is running. However,
+  during xcan_chip_start() the interface is considered running,
+  causing the resume handler to incorrectly call netif_start_queue()
+  at the beginning of xcan_chip_start(), and on xcan_chip_start() error
+  return the suspend handler detaches the device leaving the user
+  unable to bring-up the device anymore.
+
+- The device is not brought properly up on system resume. A reset is
+  done and the code tries to determine the bus state after that.
+  However, after reset the device is always in Configuration mode
+  (down), so the state checking code does not make sense and
+  communication will also not work.
+
+- The suspend callback tries to set the device to sleep mode (low-power
+  mode which monitors the bus and brings the device back to normal mode
+  on activity), but then immediately disables the clocks (possibly
+  before the device reaches the sleep mode), which does not make sense
+  to me. If a clean shutdown is wanted before disabling clocks, we can
+  just bring it down completely instead of only sleep mode.
+
+Reorganize the PM code so that only the clock logic remains in the
+runtime PM callbacks and the system PM callbacks contain the device
+bring-up/down logic. This makes calling the runtime PM callbacks during
+e.g. xcan_chip_start() safe.
+
+The system PM callbacks now simply call common code to start/stop the
+HW if the interface was running, replacing the broken code from before.
+
+xcan_chip_stop() is updated to use the common reset code so that it will
+wait for the reset to complete. Reset also disables all interrupts so do
+not do that separately.
+
+Also, the device_may_wakeup() checks are removed as the driver does not
+have wakeup support.
+
+Tested on Zynq-7000 integrated CAN.
+
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Cc: Michal Simek <michal.simek@xilinx.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/xilinx_can.c |   69 +++++++++++++++++--------------------------
+ 1 file changed, 28 insertions(+), 41 deletions(-)
+
+--- a/drivers/net/can/xilinx_can.c
++++ b/drivers/net/can/xilinx_can.c
+@@ -811,13 +811,9 @@ static irqreturn_t xcan_interrupt(int ir
+ static void xcan_chip_stop(struct net_device *ndev)
+ {
+       struct xcan_priv *priv = netdev_priv(ndev);
+-      u32 ier;
+       /* Disable interrupts and leave the can in configuration mode */
+-      ier = priv->read_reg(priv, XCAN_IER_OFFSET);
+-      ier &= ~XCAN_INTR_ALL;
+-      priv->write_reg(priv, XCAN_IER_OFFSET, ier);
+-      priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
++      set_reset_mode(ndev);
+       priv->can.state = CAN_STATE_STOPPED;
+ }
+@@ -950,10 +946,15 @@ static const struct net_device_ops xcan_
+  */
+ static int __maybe_unused xcan_suspend(struct device *dev)
+ {
+-      if (!device_may_wakeup(dev))
+-              return pm_runtime_force_suspend(dev);
++      struct net_device *ndev = dev_get_drvdata(dev);
+-      return 0;
++      if (netif_running(ndev)) {
++              netif_stop_queue(ndev);
++              netif_device_detach(ndev);
++              xcan_chip_stop(ndev);
++      }
++
++      return pm_runtime_force_suspend(dev);
+ }
+ /**
+@@ -965,11 +966,27 @@ static int __maybe_unused xcan_suspend(s
+  */
+ static int __maybe_unused xcan_resume(struct device *dev)
+ {
+-      if (!device_may_wakeup(dev))
+-              return pm_runtime_force_resume(dev);
++      struct net_device *ndev = dev_get_drvdata(dev);
++      int ret;
+-      return 0;
++      ret = pm_runtime_force_resume(dev);
++      if (ret) {
++              dev_err(dev, "pm_runtime_force_resume failed on resume\n");
++              return ret;
++      }
++
++      if (netif_running(ndev)) {
++              ret = xcan_chip_start(ndev);
++              if (ret) {
++                      dev_err(dev, "xcan_chip_start failed on resume\n");
++                      return ret;
++              }
++
++              netif_device_attach(ndev);
++              netif_start_queue(ndev);
++      }
++      return 0;
+ }
+ /**
+@@ -984,14 +1001,6 @@ static int __maybe_unused xcan_runtime_s
+       struct net_device *ndev = dev_get_drvdata(dev);
+       struct xcan_priv *priv = netdev_priv(ndev);
+-      if (netif_running(ndev)) {
+-              netif_stop_queue(ndev);
+-              netif_device_detach(ndev);
+-      }
+-
+-      priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK);
+-      priv->can.state = CAN_STATE_SLEEPING;
+-
+       clk_disable_unprepare(priv->bus_clk);
+       clk_disable_unprepare(priv->can_clk);
+@@ -1010,7 +1019,6 @@ static int __maybe_unused xcan_runtime_r
+       struct net_device *ndev = dev_get_drvdata(dev);
+       struct xcan_priv *priv = netdev_priv(ndev);
+       int ret;
+-      u32 isr, status;
+       ret = clk_prepare_enable(priv->bus_clk);
+       if (ret) {
+@@ -1024,27 +1032,6 @@ static int __maybe_unused xcan_runtime_r
+               return ret;
+       }
+-      priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
+-      isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+-      status = priv->read_reg(priv, XCAN_SR_OFFSET);
+-
+-      if (netif_running(ndev)) {
+-              if (isr & XCAN_IXR_BSOFF_MASK) {
+-                      priv->can.state = CAN_STATE_BUS_OFF;
+-                      priv->write_reg(priv, XCAN_SRR_OFFSET,
+-                                      XCAN_SRR_RESET_MASK);
+-              } else if ((status & XCAN_SR_ESTAT_MASK) ==
+-                                      XCAN_SR_ESTAT_MASK) {
+-                      priv->can.state = CAN_STATE_ERROR_PASSIVE;
+-              } else if (status & XCAN_SR_ERRWRN_MASK) {
+-                      priv->can.state = CAN_STATE_ERROR_WARNING;
+-              } else {
+-                      priv->can.state = CAN_STATE_ERROR_ACTIVE;
+-              }
+-              netif_device_attach(ndev);
+-              netif_start_queue(ndev);
+-      }
+-
+       return 0;
+ }
diff --git a/queue-4.17/can-xilinx_can-fix-recovery-from-error-states-not-being-propagated.patch b/queue-4.17/can-xilinx_can-fix-recovery-from-error-states-not-being-propagated.patch
new file mode 100644 (file)
index 0000000..c78c6cf
--- /dev/null
@@ -0,0 +1,234 @@
+From 877e0b75947e2c7acf5624331bb17ceb093c98ae Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Wed, 8 Feb 2017 13:13:40 +0200
+Subject: can: xilinx_can: fix recovery from error states not being propagated
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+commit 877e0b75947e2c7acf5624331bb17ceb093c98ae upstream.
+
+The xilinx_can driver contains no mechanism for propagating recovery
+from CAN_STATE_ERROR_WARNING and CAN_STATE_ERROR_PASSIVE.
+
+Add such a mechanism by factoring the handling of
+XCAN_STATE_ERROR_PASSIVE and XCAN_STATE_ERROR_WARNING out of
+xcan_err_interrupt and checking for recovery after RX and TX if the
+interface is in one of those states.
+
+Tested with the integrated CAN on Zynq-7000 SoC.
+
+Fixes: b1201e44f50b ("can: xilinx CAN controller support")
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/xilinx_can.c |  155 +++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 127 insertions(+), 28 deletions(-)
+
+--- a/drivers/net/can/xilinx_can.c
++++ b/drivers/net/can/xilinx_can.c
+@@ -2,6 +2,7 @@
+  *
+  * Copyright (C) 2012 - 2014 Xilinx, Inc.
+  * Copyright (C) 2009 PetaLogix. All rights reserved.
++ * Copyright (C) 2017 Sandvik Mining and Construction Oy
+  *
+  * Description:
+  * This driver is developed for Axi CAN IP and for Zynq CANPS Controller.
+@@ -530,6 +531,123 @@ static int xcan_rx(struct net_device *nd
+ }
+ /**
++ * xcan_current_error_state - Get current error state from HW
++ * @ndev:     Pointer to net_device structure
++ *
++ * Checks the current CAN error state from the HW. Note that this
++ * only checks for ERROR_PASSIVE and ERROR_WARNING.
++ *
++ * Return:
++ * ERROR_PASSIVE or ERROR_WARNING if either is active, ERROR_ACTIVE
++ * otherwise.
++ */
++static enum can_state xcan_current_error_state(struct net_device *ndev)
++{
++      struct xcan_priv *priv = netdev_priv(ndev);
++      u32 status = priv->read_reg(priv, XCAN_SR_OFFSET);
++
++      if ((status & XCAN_SR_ESTAT_MASK) == XCAN_SR_ESTAT_MASK)
++              return CAN_STATE_ERROR_PASSIVE;
++      else if (status & XCAN_SR_ERRWRN_MASK)
++              return CAN_STATE_ERROR_WARNING;
++      else
++              return CAN_STATE_ERROR_ACTIVE;
++}
++
++/**
++ * xcan_set_error_state - Set new CAN error state
++ * @ndev:     Pointer to net_device structure
++ * @new_state:        The new CAN state to be set
++ * @cf:               Error frame to be populated or NULL
++ *
++ * Set new CAN error state for the device, updating statistics and
++ * populating the error frame if given.
++ */
++static void xcan_set_error_state(struct net_device *ndev,
++                               enum can_state new_state,
++                               struct can_frame *cf)
++{
++      struct xcan_priv *priv = netdev_priv(ndev);
++      u32 ecr = priv->read_reg(priv, XCAN_ECR_OFFSET);
++      u32 txerr = ecr & XCAN_ECR_TEC_MASK;
++      u32 rxerr = (ecr & XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT;
++
++      priv->can.state = new_state;
++
++      if (cf) {
++              cf->can_id |= CAN_ERR_CRTL;
++              cf->data[6] = txerr;
++              cf->data[7] = rxerr;
++      }
++
++      switch (new_state) {
++      case CAN_STATE_ERROR_PASSIVE:
++              priv->can.can_stats.error_passive++;
++              if (cf)
++                      cf->data[1] = (rxerr > 127) ?
++                                      CAN_ERR_CRTL_RX_PASSIVE :
++                                      CAN_ERR_CRTL_TX_PASSIVE;
++              break;
++      case CAN_STATE_ERROR_WARNING:
++              priv->can.can_stats.error_warning++;
++              if (cf)
++                      cf->data[1] |= (txerr > rxerr) ?
++                                      CAN_ERR_CRTL_TX_WARNING :
++                                      CAN_ERR_CRTL_RX_WARNING;
++              break;
++      case CAN_STATE_ERROR_ACTIVE:
++              if (cf)
++                      cf->data[1] |= CAN_ERR_CRTL_ACTIVE;
++              break;
++      default:
++              /* non-ERROR states are handled elsewhere */
++              WARN_ON(1);
++              break;
++      }
++}
++
++/**
++ * xcan_update_error_state_after_rxtx - Update CAN error state after RX/TX
++ * @ndev:     Pointer to net_device structure
++ *
++ * If the device is in a ERROR-WARNING or ERROR-PASSIVE state, check if
++ * the performed RX/TX has caused it to drop to a lesser state and set
++ * the interface state accordingly.
++ */
++static void xcan_update_error_state_after_rxtx(struct net_device *ndev)
++{
++      struct xcan_priv *priv = netdev_priv(ndev);
++      enum can_state old_state = priv->can.state;
++      enum can_state new_state;
++
++      /* changing error state due to successful frame RX/TX can only
++       * occur from these states
++       */
++      if (old_state != CAN_STATE_ERROR_WARNING &&
++          old_state != CAN_STATE_ERROR_PASSIVE)
++              return;
++
++      new_state = xcan_current_error_state(ndev);
++
++      if (new_state != old_state) {
++              struct sk_buff *skb;
++              struct can_frame *cf;
++
++              skb = alloc_can_err_skb(ndev, &cf);
++
++              xcan_set_error_state(ndev, new_state, skb ? cf : NULL);
++
++              if (skb) {
++                      struct net_device_stats *stats = &ndev->stats;
++
++                      stats->rx_packets++;
++                      stats->rx_bytes += cf->can_dlc;
++                      netif_rx(skb);
++              }
++      }
++}
++
++/**
+  * xcan_err_interrupt - error frame Isr
+  * @ndev:     net_device pointer
+  * @isr:      interrupt status register value
+@@ -544,16 +662,12 @@ static void xcan_err_interrupt(struct ne
+       struct net_device_stats *stats = &ndev->stats;
+       struct can_frame *cf;
+       struct sk_buff *skb;
+-      u32 err_status, status, txerr = 0, rxerr = 0;
++      u32 err_status;
+       skb = alloc_can_err_skb(ndev, &cf);
+       err_status = priv->read_reg(priv, XCAN_ESR_OFFSET);
+       priv->write_reg(priv, XCAN_ESR_OFFSET, err_status);
+-      txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK;
+-      rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) &
+-                      XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT);
+-      status = priv->read_reg(priv, XCAN_SR_OFFSET);
+       if (isr & XCAN_IXR_BSOFF_MASK) {
+               priv->can.state = CAN_STATE_BUS_OFF;
+@@ -563,28 +677,10 @@ static void xcan_err_interrupt(struct ne
+               can_bus_off(ndev);
+               if (skb)
+                       cf->can_id |= CAN_ERR_BUSOFF;
+-      } else if ((status & XCAN_SR_ESTAT_MASK) == XCAN_SR_ESTAT_MASK) {
+-              priv->can.state = CAN_STATE_ERROR_PASSIVE;
+-              priv->can.can_stats.error_passive++;
+-              if (skb) {
+-                      cf->can_id |= CAN_ERR_CRTL;
+-                      cf->data[1] = (rxerr > 127) ?
+-                                      CAN_ERR_CRTL_RX_PASSIVE :
+-                                      CAN_ERR_CRTL_TX_PASSIVE;
+-                      cf->data[6] = txerr;
+-                      cf->data[7] = rxerr;
+-              }
+-      } else if (status & XCAN_SR_ERRWRN_MASK) {
+-              priv->can.state = CAN_STATE_ERROR_WARNING;
+-              priv->can.can_stats.error_warning++;
+-              if (skb) {
+-                      cf->can_id |= CAN_ERR_CRTL;
+-                      cf->data[1] |= (txerr > rxerr) ?
+-                                      CAN_ERR_CRTL_TX_WARNING :
+-                                      CAN_ERR_CRTL_RX_WARNING;
+-                      cf->data[6] = txerr;
+-                      cf->data[7] = rxerr;
+-              }
++      } else {
++              enum can_state new_state = xcan_current_error_state(ndev);
++
++              xcan_set_error_state(ndev, new_state, skb ? cf : NULL);
+       }
+       /* Check for Arbitration lost interrupt */
+@@ -714,8 +810,10 @@ static int xcan_rx_poll(struct napi_stru
+               isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+       }
+-      if (work_done)
++      if (work_done) {
+               can_led_event(ndev, CAN_LED_EVENT_RX);
++              xcan_update_error_state_after_rxtx(ndev);
++      }
+       if (work_done < quota) {
+               napi_complete_done(napi, work_done);
+@@ -746,6 +844,7 @@ static void xcan_tx_interrupt(struct net
+               isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+       }
+       can_led_event(ndev, CAN_LED_EVENT_TX);
++      xcan_update_error_state_after_rxtx(ndev);
+       netif_wake_queue(ndev);
+ }
diff --git a/queue-4.17/can-xilinx_can-fix-rx-loop-if-rxnemp-is-asserted-without-rxok.patch b/queue-4.17/can-xilinx_can-fix-rx-loop-if-rxnemp-is-asserted-without-rxok.patch
new file mode 100644 (file)
index 0000000..3e8a6b2
--- /dev/null
@@ -0,0 +1,98 @@
+From 32852c561bffd613d4ed7ec464b1e03e1b7b6c5c Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Tue, 7 Feb 2017 17:01:14 +0200
+Subject: can: xilinx_can: fix RX loop if RXNEMP is asserted without RXOK
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+commit 32852c561bffd613d4ed7ec464b1e03e1b7b6c5c upstream.
+
+If the device gets into a state where RXNEMP (RX FIFO not empty)
+interrupt is asserted without RXOK (new frame received successfully)
+interrupt being asserted, xcan_rx_poll() will continue to try to clear
+RXNEMP without actually reading frames from RX FIFO. If the RX FIFO is
+not empty, the interrupt will not be cleared and napi_schedule() will
+just be called again.
+
+This situation can occur when:
+
+(a) xcan_rx() returns without reading RX FIFO due to an error condition.
+The code tries to clear both RXOK and RXNEMP but RXNEMP will not clear
+due to a frame still being in the FIFO. The frame will never be read
+from the FIFO as RXOK is no longer set.
+
+(b) A frame is received between xcan_rx_poll() reading interrupt status
+and clearing RXOK. RXOK will be cleared, but RXNEMP will again remain
+set as the new message is still in the FIFO.
+
+I'm able to trigger case (b) by flooding the bus with frames under load.
+
+There does not seem to be any benefit in using both RXNEMP and RXOK in
+the way the driver does, and the polling example in the reference manual
+(UG585 v1.10 18.3.7 Read Messages from RxFIFO) also says that either
+RXOK or RXNEMP can be used for detecting incoming messages.
+
+Fix the issue and simplify the RX processing by only using RXNEMP
+without RXOK.
+
+Tested with the integrated CAN on Zynq-7000 SoC.
+
+Fixes: b1201e44f50b ("can: xilinx CAN controller support")
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/xilinx_can.c |   18 +++++-------------
+ 1 file changed, 5 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/can/xilinx_can.c
++++ b/drivers/net/can/xilinx_can.c
+@@ -101,7 +101,7 @@ enum xcan_reg {
+ #define XCAN_INTR_ALL         (XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |\
+                                XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK | \
+                                XCAN_IXR_RXNEMP_MASK | XCAN_IXR_ERROR_MASK | \
+-                               XCAN_IXR_ARBLST_MASK | XCAN_IXR_RXOK_MASK)
++                               XCAN_IXR_ARBLST_MASK)
+ /* CAN register bit shift - XCAN_<REG>_<BIT>_SHIFT */
+ #define XCAN_BTR_SJW_SHIFT            7  /* Synchronous jump width */
+@@ -709,15 +709,7 @@ static int xcan_rx_poll(struct napi_stru
+       isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+       while ((isr & XCAN_IXR_RXNEMP_MASK) && (work_done < quota)) {
+-              if (isr & XCAN_IXR_RXOK_MASK) {
+-                      priv->write_reg(priv, XCAN_ICR_OFFSET,
+-                              XCAN_IXR_RXOK_MASK);
+-                      work_done += xcan_rx(ndev);
+-              } else {
+-                      priv->write_reg(priv, XCAN_ICR_OFFSET,
+-                              XCAN_IXR_RXNEMP_MASK);
+-                      break;
+-              }
++              work_done += xcan_rx(ndev);
+               priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_RXNEMP_MASK);
+               isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+       }
+@@ -728,7 +720,7 @@ static int xcan_rx_poll(struct napi_stru
+       if (work_done < quota) {
+               napi_complete_done(napi, work_done);
+               ier = priv->read_reg(priv, XCAN_IER_OFFSET);
+-              ier |= (XCAN_IXR_RXOK_MASK | XCAN_IXR_RXNEMP_MASK);
++              ier |= XCAN_IXR_RXNEMP_MASK;
+               priv->write_reg(priv, XCAN_IER_OFFSET, ier);
+       }
+       return work_done;
+@@ -800,9 +792,9 @@ static irqreturn_t xcan_interrupt(int ir
+       }
+       /* Check for the type of receive interrupt and Processing it */
+-      if (isr & (XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK)) {
++      if (isr & XCAN_IXR_RXNEMP_MASK) {
+               ier = priv->read_reg(priv, XCAN_IER_OFFSET);
+-              ier &= ~(XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK);
++              ier &= ~XCAN_IXR_RXNEMP_MASK;
+               priv->write_reg(priv, XCAN_IER_OFFSET, ier);
+               napi_schedule(&priv->napi);
+       }
diff --git a/queue-4.17/can-xilinx_can-fix-rx-overflow-interrupt-not-being-enabled.patch b/queue-4.17/can-xilinx_can-fix-rx-overflow-interrupt-not-being-enabled.patch
new file mode 100644 (file)
index 0000000..078010a
--- /dev/null
@@ -0,0 +1,37 @@
+From 83997997252f5d3fc7f04abc24a89600c2b504ab Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Mon, 26 Feb 2018 14:27:13 +0200
+Subject: can: xilinx_can: fix RX overflow interrupt not being enabled
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+commit 83997997252f5d3fc7f04abc24a89600c2b504ab upstream.
+
+RX overflow interrupt (RXOFLW) is disabled even though xcan_interrupt()
+processes it. This means that an RX overflow interrupt will only be
+processed when another interrupt gets asserted (e.g. for RX/TX).
+
+Fix that by enabling the RXOFLW interrupt.
+
+Fixes: b1201e44f50b ("can: xilinx CAN controller support")
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Cc: Michal Simek <michal.simek@xilinx.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/xilinx_can.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/can/xilinx_can.c
++++ b/drivers/net/can/xilinx_can.c
+@@ -104,7 +104,7 @@ enum xcan_reg {
+ #define XCAN_INTR_ALL         (XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |\
+                                XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK | \
+                                XCAN_IXR_RXNEMP_MASK | XCAN_IXR_ERROR_MASK | \
+-                               XCAN_IXR_ARBLST_MASK)
++                               XCAN_IXR_RXOFLW_MASK | XCAN_IXR_ARBLST_MASK)
+ /* CAN register bit shift - XCAN_<REG>_<BIT>_SHIFT */
+ #define XCAN_BTR_SJW_SHIFT            7  /* Synchronous jump width */
diff --git a/queue-4.17/can-xilinx_can-keep-only-1-2-frames-in-tx-fifo-to-fix-tx-accounting.patch b/queue-4.17/can-xilinx_can-keep-only-1-2-frames-in-tx-fifo-to-fix-tx-accounting.patch
new file mode 100644 (file)
index 0000000..423dbec
--- /dev/null
@@ -0,0 +1,335 @@
+From 620050d9c2be15c47017ba95efe59e0832e99a56 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+Date: Thu, 23 Feb 2017 14:50:03 +0200
+Subject: can: xilinx_can: keep only 1-2 frames in TX FIFO to fix TX accounting
+
+From: Anssi Hannula <anssi.hannula@bitwise.fi>
+
+commit 620050d9c2be15c47017ba95efe59e0832e99a56 upstream.
+
+The xilinx_can driver assumes that the TXOK interrupt only clears after
+it has been acknowledged as many times as there have been successfully
+sent frames.
+
+However, the documentation does not mention such behavior, instead
+saying just that the interrupt is cleared when the clear bit is set.
+
+Similarly, testing seems to also suggest that it is immediately cleared
+regardless of the amount of frames having been sent. Performing some
+heavy TX load and then going back to idle has the tx_head drifting
+further away from tx_tail over time, steadily reducing the amount of
+frames the driver keeps in the TX FIFO (but not to zero, as the TXOK
+interrupt always frees up space for 1 frame from the driver's
+perspective, so frames continue to be sent) and delaying the local echo
+frames.
+
+The TX FIFO tracking is also otherwise buggy as it does not account for
+TX FIFO being cleared after software resets, causing
+  BUG!, TX FIFO full when queue awake!
+messages to be output.
+
+There does not seem to be any way to accurately track the state of the
+TX FIFO for local echo support while using the full TX FIFO.
+
+The Zynq version of the HW (but not the soft-AXI version) has watermark
+programming support and with it an additional TX-FIFO-empty interrupt
+bit.
+
+Modify the driver to only put 1 frame into TX FIFO at a time on soft-AXI
+and 2 frames at a time on Zynq. On Zynq the TXFEMP interrupt bit is used
+to detect whether 1 or 2 frames have been sent at interrupt processing
+time.
+
+Tested with the integrated CAN on Zynq-7000 SoC. The 1-frame-FIFO mode
+was also tested.
+
+An alternative way to solve this would be to drop local echo support but
+keep using the full TX FIFO.
+
+v2: Add FIFO space check before TX queue wake with locking to
+synchronize with queue stop. This avoids waking the queue when xmit()
+had just filled it.
+
+v3: Keep local echo support and reduce the amount of frames in FIFO
+instead as suggested by Marc Kleine-Budde.
+
+Fixes: b1201e44f50b ("can: xilinx CAN controller support")
+Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/xilinx_can.c |  139 ++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 123 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/can/xilinx_can.c
++++ b/drivers/net/can/xilinx_can.c
+@@ -26,8 +26,10 @@
+ #include <linux/module.h>
+ #include <linux/netdevice.h>
+ #include <linux/of.h>
++#include <linux/of_device.h>
+ #include <linux/platform_device.h>
+ #include <linux/skbuff.h>
++#include <linux/spinlock.h>
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include <linux/can/dev.h>
+@@ -119,6 +121,7 @@ enum xcan_reg {
+ /**
+  * struct xcan_priv - This definition define CAN driver instance
+  * @can:                      CAN private data structure.
++ * @tx_lock:                  Lock for synchronizing TX interrupt handling
+  * @tx_head:                  Tx CAN packets ready to send on the queue
+  * @tx_tail:                  Tx CAN packets successfully sended on the queue
+  * @tx_max:                   Maximum number packets the driver can send
+@@ -133,6 +136,7 @@ enum xcan_reg {
+  */
+ struct xcan_priv {
+       struct can_priv can;
++      spinlock_t tx_lock;
+       unsigned int tx_head;
+       unsigned int tx_tail;
+       unsigned int tx_max;
+@@ -160,6 +164,11 @@ static const struct can_bittiming_const
+       .brp_inc = 1,
+ };
++#define XCAN_CAP_WATERMARK    0x0001
++struct xcan_devtype_data {
++      unsigned int caps;
++};
++
+ /**
+  * xcan_write_reg_le - Write a value to the device register little endian
+  * @priv:     Driver private data structure
+@@ -239,6 +248,10 @@ static int set_reset_mode(struct net_dev
+               usleep_range(500, 10000);
+       }
++      /* reset clears FIFOs */
++      priv->tx_head = 0;
++      priv->tx_tail = 0;
++
+       return 0;
+ }
+@@ -393,6 +406,7 @@ static int xcan_start_xmit(struct sk_buf
+       struct net_device_stats *stats = &ndev->stats;
+       struct can_frame *cf = (struct can_frame *)skb->data;
+       u32 id, dlc, data[2] = {0, 0};
++      unsigned long flags;
+       if (can_dropped_invalid_skb(ndev, skb))
+               return NETDEV_TX_OK;
+@@ -440,6 +454,9 @@ static int xcan_start_xmit(struct sk_buf
+               data[1] = be32_to_cpup((__be32 *)(cf->data + 4));
+       can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max);
++
++      spin_lock_irqsave(&priv->tx_lock, flags);
++
+       priv->tx_head++;
+       /* Write the Frame to Xilinx CAN TX FIFO */
+@@ -455,10 +472,16 @@ static int xcan_start_xmit(struct sk_buf
+               stats->tx_bytes += cf->can_dlc;
+       }
++      /* Clear TX-FIFO-empty interrupt for xcan_tx_interrupt() */
++      if (priv->tx_max > 1)
++              priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXFEMP_MASK);
++
+       /* Check if the TX buffer is full */
+       if ((priv->tx_head - priv->tx_tail) == priv->tx_max)
+               netif_stop_queue(ndev);
++      spin_unlock_irqrestore(&priv->tx_lock, flags);
++
+       return NETDEV_TX_OK;
+ }
+@@ -832,19 +855,71 @@ static void xcan_tx_interrupt(struct net
+ {
+       struct xcan_priv *priv = netdev_priv(ndev);
+       struct net_device_stats *stats = &ndev->stats;
++      unsigned int frames_in_fifo;
++      int frames_sent = 1; /* TXOK => at least 1 frame was sent */
++      unsigned long flags;
++      int retries = 0;
++
++      /* Synchronize with xmit as we need to know the exact number
++       * of frames in the FIFO to stay in sync due to the TXFEMP
++       * handling.
++       * This also prevents a race between netif_wake_queue() and
++       * netif_stop_queue().
++       */
++      spin_lock_irqsave(&priv->tx_lock, flags);
++
++      frames_in_fifo = priv->tx_head - priv->tx_tail;
++
++      if (WARN_ON_ONCE(frames_in_fifo == 0)) {
++              /* clear TXOK anyway to avoid getting back here */
++              priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK);
++              spin_unlock_irqrestore(&priv->tx_lock, flags);
++              return;
++      }
++
++      /* Check if 2 frames were sent (TXOK only means that at least 1
++       * frame was sent).
++       */
++      if (frames_in_fifo > 1) {
++              WARN_ON(frames_in_fifo > priv->tx_max);
++
++              /* Synchronize TXOK and isr so that after the loop:
++               * (1) isr variable is up-to-date at least up to TXOK clear
++               *     time. This avoids us clearing a TXOK of a second frame
++               *     but not noticing that the FIFO is now empty and thus
++               *     marking only a single frame as sent.
++               * (2) No TXOK is left. Having one could mean leaving a
++               *     stray TXOK as we might process the associated frame
++               *     via TXFEMP handling as we read TXFEMP *after* TXOK
++               *     clear to satisfy (1).
++               */
++              while ((isr & XCAN_IXR_TXOK_MASK) && !WARN_ON(++retries == 100)) {
++                      priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK);
++                      isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
++              }
+-      while ((priv->tx_head - priv->tx_tail > 0) &&
+-                      (isr & XCAN_IXR_TXOK_MASK)) {
++              if (isr & XCAN_IXR_TXFEMP_MASK) {
++                      /* nothing in FIFO anymore */
++                      frames_sent = frames_in_fifo;
++              }
++      } else {
++              /* single frame in fifo, just clear TXOK */
+               priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK);
++      }
++
++      while (frames_sent--) {
+               can_get_echo_skb(ndev, priv->tx_tail %
+                                       priv->tx_max);
+               priv->tx_tail++;
+               stats->tx_packets++;
+-              isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
+       }
++
++      netif_wake_queue(ndev);
++
++      spin_unlock_irqrestore(&priv->tx_lock, flags);
++
+       can_led_event(ndev, CAN_LED_EVENT_TX);
+       xcan_update_error_state_after_rxtx(ndev);
+-      netif_wake_queue(ndev);
+ }
+ /**
+@@ -1138,6 +1213,18 @@ static const struct dev_pm_ops xcan_dev_
+       SET_RUNTIME_PM_OPS(xcan_runtime_suspend, xcan_runtime_resume, NULL)
+ };
++static const struct xcan_devtype_data xcan_zynq_data = {
++      .caps = XCAN_CAP_WATERMARK,
++};
++
++/* Match table for OF platform binding */
++static const struct of_device_id xcan_of_match[] = {
++      { .compatible = "xlnx,zynq-can-1.0", .data = &xcan_zynq_data },
++      { .compatible = "xlnx,axi-can-1.00.a", },
++      { /* end of list */ },
++};
++MODULE_DEVICE_TABLE(of, xcan_of_match);
++
+ /**
+  * xcan_probe - Platform registration call
+  * @pdev:     Handle to the platform device structure
+@@ -1152,8 +1239,10 @@ static int xcan_probe(struct platform_de
+       struct resource *res; /* IO mem resources */
+       struct net_device *ndev;
+       struct xcan_priv *priv;
++      const struct of_device_id *of_id;
++      int caps = 0;
+       void __iomem *addr;
+-      int ret, rx_max, tx_max;
++      int ret, rx_max, tx_max, tx_fifo_depth;
+       /* Get the virtual base address for the device */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -1163,7 +1252,8 @@ static int xcan_probe(struct platform_de
+               goto err;
+       }
+-      ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &tx_max);
++      ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth",
++                                 &tx_fifo_depth);
+       if (ret < 0)
+               goto err;
+@@ -1171,6 +1261,30 @@ static int xcan_probe(struct platform_de
+       if (ret < 0)
+               goto err;
++      of_id = of_match_device(xcan_of_match, &pdev->dev);
++      if (of_id) {
++              const struct xcan_devtype_data *devtype_data = of_id->data;
++
++              if (devtype_data)
++                      caps = devtype_data->caps;
++      }
++
++      /* There is no way to directly figure out how many frames have been
++       * sent when the TXOK interrupt is processed. If watermark programming
++       * is supported, we can have 2 frames in the FIFO and use TXFEMP
++       * to determine if 1 or 2 frames have been sent.
++       * Theoretically we should be able to use TXFWMEMP to determine up
++       * to 3 frames, but it seems that after putting a second frame in the
++       * FIFO, with watermark at 2 frames, it can happen that TXFWMEMP (less
++       * than 2 frames in FIFO) is set anyway with no TXOK (a frame was
++       * sent), which is not a sensible state - possibly TXFWMEMP is not
++       * completely synchronized with the rest of the bits?
++       */
++      if (caps & XCAN_CAP_WATERMARK)
++              tx_max = min(tx_fifo_depth, 2);
++      else
++              tx_max = 1;
++
+       /* Create a CAN device instance */
+       ndev = alloc_candev(sizeof(struct xcan_priv), tx_max);
+       if (!ndev)
+@@ -1185,6 +1299,7 @@ static int xcan_probe(struct platform_de
+                                       CAN_CTRLMODE_BERR_REPORTING;
+       priv->reg_base = addr;
+       priv->tx_max = tx_max;
++      spin_lock_init(&priv->tx_lock);
+       /* Get IRQ for the device */
+       ndev->irq = platform_get_irq(pdev, 0);
+@@ -1249,9 +1364,9 @@ static int xcan_probe(struct platform_de
+       pm_runtime_put(&pdev->dev);
+-      netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n",
++      netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth: actual %d, using %d\n",
+                       priv->reg_base, ndev->irq, priv->can.clock.freq,
+-                      priv->tx_max);
++                      tx_fifo_depth, priv->tx_max);
+       return 0;
+@@ -1285,14 +1400,6 @@ static int xcan_remove(struct platform_d
+       return 0;
+ }
+-/* Match table for OF platform binding */
+-static const struct of_device_id xcan_of_match[] = {
+-      { .compatible = "xlnx,zynq-can-1.0", },
+-      { .compatible = "xlnx,axi-can-1.00.a", },
+-      { /* end of list */ },
+-};
+-MODULE_DEVICE_TABLE(of, xcan_of_match);
+-
+ static struct platform_driver xcan_driver = {
+       .probe = xcan_probe,
+       .remove = xcan_remove,
diff --git a/queue-4.17/driver-core-partially-revert-driver-core-correct-device-s-shutdown-order.patch b/queue-4.17/driver-core-partially-revert-driver-core-correct-device-s-shutdown-order.patch
new file mode 100644 (file)
index 0000000..ca4cd9e
--- /dev/null
@@ -0,0 +1,70 @@
+From 722e5f2b1eec7de61117b7c0a7914761e3da2eda Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Tue, 10 Jul 2018 14:51:33 +0200
+Subject: driver core: Partially revert "driver core: correct device's shutdown order"
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 722e5f2b1eec7de61117b7c0a7914761e3da2eda upstream.
+
+Commit 52cdbdd49853 (driver core: correct device's shutdown order)
+introduced a regression by breaking device shutdown on some systems.
+
+Namely, the devices_kset_move_last() call in really_probe() added by
+that commit is a mistake as it may cause parents to follow children
+in the devices_kset list which then causes shutdown to fail.  For
+example, if a device has children before really_probe() is called
+for it (which is not uncommon), that call will cause it to be
+reordered after the children in the devices_kset list and the
+ordering of that list will not reflect the correct device shutdown
+order any more.
+
+Also it causes the devices_kset list to be constantly reordered
+until all drivers have been probed which is totally pointless
+overhead in the majority of cases and it only covered an issue
+with system shutdown, while system-wide suspend/resume potentially
+had the same issue on the affected platforms (which was not covered).
+
+Moreover, the shutdown issue originally addressed by the change in
+really_probe() made by commit 52cdbdd49853 is not present in 4.18-rc
+any more, since dra7 started to use the sdhci-omap driver which
+doesn't disable any regulators during shutdown, so the really_probe()
+part of commit 52cdbdd49853 can be safely reverted.  [The original
+issue was related to the omap_hsmmc driver used by dra7 previously.]
+
+For the above reasons, revert the really_probe() modifications made
+by commit 52cdbdd49853.
+
+The other code changes made by commit 52cdbdd49853 are useful and
+they need not be reverted.
+
+Fixes: 52cdbdd49853 (driver core: correct device's shutdown order)
+Link: https://lore.kernel.org/lkml/CAFgQCTt7VfqM=UyCnvNFxrSw8Z6cUtAi3HUwR4_xPAc03SgHjQ@mail.gmail.com/
+Reported-by: Pingfan Liu <kernelfans@gmail.com>
+Tested-by: Pingfan Liu <kernelfans@gmail.com>
+Reviewed-by: Kishon Vijay Abraham I <kishon@ti.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/dd.c |    8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -436,14 +436,6 @@ re_probe:
+                       goto probe_failed;
+       }
+-      /*
+-       * Ensure devices are listed in devices_kset in correct order
+-       * It's important to move Dev to the end of devices_kset before
+-       * calling .probe, because it could be recursive and parent Dev
+-       * should always go first
+-       */
+-      devices_kset_move_last(dev);
+-
+       if (dev->bus->probe) {
+               ret = dev->bus->probe(dev);
+               if (ret)
diff --git a/queue-4.17/revert-staging-r8188eu-use-lib80211-to-support-tkip.patch b/queue-4.17/revert-staging-r8188eu-use-lib80211-to-support-tkip.patch
new file mode 100644 (file)
index 0000000..26a4c93
--- /dev/null
@@ -0,0 +1,372 @@
+From 69a1d98c831ec64cbfd381f5dcb6697e1445d239 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Sat, 14 Jul 2018 20:31:26 +0200
+Subject: Revert "staging:r8188eu: Use lib80211 to support TKIP"
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 69a1d98c831ec64cbfd381f5dcb6697e1445d239 upstream.
+
+Commit b83b8b1881c4 ("staging:r8188eu: Use lib80211 to support TKIP")
+is causing 2 problems for me:
+
+1) One boot the wifi on a laptop with a r8188eu wifi device would not
+   connect and dmesg contained an oops about scheduling while atomic
+   pointing to the tkip code. This went away after reverting the commit.
+
+2) I reverted the revert to try and get the oops from 1. again to be able
+   to add it to this commit message. But now the system did connect to the
+   wifi only to print a whole bunch of oopses, followed by a hardfreeze a
+   few seconds later. Subsequent reboots also all lead to scenario 2. Until
+   I reverted the commit again.
+
+Revert the commit fixes both issues making the laptop usable again.
+
+Fixes: b83b8b1881c4 ("staging:r8188eu: Use lib80211 to support TKIP")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Ivan Safonov <insafonov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/rtl8188eu/Kconfig             |    1 
+ drivers/staging/rtl8188eu/core/rtw_recv.c     |  163 ++++++++++++++++++--------
+ drivers/staging/rtl8188eu/core/rtw_security.c |   94 +++++++-------
+ 3 files changed, 162 insertions(+), 96 deletions(-)
+
+--- a/drivers/staging/rtl8188eu/Kconfig
++++ b/drivers/staging/rtl8188eu/Kconfig
+@@ -7,7 +7,6 @@ config R8188EU
+       select LIB80211
+       select LIB80211_CRYPT_WEP
+       select LIB80211_CRYPT_CCMP
+-      select LIB80211_CRYPT_TKIP
+       ---help---
+       This option adds the Realtek RTL8188EU USB device such as TP-Link TL-WN725N.
+       If built as a module, it will be called r8188eu.
+--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
++++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
+@@ -23,7 +23,6 @@
+ #include <mon.h>
+ #include <wifi.h>
+ #include <linux/vmalloc.h>
+-#include <net/lib80211.h>
+ #define ETHERNET_HEADER_SIZE  14      /*  Ethernet Header Length */
+ #define LLC_HEADER_SIZE                       6       /*  LLC Header Length */
+@@ -221,20 +220,31 @@ u32 rtw_free_uc_swdec_pending_queue(stru
+ static int recvframe_chkmic(struct adapter *adapter,
+                           struct recv_frame *precvframe)
+ {
+-      int res = _SUCCESS;
+-      struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
+-      struct sta_info *stainfo = rtw_get_stainfo(&adapter->stapriv, prxattrib->ta);
++      int     i, res = _SUCCESS;
++      u32     datalen;
++      u8      miccode[8];
++      u8      bmic_err = false, brpt_micerror = true;
++      u8      *pframe, *payload, *pframemic;
++      u8      *mickey;
++      struct  sta_info                *stainfo;
++      struct  rx_pkt_attrib   *prxattrib = &precvframe->attrib;
++      struct  security_priv   *psecuritypriv = &adapter->securitypriv;
++
++      struct mlme_ext_priv    *pmlmeext = &adapter->mlmeextpriv;
++      struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
++
++      stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
+       if (prxattrib->encrypt == _TKIP_) {
+-              if (stainfo) {
+-                      int key_idx;
+-                      const int iv_len = 8, icv_len = 4, key_length = 32;
+-                      struct sk_buff *skb = precvframe->pkt;
+-                      u8 key[32], iv[8], icv[4], *pframe = skb->data;
+-                      void *crypto_private = NULL;
+-                      struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("TKIP"), "lib80211_crypt_tkip");
+-                      struct security_priv *psecuritypriv = &adapter->securitypriv;
++              RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
++                       ("\n %s: prxattrib->encrypt==_TKIP_\n", __func__));
++              RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
++                       ("\n %s: da=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
++                        __func__, prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2],
++                        prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5]));
++              /* calculate mic code */
++              if (stainfo) {
+                       if (IS_MCAST(prxattrib->ra)) {
+                               if (!psecuritypriv) {
+                                       res = _FAIL;
+@@ -243,58 +253,115 @@ static int recvframe_chkmic(struct adapt
+                                       DBG_88E("\n %s: didn't install group key!!!!!!!!!!\n", __func__);
+                                       goto exit;
+                               }
+-                              key_idx = prxattrib->key_index;
+-                              memcpy(key, psecuritypriv->dot118021XGrpKey[key_idx].skey, 16);
+-                              memcpy(key + 16, psecuritypriv->dot118021XGrprxmickey[key_idx].skey, 16);
++                              mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
++
++                              RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
++                                       ("\n %s: bcmc key\n", __func__));
+                       } else {
+-                              key_idx = 0;
+-                              memcpy(key, stainfo->dot118021x_UncstKey.skey, 16);
+-                              memcpy(key + 16, stainfo->dot11tkiprxmickey.skey, 16);
++                              mickey = &stainfo->dot11tkiprxmickey.skey[0];
++                              RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
++                                       ("\n %s: unicast key\n", __func__));
+                       }
+-                      if (!crypto_ops) {
+-                              res = _FAIL;
+-                              goto exit_lib80211_tkip;
+-                      }
++                      /* icv_len included the mic code */
++                      datalen = precvframe->pkt->len-prxattrib->hdrlen -
++                                prxattrib->iv_len-prxattrib->icv_len-8;
++                      pframe = precvframe->pkt->data;
++                      payload = pframe+prxattrib->hdrlen+prxattrib->iv_len;
++
++                      RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n", prxattrib->iv_len, prxattrib->icv_len));
++                      rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0],
++                                         (unsigned char)prxattrib->priority); /* care the length of the data */
+-                      memcpy(iv, pframe + prxattrib->hdrlen, iv_len);
+-                      memcpy(icv, pframe + skb->len - icv_len, icv_len);
+-                      memmove(pframe + iv_len, pframe, prxattrib->hdrlen);
++                      pframemic = payload+datalen;
+-                      skb_pull(skb, iv_len);
+-                      skb_trim(skb, skb->len - icv_len);
++                      bmic_err = false;
+-                      crypto_private = crypto_ops->init(key_idx);
+-                      if (!crypto_private) {
+-                              res = _FAIL;
+-                              goto exit_lib80211_tkip;
+-                      }
+-                      if (crypto_ops->set_key(key, key_length, NULL, crypto_private) < 0) {
+-                              res = _FAIL;
+-                              goto exit_lib80211_tkip;
++                      for (i = 0; i < 8; i++) {
++                              if (miccode[i] != *(pframemic+i)) {
++                                      RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
++                                               ("%s: miccode[%d](%02x)!=*(pframemic+%d)(%02x) ",
++                                                __func__, i, miccode[i], i, *(pframemic + i)));
++                                      bmic_err = true;
++                              }
+                       }
+-                      if (crypto_ops->decrypt_msdu(skb, key_idx, prxattrib->hdrlen, crypto_private)) {
++
++                      if (bmic_err) {
++                              RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
++                                       ("\n *(pframemic-8)-*(pframemic-1)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
++                                       *(pframemic-8), *(pframemic-7), *(pframemic-6),
++                                       *(pframemic-5), *(pframemic-4), *(pframemic-3),
++                                       *(pframemic-2), *(pframemic-1)));
++                              RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
++                                       ("\n *(pframemic-16)-*(pframemic-9)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
++                                       *(pframemic-16), *(pframemic-15), *(pframemic-14),
++                                       *(pframemic-13), *(pframemic-12), *(pframemic-11),
++                                       *(pframemic-10), *(pframemic-9)));
++                              {
++                                      uint i;
++
++                                      RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
++                                               ("\n ======demp packet (len=%d)======\n",
++                                               precvframe->pkt->len));
++                                      for (i = 0; i < precvframe->pkt->len; i += 8) {
++                                              RT_TRACE(_module_rtl871x_recv_c_,
++                                                       _drv_err_,
++                                                       ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",
++                                                       *(precvframe->pkt->data+i),
++                                                       *(precvframe->pkt->data+i+1),
++                                                       *(precvframe->pkt->data+i+2),
++                                                       *(precvframe->pkt->data+i+3),
++                                                       *(precvframe->pkt->data+i+4),
++                                                       *(precvframe->pkt->data+i+5),
++                                                       *(precvframe->pkt->data+i+6),
++                                                       *(precvframe->pkt->data+i+7)));
++                                      }
++                                      RT_TRACE(_module_rtl871x_recv_c_,
++                                               _drv_err_,
++                                               ("\n ====== demp packet end [len=%d]======\n",
++                                               precvframe->pkt->len));
++                                      RT_TRACE(_module_rtl871x_recv_c_,
++                                               _drv_err_,
++                                               ("\n hrdlen=%d,\n",
++                                               prxattrib->hdrlen));
++                              }
++
++                              RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
++                                       ("ra=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey=%d ",
++                                       prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2],
++                                       prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5], psecuritypriv->binstallGrpkey));
++
++                              /*  double check key_index for some timing issue , */
++                              /*  cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */
++                              if ((IS_MCAST(prxattrib->ra) == true)  && (prxattrib->key_index != pmlmeinfo->key_index))
++                                      brpt_micerror = false;
++
++                              if ((prxattrib->bdecrypted) && (brpt_micerror)) {
++                                      rtw_handle_tkip_mic_err(adapter, (u8)IS_MCAST(prxattrib->ra));
++                                      RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted=%d ", prxattrib->bdecrypted));
++                                      DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted);
++                              } else {
++                                      RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted=%d ", prxattrib->bdecrypted));
++                                      DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted);
++                              }
+                               res = _FAIL;
+-                              goto exit_lib80211_tkip;
++                      } else {
++                              /* mic checked ok */
++                              if ((!psecuritypriv->bcheck_grpkey) && (IS_MCAST(prxattrib->ra))) {
++                                      psecuritypriv->bcheck_grpkey = true;
++                                      RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("psecuritypriv->bcheck_grpkey = true"));
++                              }
+                       }
+-
+-                      memmove(pframe, pframe + iv_len, prxattrib->hdrlen);
+-                      skb_push(skb, iv_len);
+-                      skb_put(skb, icv_len);
+-
+-                      memcpy(pframe + prxattrib->hdrlen, iv, iv_len);
+-                      memcpy(pframe + skb->len - icv_len, icv, icv_len);
+-
+-exit_lib80211_tkip:
+-                      if (crypto_ops && crypto_private)
+-                              crypto_ops->deinit(crypto_private);
+               } else {
+                       RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+                                ("%s: rtw_get_stainfo==NULL!!!\n", __func__));
+               }
++
++              skb_trim(precvframe->pkt, precvframe->pkt->len - 8);
+       }
+ exit:
++
+       return res;
+ }
+--- a/drivers/staging/rtl8188eu/core/rtw_security.c
++++ b/drivers/staging/rtl8188eu/core/rtw_security.c
+@@ -650,71 +650,71 @@ u32      rtw_tkip_encrypt(struct adapter *pad
+       return res;
+ }
++/* The hlen isn't include the IV */
+ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
+-{
+-      struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib;
+-      u32 res = _SUCCESS;
++{                                                                                                                                     /*  exclude ICV */
++      u16 pnl;
++      u32 pnh;
++      u8   rc4key[16];
++      u8   ttkey[16];
++      u8      crc[4];
++      struct arc4context mycontext;
++      int                     length;
++
++      u8      *pframe, *payload, *iv, *prwskey;
++      union pn48 dot11txpn;
++      struct  sta_info                *stainfo;
++      struct  rx_pkt_attrib    *prxattrib = &((struct recv_frame *)precvframe)->attrib;
++      struct  security_priv   *psecuritypriv = &padapter->securitypriv;
++      u32             res = _SUCCESS;
++
++
++      pframe = (unsigned char *)((struct recv_frame *)precvframe)->pkt->data;
+       /* 4 start to decrypt recvframe */
+       if (prxattrib->encrypt == _TKIP_) {
+-              struct sta_info *stainfo = rtw_get_stainfo(&padapter->stapriv, prxattrib->ta);
+-
++              stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
+               if (stainfo) {
+-                      int key_idx;
+-                      const int iv_len = 8, icv_len = 4, key_length = 32;
+-                      void *crypto_private = NULL;
+-                      struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt;
+-                      u8 key[32], iv[8], icv[4], *pframe = skb->data;
+-                      struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("TKIP"), "lib80211_crypt_tkip");
+-                      struct security_priv *psecuritypriv = &padapter->securitypriv;
+-
+                       if (IS_MCAST(prxattrib->ra)) {
+                               if (!psecuritypriv->binstallGrpkey) {
+                                       res = _FAIL;
+                                       DBG_88E("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
+                                       goto exit;
+                               }
+-                              key_idx = prxattrib->key_index;
+-                              memcpy(key, psecuritypriv->dot118021XGrpKey[key_idx].skey, 16);
+-                              memcpy(key + 16, psecuritypriv->dot118021XGrprxmickey[key_idx].skey, 16);
++                              prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
+                       } else {
+-                              key_idx = 0;
+-                              memcpy(key, stainfo->dot118021x_UncstKey.skey, 16);
+-                              memcpy(key + 16, stainfo->dot11tkiprxmickey.skey, 16);
++                              RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__));
++                              prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+                       }
+-                      if (!crypto_ops) {
+-                              res = _FAIL;
+-                              goto exit_lib80211_tkip;
+-                      }
++                      iv = pframe+prxattrib->hdrlen;
++                      payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
++                      length = ((struct recv_frame *)precvframe)->pkt->len-prxattrib->hdrlen-prxattrib->iv_len;
+-                      memcpy(iv, pframe + prxattrib->hdrlen, iv_len);
+-                      memcpy(icv, pframe + skb->len - icv_len, icv_len);
++                      GET_TKIP_PN(iv, dot11txpn);
+-                      crypto_private = crypto_ops->init(key_idx);
+-                      if (!crypto_private) {
+-                              res = _FAIL;
+-                              goto exit_lib80211_tkip;
+-                      }
+-                      if (crypto_ops->set_key(key, key_length, NULL, crypto_private) < 0) {
+-                              res = _FAIL;
+-                              goto exit_lib80211_tkip;
+-                      }
+-                      if (crypto_ops->decrypt_mpdu(skb, prxattrib->hdrlen, crypto_private)) {
++                      pnl = (u16)(dot11txpn.val);
++                      pnh = (u32)(dot11txpn.val>>16);
++
++                      phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh);
++                      phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
++
++                      /* 4 decrypt payload include icv */
++
++                      arcfour_init(&mycontext, rc4key, 16);
++                      arcfour_encrypt(&mycontext, payload, payload, length);
++
++                      *((__le32 *)crc) = getcrc32(payload, length-4);
++
++                      if (crc[3] != payload[length-1] ||
++                          crc[2] != payload[length-2] ||
++                          crc[1] != payload[length-3] ||
++                          crc[0] != payload[length-4]) {
++                              RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
++                                       ("rtw_wep_decrypt:icv error crc (%4ph)!=payload (%4ph)\n",
++                                       &crc, &payload[length-4]));
+                               res = _FAIL;
+-                              goto exit_lib80211_tkip;
+                       }
+-
+-                      memmove(pframe, pframe + iv_len, prxattrib->hdrlen);
+-                      skb_push(skb, iv_len);
+-                      skb_put(skb, icv_len);
+-
+-                      memcpy(pframe + prxattrib->hdrlen, iv, iv_len);
+-                      memcpy(pframe + skb->len - icv_len, icv, icv_len);
+-
+-exit_lib80211_tkip:
+-                      if (crypto_ops && crypto_private)
+-                              crypto_ops->deinit(crypto_private);
+               } else {
+                       RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt: stainfo==NULL!!!\n"));
+                       res = _FAIL;
index 5bf12943b4fde01affe8acba85caa65389d01977..c0de36dc5e6cec5d50b4cc043a61804784dabe70 100644 (file)
@@ -44,3 +44,23 @@ tcp-avoid-collapses-in-tcp_prune_queue-if-possible.patch
 tcp-detect-malicious-patterns-in-tcp_collapse_ofo_queue.patch
 tcp-call-tcp_drop-from-tcp_data_queue_ofo.patch
 tcp-add-tcp_ooo_try_coalesce-helper.patch
+revert-staging-r8188eu-use-lib80211-to-support-tkip.patch
+staging-speakup-fix-wraparound-in-uaccess-length-check.patch
+usb-cdc_acm-add-quirk-for-castles-vega3000.patch
+usb-core-handle-hub-c_port_over_current-condition.patch
+usb-dwc2-fix-dma-alignment-to-start-at-allocated-boundary.patch
+usb-xhci-fix-memory-leak-in-xhci_endpoint_reset.patch
+usb-gadget-fix-os-descriptors-support.patch
+usb-gadget-f_fs-only-return-delayed-status-when-len-is-0.patch
+acpica-aml-parser-ignore-dispatcher-error-status-during-table-load.patch
+driver-core-partially-revert-driver-core-correct-device-s-shutdown-order.patch
+can-xilinx_can-fix-rx-loop-if-rxnemp-is-asserted-without-rxok.patch
+can-xilinx_can-fix-power-management-handling.patch
+can-xilinx_can-fix-recovery-from-error-states-not-being-propagated.patch
+can-xilinx_can-fix-device-dropping-off-bus-on-rx-overrun.patch
+can-xilinx_can-keep-only-1-2-frames-in-tx-fifo-to-fix-tx-accounting.patch
+can-xilinx_can-fix-incorrect-clear-of-non-processed-interrupts.patch
+can-xilinx_can-fix-rx-overflow-interrupt-not-being-enabled.patch
+can-peak_canfd-fix-firmware-v3.3.0-limit-allocation-to-32-bit-dma-addr-only.patch
+can-m_can-fix-runtime-resume-call.patch
+can-m_can.c-fix-setup-of-cccr-register-clear-cccr-niso-bit-before-checking-can.ctrlmode.patch
diff --git a/queue-4.17/staging-speakup-fix-wraparound-in-uaccess-length-check.patch b/queue-4.17/staging-speakup-fix-wraparound-in-uaccess-length-check.patch
new file mode 100644 (file)
index 0000000..545fcdb
--- /dev/null
@@ -0,0 +1,52 @@
+From b96fba8d5855c3617adbfb43ca4723a808cac954 Mon Sep 17 00:00:00 2001
+From: Samuel Thibault <samuel.thibault@ens-lyon.org>
+Date: Fri, 13 Jul 2018 00:29:36 +0200
+Subject: staging: speakup: fix wraparound in uaccess length check
+
+From: Samuel Thibault <samuel.thibault@ens-lyon.org>
+
+commit b96fba8d5855c3617adbfb43ca4723a808cac954 upstream.
+
+If softsynthx_read() is called with `count < 3`, `count - 3` wraps, causing
+the loop to copy as much data as available to the provided buffer. If
+softsynthx_read() is invoked through sys_splice(), this causes an
+unbounded kernel write; but even when userspace just reads from it
+normally, a small size could cause userspace crashes.
+
+Fixes: 425e586cf95b ("speakup: add unicode variant of /dev/softsynth")
+Cc: stable@vger.kernel.org
+Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
+Signed-off-by: Jann Horn <jannh@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/speakup/speakup_soft.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/speakup/speakup_soft.c
++++ b/drivers/staging/speakup/speakup_soft.c
+@@ -197,11 +197,15 @@ static ssize_t softsynthx_read(struct fi
+       int chars_sent = 0;
+       char __user *cp;
+       char *init;
++      size_t bytes_per_ch = unicode ? 3 : 1;
+       u16 ch;
+       int empty;
+       unsigned long flags;
+       DEFINE_WAIT(wait);
++      if (count < bytes_per_ch)
++              return -EINVAL;
++
+       spin_lock_irqsave(&speakup_info.spinlock, flags);
+       while (1) {
+               prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE);
+@@ -227,7 +231,7 @@ static ssize_t softsynthx_read(struct fi
+       init = get_initstring();
+       /* Keep 3 bytes available for a 16bit UTF-8-encoded character */
+-      while (chars_sent <= count - 3) {
++      while (chars_sent <= count - bytes_per_ch) {
+               if (speakup_info.flushing) {
+                       speakup_info.flushing = 0;
+                       ch = '\x18';
diff --git a/queue-4.17/usb-cdc_acm-add-quirk-for-castles-vega3000.patch b/queue-4.17/usb-cdc_acm-add-quirk-for-castles-vega3000.patch
new file mode 100644 (file)
index 0000000..d749c67
--- /dev/null
@@ -0,0 +1,33 @@
+From 1445cbe476fc3dd09c0b380b206526a49403c071 Mon Sep 17 00:00:00 2001
+From: Lubomir Rintel <lkundrak@v3.sk>
+Date: Tue, 10 Jul 2018 08:28:49 +0200
+Subject: usb: cdc_acm: Add quirk for Castles VEGA3000
+
+From: Lubomir Rintel <lkundrak@v3.sk>
+
+commit 1445cbe476fc3dd09c0b380b206526a49403c071 upstream.
+
+The device (a POS terminal) implements CDC ACM, but has not union
+descriptor.
+
+Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1831,6 +1831,9 @@ static const struct usb_device_id acm_id
+       { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */
+       .driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */
+       },
++      { USB_DEVICE(0x0ca6, 0xa050), /* Castles VEGA3000 */
++      .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
++      },
+       { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */
+       .driver_info = CLEAR_HALT_CONDITIONS,
diff --git a/queue-4.17/usb-core-handle-hub-c_port_over_current-condition.patch b/queue-4.17/usb-core-handle-hub-c_port_over_current-condition.patch
new file mode 100644 (file)
index 0000000..a24647b
--- /dev/null
@@ -0,0 +1,49 @@
+From 249a32b7eeb3edb6897dd38f89651a62163ac4ed Mon Sep 17 00:00:00 2001
+From: Bin Liu <b-liu@ti.com>
+Date: Thu, 19 Jul 2018 14:39:37 -0500
+Subject: usb: core: handle hub C_PORT_OVER_CURRENT condition
+
+From: Bin Liu <b-liu@ti.com>
+
+commit 249a32b7eeb3edb6897dd38f89651a62163ac4ed upstream.
+
+Based on USB2.0 Spec Section 11.12.5,
+
+  "If a hub has per-port power switching and per-port current limiting,
+  an over-current on one port may still cause the power on another port
+  to fall below specific minimums. In this case, the affected port is
+  placed in the Power-Off state and C_PORT_OVER_CURRENT is set for the
+  port, but PORT_OVER_CURRENT is not set."
+
+so let's check C_PORT_OVER_CURRENT too for over current condition.
+
+Fixes: 08d1dec6f405 ("usb:hub set hub->change_bits when over-current happens")
+Cc: <stable@vger.kernel.org>
+Tested-by: Alessandro Antenucci <antenucci@korg.it>
+Signed-off-by: Bin Liu <b-liu@ti.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/hub.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -1142,10 +1142,14 @@ static void hub_activate(struct usb_hub
+               if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+                       /* Tell hub_wq to disconnect the device or
+-                       * check for a new connection
++                       * check for a new connection or over current condition.
++                       * Based on USB2.0 Spec Section 11.12.5,
++                       * C_PORT_OVER_CURRENT could be set while
++                       * PORT_OVER_CURRENT is not. So check for any of them.
+                        */
+                       if (udev || (portstatus & USB_PORT_STAT_CONNECTION) ||
+-                          (portstatus & USB_PORT_STAT_OVERCURRENT))
++                          (portstatus & USB_PORT_STAT_OVERCURRENT) ||
++                          (portchange & USB_PORT_STAT_C_OVERCURRENT))
+                               set_bit(port1, hub->change_bits);
+               } else if (portstatus & USB_PORT_STAT_ENABLE) {
diff --git a/queue-4.17/usb-dwc2-fix-dma-alignment-to-start-at-allocated-boundary.patch b/queue-4.17/usb-dwc2-fix-dma-alignment-to-start-at-allocated-boundary.patch
new file mode 100644 (file)
index 0000000..1ebf57a
--- /dev/null
@@ -0,0 +1,132 @@
+From 56406e017a883b54b339207b230f85599f4d70ae Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Antti=20Sepp=C3=A4l=C3=A4?= <a.seppala@gmail.com>
+Date: Thu, 5 Jul 2018 17:31:53 +0300
+Subject: usb: dwc2: Fix DMA alignment to start at allocated boundary
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Antti Seppälä <a.seppala@gmail.com>
+
+commit 56406e017a883b54b339207b230f85599f4d70ae upstream.
+
+The commit 3bc04e28a030 ("usb: dwc2: host: Get aligned DMA in a more
+supported way") introduced a common way to align DMA allocations.
+The code in the commit aligns the struct dma_aligned_buffer but the
+actual DMA address pointed by data[0] gets aligned to an offset from
+the allocated boundary by the kmalloc_ptr and the old_xfer_buffer
+pointers.
+
+This is against the recommendation in Documentation/DMA-API.txt which
+states:
+
+  Therefore, it is recommended that driver writers who don't take
+  special care to determine the cache line size at run time only map
+  virtual regions that begin and end on page boundaries (which are
+  guaranteed also to be cache line boundaries).
+
+The effect of this is that architectures with non-coherent DMA caches
+may run into memory corruption or kernel crashes with Unhandled
+kernel unaligned accesses exceptions.
+
+Fix the alignment by positioning the DMA area in front of the allocation
+and use memory at the end of the area for storing the orginal
+transfer_buffer pointer. This may have the added benefit of increased
+performance as the DMA area is now fully aligned on all architectures.
+
+Tested with Lantiq xRX200 (MIPS) and RPi Model B Rev 2 (ARM).
+
+Fixes: 3bc04e28a030 ("usb: dwc2: host: Get aligned DMA in a more supported way")
+Cc: <stable@vger.kernel.org>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Antti Seppälä <a.seppala@gmail.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc2/hcd.c |   44 +++++++++++++++++++++++---------------------
+ 1 file changed, 23 insertions(+), 21 deletions(-)
+
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -2627,34 +2627,29 @@ static void dwc2_hc_init_xfer(struct dwc
+ #define DWC2_USB_DMA_ALIGN 4
+-struct dma_aligned_buffer {
+-      void *kmalloc_ptr;
+-      void *old_xfer_buffer;
+-      u8 data[0];
+-};
+-
+ static void dwc2_free_dma_aligned_buffer(struct urb *urb)
+ {
+-      struct dma_aligned_buffer *temp;
++      void *stored_xfer_buffer;
+       if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
+               return;
+-      temp = container_of(urb->transfer_buffer,
+-                          struct dma_aligned_buffer, data);
++      /* Restore urb->transfer_buffer from the end of the allocated area */
++      memcpy(&stored_xfer_buffer, urb->transfer_buffer +
++             urb->transfer_buffer_length, sizeof(urb->transfer_buffer));
+       if (usb_urb_dir_in(urb))
+-              memcpy(temp->old_xfer_buffer, temp->data,
++              memcpy(stored_xfer_buffer, urb->transfer_buffer,
+                      urb->transfer_buffer_length);
+-      urb->transfer_buffer = temp->old_xfer_buffer;
+-      kfree(temp->kmalloc_ptr);
++      kfree(urb->transfer_buffer);
++      urb->transfer_buffer = stored_xfer_buffer;
+       urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
+ }
+ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
+ {
+-      struct dma_aligned_buffer *temp, *kmalloc_ptr;
++      void *kmalloc_ptr;
+       size_t kmalloc_size;
+       if (urb->num_sgs || urb->sg ||
+@@ -2662,22 +2657,29 @@ static int dwc2_alloc_dma_aligned_buffer
+           !((uintptr_t)urb->transfer_buffer & (DWC2_USB_DMA_ALIGN - 1)))
+               return 0;
+-      /* Allocate a buffer with enough padding for alignment */
++      /*
++       * Allocate a buffer with enough padding for original transfer_buffer
++       * pointer. This allocation is guaranteed to be aligned properly for
++       * DMA
++       */
+       kmalloc_size = urb->transfer_buffer_length +
+-              sizeof(struct dma_aligned_buffer) + DWC2_USB_DMA_ALIGN - 1;
++              sizeof(urb->transfer_buffer);
+       kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
+       if (!kmalloc_ptr)
+               return -ENOMEM;
+-      /* Position our struct dma_aligned_buffer such that data is aligned */
+-      temp = PTR_ALIGN(kmalloc_ptr + 1, DWC2_USB_DMA_ALIGN) - 1;
+-      temp->kmalloc_ptr = kmalloc_ptr;
+-      temp->old_xfer_buffer = urb->transfer_buffer;
++      /*
++       * Position value of original urb->transfer_buffer pointer to the end
++       * of allocation for later referencing
++       */
++      memcpy(kmalloc_ptr + urb->transfer_buffer_length,
++             &urb->transfer_buffer, sizeof(urb->transfer_buffer));
++
+       if (usb_urb_dir_out(urb))
+-              memcpy(temp->data, urb->transfer_buffer,
++              memcpy(kmalloc_ptr, urb->transfer_buffer,
+                      urb->transfer_buffer_length);
+-      urb->transfer_buffer = temp->data;
++      urb->transfer_buffer = kmalloc_ptr;
+       urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
diff --git a/queue-4.17/usb-gadget-f_fs-only-return-delayed-status-when-len-is-0.patch b/queue-4.17/usb-gadget-f_fs-only-return-delayed-status-when-len-is-0.patch
new file mode 100644 (file)
index 0000000..f80d7dc
--- /dev/null
@@ -0,0 +1,54 @@
+From 4d644abf25698362bd33d17c9ddc8f7122c30f17 Mon Sep 17 00:00:00 2001
+From: Jerry Zhang <zhangjerry@google.com>
+Date: Mon, 2 Jul 2018 12:48:08 -0700
+Subject: usb: gadget: f_fs: Only return delayed status when len is 0
+
+From: Jerry Zhang <zhangjerry@google.com>
+
+commit 4d644abf25698362bd33d17c9ddc8f7122c30f17 upstream.
+
+Commit 1b9ba000 ("Allow function drivers to pause control
+transfers") states that USB_GADGET_DELAYED_STATUS is only
+supported if data phase is 0 bytes.
+
+It seems that when the length is not 0 bytes, there is no
+need to explicitly delay the data stage since the transfer
+is not completed until the user responds. However, when the
+length is 0, there is no data stage and the transfer is
+finished once setup() returns, hence there is a need to
+explicitly delay completion.
+
+This manifests as the following bugs:
+
+Prior to 946ef68ad4e4 ('Let setup() return
+USB_GADGET_DELAYED_STATUS'), when setup is 0 bytes, ffs
+would require user to queue a 0 byte request in order to
+clear setup state. However, that 0 byte request was actually
+not needed and would hang and cause errors in other setup
+requests.
+
+After the above commit, 0 byte setups work since the gadget
+now accepts empty queues to ep0 to clear the delay, but all
+other setups hang.
+
+Fixes: 946ef68ad4e4 ("Let setup() return USB_GADGET_DELAYED_STATUS")
+Signed-off-by: Jerry Zhang <zhangjerry@google.com>
+Cc: stable <stable@vger.kernel.org>
+Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_fs.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_fs.c
++++ b/drivers/usb/gadget/function/f_fs.c
+@@ -3242,7 +3242,7 @@ static int ffs_func_setup(struct usb_fun
+       __ffs_event_add(ffs, FUNCTIONFS_SETUP);
+       spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
+-      return USB_GADGET_DELAYED_STATUS;
++      return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
+ }
+ static bool ffs_func_req_match(struct usb_function *f,
diff --git a/queue-4.17/usb-gadget-fix-os-descriptors-support.patch b/queue-4.17/usb-gadget-fix-os-descriptors-support.patch
new file mode 100644 (file)
index 0000000..642f826
--- /dev/null
@@ -0,0 +1,39 @@
+From 50b9773c13bffbef32060e67c4483ea7b2eca7b5 Mon Sep 17 00:00:00 2001
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Date: Wed, 27 Jun 2018 12:33:56 +1000
+Subject: usb: gadget: Fix OS descriptors support
+
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+
+commit 50b9773c13bffbef32060e67c4483ea7b2eca7b5 upstream.
+
+The current code is broken as it re-defines "req" inside the
+if block, then goto out of it. Thus the request that ends
+up being sent is not the one that was populated by the
+code in question.
+
+This fixes RNDIS driver autodetect by Windows 10 for me.
+
+The bug was introduced by Chris rework to remove the local
+queuing inside the if { } block of the redefined request.
+
+Fixes: 636ba13aec8a ("usb: gadget: composite: remove duplicated code in OS desc handling")
+Cc: <stable@vger.kernel.org> # v4.17
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/composite.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/usb/gadget/composite.c
++++ b/drivers/usb/gadget/composite.c
+@@ -1816,7 +1816,6 @@ unknown:
+               if (cdev->use_os_string && cdev->os_desc_config &&
+                   (ctrl->bRequestType & USB_TYPE_VENDOR) &&
+                   ctrl->bRequest == cdev->b_vendor_code) {
+-                      struct usb_request              *req;
+                       struct usb_configuration        *os_desc_cfg;
+                       u8                              *buf;
+                       int                             interface;
diff --git a/queue-4.17/usb-xhci-fix-memory-leak-in-xhci_endpoint_reset.patch b/queue-4.17/usb-xhci-fix-memory-leak-in-xhci_endpoint_reset.patch
new file mode 100644 (file)
index 0000000..a1a6449
--- /dev/null
@@ -0,0 +1,31 @@
+From d89b7664f76047e7beca8f07e86f2ccfad085a28 Mon Sep 17 00:00:00 2001
+From: Zheng Xiaowei <zhengxiaowei@ruijie.com.cn>
+Date: Fri, 20 Jul 2018 18:05:11 +0300
+Subject: usb: xhci: Fix memory leak in xhci_endpoint_reset()
+
+From: Zheng Xiaowei <zhengxiaowei@ruijie.com.cn>
+
+commit d89b7664f76047e7beca8f07e86f2ccfad085a28 upstream.
+
+If td_list is not empty the cfg_cmd will not be freed,
+call xhci_free_command to free it.
+
+Signed-off-by: Zheng Xiaowei <zhengxiaowei@ruijie.com.cn>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -2981,6 +2981,7 @@ static void xhci_endpoint_reset(struct u
+       if (!list_empty(&ep->ring->td_list)) {
+               dev_err(&udev->dev, "EP not empty, refuse reset\n");
+               spin_unlock_irqrestore(&xhci->lock, flags);
++              xhci_free_command(xhci, cfg_cmd);
+               goto cleanup;
+       }
+       xhci_queue_stop_endpoint(xhci, stop_cmd, udev->slot_id, ep_index, 0);