aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2012-05-24 12:24:34 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-06-06 07:21:22 -0400
commit59c647b6266506cbbceadfabfd01168148f026c5 (patch)
tree7fc0ea93110ea25bcbb96f42253931bc59199873
parentcde5b48700bde6edc24c26d3d1bbec219e0ef2a1 (diff)
iwlwifi: allocate Tx cmd pool per device
Different transports will have different needs: New tranports need headroom for their own use before the Tx cmd. So allocate the Tx cmd pool in the transport and give it a unique name based on dev_name. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c22
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h29
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c19
5 files changed, 58 insertions, 26 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index af9de9542922..c29e6378a11d 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -1001,8 +1001,6 @@ struct iwl_priv {
1001 enum iwl_ucode_type cur_ucode; 1001 enum iwl_ucode_type cur_ucode;
1002}; /*iwl_priv */ 1002}; /*iwl_priv */
1003 1003
1004extern struct kmem_cache *iwl_tx_cmd_pool;
1005
1006static inline struct iwl_rxon_context * 1004static inline struct iwl_rxon_context *
1007iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) 1005iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
1008{ 1006{
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 441188725985..6cca1f403da3 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -2290,10 +2290,11 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
2290 2290
2291static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) 2291static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
2292{ 2292{
2293 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2293 struct ieee80211_tx_info *info; 2294 struct ieee80211_tx_info *info;
2294 2295
2295 info = IEEE80211_SKB_CB(skb); 2296 info = IEEE80211_SKB_CB(skb);
2296 kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); 2297 iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
2297 dev_kfree_skb_any(skb); 2298 dev_kfree_skb_any(skb);
2298} 2299}
2299 2300
@@ -2328,9 +2329,6 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
2328 * driver and module entry point 2329 * driver and module entry point
2329 * 2330 *
2330 *****************************************************************************/ 2331 *****************************************************************************/
2331
2332struct kmem_cache *iwl_tx_cmd_pool;
2333
2334static int __init iwl_init(void) 2332static int __init iwl_init(void)
2335{ 2333{
2336 2334
@@ -2338,29 +2336,18 @@ static int __init iwl_init(void)
2338 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); 2336 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
2339 pr_info(DRV_COPYRIGHT "\n"); 2337 pr_info(DRV_COPYRIGHT "\n");
2340 2338
2341 iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd",
2342 sizeof(struct iwl_device_cmd),
2343 sizeof(void *), 0, NULL);
2344 if (!iwl_tx_cmd_pool)
2345 return -ENOMEM;
2346
2347 ret = iwlagn_rate_control_register(); 2339 ret = iwlagn_rate_control_register();
2348 if (ret) { 2340 if (ret) {
2349 pr_err("Unable to register rate control algorithm: %d\n", ret); 2341 pr_err("Unable to register rate control algorithm: %d\n", ret);
2350 goto error_rc_register; 2342 return ret;
2351 } 2343 }
2352 2344
2353 ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops); 2345 ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops);
2354 if (ret) { 2346 if (ret) {
2355 pr_err("Unable to register op_mode: %d\n", ret); 2347 pr_err("Unable to register op_mode: %d\n", ret);
2356 goto error_opmode_register; 2348 iwlagn_rate_control_unregister();
2357 } 2349 }
2358 return ret;
2359 2350
2360error_opmode_register:
2361 iwlagn_rate_control_unregister();
2362error_rc_register:
2363 kmem_cache_destroy(iwl_tx_cmd_pool);
2364 return ret; 2351 return ret;
2365} 2352}
2366module_init(iwl_init); 2353module_init(iwl_init);
@@ -2369,6 +2356,5 @@ static void __exit iwl_exit(void)
2369{ 2356{
2370 iwl_opmode_deregister("iwldvm"); 2357 iwl_opmode_deregister("iwldvm");
2371 iwlagn_rate_control_unregister(); 2358 iwlagn_rate_control_unregister();
2372 kmem_cache_destroy(iwl_tx_cmd_pool);
2373} 2359}
2374module_exit(iwl_exit); 2360module_exit(iwl_exit);
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 7fdbd175c551..7e3bd6281551 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -295,7 +295,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
295 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 295 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
296 struct iwl_station_priv *sta_priv = NULL; 296 struct iwl_station_priv *sta_priv = NULL;
297 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; 297 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
298 struct iwl_device_cmd *dev_cmd = NULL; 298 struct iwl_device_cmd *dev_cmd;
299 struct iwl_tx_cmd *tx_cmd; 299 struct iwl_tx_cmd *tx_cmd;
300 __le16 fc; 300 __le16 fc;
301 u8 hdr_len; 301 u8 hdr_len;
@@ -377,7 +377,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
377 if (info->flags & IEEE80211_TX_CTL_AMPDU) 377 if (info->flags & IEEE80211_TX_CTL_AMPDU)
378 is_agg = true; 378 is_agg = true;
379 379
380 dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC); 380 dev_cmd = iwl_trans_alloc_tx_cmd(priv->trans);
381 381
382 if (unlikely(!dev_cmd)) 382 if (unlikely(!dev_cmd))
383 goto drop_unlock_priv; 383 goto drop_unlock_priv;
@@ -492,7 +492,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
492 492
493drop_unlock_sta: 493drop_unlock_sta:
494 if (dev_cmd) 494 if (dev_cmd)
495 kmem_cache_free(iwl_tx_cmd_pool, dev_cmd); 495 iwl_trans_free_tx_cmd(priv->trans, dev_cmd);
496 spin_unlock(&priv->sta_lock); 496 spin_unlock(&priv->sta_lock);
497drop_unlock_priv: 497drop_unlock_priv:
498 return -1; 498 return -1;
@@ -1193,8 +1193,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
1193 1193
1194 info = IEEE80211_SKB_CB(skb); 1194 info = IEEE80211_SKB_CB(skb);
1195 ctx = info->driver_data[0]; 1195 ctx = info->driver_data[0];
1196 kmem_cache_free(iwl_tx_cmd_pool, 1196 iwl_trans_free_tx_cmd(priv->trans,
1197 (info->driver_data[1])); 1197 info->driver_data[1]);
1198 1198
1199 memset(&info->status, 0, sizeof(info->status)); 1199 memset(&info->status, 0, sizeof(info->status));
1200 1200
@@ -1357,7 +1357,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1357 WARN_ON_ONCE(1); 1357 WARN_ON_ONCE(1);
1358 1358
1359 info = IEEE80211_SKB_CB(skb); 1359 info = IEEE80211_SKB_CB(skb);
1360 kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); 1360 iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
1361 1361
1362 if (freed == 1) { 1362 if (freed == 1) {
1363 /* this is the first skb we deliver in this batch */ 1363 /* this is the first skb we deliver in this batch */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 90ef0dc5f275..00efde8e5536 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -433,6 +433,11 @@ enum iwl_trans_state {
433 * @hw_id_str: a string with info about HW ID. Set during transport allocation. 433 * @hw_id_str: a string with info about HW ID. Set during transport allocation.
434 * @pm_support: set to true in start_hw if link pm is supported 434 * @pm_support: set to true in start_hw if link pm is supported
435 * @wait_command_queue: the wait_queue for SYNC host commands 435 * @wait_command_queue: the wait_queue for SYNC host commands
436 * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
437 * The user should use iwl_trans_{alloc,free}_tx_cmd.
438 * @dev_cmd_headroom: room needed for the transport's private use before the
439 * device_cmd for Tx - for internal use only
440 * The user should use iwl_trans_{alloc,free}_tx_cmd.
436 */ 441 */
437struct iwl_trans { 442struct iwl_trans {
438 const struct iwl_trans_ops *ops; 443 const struct iwl_trans_ops *ops;
@@ -450,6 +455,10 @@ struct iwl_trans {
450 455
451 wait_queue_head_t wait_command_queue; 456 wait_queue_head_t wait_command_queue;
452 457
458 /* The following fields are internal only */
459 struct kmem_cache *dev_cmd_pool;
460 size_t dev_cmd_headroom;
461
453 /* pointer to trans specific struct */ 462 /* pointer to trans specific struct */
454 /*Ensure that this pointer will always be aligned to sizeof pointer */ 463 /*Ensure that this pointer will always be aligned to sizeof pointer */
455 char trans_specific[0] __aligned(sizeof(void *)); 464 char trans_specific[0] __aligned(sizeof(void *));
@@ -525,6 +534,26 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
525 return trans->ops->send_cmd(trans, cmd); 534 return trans->ops->send_cmd(trans, cmd);
526} 535}
527 536
537static inline struct iwl_device_cmd *
538iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
539{
540 u8 *dev_cmd_ptr = kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
541
542 if (unlikely(dev_cmd_ptr == NULL))
543 return NULL;
544
545 return (struct iwl_device_cmd *)
546 (dev_cmd_ptr + trans->dev_cmd_headroom);
547}
548
549static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
550 struct iwl_device_cmd *dev_cmd)
551{
552 u8 *dev_cmd_ptr = (u8 *)dev_cmd - trans->dev_cmd_headroom;
553
554 kmem_cache_free(trans->dev_cmd_pool, dev_cmd_ptr);
555}
556
528static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, 557static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
529 struct iwl_device_cmd *dev_cmd, int queue) 558 struct iwl_device_cmd *dev_cmd, int queue)
530{ 559{
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 0f59e1f2bcac..1eabb834e32a 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1528,6 +1528,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
1528 iounmap(trans_pcie->hw_base); 1528 iounmap(trans_pcie->hw_base);
1529 pci_release_regions(trans_pcie->pci_dev); 1529 pci_release_regions(trans_pcie->pci_dev);
1530 pci_disable_device(trans_pcie->pci_dev); 1530 pci_disable_device(trans_pcie->pci_dev);
1531 kmem_cache_destroy(trans->dev_cmd_pool);
1531 1532
1532 kfree(trans); 1533 kfree(trans);
1533} 1534}
@@ -2042,6 +2043,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
2042{ 2043{
2043 struct iwl_trans_pcie *trans_pcie; 2044 struct iwl_trans_pcie *trans_pcie;
2044 struct iwl_trans *trans; 2045 struct iwl_trans *trans;
2046 char cmd_pool_name[100];
2045 u16 pci_cmd; 2047 u16 pci_cmd;
2046 int err; 2048 int err;
2047 2049
@@ -2138,8 +2140,25 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
2138 init_waitqueue_head(&trans->wait_command_queue); 2140 init_waitqueue_head(&trans->wait_command_queue);
2139 spin_lock_init(&trans->reg_lock); 2141 spin_lock_init(&trans->reg_lock);
2140 2142
2143 snprintf(cmd_pool_name, sizeof(cmd_pool_name), "iwl_cmd_pool:%s",
2144 dev_name(trans->dev));
2145
2146 trans->dev_cmd_headroom = 0;
2147 trans->dev_cmd_pool =
2148 kmem_cache_create(cmd_pool_name,
2149 sizeof(struct iwl_device_cmd)
2150 + trans->dev_cmd_headroom,
2151 sizeof(void *),
2152 SLAB_HWCACHE_ALIGN,
2153 NULL);
2154
2155 if (!trans->dev_cmd_pool)
2156 goto out_pci_disable_msi;
2157
2141 return trans; 2158 return trans;
2142 2159
2160out_pci_disable_msi:
2161 pci_disable_msi(pdev);
2143out_pci_release_regions: 2162out_pci_release_regions:
2144 pci_release_regions(pdev); 2163 pci_release_regions(pdev);
2145out_pci_disable_device: 2164out_pci_disable_device: