]>
Commit | Line | Data |
---|---|---|
75a6faf6 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
a4d36e20 DV |
2 | /* |
3 | * aQuantia Corporation Network Driver | |
04a18399 | 4 | * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved |
a4d36e20 DV |
5 | */ |
6 | ||
7 | /* File aq_pci_func.c: Definition of PCI functions. */ | |
8 | ||
5b97b0d1 IR |
9 | #include <linux/interrupt.h> |
10 | #include <linux/module.h> | |
11 | ||
23ee07ad | 12 | #include "aq_main.h" |
a4d36e20 DV |
13 | #include "aq_nic.h" |
14 | #include "aq_vec.h" | |
15 | #include "aq_hw.h" | |
23ee07ad | 16 | #include "aq_pci_func.h" |
5b97b0d1 IR |
17 | #include "hw_atl/hw_atl_a0.h" |
18 | #include "hw_atl/hw_atl_b0.h" | |
8d0bcb01 | 19 | #include "aq_filters.h" |
4c013153 | 20 | #include "aq_drvinfo.h" |
62c1c2e6 | 21 | #include "aq_macsec.h" |
a4d36e20 | 22 | |
5b97b0d1 | 23 | static const struct pci_device_id aq_pci_tbl[] = { |
efe779b7 IR |
24 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_0001), }, |
25 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D100), }, | |
26 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D107), }, | |
27 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D108), }, | |
28 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D109), }, | |
29 | ||
30 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC100), }, | |
31 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC107), }, | |
32 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC108), }, | |
33 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC109), }, | |
34 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111), }, | |
35 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112), }, | |
36 | ||
37 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC100S), }, | |
38 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC107S), }, | |
39 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC108S), }, | |
40 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC109S), }, | |
41 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111S), }, | |
42 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112S), }, | |
43 | ||
5b97b0d1 IR |
44 | {} |
45 | }; | |
46 | ||
e8a22b5f | 47 | static const struct aq_board_revision_s hw_atl_boards[] = { |
4948293f IR |
48 | { AQ_DEVICE_ID_0001, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc107, }, |
49 | { AQ_DEVICE_ID_D100, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc100, }, | |
50 | { AQ_DEVICE_ID_D107, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc107, }, | |
51 | { AQ_DEVICE_ID_D108, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc108, }, | |
52 | { AQ_DEVICE_ID_D109, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc109, }, | |
53 | ||
54 | { AQ_DEVICE_ID_0001, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc107, }, | |
55 | { AQ_DEVICE_ID_D100, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc100, }, | |
56 | { AQ_DEVICE_ID_D107, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc107, }, | |
57 | { AQ_DEVICE_ID_D108, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc108, }, | |
58 | { AQ_DEVICE_ID_D109, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc109, }, | |
59 | ||
6de556c3 | 60 | { AQ_DEVICE_ID_AQC100, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100, }, |
4948293f IR |
61 | { AQ_DEVICE_ID_AQC107, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, }, |
62 | { AQ_DEVICE_ID_AQC108, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108, }, | |
63 | { AQ_DEVICE_ID_AQC109, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109, }, | |
64 | { AQ_DEVICE_ID_AQC111, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111, }, | |
65 | { AQ_DEVICE_ID_AQC112, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112, }, | |
66 | ||
67 | { AQ_DEVICE_ID_AQC100S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100s, }, | |
68 | { AQ_DEVICE_ID_AQC107S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107s, }, | |
69 | { AQ_DEVICE_ID_AQC108S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108s, }, | |
70 | { AQ_DEVICE_ID_AQC109S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109s, }, | |
71 | { AQ_DEVICE_ID_AQC111S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111s, }, | |
72 | { AQ_DEVICE_ID_AQC112S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112s, }, | |
4948293f IR |
73 | }; |
74 | ||
5b97b0d1 IR |
75 | MODULE_DEVICE_TABLE(pci, aq_pci_tbl); |
76 | ||
4948293f IR |
77 | static int aq_pci_probe_get_hw_by_id(struct pci_dev *pdev, |
78 | const struct aq_hw_ops **ops, | |
79 | const struct aq_hw_caps_s **caps) | |
5b97b0d1 | 80 | { |
a26b0b53 | 81 | int i; |
4948293f IR |
82 | |
83 | if (pdev->vendor != PCI_VENDOR_ID_AQUANTIA) | |
84 | return -EINVAL; | |
85 | ||
86 | for (i = 0; i < ARRAY_SIZE(hw_atl_boards); i++) { | |
87 | if (hw_atl_boards[i].devid == pdev->device && | |
88 | (hw_atl_boards[i].revision == AQ_HWREV_ANY || | |
89 | hw_atl_boards[i].revision == pdev->revision)) { | |
90 | *ops = hw_atl_boards[i].ops; | |
91 | *caps = hw_atl_boards[i].caps; | |
92 | break; | |
93 | } | |
94 | } | |
5b97b0d1 | 95 | |
4948293f IR |
96 | if (i == ARRAY_SIZE(hw_atl_boards)) |
97 | return -EINVAL; | |
5b97b0d1 | 98 | |
4948293f | 99 | return 0; |
5b97b0d1 IR |
100 | } |
101 | ||
23ee07ad | 102 | int aq_pci_func_init(struct pci_dev *pdev) |
a4d36e20 | 103 | { |
a26b0b53 | 104 | int err; |
a4d36e20 | 105 | |
23ee07ad | 106 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); |
a4d36e20 | 107 | if (!err) { |
23ee07ad IR |
108 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); |
109 | ||
a4d36e20 DV |
110 | } |
111 | if (err) { | |
23ee07ad | 112 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
a4d36e20 | 113 | if (!err) |
23ee07ad | 114 | err = pci_set_consistent_dma_mask(pdev, |
a4d36e20 | 115 | DMA_BIT_MASK(32)); |
a4d36e20 DV |
116 | } |
117 | if (err != 0) { | |
118 | err = -ENOSR; | |
119 | goto err_exit; | |
120 | } | |
121 | ||
23ee07ad | 122 | err = pci_request_regions(pdev, AQ_CFG_DRV_NAME "_mmio"); |
a4d36e20 DV |
123 | if (err < 0) |
124 | goto err_exit; | |
125 | ||
23ee07ad | 126 | pci_set_master(pdev); |
a4d36e20 | 127 | |
23ee07ad | 128 | return 0; |
a4d36e20 DV |
129 | |
130 | err_exit: | |
a4d36e20 DV |
131 | return err; |
132 | } | |
133 | ||
23ee07ad | 134 | int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i, |
4c83f170 IR |
135 | char *name, irq_handler_t irq_handler, |
136 | void *irq_arg, cpumask_t *affinity_mask) | |
a4d36e20 | 137 | { |
36a4a50f | 138 | struct pci_dev *pdev = self->pdev; |
a26b0b53 | 139 | int err; |
a4d36e20 | 140 | |
36a4a50f | 141 | if (pdev->msix_enabled || pdev->msi_enabled) |
4c83f170 IR |
142 | err = request_irq(pci_irq_vector(pdev, i), irq_handler, 0, |
143 | name, irq_arg); | |
36a4a50f CH |
144 | else |
145 | err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr_legacy, | |
4c83f170 | 146 | IRQF_SHARED, name, irq_arg); |
a4d36e20 DV |
147 | |
148 | if (err >= 0) { | |
149 | self->msix_entry_mask |= (1 << i); | |
a4d36e20 | 150 | |
4c83f170 | 151 | if (pdev->msix_enabled && affinity_mask) |
36a4a50f | 152 | irq_set_affinity_hint(pci_irq_vector(pdev, i), |
a4d36e20 DV |
153 | affinity_mask); |
154 | } | |
4c83f170 | 155 | |
a4d36e20 DV |
156 | return err; |
157 | } | |
158 | ||
23ee07ad | 159 | void aq_pci_func_free_irqs(struct aq_nic_s *self) |
a4d36e20 | 160 | { |
36a4a50f | 161 | struct pci_dev *pdev = self->pdev; |
a26b0b53 | 162 | unsigned int i; |
4c83f170 | 163 | void *irq_data; |
a4d36e20 DV |
164 | |
165 | for (i = 32U; i--;) { | |
166 | if (!((1U << i) & self->msix_entry_mask)) | |
167 | continue; | |
4c83f170 IR |
168 | if (self->aq_nic_cfg.link_irq_vec && |
169 | i == self->aq_nic_cfg.link_irq_vec) | |
170 | irq_data = self; | |
171 | else if (i < AQ_CFG_VECS_MAX) | |
172 | irq_data = self->aq_vec[i]; | |
173 | else | |
13b7997a | 174 | continue; |
a4d36e20 | 175 | |
36a4a50f CH |
176 | if (pdev->msix_enabled) |
177 | irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL); | |
4c83f170 | 178 | free_irq(pci_irq_vector(pdev, i), irq_data); |
a4d36e20 DV |
179 | self->msix_entry_mask &= ~(1U << i); |
180 | } | |
181 | } | |
182 | ||
23ee07ad | 183 | unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self) |
a4d36e20 | 184 | { |
36a4a50f CH |
185 | if (self->pdev->msix_enabled) |
186 | return AQ_HW_IRQ_MSIX; | |
187 | if (self->pdev->msi_enabled) | |
18eac376 | 188 | return AQ_HW_IRQ_MSI; |
7b0c342f | 189 | |
36a4a50f | 190 | return AQ_HW_IRQ_LEGACY; |
a4d36e20 DV |
191 | } |
192 | ||
23ee07ad | 193 | static void aq_pci_free_irq_vectors(struct aq_nic_s *self) |
a4d36e20 | 194 | { |
36a4a50f | 195 | pci_free_irq_vectors(self->pdev); |
23ee07ad | 196 | } |
a4d36e20 | 197 | |
23ee07ad IR |
198 | static int aq_pci_probe(struct pci_dev *pdev, |
199 | const struct pci_device_id *pci_id) | |
200 | { | |
23ee07ad IR |
201 | struct net_device *ndev; |
202 | resource_size_t mmio_pa; | |
7b0c342f | 203 | struct aq_nic_s *self; |
23ee07ad | 204 | u32 numvecs; |
7b0c342f ND |
205 | u32 bar; |
206 | int err; | |
a4d36e20 | 207 | |
23ee07ad IR |
208 | err = pci_enable_device(pdev); |
209 | if (err) | |
210 | return err; | |
a4d36e20 | 211 | |
23ee07ad IR |
212 | err = aq_pci_func_init(pdev); |
213 | if (err) | |
214 | goto err_pci_func; | |
a4d36e20 | 215 | |
23ee07ad | 216 | ndev = aq_ndev_alloc(); |
f03e4f8a WY |
217 | if (!ndev) { |
218 | err = -ENOMEM; | |
23ee07ad | 219 | goto err_ndev; |
f03e4f8a | 220 | } |
a4d36e20 | 221 | |
23ee07ad IR |
222 | self = netdev_priv(ndev); |
223 | self->pdev = pdev; | |
224 | SET_NETDEV_DEV(ndev, &pdev->dev); | |
225 | pci_set_drvdata(pdev, self); | |
a4d36e20 | 226 | |
f5dce08a ND |
227 | mutex_init(&self->fwreq_mutex); |
228 | ||
23ee07ad IR |
229 | err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops, |
230 | &aq_nic_get_cfg(self)->aq_hw_caps); | |
231 | if (err) | |
232 | goto err_ioremap; | |
a4d36e20 | 233 | |
23ee07ad | 234 | self->aq_hw = kzalloc(sizeof(*self->aq_hw), GFP_KERNEL); |
370c1052 DC |
235 | if (!self->aq_hw) { |
236 | err = -ENOMEM; | |
237 | goto err_ioremap; | |
238 | } | |
23ee07ad | 239 | self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self); |
a4d36e20 | 240 | |
23ee07ad IR |
241 | for (bar = 0; bar < 4; ++bar) { |
242 | if (IORESOURCE_MEM & pci_resource_flags(pdev, bar)) { | |
243 | resource_size_t reg_sz; | |
6849540a | 244 | |
23ee07ad IR |
245 | mmio_pa = pci_resource_start(pdev, bar); |
246 | if (mmio_pa == 0U) { | |
247 | err = -EIO; | |
370c1052 | 248 | goto err_free_aq_hw; |
23ee07ad | 249 | } |
a4d36e20 | 250 | |
23ee07ad IR |
251 | reg_sz = pci_resource_len(pdev, bar); |
252 | if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) { | |
253 | err = -EIO; | |
370c1052 | 254 | goto err_free_aq_hw; |
23ee07ad | 255 | } |
a4d36e20 | 256 | |
4bdc0d67 | 257 | self->aq_hw->mmio = ioremap(mmio_pa, reg_sz); |
23ee07ad IR |
258 | if (!self->aq_hw->mmio) { |
259 | err = -EIO; | |
370c1052 | 260 | goto err_free_aq_hw; |
23ee07ad IR |
261 | } |
262 | break; | |
263 | } | |
264 | } | |
a4d36e20 | 265 | |
23ee07ad IR |
266 | if (bar == 4) { |
267 | err = -EIO; | |
370c1052 | 268 | goto err_free_aq_hw; |
a4d36e20 | 269 | } |
a4d36e20 | 270 | |
23ee07ad IR |
271 | numvecs = min((u8)AQ_CFG_VECS_DEF, |
272 | aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs); | |
273 | numvecs = min(numvecs, num_online_cpus()); | |
04a18399 EP |
274 | /* Request IRQ vector for PTP */ |
275 | numvecs += 1; | |
276 | ||
4c83f170 | 277 | numvecs += AQ_HW_SERVICE_IRQS; |
23ee07ad IR |
278 | /*enable interrupts */ |
279 | #if !AQ_CFG_FORCE_LEGACY_INT | |
58d813af CIK |
280 | err = pci_alloc_irq_vectors(self->pdev, 1, numvecs, |
281 | PCI_IRQ_MSIX | PCI_IRQ_MSI | | |
282 | PCI_IRQ_LEGACY); | |
a09bd81b | 283 | |
58d813af | 284 | if (err < 0) |
a09bd81b | 285 | goto err_hwinit; |
58d813af | 286 | numvecs = err; |
23ee07ad | 287 | #endif |
a09bd81b | 288 | self->irqvecs = numvecs; |
a4d36e20 | 289 | |
23ee07ad IR |
290 | /* net device init */ |
291 | aq_nic_cfg_start(self); | |
5b97b0d1 | 292 | |
23ee07ad | 293 | aq_nic_ndev_init(self); |
5b97b0d1 | 294 | |
23ee07ad | 295 | err = aq_nic_ndev_register(self); |
5b97b0d1 | 296 | if (err < 0) |
23ee07ad | 297 | goto err_register; |
5b97b0d1 | 298 | |
4c013153 YE |
299 | aq_drvinfo_init(ndev); |
300 | ||
23ee07ad IR |
301 | return 0; |
302 | ||
303 | err_register: | |
304 | aq_nic_free_vectors(self); | |
305 | aq_pci_free_irq_vectors(self); | |
306 | err_hwinit: | |
307 | iounmap(self->aq_hw->mmio); | |
370c1052 DC |
308 | err_free_aq_hw: |
309 | kfree(self->aq_hw); | |
23ee07ad IR |
310 | err_ioremap: |
311 | free_netdev(ndev); | |
23ee07ad | 312 | err_ndev: |
a09bd81b IR |
313 | pci_release_regions(pdev); |
314 | err_pci_func: | |
23ee07ad | 315 | pci_disable_device(pdev); |
7b0c342f | 316 | |
5b97b0d1 IR |
317 | return err; |
318 | } | |
319 | ||
320 | static void aq_pci_remove(struct pci_dev *pdev) | |
321 | { | |
23ee07ad IR |
322 | struct aq_nic_s *self = pci_get_drvdata(pdev); |
323 | ||
324 | if (self->ndev) { | |
8d0bcb01 | 325 | aq_clear_rxnfc_all_rules(self); |
23ee07ad IR |
326 | if (self->ndev->reg_state == NETREG_REGISTERED) |
327 | unregister_netdev(self->ndev); | |
62c1c2e6 DB |
328 | |
329 | #if IS_ENABLED(CONFIG_MACSEC) | |
330 | aq_macsec_free(self); | |
331 | #endif | |
23ee07ad IR |
332 | aq_nic_free_vectors(self); |
333 | aq_pci_free_irq_vectors(self); | |
334 | iounmap(self->aq_hw->mmio); | |
335 | kfree(self->aq_hw); | |
336 | pci_release_regions(pdev); | |
337 | free_netdev(self->ndev); | |
338 | } | |
5b97b0d1 | 339 | |
23ee07ad | 340 | pci_disable_device(pdev); |
5b97b0d1 IR |
341 | } |
342 | ||
90869ddf IR |
343 | static void aq_pci_shutdown(struct pci_dev *pdev) |
344 | { | |
345 | struct aq_nic_s *self = pci_get_drvdata(pdev); | |
346 | ||
347 | aq_nic_shutdown(self); | |
348 | ||
349 | pci_disable_device(pdev); | |
350 | ||
351 | if (system_state == SYSTEM_POWER_OFF) { | |
352 | pci_wake_from_d3(pdev, false); | |
353 | pci_set_power_state(pdev, PCI_D3hot); | |
354 | } | |
355 | } | |
356 | ||
8aaa112a | 357 | static int aq_suspend_common(struct device *dev, bool deep) |
5b97b0d1 | 358 | { |
8aaa112a ND |
359 | struct aq_nic_s *nic = pci_get_drvdata(to_pci_dev(dev)); |
360 | ||
361 | rtnl_lock(); | |
362 | ||
363 | nic->power_state = AQ_HW_POWER_STATE_D3; | |
364 | netif_device_detach(nic->ndev); | |
365 | netif_tx_stop_all_queues(nic->ndev); | |
5b97b0d1 | 366 | |
52a22f4d PB |
367 | if (netif_running(nic->ndev)) |
368 | aq_nic_stop(nic); | |
8aaa112a ND |
369 | |
370 | if (deep) { | |
371 | aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol); | |
372 | aq_nic_set_power(nic); | |
373 | } | |
374 | ||
375 | rtnl_unlock(); | |
376 | ||
377 | return 0; | |
5b97b0d1 IR |
378 | } |
379 | ||
8aaa112a | 380 | static int atl_resume_common(struct device *dev, bool deep) |
5b97b0d1 | 381 | { |
8aaa112a ND |
382 | struct pci_dev *pdev = to_pci_dev(dev); |
383 | struct aq_nic_s *nic; | |
52a22f4d | 384 | int ret = 0; |
8aaa112a ND |
385 | |
386 | nic = pci_get_drvdata(pdev); | |
387 | ||
388 | rtnl_lock(); | |
389 | ||
390 | pci_set_power_state(pdev, PCI_D0); | |
391 | pci_restore_state(pdev); | |
392 | ||
393 | if (deep) { | |
394 | ret = aq_nic_init(nic); | |
395 | if (ret) | |
396 | goto err_exit; | |
397 | } | |
398 | ||
52a22f4d PB |
399 | if (netif_running(nic->ndev)) { |
400 | ret = aq_nic_start(nic); | |
401 | if (ret) | |
402 | goto err_exit; | |
403 | } | |
8aaa112a ND |
404 | |
405 | netif_device_attach(nic->ndev); | |
406 | netif_tx_start_all_queues(nic->ndev); | |
5b97b0d1 | 407 | |
8aaa112a ND |
408 | err_exit: |
409 | rtnl_unlock(); | |
410 | ||
411 | return ret; | |
412 | } | |
413 | ||
414 | static int aq_pm_freeze(struct device *dev) | |
415 | { | |
416 | return aq_suspend_common(dev, false); | |
5b97b0d1 IR |
417 | } |
418 | ||
8aaa112a ND |
419 | static int aq_pm_suspend_poweroff(struct device *dev) |
420 | { | |
421 | return aq_suspend_common(dev, true); | |
422 | } | |
423 | ||
424 | static int aq_pm_thaw(struct device *dev) | |
425 | { | |
426 | return atl_resume_common(dev, false); | |
427 | } | |
428 | ||
429 | static int aq_pm_resume_restore(struct device *dev) | |
430 | { | |
431 | return atl_resume_common(dev, true); | |
432 | } | |
433 | ||
0ee0bbb0 | 434 | static const struct dev_pm_ops aq_pm_ops = { |
8aaa112a ND |
435 | .suspend = aq_pm_suspend_poweroff, |
436 | .poweroff = aq_pm_suspend_poweroff, | |
437 | .freeze = aq_pm_freeze, | |
438 | .resume = aq_pm_resume_restore, | |
439 | .restore = aq_pm_resume_restore, | |
440 | .thaw = aq_pm_thaw, | |
441 | }; | |
442 | ||
5b97b0d1 IR |
443 | static struct pci_driver aq_pci_ops = { |
444 | .name = AQ_CFG_DRV_NAME, | |
445 | .id_table = aq_pci_tbl, | |
446 | .probe = aq_pci_probe, | |
447 | .remove = aq_pci_remove, | |
90869ddf | 448 | .shutdown = aq_pci_shutdown, |
8aaa112a ND |
449 | #ifdef CONFIG_PM |
450 | .driver.pm = &aq_pm_ops, | |
451 | #endif | |
5b97b0d1 IR |
452 | }; |
453 | ||
58608082 ND |
454 | int aq_pci_func_register_driver(void) |
455 | { | |
456 | return pci_register_driver(&aq_pci_ops); | |
457 | } | |
458 | ||
459 | void aq_pci_func_unregister_driver(void) | |
460 | { | |
461 | pci_unregister_driver(&aq_pci_ops); | |
462 | } | |
463 |