Commit f379fb99 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless

John W. Linville says:

====================
I present to you another batch of fixes intended for the 3.9 stream...

On the bluetooth bits, Gustavo says:

"I put together 3 fixes intended for 3.9, there are support for two
new devices and a NULL dereference fix in the SCO code."

Amitkumar Karwar fixes a command queueing race in mwifiex.

Bing Zhao provides a pair of mwifiex related to cleaning-up before
a shutdown.

Felix Fietkau provides an ath9k fix for a regression caused by an
earlier calibration fix, and another ath9k fix to avoid race conditions
that unnecessarily lead to chip resets.

Jussi Kivilinna prevents and skbuff leak in rtlwifi.

Stanislaw Gruszka corrects a length paramater for a DMA buffer mapping
operation in iwlegacy.

Please let me know if there are problems!
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9d73adf4 b9d53190
...@@ -73,9 +73,11 @@ static struct usb_device_id ath3k_table[] = { ...@@ -73,9 +73,11 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x03F0, 0x311D) }, { USB_DEVICE(0x03F0, 0x311D) },
/* Atheros AR3012 with sflash firmware*/ /* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x0036) },
{ USB_DEVICE(0x0CF3, 0x3004) }, { USB_DEVICE(0x0CF3, 0x3004) },
{ USB_DEVICE(0x0CF3, 0x3008) }, { USB_DEVICE(0x0CF3, 0x3008) },
{ USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x0CF3, 0x817a) },
{ USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x04CA, 0x3004) }, { USB_DEVICE(0x04CA, 0x3004) },
{ USB_DEVICE(0x04CA, 0x3005) }, { USB_DEVICE(0x04CA, 0x3005) },
...@@ -107,9 +109,11 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); ...@@ -107,9 +109,11 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
static struct usb_device_id ath3k_blist_tbl[] = { static struct usb_device_id ath3k_blist_tbl[] = {
/* Atheros AR3012 with sflash firmware*/ /* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
......
...@@ -131,9 +131,11 @@ static struct usb_device_id blacklist_table[] = { ...@@ -131,9 +131,11 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
/* Atheros 3012 with sflash firmware */ /* Atheros 3012 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
......
...@@ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, ...@@ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
AR_PHY_AGC_CONTROL_FLTR_CAL | AR_PHY_AGC_CONTROL_FLTR_CAL |
AR_PHY_AGC_CONTROL_PKDET_CAL; AR_PHY_AGC_CONTROL_PKDET_CAL;
/* Use chip chainmask only for calibration */
ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
if (rtt) { if (rtt) {
...@@ -1150,6 +1151,9 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, ...@@ -1150,6 +1151,9 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
ar9003_hw_rtt_disable(ah); ar9003_hw_rtt_disable(ah);
} }
/* Revert chainmask to runtime parameters */
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
/* Initialize list pointers */ /* Initialize list pointers */
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
......
...@@ -28,21 +28,21 @@ void ath_tx_complete_poll_work(struct work_struct *work) ...@@ -28,21 +28,21 @@ void ath_tx_complete_poll_work(struct work_struct *work)
int i; int i;
bool needreset = false; bool needreset = false;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) for (i = 0; i < IEEE80211_NUM_ACS; i++) {
if (ATH_TXQ_SETUP(sc, i)) { txq = sc->tx.txq_map[i];
txq = &sc->tx.txq[i];
ath_txq_lock(sc, txq); ath_txq_lock(sc, txq);
if (txq->axq_depth) { if (txq->axq_depth) {
if (txq->axq_tx_inprogress) { if (txq->axq_tx_inprogress) {
needreset = true; needreset = true;
ath_txq_unlock(sc, txq); ath_txq_unlock(sc, txq);
break; break;
} else { } else {
txq->axq_tx_inprogress = true; txq->axq_tx_inprogress = true;
}
} }
ath_txq_unlock_complete(sc, txq);
} }
ath_txq_unlock_complete(sc, txq);
}
if (needreset) { if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
......
...@@ -475,6 +475,7 @@ il3945_tx_skb(struct il_priv *il, ...@@ -475,6 +475,7 @@ il3945_tx_skb(struct il_priv *il,
dma_addr_t txcmd_phys; dma_addr_t txcmd_phys;
int txq_id = skb_get_queue_mapping(skb); int txq_id = skb_get_queue_mapping(skb);
u16 len, idx, hdr_len; u16 len, idx, hdr_len;
u16 firstlen, secondlen;
u8 id; u8 id;
u8 unicast; u8 unicast;
u8 sta_id; u8 sta_id;
...@@ -589,21 +590,22 @@ il3945_tx_skb(struct il_priv *il, ...@@ -589,21 +590,22 @@ il3945_tx_skb(struct il_priv *il,
len = len =
sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) + sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) +
hdr_len; hdr_len;
len = (len + 3) & ~3; firstlen = (len + 3) & ~3;
/* Physical address of this Tx command's header (not MAC header!), /* Physical address of this Tx command's header (not MAC header!),
* within command buffer array. */ * within command buffer array. */
txcmd_phys = txcmd_phys =
pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE); pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen,
PCI_DMA_TODEVICE);
if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys))) if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys)))
goto drop_unlock; goto drop_unlock;
/* Set up TFD's 2nd entry to point directly to remainder of skb, /* Set up TFD's 2nd entry to point directly to remainder of skb,
* if any (802.11 null frames have no payload). */ * if any (802.11 null frames have no payload). */
len = skb->len - hdr_len; secondlen = skb->len - hdr_len;
if (len) { if (secondlen > 0) {
phys_addr = phys_addr =
pci_map_single(il->pci_dev, skb->data + hdr_len, len, pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr))) if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr)))
goto drop_unlock; goto drop_unlock;
...@@ -611,12 +613,12 @@ il3945_tx_skb(struct il_priv *il, ...@@ -611,12 +613,12 @@ il3945_tx_skb(struct il_priv *il,
/* Add buffer containing Tx command and MAC(!) header to TFD's /* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */ * first entry */
il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0);
dma_unmap_addr_set(out_meta, mapping, txcmd_phys); dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
dma_unmap_len_set(out_meta, len, len); dma_unmap_len_set(out_meta, len, firstlen);
if (len) if (secondlen > 0)
il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0, il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen, 0,
U32_PAD(len)); U32_PAD(secondlen));
if (!ieee80211_has_morefrags(hdr->frame_control)) { if (!ieee80211_has_morefrags(hdr->frame_control)) {
txq->need_update = 1; txq->need_update = 1;
......
...@@ -157,6 +157,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, ...@@ -157,6 +157,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
return -1; return -1;
} }
cmd_code = le16_to_cpu(host_cmd->command);
cmd_size = le16_to_cpu(host_cmd->size);
if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
cmd_code != HostCmd_CMD_FUNC_INIT) {
dev_err(adapter->dev,
"DNLD_CMD: FW in reset state, ignore cmd %#x\n",
cmd_code);
mwifiex_complete_cmd(adapter, cmd_node);
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
return -1;
}
/* Set command sequence number */ /* Set command sequence number */
adapter->seq_num++; adapter->seq_num++;
host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
...@@ -168,9 +182,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, ...@@ -168,9 +182,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
adapter->curr_cmd = cmd_node; adapter->curr_cmd = cmd_node;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
cmd_code = le16_to_cpu(host_cmd->command);
cmd_size = le16_to_cpu(host_cmd->size);
/* Adjust skb length */ /* Adjust skb length */
if (cmd_node->cmd_skb->len > cmd_size) if (cmd_node->cmd_skb->len > cmd_size)
/* /*
...@@ -484,8 +495,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, ...@@ -484,8 +495,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
data_buf); data_buf);
if (!ret)
ret = mwifiex_wait_queue_complete(adapter);
return ret; return ret;
} }
...@@ -588,9 +597,10 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, ...@@ -588,9 +597,10 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
if (cmd_no == HostCmd_CMD_802_11_SCAN) { if (cmd_no == HostCmd_CMD_802_11_SCAN) {
mwifiex_queue_scan_cmd(priv, cmd_node); mwifiex_queue_scan_cmd(priv, cmd_node);
} else { } else {
adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
queue_work(adapter->workqueue, &adapter->main_work); queue_work(adapter->workqueue, &adapter->main_work);
if (cmd_node->wait_q_enabled)
ret = mwifiex_wait_queue_complete(adapter, cmd_node);
} }
return ret; return ret;
......
...@@ -709,6 +709,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) ...@@ -709,6 +709,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
return ret; return ret;
} }
/* cancel current command */
if (adapter->curr_cmd) {
dev_warn(adapter->dev, "curr_cmd is still in processing\n");
del_timer(&adapter->cmd_timer);
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
adapter->curr_cmd = NULL;
}
/* shut down mwifiex */ /* shut down mwifiex */
dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
......
...@@ -723,7 +723,6 @@ struct mwifiex_adapter { ...@@ -723,7 +723,6 @@ struct mwifiex_adapter {
u16 cmd_wait_q_required; u16 cmd_wait_q_required;
struct mwifiex_wait_queue cmd_wait_q; struct mwifiex_wait_queue cmd_wait_q;
u8 scan_wait_q_woken; u8 scan_wait_q_woken;
struct cmd_ctrl_node *cmd_queued;
spinlock_t queue_lock; /* lock for tx queues */ spinlock_t queue_lock; /* lock for tx queues */
struct completion fw_load; struct completion fw_load;
u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
...@@ -1018,7 +1017,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, ...@@ -1018,7 +1017,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
struct mwifiex_multicast_list *mcast_list); struct mwifiex_multicast_list *mcast_list);
int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
struct net_device *dev); struct net_device *dev);
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
struct cmd_ctrl_node *cmd_queued);
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
struct cfg80211_ssid *req_ssid); struct cfg80211_ssid *req_ssid);
int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
......
...@@ -1388,10 +1388,13 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, ...@@ -1388,10 +1388,13 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
list_del(&cmd_node->list); list_del(&cmd_node->list);
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags); flags);
adapter->cmd_queued = cmd_node;
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true); true);
queue_work(adapter->workqueue, &adapter->main_work); queue_work(adapter->workqueue, &adapter->main_work);
/* Perform internal scan synchronously */
if (!priv->scan_request)
mwifiex_wait_queue_complete(adapter, cmd_node);
} else { } else {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags); flags);
...@@ -1946,9 +1949,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv, ...@@ -1946,9 +1949,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
/* Normal scan */ /* Normal scan */
ret = mwifiex_scan_networks(priv, NULL); ret = mwifiex_scan_networks(priv, NULL);
if (!ret)
ret = mwifiex_wait_queue_complete(priv->adapter);
up(&priv->async_sem); up(&priv->async_sem);
return ret; return ret;
......
...@@ -54,16 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, ...@@ -54,16 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
* This function waits on a cmd wait queue. It also cancels the pending * This function waits on a cmd wait queue. It also cancels the pending
* request after waking up, in case of errors. * request after waking up, in case of errors.
*/ */
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
struct cmd_ctrl_node *cmd_queued)
{ {
int status; int status;
struct cmd_ctrl_node *cmd_queued;
if (!adapter->cmd_queued)
return 0;
cmd_queued = adapter->cmd_queued;
adapter->cmd_queued = NULL;
dev_dbg(adapter->dev, "cmd pending\n"); dev_dbg(adapter->dev, "cmd pending\n");
atomic_inc(&adapter->cmd_pending); atomic_inc(&adapter->cmd_pending);
......
...@@ -851,6 +851,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -851,6 +851,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
if (unlikely(!_urb)) { if (unlikely(!_urb)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Can't allocate urb. Drop skb!\n"); "Can't allocate urb. Drop skb!\n");
kfree_skb(skb);
return; return;
} }
_rtl_submit_tx_urb(hw, _urb); _rtl_submit_tx_urb(hw, _urb);
......
...@@ -359,6 +359,7 @@ static void __sco_sock_close(struct sock *sk) ...@@ -359,6 +359,7 @@ static void __sco_sock_close(struct sock *sk)
sco_chan_del(sk, ECONNRESET); sco_chan_del(sk, ECONNRESET);
break; break;
case BT_CONNECT2:
case BT_CONNECT: case BT_CONNECT:
case BT_DISCONN: case BT_DISCONN:
sco_chan_del(sk, ECONNRESET); sco_chan_del(sk, ECONNRESET);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment