diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 87 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-io.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-pci.c | 113 |
4 files changed, 131 insertions, 84 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0098245a62ed..72db1a9fab84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -3486,7 +3486,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3486 | int err = 0; | 3486 | int err = 0; |
3487 | struct iwl_priv *priv; | 3487 | struct iwl_priv *priv; |
3488 | struct ieee80211_hw *hw; | 3488 | struct ieee80211_hw *hw; |
3489 | u16 pci_cmd, num_mac; | 3489 | u16 num_mac; |
3490 | u32 hw_rev; | 3490 | u32 hw_rev; |
3491 | 3491 | ||
3492 | /************************ | 3492 | /************************ |
@@ -3532,49 +3532,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3532 | if (iwl_alloc_traffic_mem(priv)) | 3532 | if (iwl_alloc_traffic_mem(priv)) |
3533 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); | 3533 | IWL_ERR(priv, "Not enough memory to generate traffic log\n"); |
3534 | 3534 | ||
3535 | /************************** | ||
3536 | * 2. Initializing PCI bus | ||
3537 | **************************/ | ||
3538 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
3539 | PCIE_LINK_STATE_CLKPM); | ||
3540 | |||
3541 | if (pci_enable_device(pdev)) { | ||
3542 | err = -ENODEV; | ||
3543 | goto out_ieee80211_free_hw; | ||
3544 | } | ||
3545 | |||
3546 | pci_set_master(pdev); | ||
3547 | |||
3548 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); | ||
3549 | if (!err) | ||
3550 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); | ||
3551 | if (err) { | ||
3552 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
3553 | if (!err) | ||
3554 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
3555 | /* both attempts failed: */ | ||
3556 | if (err) { | ||
3557 | IWL_WARN(priv, "No suitable DMA available.\n"); | ||
3558 | goto out_pci_disable_device; | ||
3559 | } | ||
3560 | } | ||
3561 | |||
3562 | err = pci_request_regions(pdev, DRV_NAME); | ||
3563 | if (err) | ||
3564 | goto out_pci_disable_device; | ||
3565 | |||
3566 | /*********************** | ||
3567 | * 3. Read REV register | ||
3568 | ***********************/ | ||
3569 | priv->hw_base = pci_iomap(pdev, 0, 0); | ||
3570 | if (!priv->hw_base) { | ||
3571 | err = -ENODEV; | ||
3572 | goto out_pci_release_regions; | ||
3573 | } | ||
3574 | |||
3575 | IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n", | ||
3576 | (unsigned long long) pci_resource_len(pdev, 0)); | ||
3577 | IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); | ||
3578 | 3535 | ||
3579 | /* these spin locks will be used in apm_ops.init and EEPROM access | 3536 | /* these spin locks will be used in apm_ops.init and EEPROM access |
3580 | * we should init now | 3537 | * we should init now |
@@ -3589,17 +3546,16 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3589 | */ | 3546 | */ |
3590 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 3547 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
3591 | 3548 | ||
3549 | /*********************** | ||
3550 | * 3. Read REV register | ||
3551 | ***********************/ | ||
3592 | hw_rev = iwl_hw_detect(priv); | 3552 | hw_rev = iwl_hw_detect(priv); |
3593 | IWL_INFO(priv, "Detected %s, REV=0x%X\n", | 3553 | IWL_INFO(priv, "Detected %s, REV=0x%X\n", |
3594 | priv->cfg->name, hw_rev); | 3554 | priv->cfg->name, hw_rev); |
3595 | 3555 | ||
3596 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | ||
3597 | * PCI Tx retries from interfering with C3 CPU state */ | ||
3598 | pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); | ||
3599 | |||
3600 | if (iwl_prepare_card_hw(priv)) { | 3556 | if (iwl_prepare_card_hw(priv)) { |
3601 | IWL_WARN(priv, "Failed, HW not ready\n"); | 3557 | IWL_WARN(priv, "Failed, HW not ready\n"); |
3602 | goto out_iounmap; | 3558 | goto out_free_traffic_mem; |
3603 | } | 3559 | } |
3604 | 3560 | ||
3605 | /***************** | 3561 | /***************** |
@@ -3609,7 +3565,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3609 | err = iwl_eeprom_init(priv, hw_rev); | 3565 | err = iwl_eeprom_init(priv, hw_rev); |
3610 | if (err) { | 3566 | if (err) { |
3611 | IWL_ERR(priv, "Unable to init EEPROM\n"); | 3567 | IWL_ERR(priv, "Unable to init EEPROM\n"); |
3612 | goto out_iounmap; | 3568 | goto out_free_traffic_mem; |
3613 | } | 3569 | } |
3614 | err = iwl_eeprom_check_version(priv); | 3570 | err = iwl_eeprom_check_version(priv); |
3615 | if (err) | 3571 | if (err) |
@@ -3639,6 +3595,7 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3639 | * 5. Setup HW constants | 3595 | * 5. Setup HW constants |
3640 | ************************/ | 3596 | ************************/ |
3641 | if (iwl_set_hw_params(priv)) { | 3597 | if (iwl_set_hw_params(priv)) { |
3598 | err = -ENOENT; | ||
3642 | IWL_ERR(priv, "failed to set hw parameters\n"); | 3599 | IWL_ERR(priv, "failed to set hw parameters\n"); |
3643 | goto out_free_eeprom; | 3600 | goto out_free_eeprom; |
3644 | } | 3601 | } |
@@ -3655,15 +3612,13 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3655 | /******************** | 3612 | /******************** |
3656 | * 7. Setup services | 3613 | * 7. Setup services |
3657 | ********************/ | 3614 | ********************/ |
3658 | pci_enable_msi(priv->pci_dev); | ||
3659 | |||
3660 | iwl_alloc_isr_ict(priv); | 3615 | iwl_alloc_isr_ict(priv); |
3661 | 3616 | ||
3662 | err = request_irq(priv->pci_dev->irq, iwl_isr_ict, | 3617 | err = request_irq(priv->pci_dev->irq, iwl_isr_ict, |
3663 | IRQF_SHARED, DRV_NAME, priv); | 3618 | IRQF_SHARED, DRV_NAME, priv); |
3664 | if (err) { | 3619 | if (err) { |
3665 | IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); | 3620 | IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); |
3666 | goto out_disable_msi; | 3621 | goto out_uninit_drv; |
3667 | } | 3622 | } |
3668 | 3623 | ||
3669 | iwl_setup_deferred_work(priv); | 3624 | iwl_setup_deferred_work(priv); |
@@ -3671,16 +3626,9 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3671 | iwl_testmode_init(priv); | 3626 | iwl_testmode_init(priv); |
3672 | 3627 | ||
3673 | /********************************************* | 3628 | /********************************************* |
3674 | * 8. Enable interrupts and read RFKILL state | 3629 | * 8. Enable interrupts |
3675 | *********************************************/ | 3630 | *********************************************/ |
3676 | 3631 | ||
3677 | /* enable rfkill interrupt: hw bug w/a */ | ||
3678 | pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); | ||
3679 | if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { | ||
3680 | pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; | ||
3681 | pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); | ||
3682 | } | ||
3683 | |||
3684 | iwl_enable_rfkill_int(priv); | 3632 | iwl_enable_rfkill_int(priv); |
3685 | 3633 | ||
3686 | /* If platform's RF_KILL switch is NOT set to KILL */ | 3634 | /* If platform's RF_KILL switch is NOT set to KILL */ |
@@ -3707,20 +3655,12 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3707 | destroy_workqueue(priv->workqueue); | 3655 | destroy_workqueue(priv->workqueue); |
3708 | priv->workqueue = NULL; | 3656 | priv->workqueue = NULL; |
3709 | free_irq(priv->pci_dev->irq, priv); | 3657 | free_irq(priv->pci_dev->irq, priv); |
3710 | out_disable_msi: | ||
3711 | iwl_free_isr_ict(priv); | 3658 | iwl_free_isr_ict(priv); |
3712 | pci_disable_msi(priv->pci_dev); | 3659 | out_uninit_drv: |
3713 | iwl_uninit_drv(priv); | 3660 | iwl_uninit_drv(priv); |
3714 | out_free_eeprom: | 3661 | out_free_eeprom: |
3715 | iwl_eeprom_free(priv); | 3662 | iwl_eeprom_free(priv); |
3716 | out_iounmap: | 3663 | out_free_traffic_mem: |
3717 | pci_iounmap(pdev, priv->hw_base); | ||
3718 | out_pci_release_regions: | ||
3719 | priv->bus.ops->set_drv_data(&priv->bus, NULL); | ||
3720 | pci_release_regions(pdev); | ||
3721 | out_pci_disable_device: | ||
3722 | pci_disable_device(pdev); | ||
3723 | out_ieee80211_free_hw: | ||
3724 | iwl_free_traffic_mem(priv); | 3664 | iwl_free_traffic_mem(priv); |
3725 | ieee80211_free_hw(priv->hw); | 3665 | ieee80211_free_hw(priv->hw); |
3726 | out: | 3666 | out: |
@@ -3729,7 +3669,6 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3729 | 3669 | ||
3730 | void __devexit iwl_remove(struct iwl_priv * priv) | 3670 | void __devexit iwl_remove(struct iwl_priv * priv) |
3731 | { | 3671 | { |
3732 | struct pci_dev *pdev = priv->pci_dev; | ||
3733 | unsigned long flags; | 3672 | unsigned long flags; |
3734 | 3673 | ||
3735 | wait_for_completion(&priv->_agn.firmware_loading_complete); | 3674 | wait_for_completion(&priv->_agn.firmware_loading_complete); |
@@ -3788,10 +3727,6 @@ void __devexit iwl_remove(struct iwl_priv * priv) | |||
3788 | iwl_free_traffic_mem(priv); | 3727 | iwl_free_traffic_mem(priv); |
3789 | 3728 | ||
3790 | free_irq(priv->pci_dev->irq, priv); | 3729 | free_irq(priv->pci_dev->irq, priv); |
3791 | pci_disable_msi(priv->pci_dev); | ||
3792 | pci_iounmap(pdev, priv->hw_base); | ||
3793 | pci_release_regions(pdev); | ||
3794 | pci_disable_device(pdev); | ||
3795 | priv->bus.ops->set_drv_data(&priv->bus, NULL); | 3730 | priv->bus.ops->set_drv_data(&priv->bus, NULL); |
3796 | 3731 | ||
3797 | iwl_uninit_drv(priv); | 3732 | iwl_uninit_drv(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 49e6c68f9b75..700e9f92129c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -1195,10 +1195,16 @@ struct iwl_bus; | |||
1195 | * struct iwl_bus_ops - bus specific operations | 1195 | * struct iwl_bus_ops - bus specific operations |
1196 | * @set_drv_data: set the priv pointer to the bus layer | 1196 | * @set_drv_data: set the priv pointer to the bus layer |
1197 | * @get_dev: returns the device struct | 1197 | * @get_dev: returns the device struct |
1198 | * @write8: write a byte to register at offset ofs | ||
1199 | * @write32: write a dword to register at offset ofs | ||
1200 | * @wread32: read a dword at register at offset ofs | ||
1198 | */ | 1201 | */ |
1199 | struct iwl_bus_ops { | 1202 | struct iwl_bus_ops { |
1200 | void (*set_drv_data)(struct iwl_bus *bus, void *priv); | 1203 | void (*set_drv_data)(struct iwl_bus *bus, void *priv); |
1201 | struct device *(*get_dev)(const struct iwl_bus *bus); | 1204 | struct device *(*get_dev)(const struct iwl_bus *bus); |
1205 | void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); | ||
1206 | void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); | ||
1207 | u32 (*read32)(struct iwl_bus *bus, u32 ofs); | ||
1202 | }; | 1208 | }; |
1203 | 1209 | ||
1204 | struct iwl_bus { | 1210 | struct iwl_bus { |
@@ -1282,9 +1288,6 @@ struct iwl_priv { | |||
1282 | /* basic pci-network driver stuff */ | 1288 | /* basic pci-network driver stuff */ |
1283 | struct pci_dev *pci_dev; | 1289 | struct pci_dev *pci_dev; |
1284 | 1290 | ||
1285 | /* pci hardware address support */ | ||
1286 | void __iomem *hw_base; | ||
1287 | |||
1288 | struct iwl_bus bus; /* bus specific data */ | 1291 | struct iwl_bus bus; /* bus specific data */ |
1289 | 1292 | ||
1290 | /* microcode/device supports multiple contexts */ | 1293 | /* microcode/device supports multiple contexts */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 869edc580ec6..c56eae74c3cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -38,18 +38,18 @@ | |||
38 | static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) | 38 | static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) |
39 | { | 39 | { |
40 | trace_iwlwifi_dev_iowrite8(priv, ofs, val); | 40 | trace_iwlwifi_dev_iowrite8(priv, ofs, val); |
41 | iowrite8(val, priv->hw_base + ofs); | 41 | priv->bus.ops->write8(&priv->bus, ofs, val); |
42 | } | 42 | } |
43 | 43 | ||
44 | static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) | 44 | static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) |
45 | { | 45 | { |
46 | trace_iwlwifi_dev_iowrite32(priv, ofs, val); | 46 | trace_iwlwifi_dev_iowrite32(priv, ofs, val); |
47 | iowrite32(val, priv->hw_base + ofs); | 47 | priv->bus.ops->write32(&priv->bus, ofs, val); |
48 | } | 48 | } |
49 | 49 | ||
50 | static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) | 50 | static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) |
51 | { | 51 | { |
52 | u32 val = ioread32(priv->hw_base + ofs); | 52 | u32 val = priv->bus.ops->read32(&priv->bus, ofs); |
53 | trace_iwlwifi_dev_ioread32(priv, ofs, val); | 53 | trace_iwlwifi_dev_ioread32(priv, ofs, val); |
54 | return val; | 54 | return val; |
55 | } | 55 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 00458fc2c402..43de98efa3e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c | |||
@@ -91,9 +91,28 @@ static struct device *iwl_pci_get_dev(const struct iwl_bus *bus) | |||
91 | return &(IWL_BUS_GET_PCI_DEV(bus)->dev); | 91 | return &(IWL_BUS_GET_PCI_DEV(bus)->dev); |
92 | } | 92 | } |
93 | 93 | ||
94 | static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val) | ||
95 | { | ||
96 | iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); | ||
97 | } | ||
98 | |||
99 | static void iwl_pci_write32(struct iwl_bus *bus, u32 ofs, u32 val) | ||
100 | { | ||
101 | iowrite32(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); | ||
102 | } | ||
103 | |||
104 | static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) | ||
105 | { | ||
106 | u32 val = ioread32(IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); | ||
107 | return val; | ||
108 | } | ||
109 | |||
94 | static struct iwl_bus_ops pci_ops = { | 110 | static struct iwl_bus_ops pci_ops = { |
95 | .set_drv_data = iwl_pci_set_drv_data, | 111 | .set_drv_data = iwl_pci_set_drv_data, |
96 | .get_dev = iwl_pci_get_dev, | 112 | .get_dev = iwl_pci_get_dev, |
113 | .write8 = iwl_pci_write8, | ||
114 | .write32 = iwl_pci_write32, | ||
115 | .read32 = iwl_pci_read32, | ||
97 | }; | 116 | }; |
98 | 117 | ||
99 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 118 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
@@ -296,6 +315,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
296 | { | 315 | { |
297 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); | 316 | struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); |
298 | struct iwl_pci_bus *bus; | 317 | struct iwl_pci_bus *bus; |
318 | u8 rev_id; | ||
319 | u16 pci_cmd; | ||
299 | int err; | 320 | int err; |
300 | 321 | ||
301 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); | 322 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); |
@@ -307,16 +328,103 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
307 | 328 | ||
308 | bus->pci_dev = pdev; | 329 | bus->pci_dev = pdev; |
309 | 330 | ||
331 | /* W/A - seems to solve weird behavior. We need to remove this if we | ||
332 | * don't want to stay in L1 all the time. This wastes a lot of power */ | ||
333 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
334 | PCIE_LINK_STATE_CLKPM); | ||
335 | |||
336 | if (pci_enable_device(pdev)) { | ||
337 | err = -ENODEV; | ||
338 | goto out_no_pci; | ||
339 | } | ||
340 | |||
341 | pci_set_master(pdev); | ||
342 | |||
343 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); | ||
344 | if (!err) | ||
345 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); | ||
346 | if (err) { | ||
347 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
348 | if (!err) | ||
349 | err = pci_set_consistent_dma_mask(pdev, | ||
350 | DMA_BIT_MASK(32)); | ||
351 | /* both attempts failed: */ | ||
352 | if (err) { | ||
353 | pr_err("No suitable DMA available.\n"); | ||
354 | goto out_pci_disable_device; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | err = pci_request_regions(pdev, DRV_NAME); | ||
359 | if (err) { | ||
360 | pr_err("pci_request_regions failed"); | ||
361 | goto out_pci_disable_device; | ||
362 | } | ||
363 | |||
364 | bus->hw_base = pci_iomap(pdev, 0, 0); | ||
365 | if (!bus->hw_base) { | ||
366 | pr_err("pci_iomap failed"); | ||
367 | err = -ENODEV; | ||
368 | goto out_pci_release_regions; | ||
369 | } | ||
370 | |||
371 | pr_info("pci_resource_len = 0x%08llx\n", | ||
372 | (unsigned long long) pci_resource_len(pdev, 0)); | ||
373 | pr_info("pci_resource_base = %p\n", bus->hw_base); | ||
374 | |||
375 | pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); | ||
376 | pr_info("HW Revision ID = 0x%X\n", rev_id); | ||
377 | |||
378 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | ||
379 | * PCI Tx retries from interfering with C3 CPU state */ | ||
380 | pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); | ||
381 | |||
382 | err = pci_enable_msi(pdev); | ||
383 | if (err) { | ||
384 | pr_err("pci_enable_msi failed"); | ||
385 | goto out_iounmap; | ||
386 | } | ||
387 | |||
388 | /* TODO: Move this away, not needed if not MSI */ | ||
389 | /* enable rfkill interrupt: hw bug w/a */ | ||
390 | pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); | ||
391 | if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { | ||
392 | pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; | ||
393 | pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); | ||
394 | } | ||
395 | |||
310 | err = iwl_probe((void *) bus, &pci_ops, cfg); | 396 | err = iwl_probe((void *) bus, &pci_ops, cfg); |
311 | if (err) | 397 | if (err) |
312 | goto out_no_pci; | 398 | goto out_disable_msi; |
313 | return 0; | 399 | return 0; |
314 | 400 | ||
401 | out_disable_msi: | ||
402 | pci_disable_msi(pdev); | ||
403 | out_iounmap: | ||
404 | pci_iounmap(pdev, bus->hw_base); | ||
405 | out_pci_release_regions: | ||
406 | pci_set_drvdata(pdev, NULL); | ||
407 | pci_release_regions(pdev); | ||
408 | out_pci_disable_device: | ||
409 | pci_disable_device(pdev); | ||
315 | out_no_pci: | 410 | out_no_pci: |
316 | kfree(bus); | 411 | kfree(bus); |
317 | return err; | 412 | return err; |
318 | } | 413 | } |
319 | 414 | ||
415 | static void iwl_pci_down(void *bus) | ||
416 | { | ||
417 | struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus; | ||
418 | |||
419 | pci_disable_msi(pci_bus->pci_dev); | ||
420 | pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base); | ||
421 | pci_release_regions(pci_bus->pci_dev); | ||
422 | pci_disable_device(pci_bus->pci_dev); | ||
423 | pci_set_drvdata(pci_bus->pci_dev, NULL); | ||
424 | |||
425 | kfree(pci_bus); | ||
426 | } | ||
427 | |||
320 | static void __devexit iwl_pci_remove(struct pci_dev *pdev) | 428 | static void __devexit iwl_pci_remove(struct pci_dev *pdev) |
321 | { | 429 | { |
322 | struct iwl_priv *priv = pci_get_drvdata(pdev); | 430 | struct iwl_priv *priv = pci_get_drvdata(pdev); |
@@ -326,7 +434,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
326 | return; | 434 | return; |
327 | 435 | ||
328 | iwl_remove(priv); | 436 | iwl_remove(priv); |
329 | kfree(IWL_BUS_GET_PCI_BUS(&priv->bus)); | 437 | |
438 | iwl_pci_down(IWL_BUS_GET_PCI_BUS(&priv->bus)); | ||
330 | } | 439 | } |
331 | 440 | ||
332 | #ifdef CONFIG_PM | 441 | #ifdef CONFIG_PM |