aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-drv.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c141
1 files changed, 119 insertions, 22 deletions
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