aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/pci.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/ath/ath9k/pci.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/pci.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c112
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
21static struct pci_device_id ath_pci_id_table[] __devinitdata = { 21static 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 */
34static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) 35static 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
51static void ath_pci_cleanup(struct ath_softc *sc) 53static 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
60static 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
78static struct ath_bus_ops ath_pci_bus_ops = { 73/*
74 * Bluetooth coexistance requires disabling ASPM.
75 */
76static 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
90static 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
84static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 96static 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;
211bad4: 217
212 ath_detach(sc); 218err_init:
213bad3: 219 free_irq(sc->irq, sc);
220err_irq:
214 ieee80211_free_hw(hw); 221 ieee80211_free_hw(hw);
215bad2: 222err_alloc_hw:
216 pci_iounmap(pdev, mem); 223 pci_iounmap(pdev, mem);
217bad1: 224err_iomap:
218 pci_release_region(pdev, 0); 225 pci_release_region(pdev, 0);
219bad: 226err_region:
227 /* Nothing */
228err_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