aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-03-12 19:58:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-03-25 16:41:47 -0400
commit712b6cf57a53da608a682b5f782c5785bda76001 (patch)
tree895f6b079b1fca450a644b58b04cb728e656f557
parent19758bef09abe9d2a14575ffb6f686947e97fcb1 (diff)
iwlwifi: Add debugfs to iwl core
This patch adds debugfs support to iwl core currently only iwl4965 is supported Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig6
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c319
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c14
7 files changed, 377 insertions, 6 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index acb807936131..1ab14ed33f58 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -76,6 +76,12 @@ config IWLWIFI_DEBUG
76 as the debug information can assist others in helping you resolve 76 as the debug information can assist others in helping you resolve
77 any problems you may encounter. 77 any problems you may encounter.
78 78
79config IWLWIFI_DEBUGFS
80 bool "Iwlwifi debugfs support"
81 depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS
82 ---help---
83 Enable creation of debugfs files for the iwlwifi drivers.
84
79config IWL3945 85config IWL3945
80 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection" 86 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
81 depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL 87 depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 59d9c90d3610..86ac1fc60bbb 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,6 +1,10 @@
1obj-$(CONFIG_IWLCORE) += iwlcore.o 1obj-$(CONFIG_IWLCORE) += iwlcore.o
2iwlcore-objs = iwl-core.o iwl-eeprom.o 2iwlcore-objs = iwl-core.o iwl-eeprom.o
3 3
4ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y)
5 iwlcore-objs += iwl-debugfs.o
6endif
7
4obj-$(CONFIG_IWL3945) += iwl3945.o 8obj-$(CONFIG_IWL3945) += iwl3945.o
5iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o 9iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o
6 10
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index aded6010ce20..cec62ba803b5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -1212,7 +1212,11 @@ struct iwl_priv {
1212 /* debugging info */ 1212 /* debugging info */
1213 u32 framecnt_to_us; 1213 u32 framecnt_to_us;
1214 atomic_t restrict_refcnt; 1214 atomic_t restrict_refcnt;
1215#endif 1215#ifdef CONFIG_IWLWIFI_DEBUGFS
1216 /* debugfs */
1217 struct iwl_debugfs *dbgfs;
1218#endif /* CONFIG_IWLWIFI_DEBUGFS */
1219#endif /* CONFIG_IWLWIFI_DEBUG */
1216 1220
1217 struct work_struct txpower_work; 1221 struct work_struct txpower_work;
1218#ifdef CONFIG_IWL4965_SENSITIVITY 1222#ifdef CONFIG_IWL4965_SENSITIVITY
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 4645d194773e..3a9fc905e6bc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -30,6 +30,7 @@
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/version.h> 31#include <linux/version.h>
32 32
33struct iwl_priv; /* FIXME: remove */
33#include "iwl-debug.h" 34#include "iwl-debug.h"
34#include "iwl-eeprom.h" 35#include "iwl-eeprom.h"
35#include "iwl-core.h" 36#include "iwl-core.h"
@@ -37,7 +38,7 @@
37MODULE_DESCRIPTION("iwl core"); 38MODULE_DESCRIPTION("iwl core");
38MODULE_VERSION(IWLWIFI_VERSION); 39MODULE_VERSION(IWLWIFI_VERSION);
39MODULE_AUTHOR(DRV_COPYRIGHT); 40MODULE_AUTHOR(DRV_COPYRIGHT);
40MODULE_LICENSE("GPL/BSD"); 41MODULE_LICENSE("GPL");
41 42
42#ifdef CONFIG_IWLWIFI_DEBUG 43#ifdef CONFIG_IWLWIFI_DEBUG
43u32 iwl_debug_level; 44u32 iwl_debug_level;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 067700620e21..c60724c21db8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -49,8 +49,27 @@ static inline void iwl_print_hex_dump(int level, void *p, u32 len)
49 print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, 49 print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
50 p, len, 1); 50 p, len, 1);
51} 51}
52#else
53 52
53#ifdef CONFIG_IWLWIFI_DEBUGFS
54struct iwl_debugfs {
55 const char *name;
56 struct dentry *dir_drv;
57 struct dentry *dir_data;
58 struct dir_data_files{
59 struct dentry *file_sram;
60 struct dentry *file_stations;
61 struct dentry *file_rx_statistics;
62 struct dentry *file_tx_statistics;
63 } dbgfs_data_files;
64 u32 sram_offset;
65 u32 sram_len;
66};
67
68int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
69void iwl_dbgfs_unregister(struct iwl_priv *priv);
70#endif
71
72#else
54static inline void IWL_DEBUG(int level, const char *fmt, ...) 73static inline void IWL_DEBUG(int level, const char *fmt, ...)
55{ 74{
56} 75}
@@ -64,6 +83,16 @@ static inline void iwl_print_hex_dump(int level, void *p, u32 len)
64 83
65 84
66 85
86#ifndef CONFIG_IWLWIFI_DEBUGFS
87static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
88{
89 return 0;
90}
91static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
92{
93}
94#endif /* CONFIG_IWLWIFI_DEBUGFS */
95
67/* 96/*
68 * To use the debug system; 97 * To use the debug system;
69 * 98 *
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
new file mode 100644
index 000000000000..c659bd3bc346
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -0,0 +1,319 @@
1/******************************************************************************
2 *
3 * GPL LICENSE SUMMARY
4 *
5 * Copyright(c) 2008 Intel Corporation. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19 * USA
20 *
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * Contact Information:
25 * Tomas Winkler <tomas.winkler@intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *****************************************************************************/
28
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/debugfs.h>
32
33#include <linux/ieee80211.h>
34#include <net/mac80211.h>
35
36
37#include "iwl-4965.h"
38#include "iwl-debug.h"
39#include "iwl-4965-io.h"
40
41
42/* create and remove of files */
43#define DEBUGFS_ADD_DIR(name, parent) do { \
44 dbgfs->dir_##name = debugfs_create_dir(#name, parent); \
45 if (!(dbgfs->dir_##name)) \
46 goto err; \
47} while (0)
48
49#define DEBUGFS_ADD_FILE(name, parent) do { \
50 dbgfs->dbgfs_##parent##_files.file_##name = \
51 debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
52 &iwl_dbgfs_##name##_ops); \
53 if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
54 goto err; \
55} while (0)
56
57#define DEBUGFS_REMOVE(name) do { \
58 debugfs_remove(name); \
59 name = NULL; \
60} while (0);
61
62/* file operation */
63#define DEBUGFS_READ_FUNC(name) \
64static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
65 char __user *user_buf, \
66 size_t count, loff_t *ppos);
67
68#define DEBUGFS_WRITE_FUNC(name) \
69static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
70 const char __user *user_buf, \
71 size_t count, loff_t *ppos);
72
73
74static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
75{
76 file->private_data = inode->i_private;
77 return 0;
78}
79
80#define DEBUGFS_READ_FILE_OPS(name) \
81 DEBUGFS_READ_FUNC(name); \
82static const struct file_operations iwl_dbgfs_##name##_ops = { \
83 .read = iwl_dbgfs_##name##_read, \
84 .open = iwl_dbgfs_open_file_generic, \
85};
86
87#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
88 DEBUGFS_READ_FUNC(name); \
89 DEBUGFS_WRITE_FUNC(name); \
90static const struct file_operations iwl_dbgfs_##name##_ops = { \
91 .write = iwl_dbgfs_##name##_write, \
92 .read = iwl_dbgfs_##name##_read, \
93 .open = iwl_dbgfs_open_file_generic, \
94};
95
96
97static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
98 char __user *user_buf,
99 size_t count, loff_t *ppos) {
100
101 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
102 char buf[256];
103 int pos = 0;
104
105 pos += sprintf(buf+pos, "mgmt: %u\n", priv->tx_stats[0].cnt);
106 pos += sprintf(buf+pos, "ctrl: %u\n", priv->tx_stats[1].cnt);
107 pos += sprintf(buf+pos, "data: %u\n", priv->tx_stats[2].cnt);
108
109 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
110}
111
112static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
113 char __user *user_buf,
114 size_t count, loff_t *ppos) {
115
116 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
117 char buf[256];
118 int pos = 0;
119
120 pos += sprintf(buf+pos, "mgmt: %u\n", priv->rx_stats[0].cnt);
121 pos += sprintf(buf+pos, "ctrl: %u\n", priv->rx_stats[1].cnt);
122 pos += sprintf(buf+pos, "data: %u\n", priv->rx_stats[2].cnt);
123
124 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
125}
126
127#define BYTE1_MASK 0x000000ff;
128#define BYTE2_MASK 0x0000ffff;
129#define BYTE3_MASK 0x00ffffff;
130static ssize_t iwl_dbgfs_sram_read(struct file *file,
131 char __user *user_buf,
132 size_t count, loff_t *ppos)
133{
134 u32 val;
135 char buf[1024];
136 ssize_t ret;
137 int i;
138 int pos = 0;
139 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
140
141 printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n",
142 priv->dbgfs->sram_offset, priv->dbgfs->sram_len);
143
144 iwl4965_grab_nic_access(priv);
145 for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
146 val = iwl4965_read_targ_mem(priv, priv->dbgfs->sram_offset + \
147 priv->dbgfs->sram_len - i);
148 if (i < 4) {
149 switch (i) {
150 case 1:
151 val &= BYTE1_MASK;
152 break;
153 case 2:
154 val &= BYTE2_MASK;
155 break;
156 case 3:
157 val &= BYTE3_MASK;
158 break;
159 }
160 }
161 pos += sprintf(buf+pos, "0x%08x ", val);
162 }
163 pos += sprintf(buf+pos, "\n");
164 iwl4965_release_nic_access(priv);
165
166 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
167 return ret;
168}
169
170static ssize_t iwl_dbgfs_sram_write(struct file *file,
171 const char __user *user_buf,
172 size_t count, loff_t *ppos)
173{
174 struct iwl_priv *priv = file->private_data;
175 char buf[64];
176 int buf_size;
177 u32 offset, len;
178
179 memset(buf, 0, sizeof(buf));
180 buf_size = min(count, sizeof(buf) - 1);
181 if (copy_from_user(buf, user_buf, buf_size))
182 return -EFAULT;
183
184 if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
185 priv->dbgfs->sram_offset = offset;
186 priv->dbgfs->sram_len = len;
187 } else {
188 priv->dbgfs->sram_offset = 0;
189 priv->dbgfs->sram_len = 0;
190 }
191
192 return count;
193}
194
195static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
196 size_t count, loff_t *ppos)
197{
198 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
199 struct iwl4965_station_entry *station;
200 int max_sta = priv->hw_setting.max_stations;
201 char *buf;
202 int i, j, pos = 0;
203 ssize_t ret;
204 /* Add 30 for initial string */
205 const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
206 DECLARE_MAC_BUF(mac);
207
208 buf = kmalloc(bufsz, GFP_KERNEL);
209 if(!buf)
210 return -ENOMEM;
211
212 pos += sprintf(buf+pos, "num of stations: %d\n\n",
213 priv->num_stations);
214
215 for (i = 0; i < max_sta; i++) {
216 station = &priv->stations[i];
217 if (station->used) {
218 pos += sprintf(buf+pos, "station %d:\ngeneral data:\n",
219 i+1);
220 print_mac(mac, station->sta.sta.addr);
221 pos += sprintf(buf+pos, "id: %u\n",
222 station->sta.sta.sta_id);
223 pos += sprintf(buf+pos, "mode: %u\n",
224 station->sta.mode);
225 pos += sprintf(buf+pos, "flags: 0x%x\n",
226 station->sta.station_flags_msk);
227 pos += sprintf(buf+pos, "ps_status: %u\n",
228 station->ps_status);
229
230 pos += sprintf(buf+pos, "tid data:\n");
231
232 pos += sprintf(buf+pos, "seq_num\t\ttxq_id\t");
233 pos += sprintf(buf+pos, "frame_count\twait_for_ba\t");
234 pos += sprintf(buf+pos, "start_idx\tbitmap0\t");
235 pos += sprintf(buf+pos, "bitmap1\trate_n_flags\n");
236
237 for (j = 0; j < MAX_TID_COUNT; j++) {
238 pos += sprintf(buf+pos, "[%d]:\t\t%u\t",
239 j, station->tid[j].seq_number);
240 pos += sprintf(buf+pos, "%u\t\t%u\t\t%u\t\t",
241 station->tid[j].agg.txq_id,
242 station->tid[j].agg.frame_count,
243 station->tid[j].agg.wait_for_ba);
244 pos += sprintf(buf+pos, "%u\t%llu\t%u\n",
245 station->tid[j].agg.start_idx,
246 station->tid[j].agg.bitmap,
247 station->tid[j].agg.rate_n_flags);
248 }
249 pos += sprintf(buf+pos, "\n");
250 }
251 }
252
253 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
254 kfree(buf);
255 return ret;
256}
257
258
259DEBUGFS_READ_WRITE_FILE_OPS(sram);
260DEBUGFS_READ_FILE_OPS(stations);
261DEBUGFS_READ_FILE_OPS(rx_statistics);
262DEBUGFS_READ_FILE_OPS(tx_statistics);
263
264/*
265 * Create the debugfs files and directories
266 *
267 */
268int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
269{
270 struct iwl_debugfs *dbgfs;
271
272 dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
273 if (!dbgfs) {
274 goto err;
275 }
276
277 priv->dbgfs = dbgfs;
278 dbgfs->name = name;
279 dbgfs->dir_drv = debugfs_create_dir(name, NULL);
280 if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){
281 goto err;
282 }
283
284 DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
285 DEBUGFS_ADD_FILE(sram, data);
286 DEBUGFS_ADD_FILE(stations, data);
287 DEBUGFS_ADD_FILE(rx_statistics, data);
288 DEBUGFS_ADD_FILE(tx_statistics, data);
289
290 return 0;
291
292err:
293 IWL_ERROR("Can't open the debugfs directory\n");
294 iwl_dbgfs_unregister(priv);
295 return -ENOENT;
296}
297EXPORT_SYMBOL(iwl_dbgfs_register);
298
299/**
300 * Remove the debugfs files and directories
301 *
302 */
303void iwl_dbgfs_unregister(struct iwl_priv *priv)
304{
305 if (!(priv->dbgfs))
306 return;
307
308 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
309 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
310 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
311 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
312 DEBUGFS_REMOVE(priv->dbgfs->dir_data);
313 DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
314 kfree(priv->dbgfs);
315 priv->dbgfs = NULL;
316}
317EXPORT_SYMBOL(iwl_dbgfs_unregister);
318
319
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 4f6ed6942065..396940e701e5 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -8690,6 +8690,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8690 goto out_release_irq; 8690 goto out_release_irq;
8691 } 8691 }
8692 8692
8693 err = iwl_dbgfs_register(priv, DRV_NAME);
8694 if (err) {
8695 IWL_ERROR("failed to create debugfs files\n");
8696 goto out_remove_sysfs;
8697 }
8693 /* nic init */ 8698 /* nic init */
8694 iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS, 8699 iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
8695 CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); 8700 CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
@@ -8700,13 +8705,13 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8700 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); 8705 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
8701 if (err < 0) { 8706 if (err < 0) {
8702 IWL_DEBUG_INFO("Failed to init the card\n"); 8707 IWL_DEBUG_INFO("Failed to init the card\n");
8703 goto out_remove_sysfs; 8708 goto out_remove_dbgfs;
8704 } 8709 }
8705 /* Read the EEPROM */ 8710 /* Read the EEPROM */
8706 err = iwl_eeprom_init(priv); 8711 err = iwl_eeprom_init(priv);
8707 if (err) { 8712 if (err) {
8708 IWL_ERROR("Unable to init EEPROM\n"); 8713 IWL_ERROR("Unable to init EEPROM\n");
8709 goto out_remove_sysfs; 8714 goto out_remove_dbgfs;
8710 } 8715 }
8711 /* MAC Address location in EEPROM same for 3945/4965 */ 8716 /* MAC Address location in EEPROM same for 3945/4965 */
8712 iwl_eeprom_get_mac(priv, priv->mac_addr); 8717 iwl_eeprom_get_mac(priv, priv->mac_addr);
@@ -8716,7 +8721,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8716 err = iwl4965_init_channel_map(priv); 8721 err = iwl4965_init_channel_map(priv);
8717 if (err) { 8722 if (err) {
8718 IWL_ERROR("initializing regulatory failed: %d\n", err); 8723 IWL_ERROR("initializing regulatory failed: %d\n", err);
8719 goto out_remove_sysfs; 8724 goto out_remove_dbgfs;
8720 } 8725 }
8721 8726
8722 err = iwl4965_init_geos(priv); 8727 err = iwl4965_init_geos(priv);
@@ -8743,6 +8748,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
8743 iwl4965_free_geos(priv); 8748 iwl4965_free_geos(priv);
8744 out_free_channel_map: 8749 out_free_channel_map:
8745 iwl4965_free_channel_map(priv); 8750 iwl4965_free_channel_map(priv);
8751 out_remove_dbgfs:
8752 iwl_dbgfs_unregister(priv);
8746 out_remove_sysfs: 8753 out_remove_sysfs:
8747 sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); 8754 sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
8748 8755
@@ -8787,6 +8794,7 @@ static void iwl4965_pci_remove(struct pci_dev *pdev)
8787 } 8794 }
8788 } 8795 }
8789 8796
8797 iwl_dbgfs_unregister(priv);
8790 sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); 8798 sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
8791 8799
8792 iwl4965_dealloc_ucode_pci(priv); 8800 iwl4965_dealloc_ucode_pci(priv);