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.c167
1 files changed, 133 insertions, 34 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index cc41cfaedfbd..198634b75ed0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -64,6 +64,7 @@
64#include <linux/dma-mapping.h> 64#include <linux/dma-mapping.h>
65#include <linux/firmware.h> 65#include <linux/firmware.h>
66#include <linux/module.h> 66#include <linux/module.h>
67#include <linux/vmalloc.h>
67 68
68#include "iwl-drv.h" 69#include "iwl-drv.h"
69#include "iwl-debug.h" 70#include "iwl-debug.h"
@@ -101,6 +102,10 @@ MODULE_VERSION(DRV_VERSION);
101MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); 102MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
102MODULE_LICENSE("GPL"); 103MODULE_LICENSE("GPL");
103 104
105#ifdef CONFIG_IWLWIFI_DEBUGFS
106static struct dentry *iwl_dbgfs_root;
107#endif
108
104/** 109/**
105 * struct iwl_drv - drv common data 110 * struct iwl_drv - drv common data
106 * @list: list of drv structures using this opmode 111 * @list: list of drv structures using this opmode
@@ -126,6 +131,12 @@ struct iwl_drv {
126 char firmware_name[25]; /* name of firmware file to load */ 131 char firmware_name[25]; /* name of firmware file to load */
127 132
128 struct completion request_firmware_complete; 133 struct completion request_firmware_complete;
134
135#ifdef CONFIG_IWLWIFI_DEBUGFS
136 struct dentry *dbgfs_drv;
137 struct dentry *dbgfs_trans;
138 struct dentry *dbgfs_op_mode;
139#endif
129}; 140};
130 141
131#define DVM_OP_MODE 0 142#define DVM_OP_MODE 0
@@ -154,10 +165,8 @@ struct fw_sec {
154 165
155static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) 166static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
156{ 167{
157 if (desc->v_addr) 168 vfree(desc->data);
158 dma_free_coherent(drv->trans->dev, desc->len, 169 desc->data = NULL;
159 desc->v_addr, desc->p_addr);
160 desc->v_addr = NULL;
161 desc->len = 0; 170 desc->len = 0;
162} 171}
163 172
@@ -176,25 +185,29 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
176} 185}
177 186
178static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, 187static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
179 struct fw_sec *sec) 188 struct fw_sec *sec)
180{ 189{
181 if (!sec || !sec->size) { 190 void *data;
182 desc->v_addr = NULL; 191
192 desc->data = NULL;
193
194 if (!sec || !sec->size)
183 return -EINVAL; 195 return -EINVAL;
184 }
185 196
186 desc->v_addr = dma_alloc_coherent(drv->trans->dev, sec->size, 197 data = vmalloc(sec->size);
187 &desc->p_addr, GFP_KERNEL); 198 if (!data)
188 if (!desc->v_addr)
189 return -ENOMEM; 199 return -ENOMEM;
190 200
191 desc->len = sec->size; 201 desc->len = sec->size;
192 desc->offset = sec->offset; 202 desc->offset = sec->offset;
193 memcpy(desc->v_addr, sec->data, sec->size); 203 memcpy(data, sec->data, desc->len);
204 desc->data = data;
205
194 return 0; 206 return 0;
195} 207}
196 208
197static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); 209static void iwl_req_fw_callback(const struct firmware *ucode_raw,
210 void *context);
198 211
199#define UCODE_EXPERIMENTAL_INDEX 100 212#define UCODE_EXPERIMENTAL_INDEX 100
200#define UCODE_EXPERIMENTAL_TAG "exp" 213#define UCODE_EXPERIMENTAL_TAG "exp"
@@ -231,7 +244,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
231 244
232 return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name, 245 return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name,
233 drv->trans->dev, 246 drv->trans->dev,
234 GFP_KERNEL, drv, iwl_ucode_callback); 247 GFP_KERNEL, drv, iwl_req_fw_callback);
235} 248}
236 249
237struct fw_img_parsing { 250struct fw_img_parsing {
@@ -759,13 +772,57 @@ static int validate_sec_sizes(struct iwl_drv *drv,
759 return 0; 772 return 0;
760} 773}
761 774
775static struct iwl_op_mode *
776_iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
777{
778 const struct iwl_op_mode_ops *ops = op->ops;
779 struct dentry *dbgfs_dir = NULL;
780 struct iwl_op_mode *op_mode = NULL;
781
782#ifdef CONFIG_IWLWIFI_DEBUGFS
783 drv->dbgfs_op_mode = debugfs_create_dir(op->name,
784 drv->dbgfs_drv);
785 if (!drv->dbgfs_op_mode) {
786 IWL_ERR(drv,
787 "failed to create opmode debugfs directory\n");
788 return op_mode;
789 }
790 dbgfs_dir = drv->dbgfs_op_mode;
791#endif
792
793 op_mode = ops->start(drv->trans, drv->cfg, &drv->fw, dbgfs_dir);
794
795#ifdef CONFIG_IWLWIFI_DEBUGFS
796 if (!op_mode) {
797 debugfs_remove_recursive(drv->dbgfs_op_mode);
798 drv->dbgfs_op_mode = NULL;
799 }
800#endif
801
802 return op_mode;
803}
804
805static void _iwl_op_mode_stop(struct iwl_drv *drv)
806{
807 /* op_mode can be NULL if its start failed */
808 if (drv->op_mode) {
809 iwl_op_mode_stop(drv->op_mode);
810 drv->op_mode = NULL;
811
812#ifdef CONFIG_IWLWIFI_DEBUGFS
813 debugfs_remove_recursive(drv->dbgfs_op_mode);
814 drv->dbgfs_op_mode = NULL;
815#endif
816 }
817}
818
762/** 819/**
763 * iwl_ucode_callback - callback when firmware was loaded 820 * iwl_req_fw_callback - callback when firmware was loaded
764 * 821 *
765 * If loaded successfully, copies the firmware into buffers 822 * If loaded successfully, copies the firmware into buffers
766 * for the card to fetch (via DMA). 823 * for the card to fetch (via DMA).
767 */ 824 */
768static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) 825static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
769{ 826{
770 struct iwl_drv *drv = context; 827 struct iwl_drv *drv = context;
771 struct iwl_fw *fw = &drv->fw; 828 struct iwl_fw *fw = &drv->fw;
@@ -908,8 +965,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
908 list_add_tail(&drv->list, &op->drv); 965 list_add_tail(&drv->list, &op->drv);
909 966
910 if (op->ops) { 967 if (op->ops) {
911 const struct iwl_op_mode_ops *ops = op->ops; 968 drv->op_mode = _iwl_op_mode_start(drv, op);
912 drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw);
913 969
914 if (!drv->op_mode) { 970 if (!drv->op_mode) {
915 mutex_unlock(&iwlwifi_opmode_table_mtx); 971 mutex_unlock(&iwlwifi_opmode_table_mtx);
@@ -969,24 +1025,51 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
969 init_completion(&drv->request_firmware_complete); 1025 init_completion(&drv->request_firmware_complete);
970 INIT_LIST_HEAD(&drv->list); 1026 INIT_LIST_HEAD(&drv->list);
971 1027
1028#ifdef CONFIG_IWLWIFI_DEBUGFS
1029 /* Create the device debugfs entries. */
1030 drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev),
1031 iwl_dbgfs_root);
1032
1033 if (!drv->dbgfs_drv) {
1034 IWL_ERR(drv, "failed to create debugfs directory\n");
1035 goto err_free_drv;
1036 }
1037
1038 /* Create transport layer debugfs dir */
1039 drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv);
1040
1041 if (!drv->trans->dbgfs_dir) {
1042 IWL_ERR(drv, "failed to create transport debugfs directory\n");
1043 goto err_free_dbgfs;
1044 }
1045#endif
1046
972 ret = iwl_request_firmware(drv, true); 1047 ret = iwl_request_firmware(drv, true);
973 1048
974 if (ret) { 1049 if (ret) {
975 IWL_ERR(trans, "Couldn't request the fw\n"); 1050 IWL_ERR(trans, "Couldn't request the fw\n");
976 kfree(drv); 1051 goto err_fw;
977 drv = NULL;
978 } 1052 }
979 1053
980 return drv; 1054 return drv;
1055
1056err_fw:
1057#ifdef CONFIG_IWLWIFI_DEBUGFS
1058err_free_dbgfs:
1059 debugfs_remove_recursive(drv->dbgfs_drv);
1060err_free_drv:
1061#endif
1062 kfree(drv);
1063 drv = NULL;
1064
1065 return drv;
981} 1066}
982 1067
983void iwl_drv_stop(struct iwl_drv *drv) 1068void iwl_drv_stop(struct iwl_drv *drv)
984{ 1069{
985 wait_for_completion(&drv->request_firmware_complete); 1070 wait_for_completion(&drv->request_firmware_complete);
986 1071
987 /* op_mode can be NULL if its start failed */ 1072 _iwl_op_mode_stop(drv);
988 if (drv->op_mode)
989 iwl_op_mode_stop(drv->op_mode);
990 1073
991 iwl_dealloc_ucode(drv); 1074 iwl_dealloc_ucode(drv);
992 1075
@@ -1000,6 +1083,10 @@ void iwl_drv_stop(struct iwl_drv *drv)
1000 list_del(&drv->list); 1083 list_del(&drv->list);
1001 mutex_unlock(&iwlwifi_opmode_table_mtx); 1084 mutex_unlock(&iwlwifi_opmode_table_mtx);
1002 1085
1086#ifdef CONFIG_IWLWIFI_DEBUGFS
1087 debugfs_remove_recursive(drv->dbgfs_drv);
1088#endif
1089
1003 kfree(drv); 1090 kfree(drv);
1004} 1091}
1005 1092
@@ -1022,15 +1109,18 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops)
1022{ 1109{
1023 int i; 1110 int i;
1024 struct iwl_drv *drv; 1111 struct iwl_drv *drv;
1112 struct iwlwifi_opmode_table *op;
1025 1113
1026 mutex_lock(&iwlwifi_opmode_table_mtx); 1114 mutex_lock(&iwlwifi_opmode_table_mtx);
1027 for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) { 1115 for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) {
1028 if (strcmp(iwlwifi_opmode_table[i].name, name)) 1116 op = &iwlwifi_opmode_table[i];
1117 if (strcmp(op->name, name))
1029 continue; 1118 continue;
1030 iwlwifi_opmode_table[i].ops = ops; 1119 op->ops = ops;
1031 list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) 1120 /* TODO: need to handle exceptional case */
1032 drv->op_mode = ops->start(drv->trans, drv->cfg, 1121 list_for_each_entry(drv, &op->drv, list)
1033 &drv->fw); 1122 drv->op_mode = _iwl_op_mode_start(drv, op);
1123
1034 mutex_unlock(&iwlwifi_opmode_table_mtx); 1124 mutex_unlock(&iwlwifi_opmode_table_mtx);
1035 return 0; 1125 return 0;
1036 } 1126 }
@@ -1051,12 +1141,9 @@ void iwl_opmode_deregister(const char *name)
1051 iwlwifi_opmode_table[i].ops = NULL; 1141 iwlwifi_opmode_table[i].ops = NULL;
1052 1142
1053 /* call the stop routine for all devices */ 1143 /* call the stop routine for all devices */
1054 list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list) { 1144 list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list)
1055 if (drv->op_mode) { 1145 _iwl_op_mode_stop(drv);
1056 iwl_op_mode_stop(drv->op_mode); 1146
1057 drv->op_mode = NULL;
1058 }
1059 }
1060 mutex_unlock(&iwlwifi_opmode_table_mtx); 1147 mutex_unlock(&iwlwifi_opmode_table_mtx);
1061 return; 1148 return;
1062 } 1149 }
@@ -1076,6 +1163,14 @@ static int __init iwl_drv_init(void)
1076 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); 1163 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
1077 pr_info(DRV_COPYRIGHT "\n"); 1164 pr_info(DRV_COPYRIGHT "\n");
1078 1165
1166#ifdef CONFIG_IWLWIFI_DEBUGFS
1167 /* Create the root of iwlwifi debugfs subsystem. */
1168 iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL);
1169
1170 if (!iwl_dbgfs_root)
1171 return -EFAULT;
1172#endif
1173
1079 return iwl_pci_register_driver(); 1174 return iwl_pci_register_driver();
1080} 1175}
1081module_init(iwl_drv_init); 1176module_init(iwl_drv_init);
@@ -1083,6 +1178,10 @@ module_init(iwl_drv_init);
1083static void __exit iwl_drv_exit(void) 1178static void __exit iwl_drv_exit(void)
1084{ 1179{
1085 iwl_pci_unregister_driver(); 1180 iwl_pci_unregister_driver();
1181
1182#ifdef CONFIG_IWLWIFI_DEBUGFS
1183 debugfs_remove_recursive(iwl_dbgfs_root);
1184#endif
1086} 1185}
1087module_exit(iwl_drv_exit); 1186module_exit(iwl_drv_exit);
1088 1187