From: Greg Kroah-Hartman Date: Sat, 8 Mar 2014 01:02:59 +0000 (-0800) Subject: 3.4-stable patches X-Git-Tag: v3.4.83~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6f3452526bde4e7878a7e5568bc228d501f57e65;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: iwlwifi-always-copy-first-16-bytes-of-commands.patch iwlwifi-don-t-handle-masked-interrupt.patch iwlwifi-dvm-don-t-send-bt_config-on-devices-w-o-bluetooth.patch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-null.patch iwlwifi-fix-flow-handler-debug-code.patch iwlwifi-handle-dma-mapping-failures.patch iwlwifi-pcie-add-skus-for-6000-6005-and-6235-series.patch iwlwifi-protect-sram-debugfs.patch rtlwifi-fix-endian-error-in-extracting-packet-type.patch --- diff --git a/queue-3.4/iwlwifi-always-copy-first-16-bytes-of-commands.patch b/queue-3.4/iwlwifi-always-copy-first-16-bytes-of-commands.patch new file mode 100644 index 00000000000..8783310df3e --- /dev/null +++ b/queue-3.4/iwlwifi-always-copy-first-16-bytes-of-commands.patch @@ -0,0 +1,183 @@ +From wujianguo@huawei.com Fri Mar 7 16:59:24 2014 +From: Johannes Berg +Date: Thu, 27 Feb 2014 09:52:59 +0800 +Subject: iwlwifi: always copy first 16 bytes of commands +To: +Cc: , , Johannes Berg , Jianguo Wu +Message-ID: <1393465983-10548-6-git-send-email-wujianguo@huawei.com> + + +From: Johannes Berg + +commit 8a964f44e01ad3bbc208c3e80d931ba91b9ea786 upstream. + +The FH hardware will always write back to the scratch field +in commands, even host commands not just TX commands, which +can overwrite parts of the command. This is problematic if +the command is re-used (with IWL_HCMD_DFL_NOCOPY) and can +cause calibration issues. + +Address this problem by always putting at least the first +16 bytes into the buffer we also use for the command header +and therefore make the DMA engine write back into this. + +For commands that are smaller than 16 bytes also always map +enough memory for the DMA engine to write back to. + +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +[bwh: Backported to 3.2: + - Adjust context + - Drop the IWL_HCMD_DFL_DUP handling + - Fix descriptor addresses and lengths for tracepoint, but otherwise + leave it unchanged] +Signed-off-by: Ben Hutchings +[wujg: Backported to 3.4: adjust context] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 9 +++ + drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 65 +++++++++++++++++----- + 2 files changed, 62 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +@@ -209,6 +209,15 @@ struct iwl_queue { + #define TFD_TX_CMD_SLOTS 256 + #define TFD_CMD_SLOTS 32 + ++/* ++ * The FH will write back to the first TB only, so we need ++ * to copy some data into the buffer regardless of whether ++ * it should be mapped or not. This indicates how much to ++ * copy, even for HCMDs it must be big enough to fit the ++ * DRAM scratch from the TX cmd, at least 16 bytes. ++ */ ++#define IWL_HCMD_MIN_COPY_SIZE 16 ++ + struct iwl_tx_queue { + struct iwl_queue q; + struct iwl_tfd *tfds; +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +@@ -677,10 +677,12 @@ static int iwl_enqueue_hcmd(struct iwl_t + struct iwl_cmd_meta *out_meta; + dma_addr_t phys_addr; + u32 idx; +- u16 copy_size, cmd_size; ++ u16 copy_size, cmd_size, dma_size; + bool had_nocopy = false; + int i; + u8 *cmd_dest; ++ const u8 *cmddata[IWL_MAX_CMD_TFDS]; ++ u16 cmdlen[IWL_MAX_CMD_TFDS]; + #ifdef CONFIG_IWLWIFI_DEVICE_TRACING + const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {}; + int trace_lens[IWL_MAX_CMD_TFDS + 1] = {}; +@@ -699,15 +701,30 @@ static int iwl_enqueue_hcmd(struct iwl_t + BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); + + for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { ++ cmddata[i] = cmd->data[i]; ++ cmdlen[i] = cmd->len[i]; ++ + if (!cmd->len[i]) + continue; ++ ++ /* need at least IWL_HCMD_MIN_COPY_SIZE copied */ ++ if (copy_size < IWL_HCMD_MIN_COPY_SIZE) { ++ int copy = IWL_HCMD_MIN_COPY_SIZE - copy_size; ++ ++ if (copy > cmdlen[i]) ++ copy = cmdlen[i]; ++ cmdlen[i] -= copy; ++ cmddata[i] += copy; ++ copy_size += copy; ++ } ++ + if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { + had_nocopy = true; + } else { + /* NOCOPY must not be followed by normal! */ + if (WARN_ON(had_nocopy)) + return -EINVAL; +- copy_size += cmd->len[i]; ++ copy_size += cmdlen[i]; + } + cmd_size += cmd->len[i]; + } +@@ -750,13 +767,30 @@ static int iwl_enqueue_hcmd(struct iwl_t + /* and copy the data that needs to be copied */ + + cmd_dest = out_cmd->payload; ++ copy_size = sizeof(out_cmd->hdr); + for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { +- if (!cmd->len[i]) ++ int copy = 0; ++ ++ if (!cmd->len) + continue; +- if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) +- break; +- memcpy(cmd_dest, cmd->data[i], cmd->len[i]); +- cmd_dest += cmd->len[i]; ++ ++ /* need at least IWL_HCMD_MIN_COPY_SIZE copied */ ++ if (copy_size < IWL_HCMD_MIN_COPY_SIZE) { ++ copy = IWL_HCMD_MIN_COPY_SIZE - copy_size; ++ ++ if (copy > cmd->len[i]) ++ copy = cmd->len[i]; ++ } ++ ++ /* copy everything if not nocopy/dup */ ++ if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) ++ copy = cmd->len[i]; ++ ++ if (copy) { ++ memcpy(cmd_dest, cmd->data[i], copy); ++ cmd_dest += copy; ++ copy_size += copy; ++ } + } + + IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, " +@@ -766,7 +800,14 @@ static int iwl_enqueue_hcmd(struct iwl_t + le16_to_cpu(out_cmd->hdr.sequence), cmd_size, + q->write_ptr, idx, trans_pcie->cmd_queue); + +- phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, ++ /* ++ * If the entire command is smaller than IWL_HCMD_MIN_COPY_SIZE, we must ++ * still map at least that many bytes for the hardware to write back to. ++ * We have enough space, so that's not a problem. ++ */ ++ dma_size = max_t(u16, copy_size, IWL_HCMD_MIN_COPY_SIZE); ++ ++ phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, dma_size, + DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { + idx = -ENOMEM; +@@ -774,7 +815,7 @@ static int iwl_enqueue_hcmd(struct iwl_t + } + + dma_unmap_addr_set(out_meta, mapping, phys_addr); +- dma_unmap_len_set(out_meta, len, copy_size); ++ dma_unmap_len_set(out_meta, len, dma_size); + + iwlagn_txq_attach_buf_to_tfd(trans, txq, + phys_addr, copy_size, 1); +@@ -801,10 +842,10 @@ static int iwl_enqueue_hcmd(struct iwl_t + } + + iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, +- cmd->len[i], 0); ++ cmdlen[i], 0); + #ifdef CONFIG_IWLWIFI_DEVICE_TRACING +- trace_bufs[trace_idx] = cmd->data[i]; +- trace_lens[trace_idx] = cmd->len[i]; ++ trace_bufs[trace_idx] = cmddata[i]; ++ trace_lens[trace_idx] = cmdlen[i]; + trace_idx++; + #endif + } diff --git a/queue-3.4/iwlwifi-don-t-handle-masked-interrupt.patch b/queue-3.4/iwlwifi-don-t-handle-masked-interrupt.patch new file mode 100644 index 00000000000..a1ae08f9987 --- /dev/null +++ b/queue-3.4/iwlwifi-don-t-handle-masked-interrupt.patch @@ -0,0 +1,84 @@ +From wujianguo@huawei.com Fri Mar 7 16:58:50 2014 +From: Emmanuel Grumbach +Date: Thu, 27 Feb 2014 09:52:57 +0800 +Subject: iwlwifi: don't handle masked interrupt +To: +Cc: , , Emmanuel Grumbach , Jianguo Wu +Message-ID: <1393465983-10548-4-git-send-email-wujianguo@huawei.com> + + +From: Emmanuel Grumbach + +commit 25a172655f837bdb032e451f95441bb4acec51bb upstream. + +This can lead to a panic if the driver isn't ready to +handle them. Since our interrupt line is shared, we can get +an interrupt at any time (and CONFIG_DEBUG_SHIRQ checks +that even when the interrupt is being freed). + +If the op_mode has gone away, we musn't call it. To avoid +this the transport disables the interrupts when the hw is +stopped and the op_mode is leaving. +If there is an event that would cause an interrupt the INTA +register is updated regardless of the enablement of the +interrupts: even if the interrupts are disabled, the INTA +will be changed, but the device won't issue an interrupt. +But the ISR can be called at any time, so we ought ignore +the value in the INTA otherwise we can call the op_mode +after it was freed. + +I found this bug when the op_mode_start failed, and called +iwl_trans_stop_hw(trans, true). Then I played with the +RFKILL button, and removed the module. +While removing the module, the IRQ is freed, and the ISR is +called (CONFIG_DEBUG_SHIRQ enabled). Panic. + +Signed-off-by: Emmanuel Grumbach +Reviewed-by: Gregory Greenman +Signed-off-by: Johannes Berg +[bwh: Backported to 3.2: + - Adjust context + - Pass bus(trans), not trans, to iwl_{read,write}32()] +Signed-off-by: Ben Hutchings +[wujg: Backported to 3.4: + - adjust context + - Pass trans to iwl_{read,write}32()}] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +@@ -1264,12 +1264,20 @@ static irqreturn_t iwl_isr(int irq, void + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. */ +- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ ++ inta_mask = iwl_read32(trans, CSR_INT_MASK); + iwl_write32(trans, CSR_INT_MASK, 0x00000000); + + /* Discover which interrupts are active/pending */ + inta = iwl_read32(trans, CSR_INT); + ++ if (inta & (~inta_mask)) { ++ IWL_DEBUG_ISR(trans, ++ "We got a masked interrupt (0x%08x)...Ack and ignore\n", ++ inta & (~inta_mask)); ++ iwl_write32(trans, CSR_INT, inta & (~inta_mask)); ++ inta &= inta_mask; ++ } ++ + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ +@@ -1353,7 +1361,7 @@ irqreturn_t iwl_isr_ict(int irq, void *d + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. + */ +- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ ++ inta_mask = iwl_read32(trans, CSR_INT_MASK); + iwl_write32(trans, CSR_INT_MASK, 0x00000000); + + diff --git a/queue-3.4/iwlwifi-dvm-don-t-send-bt_config-on-devices-w-o-bluetooth.patch b/queue-3.4/iwlwifi-dvm-don-t-send-bt_config-on-devices-w-o-bluetooth.patch new file mode 100644 index 00000000000..dc7c5144c88 --- /dev/null +++ b/queue-3.4/iwlwifi-dvm-don-t-send-bt_config-on-devices-w-o-bluetooth.patch @@ -0,0 +1,46 @@ +From wujianguo@huawei.com Fri Mar 7 16:59:41 2014 +From: Johannes Berg +Date: Thu, 27 Feb 2014 09:53:00 +0800 +Subject: iwlwifi: dvm: don't send BT_CONFIG on devices w/o Bluetooth +To: +Cc: , , Johannes Berg , Jianguo Wu +Message-ID: <1393465983-10548-7-git-send-email-wujianguo@huawei.com> + + +From: Johannes Berg + +commit 707aee401d2467baa785a697f40a6e2d9ee79ad5 upstream. + +The BT_CONFIG command that is sent to the device during +startup will enable BT coex unless the module parameter +turns it off, but on devices without Bluetooth this may +cause problems, as reported in Redhat BZ 885407. + +Fix this by sending the BT_CONFIG command only when the +device has Bluetooth. + +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +[bwh: Backported to 3.2: + - Adjust filename + - s/priv->lib/priv->cfg/] +Signed-off-by: Ben Hutchings +[wujg: Backported to 3.4: + - s/priv->cfg/priv->shrd->cfg/] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -680,7 +680,7 @@ int iwl_alive_start(struct iwl_priv *pri + BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); + if (ret) + return ret; +- } else { ++ } else if (priv->shrd->cfg->bt_params) { + /* + * default is 2-wire BT coexexistence support + */ diff --git a/queue-3.4/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-null.patch b/queue-3.4/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-null.patch new file mode 100644 index 00000000000..47c87c6f622 --- /dev/null +++ b/queue-3.4/iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-null.patch @@ -0,0 +1,68 @@ +From wujianguo@huawei.com Fri Mar 7 16:59:58 2014 +From: Stanislaw Gruszka +Date: Thu, 27 Feb 2014 09:53:01 +0800 +Subject: iwlwifi: dvm: fix calling ieee80211_chswitch_done() with NULL +To: +Cc: , , Stanislaw Gruszka , Jianguo Wu +Message-ID: <1393465983-10548-8-git-send-email-wujianguo@huawei.com> + + +From: Stanislaw Gruszka + +commit 9186a1fd9ed190739423db84bc344d258ef3e3d7 upstream. + +If channel switch is pending and we remove interface we can +crash like showed below due to passing NULL vif to mac80211: + +BUG: unable to handle kernel paging request at fffffffffffff8cc +IP: [] strnlen+0xd/0x40 +Call Trace: + [] string.isra.3+0x3e/0xd0 + [] vsnprintf+0x219/0x640 + [] vscnprintf+0x11/0x30 + [] vprintk_emit+0x115/0x4f0 + [] printk+0x61/0x63 + [] ieee80211_chswitch_done+0xaf/0xd0 [mac80211] + [] iwl_chswitch_done+0x34/0x40 [iwldvm] + [] iwlagn_commit_rxon+0x2a3/0xdc0 [iwldvm] + [] ? iwlagn_set_rxon_chain+0x180/0x2c0 [iwldvm] + [] iwl_set_mode+0x36/0x40 [iwldvm] + [] iwlagn_mac_remove_interface+0x8d/0x1b0 [iwldvm] + [] ieee80211_do_stop+0x29d/0x7f0 [mac80211] + +This is because we nulify ctx->vif in iwlagn_mac_remove_interface() +before calling some other functions that teardown interface. To fix +just check ctx->vif on iwl_chswitch_done(). We should not call +ieee80211_chswitch_done() as channel switch works were already canceled +by mac80211 in ieee80211_do_stop() -> ieee80211_mgd_stop(). + +Resolve: +https://bugzilla.redhat.com/show_bug.cgi?id=979581 + +Reported-by: Lukasz Jagiello +Signed-off-by: Stanislaw Gruszka +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +[bwh: Backported to 3.2: adjust context, filename] +Signed-off-by: Ben Hutchings +[wujg: Backported to 3.4: - adjust context] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-core.c ++++ b/drivers/net/wireless/iwlwifi/iwl-core.c +@@ -801,7 +801,10 @@ void iwl_chswitch_done(struct iwl_priv * + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + +- if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ++ if (!test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ++ return; ++ ++ if (ctx->vif) + ieee80211_chswitch_done(ctx->vif, is_success); + } + diff --git a/queue-3.4/iwlwifi-fix-flow-handler-debug-code.patch b/queue-3.4/iwlwifi-fix-flow-handler-debug-code.patch new file mode 100644 index 00000000000..1e9b54021cb --- /dev/null +++ b/queue-3.4/iwlwifi-fix-flow-handler-debug-code.patch @@ -0,0 +1,128 @@ +From wujianguo@huawei.com Fri Mar 7 16:58:15 2014 +From: Johannes Berg +Date: Thu, 27 Feb 2014 09:52:55 +0800 +Subject: iwlwifi: fix flow handler debug code +To: +Cc: , , Johannes Berg , Jianguo Wu +Message-ID: <1393465983-10548-2-git-send-email-wujianguo@huawei.com> + +From: Johannes Berg + +commit 94543a8d4fb302817014981489f15cb3b92ec3c2 upstream. + +iwl_dbgfs_fh_reg_read() can cause crashes and/or +BUG_ON in slub because the ifdefs are wrong, the +code in iwl_dump_fh() should use DEBUGFS, not +DEBUG to protect the buffer writing code. + +Also, while at it, clean up the arguments to the +function, some code and make it generally safer. + +Reported-by: Benjamin Herrenschmidt +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +[bwh: Backported to 3.2: adjust filenames and context] +Signed-off-by: Ben Hutchings +[wujg: Backported to 3.4: adjust context] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 - + drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 2 - + drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 27 +++++++++++----------- + 3 files changed, 16 insertions(+), 15 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +@@ -352,7 +352,7 @@ int iwl_queue_space(const struct iwl_que + ******************************************************/ + int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, + char **buf, bool display); +-int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); ++int iwl_dump_fh(struct iwl_trans *trans, char **buf); + void iwl_dump_csr(struct iwl_trans *trans); + + /***************************************************** +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +@@ -695,7 +695,7 @@ static void iwl_irq_handle_error(struct + + iwl_dump_nic_error_log(trans); + iwl_dump_csr(trans); +- iwl_dump_fh(trans, NULL, false); ++ iwl_dump_fh(trans, NULL); + iwl_dump_nic_event_log(trans, false, NULL, false); + + iwl_op_mode_nic_error(trans->op_mode); +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +@@ -1768,13 +1768,9 @@ static const char *get_fh_string(int cmd + } + } + +-int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) ++int iwl_dump_fh(struct iwl_trans *trans, char **buf) + { + int i; +-#ifdef CONFIG_IWLWIFI_DEBUG +- int pos = 0; +- size_t bufsz = 0; +-#endif + static const u32 fh_tbl[] = { + FH_RSCSR_CHNL0_STTS_WPTR_REG, + FH_RSCSR_CHNL0_RBDCB_BASE_REG, +@@ -1786,29 +1782,34 @@ int iwl_dump_fh(struct iwl_trans *trans, + FH_TSSR_TX_STATUS_REG, + FH_TSSR_TX_ERROR_REG + }; +-#ifdef CONFIG_IWLWIFI_DEBUG +- if (display) { ++ ++#ifdef CONFIG_IWLWIFI_DEBUGFS ++ if (buf) { ++ int pos = 0; ++ size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; ++ + bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + pos += scnprintf(*buf + pos, bufsz - pos, + "FH register values:\n"); +- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { ++ ++ for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) + pos += scnprintf(*buf + pos, bufsz - pos, + " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(trans, fh_tbl[i])); +- } ++ + return pos; + } + #endif + IWL_ERR(trans, "FH register values:\n"); +- for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { ++ for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) + IWL_ERR(trans, " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(trans, fh_tbl[i])); +- } ++ + return 0; + } + +@@ -2152,11 +2153,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(str + size_t count, loff_t *ppos) + { + struct iwl_trans *trans = file->private_data; +- char *buf; ++ char *buf = NULL; + int pos = 0; + ssize_t ret = -EFAULT; + +- ret = pos = iwl_dump_fh(trans, &buf, true); ++ ret = pos = iwl_dump_fh(trans, &buf); + if (buf) { + ret = simple_read_from_buffer(user_buf, + count, ppos, buf, pos); diff --git a/queue-3.4/iwlwifi-handle-dma-mapping-failures.patch b/queue-3.4/iwlwifi-handle-dma-mapping-failures.patch new file mode 100644 index 00000000000..e4b417cdabd --- /dev/null +++ b/queue-3.4/iwlwifi-handle-dma-mapping-failures.patch @@ -0,0 +1,75 @@ +From wujianguo@huawei.com Fri Mar 7 16:59:06 2014 +From: Johannes Berg +Date: Thu, 27 Feb 2014 09:52:58 +0800 +Subject: iwlwifi: handle DMA mapping failures +To: +Cc: , , Johannes Berg , Jianguo Wu +Message-ID: <1393465983-10548-5-git-send-email-wujianguo@huawei.com> + + +From: Johannes Berg + +commit 7c34158231b2eda8dcbd297be2bb1559e69cb433 upstream. + +The RX replenish code doesn't handle DMA mapping failures, +which will cause issues if there actually is a failure. This +was reported by Shuah Khan who found a DMA mapping framework +warning ("device driver failed to check map error"). + +Reported-by: Shuah Khan +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +[bwh: Backported to 3.2: + - Adjust filename, context, indentation + - Use bus(trans) instead of trans where necessary + - Use hw_params(trans).rx_page_order instead of trans_pcie->rx_page_order] +Signed-off-by: Ben Hutchings +[wujg: Backported to 3.4: + - Adjust context + - Use trans instead of bus(trans) + - Use hw_params(trans).rx_page_order instead of trans_pcie->rx_page_order] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +@@ -315,6 +315,14 @@ static void iwlagn_rx_allocate(struct iw + rxb->page_dma = dma_map_page(trans->dev, page, 0, + PAGE_SIZE << hw_params(trans).rx_page_order, + DMA_FROM_DEVICE); ++ if (dma_mapping_error(trans->dev, rxb->page_dma)) { ++ rxb->page = NULL; ++ spin_lock_irqsave(&rxq->lock, flags); ++ list_add(&rxb->list, &rxq->rx_used); ++ spin_unlock_irqrestore(&rxq->lock, flags); ++ __free_pages(page, hw_params(trans).rx_page_order); ++ return; ++ } + /* dma address must be no more than 36 bits */ + BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); + /* and also 256 byte aligned! */ +@@ -450,8 +458,19 @@ static void iwl_rx_handle_rxbuf(struct i + dma_map_page(trans->dev, rxb->page, 0, + PAGE_SIZE << hw_params(trans).rx_page_order, + DMA_FROM_DEVICE); +- list_add_tail(&rxb->list, &rxq->rx_free); +- rxq->free_count++; ++ if (dma_mapping_error(trans->dev, rxb->page_dma)) { ++ /* ++ * free the page(s) as well to not break ++ * the invariant that the items on the used ++ * list have no page(s) ++ */ ++ __free_pages(rxb->page, hw_params(trans).rx_page_order); ++ rxb->page = NULL; ++ list_add_tail(&rxb->list, &rxq->rx_used); ++ } else { ++ list_add_tail(&rxb->list, &rxq->rx_free); ++ rxq->free_count++; ++ } + } else + list_add_tail(&rxb->list, &rxq->rx_used); + spin_unlock_irqrestore(&rxq->lock, flags); diff --git a/queue-3.4/iwlwifi-pcie-add-skus-for-6000-6005-and-6235-series.patch b/queue-3.4/iwlwifi-pcie-add-skus-for-6000-6005-and-6235-series.patch new file mode 100644 index 00000000000..462d39d5b82 --- /dev/null +++ b/queue-3.4/iwlwifi-pcie-add-skus-for-6000-6005-and-6235-series.patch @@ -0,0 +1,105 @@ +From wujianguo@huawei.com Fri Mar 7 17:00:20 2014 +From: Emmanuel Grumbach +Date: Thu, 27 Feb 2014 09:53:02 +0800 +Subject: iwlwifi: pcie: add SKUs for 6000, 6005 and 6235 series +To: +Cc: , , Emmanuel Grumbach , Jianguo Wu +Message-ID: <1393465983-10548-9-git-send-email-wujianguo@huawei.com> + + +From: Emmanuel Grumbach + +commit 08a5dd3842f2ac61c6d69661d2d96022df8ae359 upstream. + +Add some new PCI IDs to the table for 6000, 6005 and 6235 series. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +[bwh: Backported to 3.2: + - Adjust filenames + - Drop const from struct iwl_cfg] +Signed-off-by: Ben Hutchings +[wujg: Backported to 3.4: + - Adjust context + - Do not drop const from struct iwl_cfg] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ++++++ + drivers/net/wireless/iwlwifi/iwl-cfg.h | 1 + + drivers/net/wireless/iwlwifi/iwl-pci.c | 10 ++++++++++ + 3 files changed, 17 insertions(+) + +--- a/drivers/net/wireless/iwlwifi/iwl-6000.c ++++ b/drivers/net/wireless/iwlwifi/iwl-6000.c +@@ -459,6 +459,12 @@ const struct iwl_cfg iwl6035_2agn_cfg = + .ht_params = &iwl6000_ht_params, + }; + ++const struct iwl_cfg iwl6035_2agn_sff_cfg = { ++ .name = "Intel(R) Centrino(R) Ultimate-N 6235 AGN", ++ IWL_DEVICE_6035, ++ .ht_params = &iwl6000_ht_params, ++}; ++ + const struct iwl_cfg iwl1030_bgn_cfg = { + .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", + IWL_DEVICE_6030, +--- a/drivers/net/wireless/iwlwifi/iwl-cfg.h ++++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h +@@ -106,6 +106,7 @@ extern const struct iwl_cfg iwl2000_2bgn + extern const struct iwl_cfg iwl2000_2bgn_d_cfg; + extern const struct iwl_cfg iwl2030_2bgn_cfg; + extern const struct iwl_cfg iwl6035_2agn_cfg; ++extern const struct iwl_cfg iwl6035_2agn_sff_cfg; + extern const struct iwl_cfg iwl105_bgn_cfg; + extern const struct iwl_cfg iwl105_bgn_d_cfg; + extern const struct iwl_cfg iwl135_bgn_cfg; +--- a/drivers/net/wireless/iwlwifi/iwl-pci.c ++++ b/drivers/net/wireless/iwlwifi/iwl-pci.c +@@ -138,13 +138,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca + + /* 6x00 Series */ + {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, ++ {IWL_PCI_DEVICE(0x422B, 0x1108, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)}, ++ {IWL_PCI_DEVICE(0x422B, 0x1128, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)}, + {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)}, + {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)}, + {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)}, + {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)}, + {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, ++ {IWL_PCI_DEVICE(0x4238, 0x1118, iwl6000_3agn_cfg)}, + {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, + {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, + +@@ -152,12 +155,16 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca + {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)}, ++ {IWL_PCI_DEVICE(0x0082, 0x1308, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, ++ {IWL_PCI_DEVICE(0x0082, 0x1328, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, ++ {IWL_PCI_DEVICE(0x0085, 0x1318, iwl6005_2agn_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)}, + {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)}, ++ {IWL_PCI_DEVICE(0x0085, 0xC228, iwl6005_2agn_sff_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_2agn_d_cfg)}, + {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_mow1_cfg)},/* low 5GHz active */ + {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_mow2_cfg)},/* high 5GHz active */ +@@ -239,8 +246,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_ca + + /* 6x35 Series */ + {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)}, ++ {IWL_PCI_DEVICE(0x088E, 0x406A, iwl6035_2agn_sff_cfg)}, + {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, ++ {IWL_PCI_DEVICE(0x088F, 0x426A, iwl6035_2agn_sff_cfg)}, + {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, ++ {IWL_PCI_DEVICE(0x088E, 0x446A, iwl6035_2agn_sff_cfg)}, + {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)}, + + /* 105 Series */ diff --git a/queue-3.4/iwlwifi-protect-sram-debugfs.patch b/queue-3.4/iwlwifi-protect-sram-debugfs.patch new file mode 100644 index 00000000000..d56c18c6245 --- /dev/null +++ b/queue-3.4/iwlwifi-protect-sram-debugfs.patch @@ -0,0 +1,38 @@ +From wujianguo@huawei.com Fri Mar 7 16:58:32 2014 +From: Johannes Berg +Date: Thu, 27 Feb 2014 09:52:56 +0800 +Subject: iwlwifi: protect SRAM debugfs +To: +Cc: , , Johannes Berg , Jianguo Wu +Message-ID: <1393465983-10548-3-git-send-email-wujianguo@huawei.com> + + +From: Johannes Berg + +commit 4fc79db178f0a0ede479b4713e00df2d106028b3 upstream. + +If the device is not started, we can't read its +SRAM and attempting to do so will cause issues. +Protect the debugfs read. + +Signed-off-by: Johannes Berg +Signed-off-by: John W. Linville +[wujg: Backported to 3.4: adjust context] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c ++++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c +@@ -227,6 +227,9 @@ static ssize_t iwl_dbgfs_sram_read(struc + const struct fw_img *img; + size_t bufsz; + ++ if (!iwl_is_ready_rf(priv)) ++ return -EAGAIN; ++ + /* default is to dump the entire data segment */ + if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { + priv->dbgfs_sram_offset = 0x800000; diff --git a/queue-3.4/rtlwifi-fix-endian-error-in-extracting-packet-type.patch b/queue-3.4/rtlwifi-fix-endian-error-in-extracting-packet-type.patch new file mode 100644 index 00000000000..ec08ef81717 --- /dev/null +++ b/queue-3.4/rtlwifi-fix-endian-error-in-extracting-packet-type.patch @@ -0,0 +1,167 @@ +From wujianguo@huawei.com Fri Mar 7 17:00:39 2014 +From: Mark Cave-Ayland +Date: Thu, 27 Feb 2014 09:53:03 +0800 +Subject: rtlwifi: Fix endian error in extracting packet type +To: +Cc: , , Mark Cave-Ayland , Jianguo Wu +Message-ID: <1393465983-10548-10-git-send-email-wujianguo@huawei.com> + + +From: Mark Cave-Ayland + +commit 0c5d63f0ab6728f05ddefa25aff55e31297f95e6 upstream. + +All of the rtlwifi drivers have an error in the routine that tests if +the data is "special". If it is, the subsequant transmission will be +at the lowest rate to enhance reliability. The 16-bit quantity is +big-endian, but was being extracted in native CPU mode. One of the +effects of this bug is to inhibit association under some conditions +as the TX rate is too high. + +Based on suggestions by Joe Perches, the entire routine is rewritten. + +One of the local headers contained duplicates of some of the ETH_P_XXX +definitions. These are deleted. + +Signed-off-by: Larry Finger +Cc: Mark Cave-Ayland +Signed-off-by: John W. Linville +[wujg: Backported to 3.4: + - adjust context + - remove rtlpriv->enter_ps = false + - use schedule_work(&rtlpriv->works.lps_leave_work)] +Signed-off-by: Jianguo Wu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/rtlwifi/base.c | 93 ++++++++++++++++-------------------- + drivers/net/wireless/rtlwifi/wifi.h | 6 -- + 2 files changed, 43 insertions(+), 56 deletions(-) + +--- a/drivers/net/wireless/rtlwifi/base.c ++++ b/drivers/net/wireless/rtlwifi/base.c +@@ -37,6 +37,7 @@ + + #include + #include ++#include + + /* + *NOTICE!!!: This file will be very big, we should +@@ -957,61 +958,51 @@ u8 rtl_is_special_data(struct ieee80211_ + if (!ieee80211_is_data(fc)) + return false; + ++ ip = (const struct iphdr *)(skb->data + mac_hdr_len + ++ SNAP_SIZE + PROTOC_TYPE_SIZE); ++ ether_type = be16_to_cpup((__be16 *) ++ (skb->data + mac_hdr_len + SNAP_SIZE)); ++ ++ switch (ether_type) { ++ case ETH_P_IP: { ++ struct udphdr *udp; ++ u16 src; ++ u16 dst; ++ ++ if (ip->protocol != IPPROTO_UDP) ++ return false; ++ udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); ++ src = be16_to_cpu(udp->source); ++ dst = be16_to_cpu(udp->dest); ++ ++ /* If this case involves port 68 (UDP BOOTP client) connecting ++ * with port 67 (UDP BOOTP server), then return true so that ++ * the lowest speed is used. ++ */ ++ if (!((src == 68 && dst == 67) || (src == 67 && dst == 68))) ++ return false; + +- ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + +- SNAP_SIZE + PROTOC_TYPE_SIZE); +- ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); +- /* ether_type = ntohs(ether_type); */ +- +- if (ETH_P_IP == ether_type) { +- if (IPPROTO_UDP == ip->protocol) { +- struct udphdr *udp = (struct udphdr *)((u8 *) ip + +- (ip->ihl << 2)); +- if (((((u8 *) udp)[1] == 68) && +- (((u8 *) udp)[3] == 67)) || +- ((((u8 *) udp)[1] == 67) && +- (((u8 *) udp)[3] == 68))) { +- /* +- * 68 : UDP BOOTP client +- * 67 : UDP BOOTP server +- */ +- RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), +- DBG_DMESG, "dhcp %s !!\n", +- is_tx ? "Tx" : "Rx"); +- +- if (is_tx) { +- schedule_work(&rtlpriv-> +- works.lps_leave_work); +- ppsc->last_delaylps_stamp_jiffies = +- jiffies; +- } +- +- return true; +- } +- } +- } else if (ETH_P_ARP == ether_type) { +- if (is_tx) { +- schedule_work(&rtlpriv->works.lps_leave_work); +- ppsc->last_delaylps_stamp_jiffies = jiffies; +- } +- +- return true; +- } else if (ETH_P_PAE == ether_type) { ++ RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, ++ "dhcp %s !!\n", is_tx ? "Tx" : "Rx"); ++ break; ++ } ++ case ETH_P_ARP: ++ break; ++ case ETH_P_PAE: + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); +- +- if (is_tx) { +- schedule_work(&rtlpriv->works.lps_leave_work); +- ppsc->last_delaylps_stamp_jiffies = jiffies; +- } +- +- return true; +- } else if (ETH_P_IPV6 == ether_type) { +- /* IPv6 */ +- return true; ++ break; ++ case ETH_P_IPV6: ++ /* TODO: Is this right? */ ++ return false; ++ default: ++ return false; + } +- +- return false; ++ if (is_tx) { ++ schedule_work(&rtlpriv->works.lps_leave_work); ++ ppsc->last_delaylps_stamp_jiffies = jiffies; ++ } ++ return true; + } + + /********************************************************* +--- a/drivers/net/wireless/rtlwifi/wifi.h ++++ b/drivers/net/wireless/rtlwifi/wifi.h +@@ -77,11 +77,7 @@ + #define RTL_SLOT_TIME_9 9 + #define RTL_SLOT_TIME_20 20 + +-/*related with tcp/ip. */ +-/*if_ehther.h*/ +-#define ETH_P_PAE 0x888E /*Port Access Entity (IEEE 802.1X) */ +-#define ETH_P_IP 0x0800 /*Internet Protocol packet */ +-#define ETH_P_ARP 0x0806 /*Address Resolution packet */ ++/*related to tcp/ip. */ + #define SNAP_SIZE 6 + #define PROTOC_TYPE_SIZE 2 + diff --git a/queue-3.4/series b/queue-3.4/series index aa59ed2f920..3416d6675f1 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -86,3 +86,12 @@ alsa-pxa2xx-fix-unlocked-snd_pcm_stop-call.patch asoc-s6000-fix-unlocked-snd_pcm_stop-call.patch staging-line6-fix-unlocked-snd_pcm_stop-call.patch alsa-asihpi-fix-unlocked-snd_pcm_stop-call.patch +iwlwifi-fix-flow-handler-debug-code.patch +iwlwifi-protect-sram-debugfs.patch +iwlwifi-don-t-handle-masked-interrupt.patch +iwlwifi-handle-dma-mapping-failures.patch +iwlwifi-always-copy-first-16-bytes-of-commands.patch +iwlwifi-dvm-don-t-send-bt_config-on-devices-w-o-bluetooth.patch +iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-null.patch +iwlwifi-pcie-add-skus-for-6000-6005-and-6235-series.patch +rtlwifi-fix-endian-error-in-extracting-packet-type.patch