Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
drv.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * This file is provided under a dual BSD/GPLv2 license. When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * GPL LICENSE SUMMARY
7  *
8  * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of version 2 of the GNU General Public License as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22  * USA
23  *
24  * The full GNU General Public License is included in this distribution
25  * in the file called LICENSE.GPL.
26  *
27  * Contact Information:
28  * Intel Linux Wireless <[email protected]>
29  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30  *
31  * BSD LICENSE
32  *
33  * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  *
40  * * Redistributions of source code must retain the above copyright
41  * notice, this list of conditions and the following disclaimer.
42  * * Redistributions in binary form must reproduce the above copyright
43  * notice, this list of conditions and the following disclaimer in
44  * the documentation and/or other materials provided with the
45  * distribution.
46  * * Neither the name Intel Corporation nor the names of its
47  * contributors may be used to endorse or promote products derived
48  * from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  *
62  *****************************************************************************/
63 
64 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
65 
66 #include <linux/module.h>
67 #include <linux/pci.h>
68 #include <linux/pci-aspm.h>
69 
70 #include "iwl-trans.h"
71 #include "iwl-drv.h"
72 #include "iwl-trans.h"
73 
74 #include "cfg.h"
75 #include "internal.h"
76 
77 #define IWL_PCI_DEVICE(dev, subdev, cfg) \
78  .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
79  .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
80  .driver_data = (kernel_ulong_t)&(cfg)
81 
82 /* Hardware specific file defines the PCI IDs table for that hardware module */
83 static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
84  {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
85  {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
86  {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
87  {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
88  {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
89  {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
90  {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
91  {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
92  {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
93  {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
94  {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
95  {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
96  {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
97  {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
98  {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
99  {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
100  {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
101  {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
102  {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
103  {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
104  {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
105  {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
106  {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
107  {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
108 
109 /* 5300 Series WiFi */
110  {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
111  {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
112  {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
113  {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
114  {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
115  {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
116  {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
117  {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
118  {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
119  {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
120  {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
121  {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
122 
123 /* 5350 Series WiFi/WiMax */
124  {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
125  {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
126  {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
127 
128 /* 5150 Series Wifi/WiMax */
129  {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
130  {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
131  {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
132  {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
133  {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
134  {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
135 
136  {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
137  {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
138  {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
139  {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
140 
141 /* 6x00 Series */
142  {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
143  {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
144  {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
145  {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
146  {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
147  {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
148  {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
149  {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
150  {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
151  {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
152 
153 /* 6x05 Series */
154  {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
155  {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
156  {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
157  {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
158  {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
159  {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
160  {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
161  {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
162  {IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
163  {IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_2agn_d_cfg)},
164  {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_mow1_cfg)},/* low 5GHz active */
165  {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_mow2_cfg)},/* high 5GHz active */
166 
167 /* 6x30 Series */
168  {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
169  {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
170  {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
171  {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
172  {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
173  {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
174  {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
175  {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
176  {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
177  {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
178  {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
179  {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
180  {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
181  {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
182  {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
183  {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
184 
185 /* 6x50 WiFi/WiMax Series */
186  {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
187  {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
188  {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
189  {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
190  {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
191  {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
192 
193 /* 6150 WiFi/WiMax Series */
194  {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
195  {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
196  {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
197  {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
198  {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
199  {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
200 
201 /* 1000 Series WiFi */
202  {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
203  {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
204  {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
205  {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
206  {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
207  {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
208  {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
209  {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
210  {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
211  {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
212  {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
213  {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
214 
215 /* 100 Series WiFi */
216  {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
217  {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
218  {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
219  {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
220  {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
221  {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
222 
223 /* 130 Series WiFi */
224  {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
225  {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
226  {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
227  {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
228  {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
229  {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
230 
231 /* 2x00 Series */
232  {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
233  {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
234  {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
235  {IWL_PCI_DEVICE(0x0890, 0x4822, iwl2000_2bgn_d_cfg)},
236 
237 /* 2x30 Series */
238  {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
239  {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
240  {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
241 
242 /* 6x35 Series */
243  {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
244  {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
245  {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
246  {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
247 
248 /* 105 Series */
249  {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
250  {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
251  {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
252  {IWL_PCI_DEVICE(0x0894, 0x0822, iwl105_bgn_d_cfg)},
253 
254 /* 135 Series */
255  {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
256  {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
257  {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
258 
259  {0}
260 };
261 MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
262 
263 /* PCI registers */
264 #define PCI_CFG_RETRY_TIMEOUT 0x041
265 
266 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
267 {
268  const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
269  struct iwl_trans *iwl_trans;
270  struct iwl_trans_pcie *trans_pcie;
271 
272  iwl_trans = iwl_trans_pcie_alloc(pdev, ent, cfg);
273  if (iwl_trans == NULL)
274  return -ENOMEM;
275 
276  pci_set_drvdata(pdev, iwl_trans);
277 
278  trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
279  trans_pcie->drv = iwl_drv_start(iwl_trans, cfg);
280  if (!trans_pcie->drv)
281  goto out_free_trans;
282 
283  /* register transport layer debugfs here */
284  if (iwl_trans_dbgfs_register(iwl_trans, iwl_trans->dbgfs_dir))
285  goto out_free_drv;
286 
287  return 0;
288 
289 out_free_drv:
290  iwl_drv_stop(trans_pcie->drv);
291 out_free_trans:
292  iwl_trans_pcie_free(iwl_trans);
293  pci_set_drvdata(pdev, NULL);
294  return -EFAULT;
295 }
296 
297 static void __devexit iwl_pci_remove(struct pci_dev *pdev)
298 {
299  struct iwl_trans *trans = pci_get_drvdata(pdev);
300  struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
301 
302  iwl_drv_stop(trans_pcie->drv);
303  iwl_trans_pcie_free(trans);
304 
305  pci_set_drvdata(pdev, NULL);
306 }
307 
308 #ifdef CONFIG_PM_SLEEP
309 
310 static int iwl_pci_suspend(struct device *device)
311 {
312  struct pci_dev *pdev = to_pci_dev(device);
313  struct iwl_trans *iwl_trans = pci_get_drvdata(pdev);
314 
315  /* Before you put code here, think about WoWLAN. You cannot check here
316  * whether WoWLAN is enabled or not, and your code will run even if
317  * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx.
318  */
319 
320  return iwl_trans_suspend(iwl_trans);
321 }
322 
323 static int iwl_pci_resume(struct device *device)
324 {
325  struct pci_dev *pdev = to_pci_dev(device);
326  struct iwl_trans *iwl_trans = pci_get_drvdata(pdev);
327 
328  /* Before you put code here, think about WoWLAN. You cannot check here
329  * whether WoWLAN is enabled or not, and your code will run even if
330  * WoWLAN is enabled - the NIC may be alive.
331  */
332 
333  /*
334  * We disable the RETRY_TIMEOUT register (0x41) to keep
335  * PCI Tx retries from interfering with C3 CPU state.
336  */
337  pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
338 
339  return iwl_trans_resume(iwl_trans);
340 }
341 
342 static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);
343 
344 #define IWL_PM_OPS (&iwl_dev_pm_ops)
345 
346 #else
347 
348 #define IWL_PM_OPS NULL
349 
350 #endif
351 
352 static struct pci_driver iwl_pci_driver = {
353  .name = DRV_NAME,
354  .id_table = iwl_hw_card_ids,
355  .probe = iwl_pci_probe,
356  .remove = __devexit_p(iwl_pci_remove),
357  .driver.pm = IWL_PM_OPS,
358 };
359 
361 {
362  int ret;
363  ret = pci_register_driver(&iwl_pci_driver);
364  if (ret)
365  pr_err("Unable to initialize PCI module\n");
366 
367  return ret;
368 }
369 
371 {
372  pci_unregister_driver(&iwl_pci_driver);
373 }