aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-hcmd.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2009-10-09 05:19:45 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-27 16:48:06 -0400
commit2f301227a1ede57504694e1f64839839f5737cac (patch)
treec148ca6c3409f5f8fed4455fba3a78fe31469135 /drivers/net/wireless/iwlwifi/iwl-hcmd.c
parentae751bab9f55c3152ebf713c89a4fb6f439c2575 (diff)
iwlwifi: use paged Rx
This switches the iwlwifi driver to use paged skb from linear skb for Rx buffer. So that it relieves some Rx buffer allocation pressure for the memory subsystem. Currently iwlwifi (4K for 3945) requests 8K bytes for Rx buffer. Due to the trailing skb_shared_info in the skb->data, alloc_skb() will do the next order allocation, which is 16K bytes. This is suboptimal and more likely to fail when the system is under memory usage pressure. Switching to paged Rx skb lets us allocate the RXB directly by alloc_pages(), so that only order 1 allocation is required. It also adjusts the area spin_lock (with IRQ disabled) protected in the tasklet because tasklet guarentees to run only on one CPU and the new unprotected code can be preempted by the IRQ handler. This saves us from spawning another workqueue to make skb_linearize/__pskb_pull_tail happy (which cannot be called in hard irq context). Finally, mac80211 doesn't support paged Rx yet. So we linearize the skb for all the management frames and software decryption or defragmentation required data frames before handed to mac80211. For all the other frames, we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211 to handle them properly. Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-hcmd.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c21
1 files changed, 6 insertions, 15 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 532c8d6cd8da..22a21a1c7f49 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -103,17 +103,8 @@ EXPORT_SYMBOL(get_cmd_string);
103 103
104static void iwl_generic_cmd_callback(struct iwl_priv *priv, 104static void iwl_generic_cmd_callback(struct iwl_priv *priv,
105 struct iwl_device_cmd *cmd, 105 struct iwl_device_cmd *cmd,
106 struct sk_buff *skb) 106 struct iwl_rx_packet *pkt)
107{ 107{
108 struct iwl_rx_packet *pkt = NULL;
109
110 if (!skb) {
111 IWL_ERR(priv, "Error: Response NULL in %s.\n",
112 get_cmd_string(cmd->hdr.cmd));
113 return;
114 }
115
116 pkt = (struct iwl_rx_packet *)skb->data;
117 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { 108 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
118 IWL_ERR(priv, "Bad return from %s (0x%08X)\n", 109 IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
119 get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); 110 get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
@@ -215,7 +206,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
215 ret = -EIO; 206 ret = -EIO;
216 goto fail; 207 goto fail;
217 } 208 }
218 if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) { 209 if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
219 IWL_ERR(priv, "Error: Response NULL in '%s'\n", 210 IWL_ERR(priv, "Error: Response NULL in '%s'\n",
220 get_cmd_string(cmd->id)); 211 get_cmd_string(cmd->id));
221 ret = -EIO; 212 ret = -EIO;
@@ -237,9 +228,9 @@ cancel:
237 ~CMD_WANT_SKB; 228 ~CMD_WANT_SKB;
238 } 229 }
239fail: 230fail:
240 if (cmd->reply_skb) { 231 if (cmd->reply_page) {
241 dev_kfree_skb_any(cmd->reply_skb); 232 free_pages(cmd->reply_page, priv->hw_params.rx_page_order);
242 cmd->reply_skb = NULL; 233 cmd->reply_page = 0;
243 } 234 }
244out: 235out:
245 clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); 236 clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
@@ -272,7 +263,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
272 u8 id, u16 len, const void *data, 263 u8 id, u16 len, const void *data,
273 void (*callback)(struct iwl_priv *priv, 264 void (*callback)(struct iwl_priv *priv,
274 struct iwl_device_cmd *cmd, 265 struct iwl_device_cmd *cmd,
275 struct sk_buff *skb)) 266 struct iwl_rx_packet *pkt))
276{ 267{
277 struct iwl_host_cmd cmd = { 268 struct iwl_host_cmd cmd = {
278 .id = id, 269 .id = id,