From: Greg Kroah-Hartman Date: Thu, 22 Mar 2012 21:15:11 +0000 (-0700) Subject: 3.3-stable patches X-Git-Tag: v3.0.26~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d4a4ee47b73b1ee74954aeab2702c6355466a785;p=thirdparty%2Fkernel%2Fstable-queue.git 3.3-stable patches added patches: ath9k-fix-going-to-full-sleep-on-ps-idle.patch genirq-fix-incorrect-check-for-forced-irq-thread-handler.patch genirq-fix-long-term-regression-in-genirq-irq_set_irq_type-handling.patch ib-iser-post-initial-receive-buffers-before-sending-the-final-login-request.patch ima-fix-kconfig-dependencies.patch iwlwifi-always-monitor-for-stuck-queues.patch math-introduce-div64_long.patch mlx4_core-fix-one-more-static-exported-function.patch mm-thp-fix-pmd_bad-triggering-in-code-paths-holding-mmap_sem-read-mode.patch ntp-fix-integer-overflow-when-setting-time.patch p54spi-release-gpio-lines-and-irq-on-error-in-p54spi_probe.patch rt2x00-add-support-for-d-link-dwa-127-to-rt2800usb.patch rtc-disable-the-alarm-in-the-hardware-v2.patch rtlwifi-handle-previous-allocation-failures-when-freeing-device-memory.patch rtlwifi-rtl8192c_common-rtl8192de-check-for-allocation-failures.patch rtlwifi-rtl8192ce-fix-loss-of-receive-performance.patch rtlwifi-rtl8192c-prevent-sleeping-from-invalid-context-in-rtl8192cu.patch rtnetlink-fix-vf-ifla-policy.patch serial-pl011-clear-pending-interrupts.patch uevent-send-events-in-correct-order-according-to-seqnum-v3.patch usb-cp210x-update-to-support-cp2105-and-multiple-interface-devices.patch usb-qcserial-don-t-grab-qmi-port-on-gobi-1000-devices.patch usb-serial-add-support-for-the-sealevel-sealink-8-2038-rohs-device.patch usb-serial-mos7840-fixed-mcs7820-device-attach-problem.patch x86-ioapic-add-register-level-checks-to-detect-bogus-io-apic-entries.patch --- diff --git a/queue-3.3/ath9k-fix-going-to-full-sleep-on-ps-idle.patch b/queue-3.3/ath9k-fix-going-to-full-sleep-on-ps-idle.patch new file mode 100644 index 00000000000..5521d98e1c5 --- /dev/null +++ b/queue-3.3/ath9k-fix-going-to-full-sleep-on-ps-idle.patch @@ -0,0 +1,42 @@ +From c1afdaff90538ef085b756454f12b29575411214 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Sat, 10 Mar 2012 13:57:04 +0100 +Subject: ath9k: fix going to full-sleep on PS idle + +From: Felix Fietkau + +commit c1afdaff90538ef085b756454f12b29575411214 upstream. + +The check for PS_WAIT_FOR_TX_ACK was inverted, the hardware should only go +to full sleep if no tx is pending. + +Reported-by: Sujith Manoharan +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/main.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -118,13 +118,15 @@ void ath9k_ps_restore(struct ath_softc * + if (--sc->ps_usecount != 0) + goto unlock; + +- if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) ++ if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) ++ goto unlock; ++ ++ if (sc->ps_idle) + mode = ATH9K_PM_FULL_SLEEP; + else if (sc->ps_enabled && + !(sc->ps_flags & (PS_WAIT_FOR_BEACON | + PS_WAIT_FOR_CAB | +- PS_WAIT_FOR_PSPOLL_DATA | +- PS_WAIT_FOR_TX_ACK))) ++ PS_WAIT_FOR_PSPOLL_DATA))) + mode = ATH9K_PM_NETWORK_SLEEP; + else + goto unlock; diff --git a/queue-3.3/genirq-fix-incorrect-check-for-forced-irq-thread-handler.patch b/queue-3.3/genirq-fix-incorrect-check-for-forced-irq-thread-handler.patch new file mode 100644 index 00000000000..518a3d49bae --- /dev/null +++ b/queue-3.3/genirq-fix-incorrect-check-for-forced-irq-thread-handler.patch @@ -0,0 +1,32 @@ +From 540b60e24f3f4781d80e47122f0c4486a03375b8 Mon Sep 17 00:00:00 2001 +From: Alexander Gordeev +Date: Fri, 9 Mar 2012 14:59:13 +0100 +Subject: genirq: Fix incorrect check for forced IRQ thread handler + +From: Alexander Gordeev + +commit 540b60e24f3f4781d80e47122f0c4486a03375b8 upstream. + +We do not want a bitwise AND between boolean operands + +Signed-off-by: Alexander Gordeev +Cc: Oleg Nesterov +Link: http://lkml.kernel.org/r/20120309135912.GA2114@dhcp-26-207.brq.redhat.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/irq/manage.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -773,7 +773,7 @@ static int irq_thread(void *data) + struct irqaction *action); + int wake; + +- if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD, ++ if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD, + &action->thread_flags)) + handler_fn = irq_forced_thread_fn; + else diff --git a/queue-3.3/genirq-fix-long-term-regression-in-genirq-irq_set_irq_type-handling.patch b/queue-3.3/genirq-fix-long-term-regression-in-genirq-irq_set_irq_type-handling.patch new file mode 100644 index 00000000000..33cf67d5be9 --- /dev/null +++ b/queue-3.3/genirq-fix-long-term-regression-in-genirq-irq_set_irq_type-handling.patch @@ -0,0 +1,93 @@ +From a09b659cd68c10ec6a30cb91ebd2c327fcd5bfe5 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Mon, 5 Mar 2012 15:07:25 -0800 +Subject: genirq: Fix long-term regression in genirq irq_set_irq_type() handling + +From: Russell King + +commit a09b659cd68c10ec6a30cb91ebd2c327fcd5bfe5 upstream. + +In 2008, commit 0c5d1eb77a8be ("genirq: record trigger type") modified the +way set_irq_type() handles the 'no trigger' condition. However, this has +an adverse effect on PCMCIA support on Intel StrongARM and probably PXA +platforms. + +PCMCIA has several status signals on the socket which can trigger +interrupts; some of these status signals depend on the card's mode +(whether it is configured in memory or IO mode). For example, cards have +a 'Ready/IRQ' signal: in memory mode, this provides an indication to +PCMCIA that the card has finished its power up initialization. In IO +mode, it provides the device interrupt signal. Other status signals +switch between on-board battery status and loud speaker output. + +In classical PCMCIA implementations, where you have a specific socket +controller, the controller provides a method to mask interrupts from the +socket, and importantly ignore any state transitions on the pins which +correspond with interrupts once masked. This masking prevents unwanted +events caused by the removal and application of socket power being +forwarded. + +However, on platforms where there is no socket controller, the PCMCIA +status and interrupt signals are routed to standard edge-triggered GPIOs. +These GPIOs can be configured to interrupt on rising edge, falling edge, +or never. This is where the problems start. + +Edge triggered interrupts are required to record events while disabled via +the usual methods of {free,request,disable,enable}_irq() to prevent +problems with dropped interrupts (eg, the 8390 driver uses disable_irq() +to defer the delivery of interrupts). As a result, these interfaces can +not be used to implement the desired behaviour. + +The side effect of this is that if the 'Ready/IRQ' GPIO is disabled via +disable_irq() on suspend, and enabled via enable_irq() after resume, we +will record the state transitions caused by powering events as valid +interrupts, and foward them to the card driver, which may attempt to +access a card which is not powered up. + +This leads delays resume while drivers spin in their interrupt handlers, +and complaints from drivers before they realize what's happened. + +Moreover, in the case of the 'Ready/IRQ' signal, this is requested and +freed by the card driver itself; the PCMCIA core has no idea whether the +interrupt is requested, and, therefore, whether a call to disable_irq() +would be valid. (We tried this around 2.4.17 / 2.5.1 kernel era, and +ended up throwing it out because of this problem.) + +Therefore, it was decided back in around 2002 to disable the edge +triggering instead, resulting in all state transitions on the GPIO being +ignored. That's what we actually need the hardware to do. + +The commit above changes this behaviour; it explicitly prevents the 'no +trigger' state being selected. + +The reason that request_irq() does not accept the 'no trigger' state is +for compatibility with existing drivers which do not provide their desired +triggering configuration. The set_irq_type() function is 'new' and not +used by non-trigger aware drivers. + +Therefore, revert this change, and restore previously working platforms +back to their former state. + +Signed-off-by: Russell King +Cc: linux@arm.linux.org.uk +Cc: Ingo Molnar +Signed-off-by: Andrew Morton +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/irq/chip.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/kernel/irq/chip.c ++++ b/kernel/irq/chip.c +@@ -61,8 +61,7 @@ int irq_set_irq_type(unsigned int irq, u + return -EINVAL; + + type &= IRQ_TYPE_SENSE_MASK; +- if (type != IRQ_TYPE_NONE) +- ret = __irq_set_trigger(desc, irq, type); ++ ret = __irq_set_trigger(desc, irq, type); + irq_put_desc_busunlock(desc, flags); + return ret; + } diff --git a/queue-3.3/ib-iser-post-initial-receive-buffers-before-sending-the-final-login-request.patch b/queue-3.3/ib-iser-post-initial-receive-buffers-before-sending-the-final-login-request.patch new file mode 100644 index 00000000000..c067f2246a6 --- /dev/null +++ b/queue-3.3/ib-iser-post-initial-receive-buffers-before-sending-the-final-login-request.patch @@ -0,0 +1,136 @@ +From 89e984e2c2cd14f77ccb26c47726ac7f13b70ae8 Mon Sep 17 00:00:00 2001 +From: Or Gerlitz +Date: Mon, 5 Mar 2012 18:21:44 +0200 +Subject: IB/iser: Post initial receive buffers before sending the final login request + +From: Or Gerlitz + +commit 89e984e2c2cd14f77ccb26c47726ac7f13b70ae8 upstream. + +An iser target may send iscsi NO-OP PDUs as soon as it marks the iSER +iSCSI session as fully operative. This means that there is window +where there are no posted receive buffers on the initiator side, so +it's possible for the iSER RC connection to break because of RNR NAK / +retry errors. To fix this, rely on the flags bits in the login +request to have FFP (0x3) in the lower nibble as a marker for the +final login request, and post an initial chunk of receive buffers +before sending that login request instead of after getting the login +response. + +Signed-off-by: Or Gerlitz +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/ulp/iser/iscsi_iser.c | 18 +++------------- + drivers/infiniband/ulp/iser/iscsi_iser.h | 1 + drivers/infiniband/ulp/iser/iser_initiator.c | 30 +++++++++++++++------------ + 3 files changed, 22 insertions(+), 27 deletions(-) + +--- a/drivers/infiniband/ulp/iser/iscsi_iser.c ++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c +@@ -364,6 +364,9 @@ iscsi_iser_conn_bind(struct iscsi_cls_se + } + ib_conn = ep->dd_data; + ++ if (iser_alloc_rx_descriptors(ib_conn)) ++ return -ENOMEM; ++ + /* binds the iSER connection retrieved from the previously + * connected ep_handle to the iSCSI layer connection. exchanges + * connection pointers */ +@@ -398,19 +401,6 @@ iscsi_iser_conn_stop(struct iscsi_cls_co + iser_conn->ib_conn = NULL; + } + +-static int +-iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn) +-{ +- struct iscsi_conn *conn = cls_conn->dd_data; +- int err; +- +- err = iser_conn_set_full_featured_mode(conn); +- if (err) +- return err; +- +- return iscsi_conn_start(cls_conn); +-} +- + static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session) + { + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); +@@ -724,7 +714,7 @@ static struct iscsi_transport iscsi_iser + .get_conn_param = iscsi_conn_get_param, + .get_ep_param = iscsi_iser_get_ep_param, + .get_session_param = iscsi_session_get_param, +- .start_conn = iscsi_iser_conn_start, ++ .start_conn = iscsi_conn_start, + .stop_conn = iscsi_iser_conn_stop, + /* iscsi host params */ + .get_host_param = iscsi_host_get_param, +--- a/drivers/infiniband/ulp/iser/iscsi_iser.h ++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h +@@ -366,4 +366,5 @@ int iser_dma_map_task_data(struct iscsi_ + void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task); + int iser_initialize_task_headers(struct iscsi_task *task, + struct iser_tx_desc *tx_desc); ++int iser_alloc_rx_descriptors(struct iser_conn *ib_conn); + #endif +--- a/drivers/infiniband/ulp/iser/iser_initiator.c ++++ b/drivers/infiniband/ulp/iser/iser_initiator.c +@@ -170,7 +170,7 @@ static void iser_create_send_desc(struct + } + + +-static int iser_alloc_rx_descriptors(struct iser_conn *ib_conn) ++int iser_alloc_rx_descriptors(struct iser_conn *ib_conn) + { + int i, j; + u64 dma_addr; +@@ -242,23 +242,24 @@ void iser_free_rx_descriptors(struct ise + kfree(ib_conn->rx_descs); + } + +-/** +- * iser_conn_set_full_featured_mode - (iSER API) +- */ +-int iser_conn_set_full_featured_mode(struct iscsi_conn *conn) ++static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req) + { + struct iscsi_iser_conn *iser_conn = conn->dd_data; + +- iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX); ++ iser_dbg("req op %x flags %x\n", req->opcode, req->flags); ++ /* check if this is the last login - going to full feature phase */ ++ if ((req->flags & ISCSI_FULL_FEATURE_PHASE) != ISCSI_FULL_FEATURE_PHASE) ++ return 0; + +- /* Check that there is no posted recv or send buffers left - */ +- /* they must be consumed during the login phase */ +- BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0); +- BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0); +- +- if (iser_alloc_rx_descriptors(iser_conn->ib_conn)) +- return -ENOMEM; ++ /* ++ * Check that there is one posted recv buffer (for the last login ++ * response) and no posted send buffers left - they must have been ++ * consumed during previous login phases. ++ */ ++ WARN_ON(iser_conn->ib_conn->post_recv_buf_count != 1); ++ WARN_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0); + ++ iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX); + /* Initial post receive buffers */ + if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX)) + return -ENOMEM; +@@ -438,6 +439,9 @@ int iser_send_control(struct iscsi_conn + err = iser_post_recvl(iser_conn->ib_conn); + if (err) + goto send_control_error; ++ err = iser_post_rx_bufs(conn, task->hdr); ++ if (err) ++ goto send_control_error; + } + + err = iser_post_send(iser_conn->ib_conn, mdesc); diff --git a/queue-3.3/ima-fix-kconfig-dependencies.patch b/queue-3.3/ima-fix-kconfig-dependencies.patch new file mode 100644 index 00000000000..886b77a2899 --- /dev/null +++ b/queue-3.3/ima-fix-kconfig-dependencies.patch @@ -0,0 +1,45 @@ +From f4a0391dfa91155bd961673b31eb42d9d45c799d Mon Sep 17 00:00:00 2001 +From: Fabio Estevam +Date: Thu, 5 Jan 2012 12:49:54 -0200 +Subject: ima: fix Kconfig dependencies + +From: Fabio Estevam + +commit f4a0391dfa91155bd961673b31eb42d9d45c799d upstream. + +Fix the following build warning: +warning: (IMA) selects TCG_TPM which has unmet direct dependencies +(HAS_IOMEM && EXPERIMENTAL) + +Suggested-by: Rajiv Andrade +Signed-off-by: Fabio Estevam +Signed-off-by: Rajiv Andrade +Signed-off-by: Mimi Zohar +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/Kconfig | 1 - + security/integrity/ima/Kconfig | 2 +- + 2 files changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/char/tpm/Kconfig ++++ b/drivers/char/tpm/Kconfig +@@ -5,7 +5,6 @@ + menuconfig TCG_TPM + tristate "TPM Hardware Support" + depends on HAS_IOMEM +- depends on EXPERIMENTAL + select SECURITYFS + ---help--- + If you have a TPM security chip in your system, which +--- a/security/integrity/ima/Kconfig ++++ b/security/integrity/ima/Kconfig +@@ -9,7 +9,7 @@ config IMA + select CRYPTO_HMAC + select CRYPTO_MD5 + select CRYPTO_SHA1 +- select TCG_TPM if !S390 && !UML ++ select TCG_TPM if HAS_IOMEM && !UML + select TCG_TIS if TCG_TPM + help + The Trusted Computing Group(TCG) runtime Integrity diff --git a/queue-3.3/iwlwifi-always-monitor-for-stuck-queues.patch b/queue-3.3/iwlwifi-always-monitor-for-stuck-queues.patch new file mode 100644 index 00000000000..c497bf89739 --- /dev/null +++ b/queue-3.3/iwlwifi-always-monitor-for-stuck-queues.patch @@ -0,0 +1,63 @@ +From 342bbf3fee2fa9a18147e74b2e3c4229a4564912 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Sun, 4 Mar 2012 08:50:46 -0800 +Subject: iwlwifi: always monitor for stuck queues + +From: Johannes Berg + +commit 342bbf3fee2fa9a18147e74b2e3c4229a4564912 upstream. + +If we only monitor while associated, the following +can happen: + - we're associated, and the queue stuck check + runs, setting the queue "touch" time to X + - we disassociate, stopping the monitoring, + which leaves the time set to X + - almost 2s later, we associate, and enqueue + a frame + - before the frame is transmitted, we monitor + for stuck queues, and find the time set to + X, although it is now later than X + 2000ms, + so we decide that the queue is stuck and + erroneously restart the device + +It happens more with P2P because there we can +go between associated/unassociated frequently. + +Reported-by: Ben Cahill +Signed-off-by: Johannes Berg +Signed-off-by: Wey-Yi Guy +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/iwl-core.c | 18 ++++-------------- + 1 file changed, 4 insertions(+), 14 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-core.c ++++ b/drivers/net/wireless/iwlwifi/iwl-core.c +@@ -1465,20 +1465,10 @@ void iwl_bg_watchdog(unsigned long data) + if (timeout == 0) + return; + +- /* monitor and check for stuck cmd queue */ +- if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue)) +- return; +- +- /* monitor and check for other stuck queues */ +- if (iwl_is_any_associated(priv)) { +- for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { +- /* skip as we already checked the command queue */ +- if (cnt == priv->shrd->cmd_queue) +- continue; +- if (iwl_check_stuck_queue(priv, cnt)) +- return; +- } +- } ++ /* monitor and check for stuck queues */ ++ for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) ++ if (iwl_check_stuck_queue(priv, cnt)) ++ return; + + mod_timer(&priv->watchdog, jiffies + + msecs_to_jiffies(IWL_WD_TICK(timeout))); diff --git a/queue-3.3/math-introduce-div64_long.patch b/queue-3.3/math-introduce-div64_long.patch new file mode 100644 index 00000000000..a8d72497931 --- /dev/null +++ b/queue-3.3/math-introduce-div64_long.patch @@ -0,0 +1,43 @@ +From f910381a55cdaa097030291f272f6e6e4380c39a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Mar 2012 12:36:13 -0400 +Subject: math: Introduce div64_long + +From: Sasha Levin + +commit f910381a55cdaa097030291f272f6e6e4380c39a upstream. + +Add a div64_long macro which is used to devide a 64bit number by a long (which +can be 4 bytes on 32bit systems and 8 bytes on 64bit systems). + +Suggested-by: Thomas Gleixner +Signed-off-by: Sasha Levin +Cc: johnstul@us.ibm.com +Link: http://lkml.kernel.org/r/1331829374-31543-1-git-send-email-levinsasha928@gmail.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/math64.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/include/linux/math64.h ++++ b/include/linux/math64.h +@@ -6,6 +6,8 @@ + + #if BITS_PER_LONG == 64 + ++#define div64_long(x,y) div64_s64((x),(y)) ++ + /** + * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder + * +@@ -45,6 +47,8 @@ static inline s64 div64_s64(s64 dividend + + #elif BITS_PER_LONG == 32 + ++#define div64_long(x,y) div_s64((x),(y)) ++ + #ifndef div_u64_rem + static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) + { diff --git a/queue-3.3/mlx4_core-fix-one-more-static-exported-function.patch b/queue-3.3/mlx4_core-fix-one-more-static-exported-function.patch new file mode 100644 index 00000000000..f5c3cfed031 --- /dev/null +++ b/queue-3.3/mlx4_core-fix-one-more-static-exported-function.patch @@ -0,0 +1,31 @@ +From e10903b087e425298fb86c6ad4b1a88735480db7 Mon Sep 17 00:00:00 2001 +From: Roland Dreier +Date: Sun, 26 Feb 2012 01:48:12 -0800 +Subject: mlx4_core: Fix one more static exported function + +From: Roland Dreier + +commit e10903b087e425298fb86c6ad4b1a88735480db7 upstream. + +Commit 22c8bff6face ("mlx4_core: Exported functions can't be static") +fixed most of this up, but forgot about mlx4_is_slave_active(). Fix +this one too. + +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/mellanox/mlx4/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/main.c ++++ b/drivers/net/ethernet/mellanox/mlx4/main.c +@@ -394,7 +394,7 @@ static int mlx4_how_many_lives_vf(struct + return ret; + } + +-static int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) ++int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) + { + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_slave_state *s_slave; diff --git a/queue-3.3/mm-thp-fix-pmd_bad-triggering-in-code-paths-holding-mmap_sem-read-mode.patch b/queue-3.3/mm-thp-fix-pmd_bad-triggering-in-code-paths-holding-mmap_sem-read-mode.patch new file mode 100644 index 00000000000..d2991b39bb4 --- /dev/null +++ b/queue-3.3/mm-thp-fix-pmd_bad-triggering-in-code-paths-holding-mmap_sem-read-mode.patch @@ -0,0 +1,461 @@ +From 1a5a9906d4e8d1976b701f889d8f35d54b928f25 Mon Sep 17 00:00:00 2001 +From: Andrea Arcangeli +Date: Wed, 21 Mar 2012 16:33:42 -0700 +Subject: mm: thp: fix pmd_bad() triggering in code paths holding mmap_sem read mode + +From: Andrea Arcangeli + +commit 1a5a9906d4e8d1976b701f889d8f35d54b928f25 upstream. + +In some cases it may happen that pmd_none_or_clear_bad() is called with +the mmap_sem hold in read mode. In those cases the huge page faults can +allocate hugepmds under pmd_none_or_clear_bad() and that can trigger a +false positive from pmd_bad() that will not like to see a pmd +materializing as trans huge. + +It's not khugepaged causing the problem, khugepaged holds the mmap_sem +in write mode (and all those sites must hold the mmap_sem in read mode +to prevent pagetables to go away from under them, during code review it +seems vm86 mode on 32bit kernels requires that too unless it's +restricted to 1 thread per process or UP builds). The race is only with +the huge pagefaults that can convert a pmd_none() into a +pmd_trans_huge(). + +Effectively all these pmd_none_or_clear_bad() sites running with +mmap_sem in read mode are somewhat speculative with the page faults, and +the result is always undefined when they run simultaneously. This is +probably why it wasn't common to run into this. For example if the +madvise(MADV_DONTNEED) runs zap_page_range() shortly before the page +fault, the hugepage will not be zapped, if the page fault runs first it +will be zapped. + +Altering pmd_bad() not to error out if it finds hugepmds won't be enough +to fix this, because zap_pmd_range would then proceed to call +zap_pte_range (which would be incorrect if the pmd become a +pmd_trans_huge()). + +The simplest way to fix this is to read the pmd in the local stack +(regardless of what we read, no need of actual CPU barriers, only +compiler barrier needed), and be sure it is not changing under the code +that computes its value. Even if the real pmd is changing under the +value we hold on the stack, we don't care. If we actually end up in +zap_pte_range it means the pmd was not none already and it was not huge, +and it can't become huge from under us (khugepaged locking explained +above). + +All we need is to enforce that there is no way anymore that in a code +path like below, pmd_trans_huge can be false, but pmd_none_or_clear_bad +can run into a hugepmd. The overhead of a barrier() is just a compiler +tweak and should not be measurable (I only added it for THP builds). I +don't exclude different compiler versions may have prevented the race +too by caching the value of *pmd on the stack (that hasn't been +verified, but it wouldn't be impossible considering +pmd_none_or_clear_bad, pmd_bad, pmd_trans_huge, pmd_none are all inlines +and there's no external function called in between pmd_trans_huge and +pmd_none_or_clear_bad). + + if (pmd_trans_huge(*pmd)) { + if (next-addr != HPAGE_PMD_SIZE) { + VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); + split_huge_page_pmd(vma->vm_mm, pmd); + } else if (zap_huge_pmd(tlb, vma, pmd, addr)) + continue; + /* fall through */ + } + if (pmd_none_or_clear_bad(pmd)) + +Because this race condition could be exercised without special +privileges this was reported in CVE-2012-1179. + +The race was identified and fully explained by Ulrich who debugged it. +I'm quoting his accurate explanation below, for reference. + +====== start quote ======= + mapcount 0 page_mapcount 1 + kernel BUG at mm/huge_memory.c:1384! + + At some point prior to the panic, a "bad pmd ..." message similar to the + following is logged on the console: + + mm/memory.c:145: bad pmd ffff8800376e1f98(80000000314000e7). + + The "bad pmd ..." message is logged by pmd_clear_bad() before it clears + the page's PMD table entry. + + 143 void pmd_clear_bad(pmd_t *pmd) + 144 { + -> 145 pmd_ERROR(*pmd); + 146 pmd_clear(pmd); + 147 } + + After the PMD table entry has been cleared, there is an inconsistency + between the actual number of PMD table entries that are mapping the page + and the page's map count (_mapcount field in struct page). When the page + is subsequently reclaimed, __split_huge_page() detects this inconsistency. + + 1381 if (mapcount != page_mapcount(page)) + 1382 printk(KERN_ERR "mapcount %d page_mapcount %d\n", + 1383 mapcount, page_mapcount(page)); + -> 1384 BUG_ON(mapcount != page_mapcount(page)); + + The root cause of the problem is a race of two threads in a multithreaded + process. Thread B incurs a page fault on a virtual address that has never + been accessed (PMD entry is zero) while Thread A is executing an madvise() + system call on a virtual address within the same 2 MB (huge page) range. + + virtual address space + .---------------------. + | | + | | + .-|---------------------| + | | | + | | |<-- B(fault) + | | | + 2 MB | |/////////////////////|-. + huge < |/////////////////////| > A(range) + page | |/////////////////////|-' + | | | + | | | + '-|---------------------| + | | + | | + '---------------------' + + - Thread A is executing an madvise(..., MADV_DONTNEED) system call + on the virtual address range "A(range)" shown in the picture. + + sys_madvise + // Acquire the semaphore in shared mode. + down_read(¤t->mm->mmap_sem) + ... + madvise_vma + switch (behavior) + case MADV_DONTNEED: + madvise_dontneed + zap_page_range + unmap_vmas + unmap_page_range + zap_pud_range + zap_pmd_range + // + // Assume that this huge page has never been accessed. + // I.e. content of the PMD entry is zero (not mapped). + // + if (pmd_trans_huge(*pmd)) { + // We don't get here due to the above assumption. + } + // + // Assume that Thread B incurred a page fault and + .---------> // sneaks in here as shown below. + | // + | if (pmd_none_or_clear_bad(pmd)) + | { + | if (unlikely(pmd_bad(*pmd))) + | pmd_clear_bad + | { + | pmd_ERROR + | // Log "bad pmd ..." message here. + | pmd_clear + | // Clear the page's PMD entry. + | // Thread B incremented the map count + | // in page_add_new_anon_rmap(), but + | // now the page is no longer mapped + | // by a PMD entry (-> inconsistency). + | } + | } + | + v + - Thread B is handling a page fault on virtual address "B(fault)" shown + in the picture. + + ... + do_page_fault + __do_page_fault + // Acquire the semaphore in shared mode. + down_read_trylock(&mm->mmap_sem) + ... + handle_mm_fault + if (pmd_none(*pmd) && transparent_hugepage_enabled(vma)) + // We get here due to the above assumption (PMD entry is zero). + do_huge_pmd_anonymous_page + alloc_hugepage_vma + // Allocate a new transparent huge page here. + ... + __do_huge_pmd_anonymous_page + ... + spin_lock(&mm->page_table_lock) + ... + page_add_new_anon_rmap + // Here we increment the page's map count (starts at -1). + atomic_set(&page->_mapcount, 0) + set_pmd_at + // Here we set the page's PMD entry which will be cleared + // when Thread A calls pmd_clear_bad(). + ... + spin_unlock(&mm->page_table_lock) + + The mmap_sem does not prevent the race because both threads are acquiring + it in shared mode (down_read). Thread B holds the page_table_lock while + the page's map count and PMD table entry are updated. However, Thread A + does not synchronize on that lock. + +====== end quote ======= + +[akpm@linux-foundation.org: checkpatch fixes] +Reported-by: Ulrich Obergfell +Signed-off-by: Andrea Arcangeli +Acked-by: Johannes Weiner +Cc: Mel Gorman +Cc: Hugh Dickins +Cc: Dave Jones +Acked-by: Larry Woodman +Acked-by: Rik van Riel +Cc: Mark Salter +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/vm86_32.c | 2 + + fs/proc/task_mmu.c | 9 ++++++ + include/asm-generic/pgtable.h | 61 ++++++++++++++++++++++++++++++++++++++++++ + mm/memcontrol.c | 4 ++ + mm/memory.c | 16 ++++++++--- + mm/mempolicy.c | 2 - + mm/mincore.c | 2 - + mm/pagewalk.c | 2 - + mm/swapfile.c | 4 -- + 9 files changed, 92 insertions(+), 10 deletions(-) + +--- a/arch/x86/kernel/vm86_32.c ++++ b/arch/x86/kernel/vm86_32.c +@@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm + spinlock_t *ptl; + int i; + ++ down_write(&mm->mmap_sem); + pgd = pgd_offset(mm, 0xA0000); + if (pgd_none_or_clear_bad(pgd)) + goto out; +@@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm + } + pte_unmap_unlock(pte, ptl); + out: ++ up_write(&mm->mmap_sem); + flush_tlb(); + } + +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -409,6 +409,9 @@ static int smaps_pte_range(pmd_t *pmd, u + } else { + spin_unlock(&walk->mm->page_table_lock); + } ++ ++ if (pmd_trans_unstable(pmd)) ++ return 0; + /* + * The mmap_sem held all the way back in m_start() is what + * keeps khugepaged out of here and from collapsing things +@@ -507,6 +510,8 @@ static int clear_refs_pte_range(pmd_t *p + struct page *page; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) { +@@ -670,6 +675,8 @@ static int pagemap_pte_range(pmd_t *pmd, + int err = 0; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + /* find the first VMA at or above 'addr' */ + vma = find_vma(walk->mm, addr); +@@ -961,6 +968,8 @@ static int gather_pte_stats(pmd_t *pmd, + spin_unlock(&walk->mm->page_table_lock); + } + ++ if (pmd_trans_unstable(pmd)) ++ return 0; + orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); + do { + struct page *page = can_gather_numa_stats(*pte, md->vma, addr); +--- a/include/asm-generic/pgtable.h ++++ b/include/asm-generic/pgtable.h +@@ -425,6 +425,8 @@ extern void untrack_pfn_vma(struct vm_ar + unsigned long size); + #endif + ++#ifdef CONFIG_MMU ++ + #ifndef CONFIG_TRANSPARENT_HUGEPAGE + static inline int pmd_trans_huge(pmd_t pmd) + { +@@ -441,7 +443,66 @@ static inline int pmd_write(pmd_t pmd) + return 0; + } + #endif /* __HAVE_ARCH_PMD_WRITE */ ++#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ ++ ++/* ++ * This function is meant to be used by sites walking pagetables with ++ * the mmap_sem hold in read mode to protect against MADV_DONTNEED and ++ * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd ++ * into a null pmd and the transhuge page fault can convert a null pmd ++ * into an hugepmd or into a regular pmd (if the hugepage allocation ++ * fails). While holding the mmap_sem in read mode the pmd becomes ++ * stable and stops changing under us only if it's not null and not a ++ * transhuge pmd. When those races occurs and this function makes a ++ * difference vs the standard pmd_none_or_clear_bad, the result is ++ * undefined so behaving like if the pmd was none is safe (because it ++ * can return none anyway). The compiler level barrier() is critically ++ * important to compute the two checks atomically on the same pmdval. ++ */ ++static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) ++{ ++ /* depend on compiler for an atomic pmd read */ ++ pmd_t pmdval = *pmd; ++ /* ++ * The barrier will stabilize the pmdval in a register or on ++ * the stack so that it will stop changing under the code. ++ */ ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ barrier(); + #endif ++ if (pmd_none(pmdval)) ++ return 1; ++ if (unlikely(pmd_bad(pmdval))) { ++ if (!pmd_trans_huge(pmdval)) ++ pmd_clear_bad(pmd); ++ return 1; ++ } ++ return 0; ++} ++ ++/* ++ * This is a noop if Transparent Hugepage Support is not built into ++ * the kernel. Otherwise it is equivalent to ++ * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in ++ * places that already verified the pmd is not none and they want to ++ * walk ptes while holding the mmap sem in read mode (write mode don't ++ * need this). If THP is not enabled, the pmd can't go away under the ++ * code even if MADV_DONTNEED runs, but if THP is enabled we need to ++ * run a pmd_trans_unstable before walking the ptes after ++ * split_huge_page_pmd returns (because it may have run when the pmd ++ * become null, but then a page fault can map in a THP and not a ++ * regular page). ++ */ ++static inline int pmd_trans_unstable(pmd_t *pmd) ++{ ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ return pmd_none_or_trans_huge_or_clear_bad(pmd); ++#else ++ return 0; ++#endif ++} ++ ++#endif /* CONFIG_MMU */ + + #endif /* !__ASSEMBLY__ */ + +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5234,6 +5234,8 @@ static int mem_cgroup_count_precharge_pt + spinlock_t *ptl; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) +@@ -5396,6 +5398,8 @@ static int mem_cgroup_move_charge_pte_ra + spinlock_t *ptl; + + split_huge_page_pmd(walk->mm, pmd); ++ if (pmd_trans_unstable(pmd)) ++ return 0; + retry: + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; addr += PAGE_SIZE) { +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1247,16 +1247,24 @@ static inline unsigned long zap_pmd_rang + do { + next = pmd_addr_end(addr, end); + if (pmd_trans_huge(*pmd)) { +- if (next-addr != HPAGE_PMD_SIZE) { ++ if (next - addr != HPAGE_PMD_SIZE) { + VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); + split_huge_page_pmd(vma->vm_mm, pmd); + } else if (zap_huge_pmd(tlb, vma, pmd, addr)) +- continue; ++ goto next; + /* fall through */ + } +- if (pmd_none_or_clear_bad(pmd)) +- continue; ++ /* ++ * Here there can be other concurrent MADV_DONTNEED or ++ * trans huge page faults running, and if the pmd is ++ * none or trans huge it can change under us. This is ++ * because MADV_DONTNEED holds the mmap_sem in read ++ * mode. ++ */ ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) ++ goto next; + next = zap_pte_range(tlb, vma, pmd, addr, next, details); ++next: + cond_resched(); + } while (pmd++, addr = next, addr != end); + +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -512,7 +512,7 @@ static inline int check_pmd_range(struct + do { + next = pmd_addr_end(addr, end); + split_huge_page_pmd(vma->vm_mm, pmd); +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + continue; + if (check_pte_range(vma, pmd, addr, next, nodes, + flags, private)) +--- a/mm/mincore.c ++++ b/mm/mincore.c +@@ -164,7 +164,7 @@ static void mincore_pmd_range(struct vm_ + } + /* fall through */ + } +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + mincore_unmapped_range(vma, addr, next, vec); + else + mincore_pte_range(vma, pmd, addr, next, vec); +--- a/mm/pagewalk.c ++++ b/mm/pagewalk.c +@@ -59,7 +59,7 @@ again: + continue; + + split_huge_page_pmd(walk->mm, pmd); +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + goto again; + err = walk_pte_range(pmd, addr, next, walk); + if (err) +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct + pmd = pmd_offset(pud, addr); + do { + next = pmd_addr_end(addr, end); +- if (unlikely(pmd_trans_huge(*pmd))) +- continue; +- if (pmd_none_or_clear_bad(pmd)) ++ if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + continue; + ret = unuse_pte_range(vma, pmd, addr, next, entry, page); + if (ret) diff --git a/queue-3.3/ntp-fix-integer-overflow-when-setting-time.patch b/queue-3.3/ntp-fix-integer-overflow-when-setting-time.patch new file mode 100644 index 00000000000..d380a1543d3 --- /dev/null +++ b/queue-3.3/ntp-fix-integer-overflow-when-setting-time.patch @@ -0,0 +1,37 @@ +From a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Mar 2012 12:36:14 -0400 +Subject: ntp: Fix integer overflow when setting time + +From: Sasha Levin + +commit a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33 upstream. + +'long secs' is passed as divisor to div_s64, which accepts a 32bit +divisor. On 64bit machines that value is trimmed back from 8 bytes +back to 4, causing a divide by zero when the number is bigger than +(1 << 32) - 1 and all 32 lower bits are 0. + +Use div64_long() instead. + +Signed-off-by: Sasha Levin +Cc: johnstul@us.ibm.com +Link: http://lkml.kernel.org/r/1331829374-31543-2-git-send-email-levinsasha928@gmail.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/time/ntp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/time/ntp.c ++++ b/kernel/time/ntp.c +@@ -275,7 +275,7 @@ static inline s64 ntp_update_offset_fll( + + time_status |= STA_MODE; + +- return div_s64(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs); ++ return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs); + } + + static void ntp_update_offset(long offset) diff --git a/queue-3.3/p54spi-release-gpio-lines-and-irq-on-error-in-p54spi_probe.patch b/queue-3.3/p54spi-release-gpio-lines-and-irq-on-error-in-p54spi_probe.patch new file mode 100644 index 00000000000..1cb43569be0 --- /dev/null +++ b/queue-3.3/p54spi-release-gpio-lines-and-irq-on-error-in-p54spi_probe.patch @@ -0,0 +1,68 @@ +From 62ebeed8d00aef75eac4fd6c161cae75a41965ca Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Thu, 1 Mar 2012 00:40:08 +0400 +Subject: p54spi: Release GPIO lines and IRQ on error in p54spi_probe + +From: Max Filippov + +commit 62ebeed8d00aef75eac4fd6c161cae75a41965ca upstream. + +This makes it possible to reload driver if insmod has failed due to +missing firmware. + +Signed-off-by: Max Filippov +Acked-by: Christian Lamparter +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/p54/p54spi.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/p54/p54spi.c ++++ b/drivers/net/wireless/p54/p54spi.c +@@ -618,19 +618,19 @@ static int __devinit p54spi_probe(struct + ret = spi_setup(spi); + if (ret < 0) { + dev_err(&priv->spi->dev, "spi_setup failed"); +- goto err_free_common; ++ goto err_free; + } + + ret = gpio_request(p54spi_gpio_power, "p54spi power"); + if (ret < 0) { + dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret); +- goto err_free_common; ++ goto err_free; + } + + ret = gpio_request(p54spi_gpio_irq, "p54spi irq"); + if (ret < 0) { + dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret); +- goto err_free_common; ++ goto err_free_gpio_power; + } + + gpio_direction_output(p54spi_gpio_power, 0); +@@ -641,7 +641,7 @@ static int __devinit p54spi_probe(struct + priv->spi); + if (ret < 0) { + dev_err(&priv->spi->dev, "request_irq() failed"); +- goto err_free_common; ++ goto err_free_gpio_irq; + } + + irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING); +@@ -673,6 +673,12 @@ static int __devinit p54spi_probe(struct + return 0; + + err_free_common: ++ free_irq(gpio_to_irq(p54spi_gpio_irq), spi); ++err_free_gpio_irq: ++ gpio_free(p54spi_gpio_irq); ++err_free_gpio_power: ++ gpio_free(p54spi_gpio_power); ++err_free: + p54_free_common(priv->hw); + return ret; + } diff --git a/queue-3.3/rt2x00-add-support-for-d-link-dwa-127-to-rt2800usb.patch b/queue-3.3/rt2x00-add-support-for-d-link-dwa-127-to-rt2800usb.patch new file mode 100644 index 00000000000..dbb349edd27 --- /dev/null +++ b/queue-3.3/rt2x00-add-support-for-d-link-dwa-127-to-rt2800usb.patch @@ -0,0 +1,31 @@ +From d42a179b941a9e4cc6cf41d0f3cbadd75fc48a89 Mon Sep 17 00:00:00 2001 +From: Gertjan van Wingerde +Date: Sat, 11 Feb 2012 21:58:09 +0100 +Subject: rt2x00: Add support for D-Link DWA-127 to rt2800usb. + +From: Gertjan van Wingerde + +commit d42a179b941a9e4cc6cf41d0f3cbadd75fc48a89 upstream. + +This is an RT3070 based device. + +Reported-by: Mikhail Kryshen +Signed-off-by: Gertjan van Wingerde +Acked-by: Ivo van Doorn +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rt2x00/rt2800usb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -922,6 +922,7 @@ static struct usb_device_id rt2800usb_de + { USB_DEVICE(0x07d1, 0x3c13) }, + { USB_DEVICE(0x07d1, 0x3c15) }, + { USB_DEVICE(0x07d1, 0x3c16) }, ++ { USB_DEVICE(0x2001, 0x3c1b) }, + /* Draytek */ + { USB_DEVICE(0x07fa, 0x7712) }, + /* DVICO */ diff --git a/queue-3.3/rtc-disable-the-alarm-in-the-hardware-v2.patch b/queue-3.3/rtc-disable-the-alarm-in-the-hardware-v2.patch new file mode 100644 index 00000000000..3d18fabdf24 --- /dev/null +++ b/queue-3.3/rtc-disable-the-alarm-in-the-hardware-v2.patch @@ -0,0 +1,74 @@ +From 41c7f7424259ff11009449f87c95656f69f9b186 Mon Sep 17 00:00:00 2001 +From: Rabin Vincent +Date: Tue, 22 Nov 2011 11:03:14 +0100 +Subject: rtc: Disable the alarm in the hardware (v2) + +From: Rabin Vincent + +commit 41c7f7424259ff11009449f87c95656f69f9b186 upstream. + +Currently, the RTC code does not disable the alarm in the hardware. + +This means that after a sequence such as the one below (the files are in the +RTC sysfs), the box will boot up after 2 minutes even though we've +asked for the alarm to be turned off. + + # echo $((`cat since_epoch`)+120) > wakealarm + # echo 0 > wakealarm + # poweroff + +Fix this by disabling the alarm when there are no timers to run. + +The original version of this patch was reverted. This version +disables the irq directly instead of setting a disabled timer +in the future. + +Cc: John Stultz +Signed-off-by: Rabin Vincent +[Merged in the second revision from Rabin] +Signed-off-by: John Stultz +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/rtc/interface.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/rtc/interface.c ++++ b/drivers/rtc/interface.c +@@ -763,6 +763,14 @@ static int rtc_timer_enqueue(struct rtc_ + return 0; + } + ++static void rtc_alarm_disable(struct rtc_device *rtc) ++{ ++ if (!rtc->ops || !rtc->ops->alarm_irq_enable) ++ return; ++ ++ rtc->ops->alarm_irq_enable(rtc->dev.parent, false); ++} ++ + /** + * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue + * @rtc rtc device +@@ -784,8 +792,10 @@ static void rtc_timer_remove(struct rtc_ + struct rtc_wkalrm alarm; + int err; + next = timerqueue_getnext(&rtc->timerqueue); +- if (!next) ++ if (!next) { ++ rtc_alarm_disable(rtc); + return; ++ } + alarm.time = rtc_ktime_to_tm(next->expires); + alarm.enabled = 1; + err = __rtc_set_alarm(rtc, &alarm); +@@ -847,7 +857,8 @@ again: + err = __rtc_set_alarm(rtc, &alarm); + if (err == -ETIME) + goto again; +- } ++ } else ++ rtc_alarm_disable(rtc); + + mutex_unlock(&rtc->ops_lock); + } diff --git a/queue-3.3/rtlwifi-handle-previous-allocation-failures-when-freeing-device-memory.patch b/queue-3.3/rtlwifi-handle-previous-allocation-failures-when-freeing-device-memory.patch new file mode 100644 index 00000000000..a4604f33540 --- /dev/null +++ b/queue-3.3/rtlwifi-handle-previous-allocation-failures-when-freeing-device-memory.patch @@ -0,0 +1,56 @@ +From 7f66c2f93e5779625c10d262c84537427a2673ca Mon Sep 17 00:00:00 2001 +From: Simon Graham +Date: Tue, 7 Feb 2012 18:07:38 -0600 +Subject: rtlwifi: Handle previous allocation failures when freeing device memory + +From: Simon Graham + +commit 7f66c2f93e5779625c10d262c84537427a2673ca upstream. + +Handle previous allocation failures when freeing device memory + +Signed-off-by: Simon Graham +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rtlwifi/pci.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/rtlwifi/pci.c ++++ b/drivers/net/wireless/rtlwifi/pci.c +@@ -1157,10 +1157,12 @@ static void _rtl_pci_free_tx_ring(struct + ring->idx = (ring->idx + 1) % ring->entries; + } + +- pci_free_consistent(rtlpci->pdev, +- sizeof(*ring->desc) * ring->entries, +- ring->desc, ring->dma); +- ring->desc = NULL; ++ if (ring->desc) { ++ pci_free_consistent(rtlpci->pdev, ++ sizeof(*ring->desc) * ring->entries, ++ ring->desc, ring->dma); ++ ring->desc = NULL; ++ } + } + + static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) +@@ -1184,12 +1186,14 @@ static void _rtl_pci_free_rx_ring(struct + kfree_skb(skb); + } + +- pci_free_consistent(rtlpci->pdev, ++ if (rtlpci->rx_ring[rx_queue_idx].desc) { ++ pci_free_consistent(rtlpci->pdev, + sizeof(*rtlpci->rx_ring[rx_queue_idx]. + desc) * rtlpci->rxringcount, + rtlpci->rx_ring[rx_queue_idx].desc, + rtlpci->rx_ring[rx_queue_idx].dma); +- rtlpci->rx_ring[rx_queue_idx].desc = NULL; ++ rtlpci->rx_ring[rx_queue_idx].desc = NULL; ++ } + } + } + diff --git a/queue-3.3/rtlwifi-rtl8192c-prevent-sleeping-from-invalid-context-in-rtl8192cu.patch b/queue-3.3/rtlwifi-rtl8192c-prevent-sleeping-from-invalid-context-in-rtl8192cu.patch new file mode 100644 index 00000000000..c67f1143d37 --- /dev/null +++ b/queue-3.3/rtlwifi-rtl8192c-prevent-sleeping-from-invalid-context-in-rtl8192cu.patch @@ -0,0 +1,53 @@ +From ebecdcc12fed5d3c81853dea61a0a78a5aefab52 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Fri, 2 Mar 2012 15:23:36 -0600 +Subject: rtlwifi: rtl8192c: Prevent sleeping from invalid context in rtl8192cu + +From: Larry Finger + +commit ebecdcc12fed5d3c81853dea61a0a78a5aefab52 upstream. + +When driver rtl8192cu is used with the debug level set to 3 or greater, +the result is "sleeping function called from invalid context" due to +an rcu_read_lock() call in the DM refresh routine in driver rtl8192c. +This lock is not necessary as the USB driver does not use the struct +being protected, thus the lock is set only when a PCI interface is +active. + +This bug is reported in https://bugzilla.kernel.org/show_bug.cgi?id=42775. + +Reported-by: Ronald Wahl +Tested-by: Ronald Wahl +Signed-off-by: Larry Finger +Cc: Ronald Wahl +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +@@ -1219,13 +1219,18 @@ static void rtl92c_dm_refresh_rate_adapt + ("PreState = %d, CurState = %d\n", + p_ra->pre_ratr_state, p_ra->ratr_state)); + +- rcu_read_lock(); +- sta = ieee80211_find_sta(mac->vif, mac->bssid); ++ /* Only the PCI card uses sta in the update rate table ++ * callback routine */ ++ if (rtlhal->interface == INTF_PCI) { ++ rcu_read_lock(); ++ sta = ieee80211_find_sta(mac->vif, mac->bssid); ++ } + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, + p_ra->ratr_state); + + p_ra->pre_ratr_state = p_ra->ratr_state; +- rcu_read_unlock(); ++ if (rtlhal->interface == INTF_PCI) ++ rcu_read_unlock(); + } + } + } diff --git a/queue-3.3/rtlwifi-rtl8192c_common-rtl8192de-check-for-allocation-failures.patch b/queue-3.3/rtlwifi-rtl8192c_common-rtl8192de-check-for-allocation-failures.patch new file mode 100644 index 00000000000..24af8f0995b --- /dev/null +++ b/queue-3.3/rtlwifi-rtl8192c_common-rtl8192de-check-for-allocation-failures.patch @@ -0,0 +1,93 @@ +From 76a92be537f1c8c259e393632301446257ca3ea9 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Sat, 7 Jan 2012 20:46:40 -0600 +Subject: rtlwifi: rtl8192c_common: rtl8192de: Check for allocation failures + +From: Larry Finger + +commit 76a92be537f1c8c259e393632301446257ca3ea9 upstream. + +In https://bugzilla.redhat.com/show_bug.cgi?id=771656, a kernel bug was +triggered due to a failed skb allocation that was not checked. This event +lead to an audit of all memory allocations in the complete rtlwifi family +of drivers. This patch fixes the rest. + +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rtlwifi/pci.c | 2 ++ + drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 2 ++ + drivers/net/wireless/rtlwifi/rtl8192de/fw.c | 14 +++++++++----- + drivers/net/wireless/rtlwifi/usb.c | 12 +++++++----- + 4 files changed, 20 insertions(+), 10 deletions(-) + +--- a/drivers/net/wireless/rtlwifi/pci.c ++++ b/drivers/net/wireless/rtlwifi/pci.c +@@ -657,6 +657,8 @@ static void _rtl_receive_one(struct ieee + return; + + uskb = dev_alloc_skb(skb->len + 128); ++ if (!uskb) ++ return; /* exit if allocation failed */ + memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status)); + pdata = (u8 *)skb_put(uskb, skb->len); + memcpy(pdata, skb->data, skb->len); +--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +@@ -788,6 +788,8 @@ void rtl92c_set_fw_rsvdpagepkt(struct ie + + + skb = dev_alloc_skb(totalpacketlen); ++ if (!skb) ++ return; + memcpy((u8 *) skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + +--- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c +@@ -763,12 +763,16 @@ void rtl92d_set_fw_rsvdpagepkt(struct ie + "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + u1RsvdPageLoc, 3); + skb = dev_alloc_skb(totalpacketlen); +- memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet, +- totalpacketlen); +- rtstatus = _rtl92d_cmd_send_packet(hw, skb); ++ if (!skb) { ++ dlok = false; ++ } else { ++ memcpy((u8 *) skb_put(skb, totalpacketlen), ++ &reserved_page_packet, totalpacketlen); ++ rtstatus = _rtl92d_cmd_send_packet(hw, skb); + +- if (rtstatus) +- dlok = true; ++ if (rtstatus) ++ dlok = true; ++ } + if (dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + ("Set RSVD page location to Fw.\n")); +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -520,12 +520,14 @@ static void _rtl_usb_rx_process_noagg(st + u8 *pdata; + + uskb = dev_alloc_skb(skb->len + 128); +- memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, +- sizeof(rx_status)); +- pdata = (u8 *)skb_put(uskb, skb->len); +- memcpy(pdata, skb->data, skb->len); ++ if (uskb) { /* drop packet on allocation failure */ ++ memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, ++ sizeof(rx_status)); ++ pdata = (u8 *)skb_put(uskb, skb->len); ++ memcpy(pdata, skb->data, skb->len); ++ ieee80211_rx_irqsafe(hw, uskb); ++ } + dev_kfree_skb_any(skb); +- ieee80211_rx_irqsafe(hw, uskb); + } else { + dev_kfree_skb_any(skb); + } diff --git a/queue-3.3/rtlwifi-rtl8192ce-fix-loss-of-receive-performance.patch b/queue-3.3/rtlwifi-rtl8192ce-fix-loss-of-receive-performance.patch new file mode 100644 index 00000000000..5507cf77cbb --- /dev/null +++ b/queue-3.3/rtlwifi-rtl8192ce-fix-loss-of-receive-performance.patch @@ -0,0 +1,40 @@ +From a9b89e2567c743483e6354f64d7a7e3a8c101e9e Mon Sep 17 00:00:00 2001 +From: Jingjun Wu +Date: Fri, 2 Mar 2012 20:52:14 -0600 +Subject: rtlwifi: rtl8192ce: Fix loss of receive performance + +From: Jingjun Wu + +commit a9b89e2567c743483e6354f64d7a7e3a8c101e9e upstream. + +Driver rtl8192ce when used with the RTL8188CE device would start at about +20 Mbps on a 54 Mbps connection, but quickly drop to 1 Mbps. One of the +symptoms is that the AP would need to retransmit each packet 4 of 5 times +before the driver would acknowledge it. Recovery is possible only by +unloading and reloading the driver. This problem was reported at +https://bugzilla.redhat.com/show_bug.cgi?id=770207. + +The problem is due to a missing update of the gain setting. + +Signed-off-by: Jingjun Wu +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +@@ -524,6 +524,10 @@ void rtl92c_dm_write_dig(struct ieee8021 + dm_digtable.cur_igvalue, dm_digtable.pre_igvalue, + dm_digtable.backoff_val)); + ++ dm_digtable.cur_igvalue += 2; ++ if (dm_digtable.cur_igvalue > 0x3f) ++ dm_digtable.cur_igvalue = 0x3f; ++ + if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) { + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, + dm_digtable.cur_igvalue); diff --git a/queue-3.3/rtnetlink-fix-vf-ifla-policy.patch b/queue-3.3/rtnetlink-fix-vf-ifla-policy.patch new file mode 100644 index 00000000000..eaced5071f9 --- /dev/null +++ b/queue-3.3/rtnetlink-fix-vf-ifla-policy.patch @@ -0,0 +1,36 @@ +From 48752f6513012a1b078da08b145d5c40a644f058 Mon Sep 17 00:00:00 2001 +From: Greg Rose +Date: Wed, 8 Feb 2012 00:45:00 +0000 +Subject: rtnetlink: Fix VF IFLA policy + +From: Greg Rose + +commit 48752f6513012a1b078da08b145d5c40a644f058 upstream. + +Add VF spoof check to IFLA policy. The original patch I submitted to +add the spoof checking feature to rtnl failed to add the proper policy +rule that identifies the data type and len. This patch corrects that +oversight. No bugs have been reported against this but it may cause +some problem for the netlink message parsing that uses the policy +table. + +Signed-off-by: Greg Rose +Tested-by: Sibai Li +Signed-off-by: Jeff Kirsher +Signed-off-by: Greg Kroah-Hartman + +--- + net/core/rtnetlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1133,6 +1133,8 @@ static const struct nla_policy ifla_vf_p + .len = sizeof(struct ifla_vf_vlan) }, + [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_vf_tx_rate) }, ++ [IFLA_VF_SPOOFCHK] = { .type = NLA_BINARY, ++ .len = sizeof(struct ifla_vf_spoofchk) }, + }; + + static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { diff --git a/queue-3.3/serial-pl011-clear-pending-interrupts.patch b/queue-3.3/serial-pl011-clear-pending-interrupts.patch new file mode 100644 index 00000000000..477d7fb5427 --- /dev/null +++ b/queue-3.3/serial-pl011-clear-pending-interrupts.patch @@ -0,0 +1,80 @@ +From 9b96fbacda34079dea0638ee1e92c56286f6114a Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Tue, 13 Mar 2012 13:27:23 +0100 +Subject: serial: PL011: clear pending interrupts + +From: Linus Walleij + +commit 9b96fbacda34079dea0638ee1e92c56286f6114a upstream. + +Chanho Min reported that when the boot loader transfers +control to the kernel, there may be pending interrupts +causing the UART to lock up in an eternal loop trying to +pick tokens from the FIFO (since the RX interrupt flag +indicates there are tokens) while in practice there are +no tokens - in fact there is only a pending IRQ flag. + +This patch address the issue with a combination of two +patches suggested by Russell King that clears and mask +all interrupts at probe() and clears any pending error +and RX interrupts at port startup time. + +We suspect the spurious interrupts are a side-effect of +switching the UART from FIFO to non-FIFO mode. + +Cc: Shreshtha Kumar Sahu +Reported-by: Chanho Min +Suggested-by: Russell King +Signed-off-by: Linus Walleij +Reviewed-by: Jong-Sung Kim +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/amba-pl011.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1381,6 +1381,10 @@ static int pl011_startup(struct uart_por + + uap->port.uartclk = clk_get_rate(uap->clk); + ++ /* Clear pending error and receive interrupts */ ++ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | ++ UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); ++ + /* + * Allocate the IRQ + */ +@@ -1417,10 +1421,6 @@ static int pl011_startup(struct uart_por + cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE; + writew(cr, uap->port.membase + UART011_CR); + +- /* Clear pending error interrupts */ +- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS, +- uap->port.membase + UART011_ICR); +- + /* + * initialise the old status of the modem signals + */ +@@ -1435,6 +1435,9 @@ static int pl011_startup(struct uart_por + * as well. + */ + spin_lock_irq(&uap->port.lock); ++ /* Clear out any spuriously appearing RX interrupts */ ++ writew(UART011_RTIS | UART011_RXIS, ++ uap->port.membase + UART011_ICR); + uap->im = UART011_RTIM; + if (!pl011_dma_rx_running(uap)) + uap->im |= UART011_RXIM; +@@ -1927,6 +1930,10 @@ static int pl011_probe(struct amba_devic + goto unmap; + } + ++ /* Ensure interrupts from this UART are masked and cleared */ ++ writew(0, uap->port.membase + UART011_IMSC); ++ writew(0xffff, uap->port.membase + UART011_ICR); ++ + uap->vendor = vendor; + uap->lcrh_rx = vendor->lcrh_rx; + uap->lcrh_tx = vendor->lcrh_tx; diff --git a/queue-3.3/series b/queue-3.3/series index af2ed42cd0d..e7a7571f94c 100644 --- a/queue-3.3/series +++ b/queue-3.3/series @@ -35,3 +35,28 @@ cdc-wdm-don-t-clear-wdm_read-unless-entire-read-buffer-is-emptied.patch usb-fsl_udc_core-fix-scheduling-while-atomic-dump-message.patch usb-fix-build-error-due-to-dma_mask-is-not-at-pdev_archdata-at-arm.patch usb-ums_realtek-do-not-use-stack-memory-for-dma-in-__do_config_autodelink.patch +usb-qcserial-don-t-grab-qmi-port-on-gobi-1000-devices.patch +usb-serial-add-support-for-the-sealevel-sealink-8-2038-rohs-device.patch +usb-cp210x-update-to-support-cp2105-and-multiple-interface-devices.patch +usb-serial-mos7840-fixed-mcs7820-device-attach-problem.patch +rt2x00-add-support-for-d-link-dwa-127-to-rt2800usb.patch +rtlwifi-rtl8192c_common-rtl8192de-check-for-allocation-failures.patch +rtlwifi-handle-previous-allocation-failures-when-freeing-device-memory.patch +rtlwifi-rtl8192c-prevent-sleeping-from-invalid-context-in-rtl8192cu.patch +rtlwifi-rtl8192ce-fix-loss-of-receive-performance.patch +serial-pl011-clear-pending-interrupts.patch +iwlwifi-always-monitor-for-stuck-queues.patch +ath9k-fix-going-to-full-sleep-on-ps-idle.patch +math-introduce-div64_long.patch +ntp-fix-integer-overflow-when-setting-time.patch +uevent-send-events-in-correct-order-according-to-seqnum-v3.patch +genirq-fix-long-term-regression-in-genirq-irq_set_irq_type-handling.patch +genirq-fix-incorrect-check-for-forced-irq-thread-handler.patch +rtc-disable-the-alarm-in-the-hardware-v2.patch +p54spi-release-gpio-lines-and-irq-on-error-in-p54spi_probe.patch +rtnetlink-fix-vf-ifla-policy.patch +ib-iser-post-initial-receive-buffers-before-sending-the-final-login-request.patch +mlx4_core-fix-one-more-static-exported-function.patch +ima-fix-kconfig-dependencies.patch +x86-ioapic-add-register-level-checks-to-detect-bogus-io-apic-entries.patch +mm-thp-fix-pmd_bad-triggering-in-code-paths-holding-mmap_sem-read-mode.patch diff --git a/queue-3.3/uevent-send-events-in-correct-order-according-to-seqnum-v3.patch b/queue-3.3/uevent-send-events-in-correct-order-according-to-seqnum-v3.patch new file mode 100644 index 00000000000..92375ef21e8 --- /dev/null +++ b/queue-3.3/uevent-send-events-in-correct-order-according-to-seqnum-v3.patch @@ -0,0 +1,94 @@ +From 7b60a18da393ed70db043a777fd9e6d5363077c4 Mon Sep 17 00:00:00 2001 +From: Andrew Vagin +Date: Wed, 7 Mar 2012 14:49:56 +0400 +Subject: uevent: send events in correct order according to seqnum (v3) + +From: Andrew Vagin + +commit 7b60a18da393ed70db043a777fd9e6d5363077c4 upstream. + +The queue handling in the udev daemon assumes that the events are +ordered. + +Before this patch uevent_seqnum is incremented under sequence_lock, +than an event is send uner uevent_sock_mutex. I want to say that code +contained a window between incrementing seqnum and sending an event. + +This patch locks uevent_sock_mutex before incrementing uevent_seqnum. + +v2: delete sequence_lock, uevent_seqnum is protected by uevent_sock_mutex +v3: unlock the mutex before the goto exit + +Thanks for Kay for the comments. + +Signed-off-by: Andrew Vagin +Tested-By: Kay Sievers +Signed-off-by: Greg Kroah-Hartman + +--- + lib/kobject_uevent.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +--- a/lib/kobject_uevent.c ++++ b/lib/kobject_uevent.c +@@ -29,16 +29,17 @@ + + u64 uevent_seqnum; + char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; +-static DEFINE_SPINLOCK(sequence_lock); + #ifdef CONFIG_NET + struct uevent_sock { + struct list_head list; + struct sock *sk; + }; + static LIST_HEAD(uevent_sock_list); +-static DEFINE_MUTEX(uevent_sock_mutex); + #endif + ++/* This lock protects uevent_seqnum and uevent_sock_list */ ++static DEFINE_MUTEX(uevent_sock_mutex); ++ + /* the strings here must match the enum in include/linux/kobject.h */ + static const char *kobject_actions[] = { + [KOBJ_ADD] = "add", +@@ -136,7 +137,6 @@ int kobject_uevent_env(struct kobject *k + struct kobject *top_kobj; + struct kset *kset; + const struct kset_uevent_ops *uevent_ops; +- u64 seq; + int i = 0; + int retval = 0; + #ifdef CONFIG_NET +@@ -243,17 +243,16 @@ int kobject_uevent_env(struct kobject *k + else if (action == KOBJ_REMOVE) + kobj->state_remove_uevent_sent = 1; + ++ mutex_lock(&uevent_sock_mutex); + /* we will send an event, so request a new sequence number */ +- spin_lock(&sequence_lock); +- seq = ++uevent_seqnum; +- spin_unlock(&sequence_lock); +- retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); +- if (retval) ++ retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum); ++ if (retval) { ++ mutex_unlock(&uevent_sock_mutex); + goto exit; ++ } + + #if defined(CONFIG_NET) + /* send netlink message */ +- mutex_lock(&uevent_sock_mutex); + list_for_each_entry(ue_sk, &uevent_sock_list, list) { + struct sock *uevent_sock = ue_sk->sk; + struct sk_buff *skb; +@@ -290,8 +289,8 @@ int kobject_uevent_env(struct kobject *k + } else + retval = -ENOMEM; + } +- mutex_unlock(&uevent_sock_mutex); + #endif ++ mutex_unlock(&uevent_sock_mutex); + + /* call uevent_helper, usually only enabled during early boot */ + if (uevent_helper[0] && !kobj_usermode_filter(kobj)) { diff --git a/queue-3.3/usb-cp210x-update-to-support-cp2105-and-multiple-interface-devices.patch b/queue-3.3/usb-cp210x-update-to-support-cp2105-and-multiple-interface-devices.patch new file mode 100644 index 00000000000..a804c60d9cc --- /dev/null +++ b/queue-3.3/usb-cp210x-update-to-support-cp2105-and-multiple-interface-devices.patch @@ -0,0 +1,152 @@ +From a5360a53a7ccad5ed9ccef210b94fef13c6e5529 Mon Sep 17 00:00:00 2001 +From: Preston Fick +Date: Fri, 24 Feb 2012 13:42:39 -0600 +Subject: usb: cp210x: Update to support CP2105 and multiple interface devices + +From: Preston Fick + +commit a5360a53a7ccad5ed9ccef210b94fef13c6e5529 upstream. + +This patch updates the cp210x driver to support CP210x multiple +interface devices devices from Silicon Labs. The existing driver +always sends control requests to interface 0, which is hardcoded in +the usb_control_msg function calls. This only allows for single +interface devices to be used, and causes a bug when using ports on an +interface other than 0 in the multiple interface devices. + +Here are the changes included in this patch: +- Updated the device list to contain the Silicon Labs factory default + VID/PID for multiple interface CP210x devices +- Created a cp210x_port_private struct created for each port on + startup, this struct holds the interface number +- Added a cp210x_release function to clean up the cp210x_port_private + memory created on startup +- Modified usb_get_config and usb_set_config to get a pointer to the + cp210x_port_private struct, and use the interface number there in the + usb_control_message wIndex param + +Signed-off-by: Preston Fick +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/cp210x.c | 44 +++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 41 insertions(+), 3 deletions(-) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -49,6 +49,7 @@ static int cp210x_tiocmset_port(struct u + unsigned int, unsigned int); + static void cp210x_break_ctl(struct tty_struct *, int); + static int cp210x_startup(struct usb_serial *); ++static void cp210x_release(struct usb_serial *); + static void cp210x_dtr_rts(struct usb_serial_port *p, int on); + + static bool debug; +@@ -121,6 +122,8 @@ static const struct usb_device_id id_tab + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ ++ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ ++ { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ + { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ + { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ +@@ -149,6 +152,10 @@ static const struct usb_device_id id_tab + + MODULE_DEVICE_TABLE(usb, id_table); + ++struct cp210x_port_private { ++ __u8 bInterfaceNumber; ++}; ++ + static struct usb_driver cp210x_driver = { + .name = "cp210x", + .probe = usb_serial_probe, +@@ -174,6 +181,7 @@ static struct usb_serial_driver cp210x_d + .tiocmget = cp210x_tiocmget, + .tiocmset = cp210x_tiocmset, + .attach = cp210x_startup, ++ .release = cp210x_release, + .dtr_rts = cp210x_dtr_rts + }; + +@@ -261,6 +269,7 @@ static int cp210x_get_config(struct usb_ + unsigned int *data, int size) + { + struct usb_serial *serial = port->serial; ++ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + __le32 *buf; + int result, i, length; + +@@ -276,7 +285,7 @@ static int cp210x_get_config(struct usb_ + /* Issue the request, attempting to read 'size' bytes */ + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + request, REQTYPE_DEVICE_TO_HOST, 0x0000, +- 0, buf, size, 300); ++ port_priv->bInterfaceNumber, buf, size, 300); + + /* Convert data into an array of integers */ + for (i = 0; i < length; i++) +@@ -307,6 +316,7 @@ static int cp210x_set_config(struct usb_ + unsigned int *data, int size) + { + struct usb_serial *serial = port->serial; ++ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + __le32 *buf; + int result, i, length; + +@@ -328,12 +338,12 @@ static int cp210x_set_config(struct usb_ + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, 0x0000, +- 0, buf, size, 300); ++ port_priv->bInterfaceNumber, buf, size, 300); + } else { + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, data[0], +- 0, NULL, 0, 300); ++ port_priv->bInterfaceNumber, NULL, 0, 300); + } + + kfree(buf); +@@ -844,11 +854,39 @@ static void cp210x_break_ctl (struct tty + + static int cp210x_startup(struct usb_serial *serial) + { ++ struct cp210x_port_private *port_priv; ++ int i; ++ + /* cp210x buffers behave strangely unless device is reset */ + usb_reset_device(serial->dev); ++ ++ for (i = 0; i < serial->num_ports; i++) { ++ port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); ++ if (!port_priv) ++ return -ENOMEM; ++ ++ memset(port_priv, 0x00, sizeof(*port_priv)); ++ port_priv->bInterfaceNumber = ++ serial->interface->cur_altsetting->desc.bInterfaceNumber; ++ ++ usb_set_serial_port_data(serial->port[i], port_priv); ++ } ++ + return 0; + } + ++static void cp210x_release(struct usb_serial *serial) ++{ ++ struct cp210x_port_private *port_priv; ++ int i; ++ ++ for (i = 0; i < serial->num_ports; i++) { ++ port_priv = usb_get_serial_port_data(serial->port[i]); ++ kfree(port_priv); ++ usb_set_serial_port_data(serial->port[i], NULL); ++ } ++} ++ + static int __init cp210x_init(void) + { + int retval; diff --git a/queue-3.3/usb-qcserial-don-t-grab-qmi-port-on-gobi-1000-devices.patch b/queue-3.3/usb-qcserial-don-t-grab-qmi-port-on-gobi-1000-devices.patch new file mode 100644 index 00000000000..3e03745219e --- /dev/null +++ b/queue-3.3/usb-qcserial-don-t-grab-qmi-port-on-gobi-1000-devices.patch @@ -0,0 +1,174 @@ +From c192c8e71a2ded01170c1a992cd21aaedc822756 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Fri, 24 Feb 2012 13:08:43 -0600 +Subject: USB: qcserial: don't grab QMI port on Gobi 1000 devices + +From: Dan Williams + +commit c192c8e71a2ded01170c1a992cd21aaedc822756 upstream. + +Gobi 1000 devices have a different port layout, which wasn't respected +by the current driver, and thus it grabbed the QMI/net port. In the +near future we'll be attaching another driver to the QMI/net port for +these devices (cdc-wdm and qmi_wwan) so make sure the qcserial driver +doesn't claim them. This patch also prevents qcserial from binding to +interfaces 0 and 1 on 1K devices because those interfaces do not +respond. + +Signed-off-by: Dan Williams +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/qcserial.c | 105 ++++++++++++++++++++++++------------------ + 1 file changed, 62 insertions(+), 43 deletions(-) + +--- a/drivers/usb/serial/qcserial.c ++++ b/drivers/usb/serial/qcserial.c +@@ -24,39 +24,44 @@ + + static bool debug; + ++#define DEVICE_G1K(v, p) \ ++ USB_DEVICE(v, p), .driver_info = 1 ++ + static const struct usb_device_id id_table[] = { +- {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ +- {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ +- {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ +- {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ +- {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ +- {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ +- {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ +- {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ +- {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */ +- {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ +- {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ +- {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi QDL device */ +- {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi QDL device */ +- {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi QDL device */ +- {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi QDL device */ +- {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi QDL device */ +- {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ +- {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ +- {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ +- {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */ +- {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */ +- {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ +- {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ +- {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ +- {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ +- {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ +- {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ +- {USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ +- {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ +- {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ +- {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ +- {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ ++ /* Gobi 1000 devices */ ++ {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ ++ {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ ++ {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ ++ {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ ++ {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ ++ {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ ++ {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */ ++ {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */ ++ {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ ++ {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ ++ {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ ++ {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ ++ {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ ++ {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */ ++ {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */ ++ {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ ++ {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ ++ {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ ++ {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ ++ {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ ++ {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ ++ {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ ++ {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ ++ {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ ++ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ ++ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ ++ ++ /* Gobi 2000 devices */ ++ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ ++ {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */ ++ {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */ ++ {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */ ++ {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */ + {USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ + {USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */ +@@ -92,6 +97,8 @@ static const struct usb_device_id id_tab + {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */ + {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ + ++ /* Gobi 3000 devices */ ++ {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */ + {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */ + {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */ + {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */ +@@ -122,8 +129,10 @@ static int qcprobe(struct usb_serial *se + int retval = -ENODEV; + __u8 nintf; + __u8 ifnum; ++ bool is_gobi1k = id->driver_info ? true : false; + + dbg("%s", __func__); ++ dbg("Is Gobi 1000 = %d", is_gobi1k); + + nintf = serial->dev->actconfig->desc.bNumInterfaces; + dbg("Num Interfaces = %d", nintf); +@@ -169,15 +178,25 @@ static int qcprobe(struct usb_serial *se + + case 3: + case 4: +- /* Composite mode */ +- /* ifnum == 0 is a broadband network adapter */ +- if (ifnum == 1) { +- /* +- * Diagnostics Monitor (serial line 9600 8N1) +- * Qualcomm DM protocol +- * use "libqcdm" (ModemManager) for communication +- */ +- dbg("Diagnostics Monitor found"); ++ /* Composite mode; don't bind to the QMI/net interface as that ++ * gets handled by other drivers. ++ */ ++ ++ /* Gobi 1K USB layout: ++ * 0: serial port (doesn't respond) ++ * 1: serial port (doesn't respond) ++ * 2: AT-capable modem port ++ * 3: QMI/net ++ * ++ * Gobi 2K+ USB layout: ++ * 0: QMI/net ++ * 1: DM/DIAG (use libqcdm from ModemManager for communication) ++ * 2: AT-capable modem port ++ * 3: NMEA ++ */ ++ ++ if (ifnum == 1 && !is_gobi1k) { ++ dbg("Gobi 2K+ DM/DIAG interface found"); + retval = usb_set_interface(serial->dev, ifnum, 0); + if (retval < 0) { + dev_err(&serial->dev->dev, +@@ -196,13 +215,13 @@ static int qcprobe(struct usb_serial *se + retval = -ENODEV; + kfree(data); + } +- } else if (ifnum==3) { ++ } else if (ifnum==3 && !is_gobi1k) { + /* + * NMEA (serial line 9600 8N1) + * # echo "\$GPS_START" > /dev/ttyUSBx + * # echo "\$GPS_STOP" > /dev/ttyUSBx + */ +- dbg("NMEA GPS interface found"); ++ dbg("Gobi 2K+ NMEA GPS interface found"); + retval = usb_set_interface(serial->dev, ifnum, 0); + if (retval < 0) { + dev_err(&serial->dev->dev, diff --git a/queue-3.3/usb-serial-add-support-for-the-sealevel-sealink-8-2038-rohs-device.patch b/queue-3.3/usb-serial-add-support-for-the-sealevel-sealink-8-2038-rohs-device.patch new file mode 100644 index 00000000000..f2a0926dea9 --- /dev/null +++ b/queue-3.3/usb-serial-add-support-for-the-sealevel-sealink-8-2038-rohs-device.patch @@ -0,0 +1,46 @@ +From 6d161b99f875269ad4ffa44375e1e54bca6fd02e Mon Sep 17 00:00:00 2001 +From: Scott Dial +Date: Fri, 24 Feb 2012 19:04:09 -0500 +Subject: usb-serial: Add support for the Sealevel SeaLINK+8 2038-ROHS device + +From: Scott Dial + +commit 6d161b99f875269ad4ffa44375e1e54bca6fd02e upstream. + +This patch adds new device IDs to the ftdi_sio module to support +the new Sealevel SeaLINK+8 2038-ROHS device. + +Signed-off-by: Scott Dial +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ftdi_sio.c | 4 ++++ + drivers/usb/serial/ftdi_sio_ids.h | 4 ++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -537,6 +537,10 @@ static struct usb_device_id id_table_com + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, ++ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) }, ++ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) }, ++ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) }, ++ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) }, + { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, + { USB_DEVICE(OCT_VID, OCT_US101_PID) }, + { USB_DEVICE(OCT_VID, OCT_DK201_PID) }, +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -689,6 +689,10 @@ + #define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ + #define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ + #define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ ++#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */ ++#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */ ++#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */ ++#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */ + + /* + * JETI SPECTROMETER SPECBOS 1201 diff --git a/queue-3.3/usb-serial-mos7840-fixed-mcs7820-device-attach-problem.patch b/queue-3.3/usb-serial-mos7840-fixed-mcs7820-device-attach-problem.patch new file mode 100644 index 00000000000..d482449535e --- /dev/null +++ b/queue-3.3/usb-serial-mos7840-fixed-mcs7820-device-attach-problem.patch @@ -0,0 +1,144 @@ +From 093ea2d3a766cb8a4c4de57efec6c0a127a58792 Mon Sep 17 00:00:00 2001 +From: Donald Lee +Date: Wed, 14 Mar 2012 15:26:33 +0800 +Subject: USB: serial: mos7840: Fixed MCS7820 device attach problem + +From: Donald Lee + +commit 093ea2d3a766cb8a4c4de57efec6c0a127a58792 upstream. + +A MCS7820 device supports two serial ports and a MCS7840 device supports +four serial ports. Both devices use the same driver, but the attach function +in driver was unable to correctly handle the port numbers for MCS7820 +device. This problem has been fixed in this patch and this fix has been +verified on x86 Linux kernel 3.2.9 with both MCS7820 and MCS7840 devices. + +Signed-off-by: Donald Lee +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7840.c | 81 +++++++++++++++++++++++++++++-------------- + 1 file changed, 56 insertions(+), 25 deletions(-) + +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -174,6 +174,7 @@ + + #define CLK_MULTI_REGISTER ((__u16)(0x02)) + #define CLK_START_VALUE_REGISTER ((__u16)(0x03)) ++#define GPIO_REGISTER ((__u16)(0x07)) + + #define SERIAL_LCR_DLAB ((__u16)(0x0080)) + +@@ -1101,14 +1102,25 @@ static int mos7840_open(struct tty_struc + mos7840_port->read_urb = port->read_urb; + + /* set up our bulk in urb */ +- +- usb_fill_bulk_urb(mos7840_port->read_urb, +- serial->dev, +- usb_rcvbulkpipe(serial->dev, +- port->bulk_in_endpointAddress), +- port->bulk_in_buffer, +- mos7840_port->read_urb->transfer_buffer_length, +- mos7840_bulk_in_callback, mos7840_port); ++ if ((serial->num_ports == 2) ++ && ((((__u16)port->number - ++ (__u16)(port->serial->minor)) % 2) != 0)) { ++ usb_fill_bulk_urb(mos7840_port->read_urb, ++ serial->dev, ++ usb_rcvbulkpipe(serial->dev, ++ (port->bulk_in_endpointAddress) + 2), ++ port->bulk_in_buffer, ++ mos7840_port->read_urb->transfer_buffer_length, ++ mos7840_bulk_in_callback, mos7840_port); ++ } else { ++ usb_fill_bulk_urb(mos7840_port->read_urb, ++ serial->dev, ++ usb_rcvbulkpipe(serial->dev, ++ port->bulk_in_endpointAddress), ++ port->bulk_in_buffer, ++ mos7840_port->read_urb->transfer_buffer_length, ++ mos7840_bulk_in_callback, mos7840_port); ++ } + + dbg("mos7840_open: bulkin endpoint is %d", + port->bulk_in_endpointAddress); +@@ -1519,13 +1531,25 @@ static int mos7840_write(struct tty_stru + memcpy(urb->transfer_buffer, current_position, transfer_size); + + /* fill urb with data and submit */ +- usb_fill_bulk_urb(urb, +- serial->dev, +- usb_sndbulkpipe(serial->dev, +- port->bulk_out_endpointAddress), +- urb->transfer_buffer, +- transfer_size, +- mos7840_bulk_out_data_callback, mos7840_port); ++ if ((serial->num_ports == 2) ++ && ((((__u16)port->number - ++ (__u16)(port->serial->minor)) % 2) != 0)) { ++ usb_fill_bulk_urb(urb, ++ serial->dev, ++ usb_sndbulkpipe(serial->dev, ++ (port->bulk_out_endpointAddress) + 2), ++ urb->transfer_buffer, ++ transfer_size, ++ mos7840_bulk_out_data_callback, mos7840_port); ++ } else { ++ usb_fill_bulk_urb(urb, ++ serial->dev, ++ usb_sndbulkpipe(serial->dev, ++ port->bulk_out_endpointAddress), ++ urb->transfer_buffer, ++ transfer_size, ++ mos7840_bulk_out_data_callback, mos7840_port); ++ } + + data1 = urb->transfer_buffer; + dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); +@@ -1838,7 +1862,7 @@ static int mos7840_send_cmd_write_baud_r + + } else { + #ifdef HW_flow_control +- / *setting h/w flow control bit to 0 */ ++ /* setting h/w flow control bit to 0 */ + Data = 0xb; + mos7840_port->shadowMCR = Data; + status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, +@@ -2305,19 +2329,26 @@ static int mos7840_ioctl(struct tty_stru + + static int mos7840_calc_num_ports(struct usb_serial *serial) + { +- int mos7840_num_ports = 0; ++ __u16 Data = 0x00; ++ int ret = 0; ++ int mos7840_num_ports; + +- dbg("numberofendpoints: cur %d, alt %d", +- (int)serial->interface->cur_altsetting->desc.bNumEndpoints, +- (int)serial->interface->altsetting->desc.bNumEndpoints); +- if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) { +- mos7840_num_ports = serial->num_ports = 2; +- } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) { ++ ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), ++ MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data, ++ VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); ++ ++ if ((Data & 0x01) == 0) { ++ mos7840_num_ports = 2; ++ serial->num_bulk_in = 2; ++ serial->num_bulk_out = 2; ++ serial->num_ports = 2; ++ } else { ++ mos7840_num_ports = 4; + serial->num_bulk_in = 4; + serial->num_bulk_out = 4; +- mos7840_num_ports = serial->num_ports = 4; ++ serial->num_ports = 4; + } +- dbg ("mos7840_num_ports = %d", mos7840_num_ports); ++ + return mos7840_num_ports; + } + diff --git a/queue-3.3/x86-ioapic-add-register-level-checks-to-detect-bogus-io-apic-entries.patch b/queue-3.3/x86-ioapic-add-register-level-checks-to-detect-bogus-io-apic-entries.patch new file mode 100644 index 00000000000..51aaf687837 --- /dev/null +++ b/queue-3.3/x86-ioapic-add-register-level-checks-to-detect-bogus-io-apic-entries.patch @@ -0,0 +1,110 @@ +From 73d63d038ee9f769f5e5b46792d227fe20e442c5 Mon Sep 17 00:00:00 2001 +From: Suresh Siddha +Date: Mon, 12 Mar 2012 11:36:33 -0700 +Subject: x86/ioapic: Add register level checks to detect bogus io-apic entries +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Suresh Siddha + +commit 73d63d038ee9f769f5e5b46792d227fe20e442c5 upstream. + +With the recent changes to clear_IO_APIC_pin() which tries to +clear remoteIRR bit explicitly, some of the users started to see +"Unable to reset IRR for apic .." messages. + +Close look shows that these are related to bogus IO-APIC entries +which return's all 1's for their io-apic registers. And the +above mentioned error messages are benign. But kernel should +have ignored such io-apic's in the first place. + +Check if register 0, 1, 2 of the listed io-apic are all 1's and +ignore such io-apic. + +Reported-by: Álvaro Castillo +Tested-by: Jon Dufresne +Signed-off-by: Suresh Siddha +Cc: yinghai@kernel.org +Cc: kernel-team@fedoraproject.org +Cc: Josh Boyer +Link: http://lkml.kernel.org/r/1331577393.31585.94.camel@sbsiddha-desk.sc.intel.com +[ Performed minor cleanup of affected code. ] +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/apic/io_apic.c | 40 ++++++++++++++++++++++++++++++++-------- + 1 file changed, 32 insertions(+), 8 deletions(-) + +--- a/arch/x86/kernel/apic/io_apic.c ++++ b/arch/x86/kernel/apic/io_apic.c +@@ -3967,18 +3967,36 @@ int mp_find_ioapic_pin(int ioapic, u32 g + static __init int bad_ioapic(unsigned long address) + { + if (nr_ioapics >= MAX_IO_APICS) { +- printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded " +- "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics); ++ pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n", ++ MAX_IO_APICS, nr_ioapics); + return 1; + } + if (!address) { +- printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address" +- " found in table, skipping!\n"); ++ pr_warn("WARNING: Bogus (zero) I/O APIC address found in table, skipping!\n"); + return 1; + } + return 0; + } + ++static __init int bad_ioapic_register(int idx) ++{ ++ union IO_APIC_reg_00 reg_00; ++ union IO_APIC_reg_01 reg_01; ++ union IO_APIC_reg_02 reg_02; ++ ++ reg_00.raw = io_apic_read(idx, 0); ++ reg_01.raw = io_apic_read(idx, 1); ++ reg_02.raw = io_apic_read(idx, 2); ++ ++ if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) { ++ pr_warn("I/O APIC 0x%x registers return all ones, skipping!\n", ++ mpc_ioapic_addr(idx)); ++ return 1; ++ } ++ ++ return 0; ++} ++ + void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) + { + int idx = 0; +@@ -3995,6 +4013,12 @@ void __init mp_register_ioapic(int id, u + ioapics[idx].mp_config.apicaddr = address; + + set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); ++ ++ if (bad_ioapic_register(idx)) { ++ clear_fixmap(FIX_IO_APIC_BASE_0 + idx); ++ return; ++ } ++ + ioapics[idx].mp_config.apicid = io_apic_unique_id(id); + ioapics[idx].mp_config.apicver = io_apic_get_version(idx); + +@@ -4015,10 +4039,10 @@ void __init mp_register_ioapic(int id, u + if (gsi_cfg->gsi_end >= gsi_top) + gsi_top = gsi_cfg->gsi_end + 1; + +- printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " +- "GSI %d-%d\n", idx, mpc_ioapic_id(idx), +- mpc_ioapic_ver(idx), mpc_ioapic_addr(idx), +- gsi_cfg->gsi_base, gsi_cfg->gsi_end); ++ pr_info("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, GSI %d-%d\n", ++ idx, mpc_ioapic_id(idx), ++ mpc_ioapic_ver(idx), mpc_ioapic_addr(idx), ++ gsi_cfg->gsi_base, gsi_cfg->gsi_end); + + nr_ioapics++; + }