diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/pci.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/pci.c | 112 |
1 files changed, 64 insertions, 48 deletions
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 903dd8ad9d43..9441c6718a30 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -18,21 +18,23 @@ | |||
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include "ath9k.h" | 19 | #include "ath9k.h" |
20 | 20 | ||
21 | static struct pci_device_id ath_pci_id_table[] __devinitdata = { | 21 | static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { |
22 | { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ | 22 | { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ |
23 | { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ | 23 | { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ |
24 | { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ | 24 | { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ |
25 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ | 25 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ |
26 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ | 26 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ |
27 | { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ | 27 | { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ |
28 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ | ||
28 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ | 29 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ |
29 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ | 30 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ |
30 | { 0 } | 31 | { 0 } |
31 | }; | 32 | }; |
32 | 33 | ||
33 | /* return bus cachesize in 4B word units */ | 34 | /* return bus cachesize in 4B word units */ |
34 | static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) | 35 | static void ath_pci_read_cachesize(struct ath_common *common, int *csz) |
35 | { | 36 | { |
37 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
36 | u8 u8tmp; | 38 | u8 u8tmp; |
37 | 39 | ||
38 | pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, &u8tmp); | 40 | pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, &u8tmp); |
@@ -48,18 +50,11 @@ static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) | |||
48 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ | 50 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ |
49 | } | 51 | } |
50 | 52 | ||
51 | static void ath_pci_cleanup(struct ath_softc *sc) | 53 | static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) |
52 | { | 54 | { |
53 | struct pci_dev *pdev = to_pci_dev(sc->dev); | 55 | struct ath_hw *ah = (struct ath_hw *) common->ah; |
54 | |||
55 | pci_iounmap(pdev, sc->mem); | ||
56 | pci_disable_device(pdev); | ||
57 | pci_release_region(pdev, 0); | ||
58 | } | ||
59 | 56 | ||
60 | static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) | 57 | common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); |
61 | { | ||
62 | (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); | ||
63 | 58 | ||
64 | if (!ath9k_hw_wait(ah, | 59 | if (!ath9k_hw_wait(ah, |
65 | AR_EEPROM_STATUS_DATA, | 60 | AR_EEPROM_STATUS_DATA, |
@@ -69,16 +64,33 @@ static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) | |||
69 | return false; | 64 | return false; |
70 | } | 65 | } |
71 | 66 | ||
72 | *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), | 67 | *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), |
73 | AR_EEPROM_STATUS_DATA_VAL); | 68 | AR_EEPROM_STATUS_DATA_VAL); |
74 | 69 | ||
75 | return true; | 70 | return true; |
76 | } | 71 | } |
77 | 72 | ||
78 | static struct ath_bus_ops ath_pci_bus_ops = { | 73 | /* |
74 | * Bluetooth coexistance requires disabling ASPM. | ||
75 | */ | ||
76 | static void ath_pci_bt_coex_prep(struct ath_common *common) | ||
77 | { | ||
78 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
79 | struct pci_dev *pdev = to_pci_dev(sc->dev); | ||
80 | u8 aspm; | ||
81 | |||
82 | if (!pdev->is_pcie) | ||
83 | return; | ||
84 | |||
85 | pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); | ||
86 | aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1); | ||
87 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); | ||
88 | } | ||
89 | |||
90 | static const struct ath_bus_ops ath_pci_bus_ops = { | ||
79 | .read_cachesize = ath_pci_read_cachesize, | 91 | .read_cachesize = ath_pci_read_cachesize, |
80 | .cleanup = ath_pci_cleanup, | ||
81 | .eeprom_read = ath_pci_eeprom_read, | 92 | .eeprom_read = ath_pci_eeprom_read, |
93 | .bt_coex_prep = ath_pci_bt_coex_prep, | ||
82 | }; | 94 | }; |
83 | 95 | ||
84 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 96 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
@@ -91,24 +103,22 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
91 | u16 subsysid; | 103 | u16 subsysid; |
92 | u32 val; | 104 | u32 val; |
93 | int ret = 0; | 105 | int ret = 0; |
94 | struct ath_hw *ah; | 106 | char hw_name[64]; |
95 | 107 | ||
96 | if (pci_enable_device(pdev)) | 108 | if (pci_enable_device(pdev)) |
97 | return -EIO; | 109 | return -EIO; |
98 | 110 | ||
99 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 111 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
100 | |||
101 | if (ret) { | 112 | if (ret) { |
102 | printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); | 113 | printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); |
103 | goto bad; | 114 | goto err_dma; |
104 | } | 115 | } |
105 | 116 | ||
106 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | 117 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
107 | |||
108 | if (ret) { | 118 | if (ret) { |
109 | printk(KERN_ERR "ath9k: 32-bit DMA consistent " | 119 | printk(KERN_ERR "ath9k: 32-bit DMA consistent " |
110 | "DMA enable failed\n"); | 120 | "DMA enable failed\n"); |
111 | goto bad; | 121 | goto err_dma; |
112 | } | 122 | } |
113 | 123 | ||
114 | /* | 124 | /* |
@@ -148,22 +158,22 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
148 | if (ret) { | 158 | if (ret) { |
149 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); | 159 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); |
150 | ret = -ENODEV; | 160 | ret = -ENODEV; |
151 | goto bad; | 161 | goto err_region; |
152 | } | 162 | } |
153 | 163 | ||
154 | mem = pci_iomap(pdev, 0, 0); | 164 | mem = pci_iomap(pdev, 0, 0); |
155 | if (!mem) { | 165 | if (!mem) { |
156 | printk(KERN_ERR "PCI memory map error\n") ; | 166 | printk(KERN_ERR "PCI memory map error\n") ; |
157 | ret = -EIO; | 167 | ret = -EIO; |
158 | goto bad1; | 168 | goto err_iomap; |
159 | } | 169 | } |
160 | 170 | ||
161 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + | 171 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + |
162 | sizeof(struct ath_softc), &ath9k_ops); | 172 | sizeof(struct ath_softc), &ath9k_ops); |
163 | if (!hw) { | 173 | if (!hw) { |
164 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); | 174 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); |
165 | ret = -ENOMEM; | 175 | ret = -ENOMEM; |
166 | goto bad2; | 176 | goto err_alloc_hw; |
167 | } | 177 | } |
168 | 178 | ||
169 | SET_IEEE80211_DEV(hw, &pdev->dev); | 179 | SET_IEEE80211_DEV(hw, &pdev->dev); |
@@ -177,46 +187,45 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
177 | sc->hw = hw; | 187 | sc->hw = hw; |
178 | sc->dev = &pdev->dev; | 188 | sc->dev = &pdev->dev; |
179 | sc->mem = mem; | 189 | sc->mem = mem; |
180 | sc->bus_ops = &ath_pci_bus_ops; | ||
181 | 190 | ||
182 | pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); | 191 | /* Will be cleared in ath9k_start() */ |
183 | ret = ath_init_device(id->device, sc, subsysid); | 192 | sc->sc_flags |= SC_OP_INVALID; |
184 | if (ret) { | ||
185 | dev_err(&pdev->dev, "failed to initialize device\n"); | ||
186 | goto bad3; | ||
187 | } | ||
188 | |||
189 | /* setup interrupt service routine */ | ||
190 | 193 | ||
191 | ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); | 194 | ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); |
192 | if (ret) { | 195 | if (ret) { |
193 | dev_err(&pdev->dev, "request_irq failed\n"); | 196 | dev_err(&pdev->dev, "request_irq failed\n"); |
194 | goto bad4; | 197 | goto err_irq; |
195 | } | 198 | } |
196 | 199 | ||
197 | sc->irq = pdev->irq; | 200 | sc->irq = pdev->irq; |
198 | 201 | ||
199 | ah = sc->sc_ah; | 202 | pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); |
203 | ret = ath9k_init_device(id->device, sc, subsysid, &ath_pci_bus_ops); | ||
204 | if (ret) { | ||
205 | dev_err(&pdev->dev, "Failed to initialize device\n"); | ||
206 | goto err_init; | ||
207 | } | ||
208 | |||
209 | ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name)); | ||
200 | printk(KERN_INFO | 210 | printk(KERN_INFO |
201 | "%s: Atheros AR%s MAC/BB Rev:%x " | 211 | "%s: %s mem=0x%lx, irq=%d\n", |
202 | "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", | ||
203 | wiphy_name(hw->wiphy), | 212 | wiphy_name(hw->wiphy), |
204 | ath_mac_bb_name(ah->hw_version.macVersion), | 213 | hw_name, |
205 | ah->hw_version.macRev, | ||
206 | ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), | ||
207 | ah->hw_version.phyRev, | ||
208 | (unsigned long)mem, pdev->irq); | 214 | (unsigned long)mem, pdev->irq); |
209 | 215 | ||
210 | return 0; | 216 | return 0; |
211 | bad4: | 217 | |
212 | ath_detach(sc); | 218 | err_init: |
213 | bad3: | 219 | free_irq(sc->irq, sc); |
220 | err_irq: | ||
214 | ieee80211_free_hw(hw); | 221 | ieee80211_free_hw(hw); |
215 | bad2: | 222 | err_alloc_hw: |
216 | pci_iounmap(pdev, mem); | 223 | pci_iounmap(pdev, mem); |
217 | bad1: | 224 | err_iomap: |
218 | pci_release_region(pdev, 0); | 225 | pci_release_region(pdev, 0); |
219 | bad: | 226 | err_region: |
227 | /* Nothing */ | ||
228 | err_dma: | ||
220 | pci_disable_device(pdev); | 229 | pci_disable_device(pdev); |
221 | return ret; | 230 | return ret; |
222 | } | 231 | } |
@@ -226,8 +235,15 @@ static void ath_pci_remove(struct pci_dev *pdev) | |||
226 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 235 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
227 | struct ath_wiphy *aphy = hw->priv; | 236 | struct ath_wiphy *aphy = hw->priv; |
228 | struct ath_softc *sc = aphy->sc; | 237 | struct ath_softc *sc = aphy->sc; |
238 | void __iomem *mem = sc->mem; | ||
239 | |||
240 | ath9k_deinit_device(sc); | ||
241 | free_irq(sc->irq, sc); | ||
242 | ieee80211_free_hw(sc->hw); | ||
229 | 243 | ||
230 | ath_cleanup(sc); | 244 | pci_iounmap(pdev, mem); |
245 | pci_disable_device(pdev); | ||
246 | pci_release_region(pdev, 0); | ||
231 | } | 247 | } |
232 | 248 | ||
233 | #ifdef CONFIG_PM | 249 | #ifdef CONFIG_PM |