diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2012-05-24 12:24:34 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-06-06 07:21:22 -0400 |
commit | 59c647b6266506cbbceadfabfd01168148f026c5 (patch) | |
tree | 7fc0ea93110ea25bcbb96f42253931bc59199873 | |
parent | cde5b48700bde6edc24c26d3d1bbec219e0ef2a1 (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.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/main.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/tx.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 29 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 19 |
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 | ||
1004 | extern struct kmem_cache *iwl_tx_cmd_pool; | ||
1005 | |||
1006 | static inline struct iwl_rxon_context * | 1004 | static inline struct iwl_rxon_context * |
1007 | iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) | 1005 | iwl_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 | ||
2291 | static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | 2291 | static 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 | |||
2332 | struct kmem_cache *iwl_tx_cmd_pool; | ||
2333 | |||
2334 | static int __init iwl_init(void) | 2332 | static 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 | ||
2360 | error_opmode_register: | ||
2361 | iwlagn_rate_control_unregister(); | ||
2362 | error_rc_register: | ||
2363 | kmem_cache_destroy(iwl_tx_cmd_pool); | ||
2364 | return ret; | 2351 | return ret; |
2365 | } | 2352 | } |
2366 | module_init(iwl_init); | 2353 | module_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 | } |
2374 | module_exit(iwl_exit); | 2360 | module_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 | ||
493 | drop_unlock_sta: | 493 | drop_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); |
497 | drop_unlock_priv: | 497 | drop_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 | */ |
437 | struct iwl_trans { | 442 | struct 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 | ||
537 | static inline struct iwl_device_cmd * | ||
538 | iwl_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 | |||
549 | static 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 | |||
528 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 557 | static 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 | ||
2160 | out_pci_disable_msi: | ||
2161 | pci_disable_msi(pdev); | ||
2143 | out_pci_release_regions: | 2162 | out_pci_release_regions: |
2144 | pci_release_regions(pdev); | 2163 | pci_release_regions(pdev); |
2145 | out_pci_disable_device: | 2164 | out_pci_disable_device: |