diff options
author | Felipe Balbi <balbi@ti.com> | 2011-10-04 16:10:28 -0400 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-10-11 09:00:46 -0400 |
commit | fbe936bcb59d8e6e054c325a441082b55538bf8f (patch) | |
tree | b2ad087630dafef90bc89fcdf2dfa2b3c1b8cf81 | |
parent | c7e7c227b63836933ef736fa2d7cc526174b1563 (diff) |
wl12xx: add an sdio glue struct to keep wl and device side-by-side
In order to fully abstract the bus, we need to save the device
structure *beside* wl1271, instead of inside it.
This will help re-structuring the driver so that we avoid the
duplicated code in the bus modules.
Signed-off-by: Felipe Balbi <balbi@ti.com>
[forward-ported and cleaned up and rephrased commit message]
Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r-- | drivers/net/wireless/wl12xx/sdio.c | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 516a8980723c..5a4268012da4 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c | |||
@@ -44,6 +44,11 @@ | |||
44 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 | 44 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | struct wl12xx_sdio_glue { | ||
48 | struct device *dev; | ||
49 | struct wl1271 *wl; | ||
50 | }; | ||
51 | |||
47 | static const struct sdio_device_id wl1271_devices[] __devinitconst = { | 52 | static const struct sdio_device_id wl1271_devices[] __devinitconst = { |
48 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, | 53 | { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, |
49 | {} | 54 | {} |
@@ -57,14 +62,14 @@ static void wl1271_sdio_set_block_size(struct wl1271 *wl, unsigned int blksz) | |||
57 | sdio_release_host(wl->if_priv); | 62 | sdio_release_host(wl->if_priv); |
58 | } | 63 | } |
59 | 64 | ||
60 | static inline struct sdio_func *wl_to_func(struct wl1271 *wl) | 65 | static inline struct wl12xx_sdio_glue *wl_to_glue(struct wl1271 *wl) |
61 | { | 66 | { |
62 | return wl->if_priv; | 67 | return wl->if_priv; |
63 | } | 68 | } |
64 | 69 | ||
65 | static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) | 70 | static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) |
66 | { | 71 | { |
67 | return &(wl_to_func(wl)->dev); | 72 | return wl_to_glue(wl)->dev; |
68 | } | 73 | } |
69 | 74 | ||
70 | static irqreturn_t wl1271_hardirq(int irq, void *cookie) | 75 | static irqreturn_t wl1271_hardirq(int irq, void *cookie) |
@@ -110,7 +115,8 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
110 | size_t len, bool fixed) | 115 | size_t len, bool fixed) |
111 | { | 116 | { |
112 | int ret; | 117 | int ret; |
113 | struct sdio_func *func = wl_to_func(wl); | 118 | struct wl12xx_sdio_glue *glue = wl_to_glue(wl); |
119 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | ||
114 | 120 | ||
115 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 121 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { |
116 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); | 122 | ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); |
@@ -135,7 +141,8 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
135 | size_t len, bool fixed) | 141 | size_t len, bool fixed) |
136 | { | 142 | { |
137 | int ret; | 143 | int ret; |
138 | struct sdio_func *func = wl_to_func(wl); | 144 | struct wl12xx_sdio_glue *glue = wl_to_glue(wl); |
145 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | ||
139 | 146 | ||
140 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { | 147 | if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { |
141 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); | 148 | sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); |
@@ -158,8 +165,9 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
158 | 165 | ||
159 | static int wl1271_sdio_power_on(struct wl1271 *wl) | 166 | static int wl1271_sdio_power_on(struct wl1271 *wl) |
160 | { | 167 | { |
161 | struct sdio_func *func = wl_to_func(wl); | ||
162 | int ret; | 168 | int ret; |
169 | struct wl12xx_sdio_glue *glue = wl_to_glue(wl); | ||
170 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | ||
163 | 171 | ||
164 | /* If enabled, tell runtime PM not to power off the card */ | 172 | /* If enabled, tell runtime PM not to power off the card */ |
165 | if (pm_runtime_enabled(&func->dev)) { | 173 | if (pm_runtime_enabled(&func->dev)) { |
@@ -182,8 +190,9 @@ out: | |||
182 | 190 | ||
183 | static int wl1271_sdio_power_off(struct wl1271 *wl) | 191 | static int wl1271_sdio_power_off(struct wl1271 *wl) |
184 | { | 192 | { |
185 | struct sdio_func *func = wl_to_func(wl); | ||
186 | int ret; | 193 | int ret; |
194 | struct wl12xx_sdio_glue *glue = wl_to_glue(wl); | ||
195 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | ||
187 | 196 | ||
188 | sdio_disable_func(func); | 197 | sdio_disable_func(func); |
189 | sdio_release_host(func); | 198 | sdio_release_host(func); |
@@ -224,21 +233,34 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
224 | struct ieee80211_hw *hw; | 233 | struct ieee80211_hw *hw; |
225 | const struct wl12xx_platform_data *wlan_data; | 234 | const struct wl12xx_platform_data *wlan_data; |
226 | struct wl1271 *wl; | 235 | struct wl1271 *wl; |
236 | struct wl12xx_sdio_glue *glue; | ||
227 | unsigned long irqflags; | 237 | unsigned long irqflags; |
228 | mmc_pm_flag_t mmcflags; | 238 | mmc_pm_flag_t mmcflags; |
229 | int ret; | 239 | int ret = -ENOMEM; |
230 | 240 | ||
231 | /* We are only able to handle the wlan function */ | 241 | /* We are only able to handle the wlan function */ |
232 | if (func->num != 0x02) | 242 | if (func->num != 0x02) |
233 | return -ENODEV; | 243 | return -ENODEV; |
234 | 244 | ||
245 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | ||
246 | if (!glue) { | ||
247 | wl1271_error("can't allocate glue"); | ||
248 | goto out; | ||
249 | } | ||
250 | |||
235 | hw = wl1271_alloc_hw(); | 251 | hw = wl1271_alloc_hw(); |
236 | if (IS_ERR(hw)) | 252 | if (IS_ERR(hw)) { |
237 | return PTR_ERR(hw); | 253 | wl1271_error("can't allocate hw"); |
254 | ret = PTR_ERR(hw); | ||
255 | goto out_free_glue; | ||
256 | } | ||
238 | 257 | ||
239 | wl = hw->priv; | 258 | wl = hw->priv; |
240 | 259 | ||
241 | wl->if_priv = func; | 260 | glue->dev = &func->dev; |
261 | glue->wl = wl; | ||
262 | |||
263 | wl->if_priv = glue; | ||
242 | wl->if_ops = &sdio_ops; | 264 | wl->if_ops = &sdio_ops; |
243 | 265 | ||
244 | /* Grab access to FN0 for ELP reg. */ | 266 | /* Grab access to FN0 for ELP reg. */ |
@@ -251,7 +273,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
251 | if (IS_ERR(wlan_data)) { | 273 | if (IS_ERR(wlan_data)) { |
252 | ret = PTR_ERR(wlan_data); | 274 | ret = PTR_ERR(wlan_data); |
253 | wl1271_error("missing wlan platform data: %d", ret); | 275 | wl1271_error("missing wlan platform data: %d", ret); |
254 | goto out_free; | 276 | goto out_free_hw; |
255 | } | 277 | } |
256 | 278 | ||
257 | wl->irq = wlan_data->irq; | 279 | wl->irq = wlan_data->irq; |
@@ -269,7 +291,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
269 | DRIVER_NAME, wl); | 291 | DRIVER_NAME, wl); |
270 | if (ret < 0) { | 292 | if (ret < 0) { |
271 | wl1271_error("request_irq() failed: %d", ret); | 293 | wl1271_error("request_irq() failed: %d", ret); |
272 | goto out_free; | 294 | goto out_free_hw; |
273 | } | 295 | } |
274 | 296 | ||
275 | ret = enable_irq_wake(wl->irq); | 297 | ret = enable_irq_wake(wl->irq); |
@@ -294,25 +316,29 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
294 | if (ret) | 316 | if (ret) |
295 | goto out_irq; | 317 | goto out_irq; |
296 | 318 | ||
297 | sdio_set_drvdata(func, wl); | 319 | sdio_set_drvdata(func, glue); |
298 | 320 | ||
299 | /* Tell PM core that we don't need the card to be powered now */ | 321 | /* Tell PM core that we don't need the card to be powered now */ |
300 | pm_runtime_put_noidle(&func->dev); | 322 | pm_runtime_put_noidle(&func->dev); |
301 | 323 | ||
302 | return 0; | 324 | return 0; |
303 | 325 | ||
304 | out_irq: | 326 | out_irq: |
305 | free_irq(wl->irq, wl); | 327 | free_irq(wl->irq, wl); |
306 | 328 | ||
307 | out_free: | 329 | out_free_hw: |
308 | wl1271_free_hw(wl); | 330 | wl1271_free_hw(wl); |
309 | 331 | ||
332 | out_free_glue: | ||
333 | kfree(glue); | ||
334 | out: | ||
310 | return ret; | 335 | return ret; |
311 | } | 336 | } |
312 | 337 | ||
313 | static void __devexit wl1271_remove(struct sdio_func *func) | 338 | static void __devexit wl1271_remove(struct sdio_func *func) |
314 | { | 339 | { |
315 | struct wl1271 *wl = sdio_get_drvdata(func); | 340 | struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); |
341 | struct wl1271 *wl = glue->wl; | ||
316 | 342 | ||
317 | /* Undo decrement done above in wl1271_probe */ | 343 | /* Undo decrement done above in wl1271_probe */ |
318 | pm_runtime_get_noresume(&func->dev); | 344 | pm_runtime_get_noresume(&func->dev); |
@@ -324,6 +350,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) | |||
324 | } | 350 | } |
325 | free_irq(wl->irq, wl); | 351 | free_irq(wl->irq, wl); |
326 | wl1271_free_hw(wl); | 352 | wl1271_free_hw(wl); |
353 | kfree(glue); | ||
327 | } | 354 | } |
328 | 355 | ||
329 | #ifdef CONFIG_PM | 356 | #ifdef CONFIG_PM |