aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-08-22 14:15:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-08-22 14:15:47 -0400
commit6de3f7e911d27d6737c79b3f6b5069044ea408ec (patch)
tree186dcf1897be76a4155f5a22a7f242c29f328c5a /drivers/net
parent33dd7699cefd175c3a5d3d6077db9c8d8322c9a7 (diff)
parent40503f7b48260a91ab65a4f8b00a2c6f004fa807 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/agn.h9
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/debugfs.c56
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c24
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/sta.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c141
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-op-mode.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h12
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c6
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h1
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c16
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c28
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c26
15 files changed, 241 insertions, 93 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index f0b8c1f7591c..75e12f29d9eb 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -487,16 +487,13 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
487} 487}
488 488
489#ifdef CONFIG_IWLWIFI_DEBUGFS 489#ifdef CONFIG_IWLWIFI_DEBUGFS
490int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); 490int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir);
491void iwl_dbgfs_unregister(struct iwl_priv *priv);
492#else 491#else
493static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) 492static inline int iwl_dbgfs_register(struct iwl_priv *priv,
493 struct dentry *dbgfs_dir)
494{ 494{
495 return 0; 495 return 0;
496} 496}
497static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
498{
499}
500#endif /* CONFIG_IWLWIFI_DEBUGFS */ 497#endif /* CONFIG_IWLWIFI_DEBUGFS */
501 498
502#ifdef CONFIG_IWLWIFI_DEBUG 499#ifdef CONFIG_IWLWIFI_DEBUG
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index 46782f1102ac..ce826bc5f111 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -2349,24 +2349,19 @@ DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled);
2349 * Create the debugfs files and directories 2349 * Create the debugfs files and directories
2350 * 2350 *
2351 */ 2351 */
2352int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) 2352int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
2353{ 2353{
2354 struct dentry *phyd = priv->hw->wiphy->debugfsdir; 2354 struct dentry *dir_data, *dir_rf, *dir_debug;
2355 struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
2356 2355
2357 dir_drv = debugfs_create_dir(name, phyd); 2356 priv->debugfs_dir = dbgfs_dir;
2358 if (!dir_drv)
2359 return -ENOMEM;
2360
2361 priv->debugfs_dir = dir_drv;
2362 2357
2363 dir_data = debugfs_create_dir("data", dir_drv); 2358 dir_data = debugfs_create_dir("data", dbgfs_dir);
2364 if (!dir_data) 2359 if (!dir_data)
2365 goto err; 2360 goto err;
2366 dir_rf = debugfs_create_dir("rf", dir_drv); 2361 dir_rf = debugfs_create_dir("rf", dbgfs_dir);
2367 if (!dir_rf) 2362 if (!dir_rf)
2368 goto err; 2363 goto err;
2369 dir_debug = debugfs_create_dir("debug", dir_drv); 2364 dir_debug = debugfs_create_dir("debug", dbgfs_dir);
2370 if (!dir_debug) 2365 if (!dir_debug)
2371 goto err; 2366 goto err;
2372 2367
@@ -2412,25 +2407,30 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
2412 /* Calibrations disabled/enabled status*/ 2407 /* Calibrations disabled/enabled status*/
2413 DEBUGFS_ADD_FILE(calib_disabled, dir_rf, S_IWUSR | S_IRUSR); 2408 DEBUGFS_ADD_FILE(calib_disabled, dir_rf, S_IWUSR | S_IRUSR);
2414 2409
2415 if (iwl_trans_dbgfs_register(priv->trans, dir_debug)) 2410 /*
2416 goto err; 2411 * Create a symlink with mac80211. This is not very robust, as it does
2412 * not remove the symlink created. The implicit assumption is that
2413 * when the opmode exits, mac80211 will also exit, and will remove
2414 * this symlink as part of its cleanup.
2415 */
2416 if (priv->mac80211_registered) {
2417 char buf[100];
2418 struct dentry *mac80211_dir, *dev_dir, *root_dir;
2419
2420 dev_dir = dbgfs_dir->d_parent;
2421 root_dir = dev_dir->d_parent;
2422 mac80211_dir = priv->hw->wiphy->debugfsdir;
2423
2424 snprintf(buf, 100, "../../%s/%s", root_dir->d_name.name,
2425 dev_dir->d_name.name);
2426
2427 if (!debugfs_create_symlink("iwlwifi", mac80211_dir, buf))
2428 goto err;
2429 }
2430
2417 return 0; 2431 return 0;
2418 2432
2419err: 2433err:
2420 IWL_ERR(priv, "Can't create the debugfs directory\n"); 2434 IWL_ERR(priv, "failed to create the dvm debugfs entries\n");
2421 iwl_dbgfs_unregister(priv);
2422 return -ENOMEM; 2435 return -ENOMEM;
2423} 2436}
2424
2425/**
2426 * Remove the debugfs files and directories
2427 *
2428 */
2429void iwl_dbgfs_unregister(struct iwl_priv *priv)
2430{
2431 if (!priv->debugfs_dir)
2432 return;
2433
2434 debugfs_remove_recursive(priv->debugfs_dir);
2435 priv->debugfs_dir = NULL;
2436}
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index e64af60a37c1..ff8162d4c454 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -195,7 +195,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
195 ARRAY_SIZE(iwlagn_iface_combinations_dualmode); 195 ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
196 } 196 }
197 197
198 hw->wiphy->max_remain_on_channel_duration = 1000; 198 hw->wiphy->max_remain_on_channel_duration = 500;
199 199
200 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | 200 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
201 WIPHY_FLAG_DISABLE_BEACON_HINTS | 201 WIPHY_FLAG_DISABLE_BEACON_HINTS |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 84d3db5aa506..7ff3f1430678 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -862,7 +862,8 @@ void iwl_down(struct iwl_priv *priv)
862 * No race since we hold the mutex here and a new one 862 * No race since we hold the mutex here and a new one
863 * can't come in at this time. 863 * can't come in at this time.
864 */ 864 */
865 ieee80211_remain_on_channel_expired(priv->hw); 865 if (priv->ucode_loaded && priv->cur_ucode != IWL_UCODE_INIT)
866 ieee80211_remain_on_channel_expired(priv->hw);
866 867
867 exit_pending = 868 exit_pending =
868 test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); 869 test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
@@ -994,7 +995,11 @@ static void iwl_bg_restart(struct work_struct *data)
994 iwlagn_prepare_restart(priv); 995 iwlagn_prepare_restart(priv);
995 mutex_unlock(&priv->mutex); 996 mutex_unlock(&priv->mutex);
996 iwl_cancel_deferred_work(priv); 997 iwl_cancel_deferred_work(priv);
997 ieee80211_restart_hw(priv->hw); 998 if (priv->mac80211_registered)
999 ieee80211_restart_hw(priv->hw);
1000 else
1001 IWL_ERR(priv,
1002 "Cannot request restart before registrating with mac80211");
998 } else { 1003 } else {
999 WARN_ON(1); 1004 WARN_ON(1);
1000 } 1005 }
@@ -1222,7 +1227,8 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
1222 1227
1223static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, 1228static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1224 const struct iwl_cfg *cfg, 1229 const struct iwl_cfg *cfg,
1225 const struct iwl_fw *fw) 1230 const struct iwl_fw *fw,
1231 struct dentry *dbgfs_dir)
1226{ 1232{
1227 struct iwl_priv *priv; 1233 struct iwl_priv *priv;
1228 struct ieee80211_hw *hw; 1234 struct ieee80211_hw *hw;
@@ -1466,13 +1472,17 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1466 if (iwlagn_mac_setup_register(priv, &fw->ucode_capa)) 1472 if (iwlagn_mac_setup_register(priv, &fw->ucode_capa))
1467 goto out_destroy_workqueue; 1473 goto out_destroy_workqueue;
1468 1474
1469 if (iwl_dbgfs_register(priv, DRV_NAME)) 1475 if (iwl_dbgfs_register(priv, dbgfs_dir))
1470 IWL_ERR(priv, 1476 goto out_mac80211_unregister;
1471 "failed to create debugfs files. Ignoring error\n");
1472 1477
1473 return op_mode; 1478 return op_mode;
1474 1479
1480out_mac80211_unregister:
1481 iwlagn_mac_unregister(priv);
1475out_destroy_workqueue: 1482out_destroy_workqueue:
1483 iwl_tt_exit(priv);
1484 iwl_testmode_free(priv);
1485 iwl_cancel_deferred_work(priv);
1476 destroy_workqueue(priv->workqueue); 1486 destroy_workqueue(priv->workqueue);
1477 priv->workqueue = NULL; 1487 priv->workqueue = NULL;
1478 iwl_uninit_drv(priv); 1488 iwl_uninit_drv(priv);
@@ -1493,8 +1503,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
1493 1503
1494 IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); 1504 IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
1495 1505
1496 iwl_dbgfs_unregister(priv);
1497
1498 iwl_testmode_free(priv); 1506 iwl_testmode_free(priv);
1499 iwlagn_mac_unregister(priv); 1507 iwlagn_mac_unregister(priv);
1500 1508
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c
index b29b798f7550..fe36a38f3505 100644
--- a/drivers/net/wireless/iwlwifi/dvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/dvm/sta.c
@@ -150,7 +150,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
150 sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); 150 sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : "");
151 151
152 if (!(flags & CMD_ASYNC)) { 152 if (!(flags & CMD_ASYNC)) {
153 cmd.flags |= CMD_WANT_SKB; 153 cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD;
154 might_sleep(); 154 might_sleep();
155 } 155 }
156 156
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index d17799b316d7..f5ca73a89870 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -433,7 +433,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
433 * only. Check this here. 433 * only. Check this here.
434 */ 434 */
435 if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON && 435 if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON &&
436 tid_data->agg.state != IWL_AGG_OFF, 436 tid_data->agg.state != IWL_AGG_OFF,
437 "Tx while agg.state = %d", tid_data->agg.state)) 437 "Tx while agg.state = %d", tid_data->agg.state))
438 goto drop_unlock_sta; 438 goto drop_unlock_sta;
439 439
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index cc41cfaedfbd..48d6d44c16d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -101,6 +101,10 @@ MODULE_VERSION(DRV_VERSION);
101MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); 101MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
102MODULE_LICENSE("GPL"); 102MODULE_LICENSE("GPL");
103 103
104#ifdef CONFIG_IWLWIFI_DEBUGFS
105static struct dentry *iwl_dbgfs_root;
106#endif
107
104/** 108/**
105 * struct iwl_drv - drv common data 109 * struct iwl_drv - drv common data
106 * @list: list of drv structures using this opmode 110 * @list: list of drv structures using this opmode
@@ -126,6 +130,12 @@ struct iwl_drv {
126 char firmware_name[25]; /* name of firmware file to load */ 130 char firmware_name[25]; /* name of firmware file to load */
127 131
128 struct completion request_firmware_complete; 132 struct completion request_firmware_complete;
133
134#ifdef CONFIG_IWLWIFI_DEBUGFS
135 struct dentry *dbgfs_drv;
136 struct dentry *dbgfs_trans;
137 struct dentry *dbgfs_op_mode;
138#endif
129}; 139};
130 140
131#define DVM_OP_MODE 0 141#define DVM_OP_MODE 0
@@ -194,7 +204,8 @@ static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
194 return 0; 204 return 0;
195} 205}
196 206
197static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); 207static void iwl_req_fw_callback(const struct firmware *ucode_raw,
208 void *context);
198 209
199#define UCODE_EXPERIMENTAL_INDEX 100 210#define UCODE_EXPERIMENTAL_INDEX 100
200#define UCODE_EXPERIMENTAL_TAG "exp" 211#define UCODE_EXPERIMENTAL_TAG "exp"
@@ -231,7 +242,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
231 242
232 return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name, 243 return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name,
233 drv->trans->dev, 244 drv->trans->dev,
234 GFP_KERNEL, drv, iwl_ucode_callback); 245 GFP_KERNEL, drv, iwl_req_fw_callback);
235} 246}
236 247
237struct fw_img_parsing { 248struct fw_img_parsing {
@@ -759,13 +770,57 @@ static int validate_sec_sizes(struct iwl_drv *drv,
759 return 0; 770 return 0;
760} 771}
761 772
773static struct iwl_op_mode *
774_iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
775{
776 const struct iwl_op_mode_ops *ops = op->ops;
777 struct dentry *dbgfs_dir = NULL;
778 struct iwl_op_mode *op_mode = NULL;
779
780#ifdef CONFIG_IWLWIFI_DEBUGFS
781 drv->dbgfs_op_mode = debugfs_create_dir(op->name,
782 drv->dbgfs_drv);
783 if (!drv->dbgfs_op_mode) {
784 IWL_ERR(drv,
785 "failed to create opmode debugfs directory\n");
786 return op_mode;
787 }
788 dbgfs_dir = drv->dbgfs_op_mode;
789#endif
790
791 op_mode = ops->start(drv->trans, drv->cfg, &drv->fw, dbgfs_dir);
792
793#ifdef CONFIG_IWLWIFI_DEBUGFS
794 if (!op_mode) {
795 debugfs_remove_recursive(drv->dbgfs_op_mode);
796 drv->dbgfs_op_mode = NULL;
797 }
798#endif
799
800 return op_mode;
801}
802
803static void _iwl_op_mode_stop(struct iwl_drv *drv)
804{
805 /* op_mode can be NULL if its start failed */
806 if (drv->op_mode) {
807 iwl_op_mode_stop(drv->op_mode);
808 drv->op_mode = NULL;
809
810#ifdef CONFIG_IWLWIFI_DEBUGFS
811 debugfs_remove_recursive(drv->dbgfs_op_mode);
812 drv->dbgfs_op_mode = NULL;
813#endif
814 }
815}
816
762/** 817/**
763 * iwl_ucode_callback - callback when firmware was loaded 818 * iwl_req_fw_callback - callback when firmware was loaded
764 * 819 *
765 * If loaded successfully, copies the firmware into buffers 820 * If loaded successfully, copies the firmware into buffers
766 * for the card to fetch (via DMA). 821 * for the card to fetch (via DMA).
767 */ 822 */
768static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) 823static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
769{ 824{
770 struct iwl_drv *drv = context; 825 struct iwl_drv *drv = context;
771 struct iwl_fw *fw = &drv->fw; 826 struct iwl_fw *fw = &drv->fw;
@@ -908,8 +963,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
908 list_add_tail(&drv->list, &op->drv); 963 list_add_tail(&drv->list, &op->drv);
909 964
910 if (op->ops) { 965 if (op->ops) {
911 const struct iwl_op_mode_ops *ops = op->ops; 966 drv->op_mode = _iwl_op_mode_start(drv, op);
912 drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw);
913 967
914 if (!drv->op_mode) { 968 if (!drv->op_mode) {
915 mutex_unlock(&iwlwifi_opmode_table_mtx); 969 mutex_unlock(&iwlwifi_opmode_table_mtx);
@@ -969,24 +1023,51 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
969 init_completion(&drv->request_firmware_complete); 1023 init_completion(&drv->request_firmware_complete);
970 INIT_LIST_HEAD(&drv->list); 1024 INIT_LIST_HEAD(&drv->list);
971 1025
1026#ifdef CONFIG_IWLWIFI_DEBUGFS
1027 /* Create the device debugfs entries. */
1028 drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
1029 iwl_dbgfs_root);
1030
1031 if (!drv->dbgfs_drv) {
1032 IWL_ERR(drv, "failed to create debugfs directory\n");
1033 goto err_free_drv;
1034 }
1035
1036 /* Create transport layer debugfs dir */
1037 drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv);
1038
1039 if (!drv->trans->dbgfs_dir) {
1040 IWL_ERR(drv, "failed to create transport debugfs directory\n");
1041 goto err_free_dbgfs;
1042 }
1043#endif
1044
972 ret = iwl_request_firmware(drv, true); 1045 ret = iwl_request_firmware(drv, true);
973 1046
974 if (ret) { 1047 if (ret) {
975 IWL_ERR(trans, "Couldn't request the fw\n"); 1048 IWL_ERR(trans, "Couldn't request the fw\n");
976 kfree(drv); 1049 goto err_fw;
977 drv = NULL;
978 } 1050 }
979 1051
980 return drv; 1052 return drv;
1053
1054err_fw:
1055#ifdef CONFIG_IWLWIFI_DEBUGFS
1056err_free_dbgfs:
1057 debugfs_remove_recursive(drv->dbgfs_drv);
1058err_free_drv:
1059#endif
1060 kfree(drv);
1061 drv = NULL;
1062
1063 return drv;
981} 1064}
982 1065
983void iwl_drv_stop(struct iwl_drv *drv) 1066void iwl_drv_stop(struct iwl_drv *drv)
984{ 1067{
985 wait_for_completion(&drv->request_firmware_complete); 1068 wait_for_completion(&drv->request_firmware_complete);
986 1069
987 /* op_mode can be NULL if its start failed */ 1070 _iwl_op_mode_stop(drv);
988 if (drv->op_mode)
989 iwl_op_mode_stop(drv->op_mode);
990 1071
991 iwl_dealloc_ucode(drv); 1072 iwl_dealloc_ucode(drv);
992 1073
@@ -1000,6 +1081,10 @@ void iwl_drv_stop(struct iwl_drv *drv)
1000 list_del(&drv->list); 1081 list_del(&drv->list);
1001 mutex_unlock(&iwlwifi_opmode_table_mtx); 1082 mutex_unlock(&iwlwifi_opmode_table_mtx);
1002 1083
1084#ifdef CONFIG_IWLWIFI_DEBUGFS
1085 debugfs_remove_recursive(drv->dbgfs_drv);
1086#endif
1087
1003 kfree(drv); 1088 kfree(drv);
1004} 1089}
1005 1090
@@ -1022,15 +1107,18 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops)
1022{ 1107{
1023 int i; 1108 int i;
1024 struct iwl_drv *drv; 1109 struct iwl_drv *drv;
1110 struct iwlwifi_opmode_table *op;
1025 1111
1026 mutex_lock(&iwlwifi_opmode_table_mtx); 1112 mutex_lock(&iwlwifi_opmode_table_mtx);
1027 for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { 1113 for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) {
1028 if (strcmp(iwlwifi_opmode_table[i].name, name)) 1114 op = &iwlwifi_opmode_table[i];
1115 if (strcmp(op->name, name))
1029 continue; 1116 continue;
1030 iwlwifi_opmode_table[i].ops = ops; 1117 op->ops = ops;
1031 list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) 1118 /* TODO: need to handle exceptional case */
1032 drv->op_mode = ops->start(drv->trans, drv->cfg, 1119 list_for_each_entry(drv, &op->drv, list)
1033 &drv->fw); 1120 drv->op_mode = _iwl_op_mode_start(drv, op);
1121
1034 mutex_unlock(&iwlwifi_opmode_table_mtx); 1122 mutex_unlock(&iwlwifi_opmode_table_mtx);
1035 return 0; 1123 return 0;
1036 } 1124 }
@@ -1051,12 +1139,9 @@ void iwl_opmode_deregister(const char *name)
1051 iwlwifi_opmode_table[i].ops = NULL; 1139 iwlwifi_opmode_table[i].ops = NULL;
1052 1140
1053 /* call the stop routine for all devices */ 1141 /* call the stop routine for all devices */
1054 list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) { 1142 list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list)
1055 if (drv->op_mode) { 1143 _iwl_op_mode_stop(drv);
1056 iwl_op_mode_stop(drv->op_mode); 1144
1057 drv->op_mode = NULL;
1058 }
1059 }
1060 mutex_unlock(&iwlwifi_opmode_table_mtx); 1145 mutex_unlock(&iwlwifi_opmode_table_mtx);
1061 return; 1146 return;
1062 } 1147 }
@@ -1076,6 +1161,14 @@ static int __init iwl_drv_init(void)
1076 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); 1161 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
1077 pr_info(DRV_COPYRIGHT "\n"); 1162 pr_info(DRV_COPYRIGHT "\n");
1078 1163
1164#ifdef CONFIG_IWLWIFI_DEBUGFS
1165 /* Create the root of iwlwifi debugfs subsystem. */
1166 iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
1167
1168 if (!iwl_dbgfs_root)
1169 return -EFAULT;
1170#endif
1171
1079 return iwl_pci_register_driver(); 1172 return iwl_pci_register_driver();
1080} 1173}
1081module_init(iwl_drv_init); 1174module_init(iwl_drv_init);
@@ -1083,6 +1176,10 @@ module_init(iwl_drv_init);
1083static void __exit iwl_drv_exit(void) 1176static void __exit iwl_drv_exit(void)
1084{ 1177{
1085 iwl_pci_unregister_driver(); 1178 iwl_pci_unregister_driver();
1179
1180#ifdef CONFIG_IWLWIFI_DEBUGFS
1181 debugfs_remove_recursive(iwl_dbgfs_root);
1182#endif
1086} 1183}
1087module_exit(iwl_drv_exit); 1184module_exit(iwl_drv_exit);
1088 1185
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h
index 2cbf137b25bf..285de5f68c05 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.h
@@ -90,9 +90,9 @@
90 * 4) The bus specific component configures the bus 90 * 4) The bus specific component configures the bus
91 * 5) The bus specific component calls to the drv bus agnostic part 91 * 5) The bus specific component calls to the drv bus agnostic part
92 * (iwl_drv_start) 92 * (iwl_drv_start)
93 * 6) iwl_drv_start fetches the fw ASYNC, iwl_ucode_callback 93 * 6) iwl_drv_start fetches the fw ASYNC, iwl_req_fw_callback
94 * 7) iwl_ucode_callback parses the fw file 94 * 7) iwl_req_fw_callback parses the fw file
95 * 8) iwl_ucode_callback starts the wifi implementation to matches the fw 95 * 8) iwl_req_fw_callback starts the wifi implementation to matches the fw
96 */ 96 */
97 97
98struct iwl_drv; 98struct iwl_drv;
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index 64886f95664f..c8d9b9517468 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -134,7 +134,8 @@ struct iwl_cfg;
134struct iwl_op_mode_ops { 134struct iwl_op_mode_ops {
135 struct iwl_op_mode *(*start)(struct iwl_trans *trans, 135 struct iwl_op_mode *(*start)(struct iwl_trans *trans,
136 const struct iwl_cfg *cfg, 136 const struct iwl_cfg *cfg,
137 const struct iwl_fw *fw); 137 const struct iwl_fw *fw,
138 struct dentry *dbgfs_dir);
138 void (*stop)(struct iwl_op_mode *op_mode); 139 void (*stop)(struct iwl_op_mode *op_mode);
139 int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, 140 int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
140 struct iwl_device_cmd *cmd); 141 struct iwl_device_cmd *cmd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 92576a3e84ef..ff1154232885 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -184,14 +184,20 @@ struct iwl_rx_packet {
184 * @CMD_SYNC: The caller will be stalled until the fw responds to the command 184 * @CMD_SYNC: The caller will be stalled until the fw responds to the command
185 * @CMD_ASYNC: Return right away and don't want for the response 185 * @CMD_ASYNC: Return right away and don't want for the response
186 * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the 186 * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
187 * response. 187 * response. The caller needs to call iwl_free_resp when done.
188 * @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the
189 * response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be
190 * copied. The pointer passed to the response handler is in the transport
191 * ownership and don't need to be freed by the op_mode. This also means
192 * that the pointer is invalidated after the op_mode's handler returns.
188 * @CMD_ON_DEMAND: This command is sent by the test mode pipe. 193 * @CMD_ON_DEMAND: This command is sent by the test mode pipe.
189 */ 194 */
190enum CMD_MODE { 195enum CMD_MODE {
191 CMD_SYNC = 0, 196 CMD_SYNC = 0,
192 CMD_ASYNC = BIT(0), 197 CMD_ASYNC = BIT(0),
193 CMD_WANT_SKB = BIT(1), 198 CMD_WANT_SKB = BIT(1),
194 CMD_ON_DEMAND = BIT(2), 199 CMD_WANT_HCMD = BIT(2),
200 CMD_ON_DEMAND = BIT(3),
195}; 201};
196 202
197#define DEF_CMD_PAYLOAD_SIZE 320 203#define DEF_CMD_PAYLOAD_SIZE 320
@@ -460,6 +466,8 @@ struct iwl_trans {
460 size_t dev_cmd_headroom; 466 size_t dev_cmd_headroom;
461 char dev_cmd_pool_name[50]; 467 char dev_cmd_pool_name[50];
462 468
469 struct dentry *dbgfs_dir;
470
463 /* pointer to trans specific struct */ 471 /* pointer to trans specific struct */
464 /*Ensure that this pointer will always be aligned to sizeof pointer */ 472 /*Ensure that this pointer will always be aligned to sizeof pointer */
465 char trans_specific[0] __aligned(sizeof(void *)); 473 char trans_specific[0] __aligned(sizeof(void *));
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index f4c3500b68c6..89bfb43f4946 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -282,8 +282,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
282 if (!trans_pcie->drv) 282 if (!trans_pcie->drv)
283 goto out_free_trans; 283 goto out_free_trans;
284 284
285 /* register transport layer debugfs here */
286 if (iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir))
287 goto out_free_drv;
288
285 return 0; 289 return 0;
286 290
291out_free_drv:
292 iwl_drv_stop(trans_pcie->drv);
287out_free_trans: 293out_free_trans:
288 iwl_trans_pcie_free(iwl_trans); 294 iwl_trans_pcie_free(iwl_trans);
289 pci_set_drvdata(pdev, NULL); 295 pci_set_drvdata(pdev, NULL);
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index d9694c58208c..3ef8d5adc991 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -184,6 +184,7 @@ struct iwl_queue {
184 184
185struct iwl_pcie_tx_queue_entry { 185struct iwl_pcie_tx_queue_entry {
186 struct iwl_device_cmd *cmd; 186 struct iwl_device_cmd *cmd;
187 struct iwl_device_cmd *copy_cmd;
187 struct sk_buff *skb; 188 struct sk_buff *skb;
188 struct iwl_cmd_meta meta; 189 struct iwl_cmd_meta meta;
189}; 190};
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 39a6ca1f009c..d80604a2bb1a 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -421,13 +421,23 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
421 index = SEQ_TO_INDEX(sequence); 421 index = SEQ_TO_INDEX(sequence);
422 cmd_index = get_cmd_index(&txq->q, index); 422 cmd_index = get_cmd_index(&txq->q, index);
423 423
424 if (reclaim) 424 if (reclaim) {
425 cmd = txq->entries[cmd_index].cmd; 425 struct iwl_pcie_tx_queue_entry *ent;
426 else 426 ent = &txq->entries[cmd_index];
427 cmd = ent->copy_cmd;
428 WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
429 } else {
427 cmd = NULL; 430 cmd = NULL;
431 }
428 432
429 err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); 433 err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
430 434
435 if (reclaim) {
436 /* The original command isn't needed any more */
437 kfree(txq->entries[cmd_index].copy_cmd);
438 txq->entries[cmd_index].copy_cmd = NULL;
439 }
440
431 /* 441 /*
432 * After here, we should always check rxcb._page_stolen, 442 * After here, we should always check rxcb._page_stolen,
433 * if it is true then one of the handlers took the page. 443 * if it is true then one of the handlers took the page.
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 939c2f78df58..38f51b04217e 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -492,10 +492,11 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
492 iwl_tx_queue_unmap(trans, txq_id); 492 iwl_tx_queue_unmap(trans, txq_id);
493 493
494 /* De-alloc array of command/tx buffers */ 494 /* De-alloc array of command/tx buffers */
495
496 if (txq_id == trans_pcie->cmd_queue) 495 if (txq_id == trans_pcie->cmd_queue)
497 for (i = 0; i < txq->q.n_window; i++) 496 for (i = 0; i < txq->q.n_window; i++) {
498 kfree(txq->entries[i].cmd); 497 kfree(txq->entries[i].cmd);
498 kfree(txq->entries[i].copy_cmd);
499 }
499 500
500 /* De-alloc circular buffer of TFDs */ 501 /* De-alloc circular buffer of TFDs */
501 if (txq->q.n_bd) { 502 if (txq->q.n_bd) {
@@ -896,6 +897,7 @@ static int iwl_set_hw_ready(struct iwl_trans *trans)
896static int iwl_prepare_card_hw(struct iwl_trans *trans) 897static int iwl_prepare_card_hw(struct iwl_trans *trans)
897{ 898{
898 int ret; 899 int ret;
900 int t = 0;
899 901
900 IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); 902 IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
901 903
@@ -908,17 +910,15 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans)
908 iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, 910 iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
909 CSR_HW_IF_CONFIG_REG_PREPARE); 911 CSR_HW_IF_CONFIG_REG_PREPARE);
910 912
911 ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, 913 do {
912 ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 914 ret = iwl_set_hw_ready(trans);
913 CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); 915 if (ret >= 0)
916 return 0;
914 917
915 if (ret < 0) 918 usleep_range(200, 1000);
916 return ret; 919 t += 200;
920 } while (t < 150000);
917 921
918 /* HW should be ready by now, check again. */
919 ret = iwl_set_hw_ready(trans);
920 if (ret >= 0)
921 return 0;
922 return ret; 922 return ret;
923} 923}
924 924
@@ -1769,7 +1769,7 @@ void iwl_dump_csr(struct iwl_trans *trans)
1769#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ 1769#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
1770 if (!debugfs_create_file(#name, mode, parent, trans, \ 1770 if (!debugfs_create_file(#name, mode, parent, trans, \
1771 &iwl_dbgfs_##name##_ops)) \ 1771 &iwl_dbgfs_##name##_ops)) \
1772 return -ENOMEM; \ 1772 goto err; \
1773} while (0) 1773} while (0)
1774 1774
1775/* file operation */ 1775/* file operation */
@@ -2033,6 +2033,10 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
2033 DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); 2033 DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
2034 DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR); 2034 DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR);
2035 return 0; 2035 return 0;
2036
2037err:
2038 IWL_ERR(trans, "failed to create the trans debugfs entry\n");
2039 return -ENOMEM;
2036} 2040}
2037#else 2041#else
2038static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, 2042static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 6baf8deef519..392d2bc5e357 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -521,7 +521,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
521 u16 copy_size, cmd_size; 521 u16 copy_size, cmd_size;
522 bool had_nocopy = false; 522 bool had_nocopy = false;
523 int i; 523 int i;
524 u8 *cmd_dest; 524 u32 cmd_pos;
525#ifdef CONFIG_IWLWIFI_DEVICE_TRACING 525#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
526 const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {}; 526 const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
527 int trace_lens[IWL_MAX_CMD_TFDS + 1] = {}; 527 int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
@@ -584,15 +584,31 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
584 INDEX_TO_SEQ(q->write_ptr)); 584 INDEX_TO_SEQ(q->write_ptr));
585 585
586 /* and copy the data that needs to be copied */ 586 /* and copy the data that needs to be copied */
587 587 cmd_pos = offsetof(struct iwl_device_cmd, payload);
588 cmd_dest = out_cmd->payload;
589 for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { 588 for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
590 if (!cmd->len[i]) 589 if (!cmd->len[i])
591 continue; 590 continue;
592 if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) 591 if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
593 break; 592 break;
594 memcpy(cmd_dest, cmd->data[i], cmd->len[i]); 593 memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
595 cmd_dest += cmd->len[i]; 594 cmd_pos += cmd->len[i];
595 }
596
597 WARN_ON_ONCE(txq->entries[idx].copy_cmd);
598
599 /*
600 * since out_cmd will be the source address of the FH, it will write
601 * the retry count there. So when the user needs to receivce the HCMD
602 * that corresponds to the response in the response handler, it needs
603 * to set CMD_WANT_HCMD.
604 */
605 if (cmd->flags & CMD_WANT_HCMD) {
606 txq->entries[idx].copy_cmd =
607 kmemdup(out_cmd, cmd_pos, GFP_ATOMIC);
608 if (unlikely(!txq->entries[idx].copy_cmd)) {
609 idx = -ENOMEM;
610 goto out;
611 }
596 } 612 }
597 613
598 IWL_DEBUG_HC(trans, 614 IWL_DEBUG_HC(trans,