aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/sdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/sdio.c')
-rw-r--r--drivers/net/wireless/wl12xx/sdio.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 93cbb8d5aba9..5b9dbeafec06 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -28,6 +28,7 @@
28#include <linux/mmc/sdio_func.h> 28#include <linux/mmc/sdio_func.h>
29#include <linux/mmc/sdio_ids.h> 29#include <linux/mmc/sdio_ids.h>
30#include <linux/mmc/card.h> 30#include <linux/mmc/card.h>
31#include <linux/mmc/host.h>
31#include <linux/gpio.h> 32#include <linux/gpio.h>
32#include <linux/wl12xx.h> 33#include <linux/wl12xx.h>
33#include <linux/pm_runtime.h> 34#include <linux/pm_runtime.h>
@@ -60,7 +61,7 @@ static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl)
60 return &(wl_to_func(wl)->dev); 61 return &(wl_to_func(wl)->dev);
61} 62}
62 63
63static irqreturn_t wl1271_irq(int irq, void *cookie) 64static irqreturn_t wl1271_hardirq(int irq, void *cookie)
64{ 65{
65 struct wl1271 *wl = cookie; 66 struct wl1271 *wl = cookie;
66 unsigned long flags; 67 unsigned long flags;
@@ -69,17 +70,14 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
69 70
70 /* complete the ELP completion */ 71 /* complete the ELP completion */
71 spin_lock_irqsave(&wl->wl_lock, flags); 72 spin_lock_irqsave(&wl->wl_lock, flags);
73 set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
72 if (wl->elp_compl) { 74 if (wl->elp_compl) {
73 complete(wl->elp_compl); 75 complete(wl->elp_compl);
74 wl->elp_compl = NULL; 76 wl->elp_compl = NULL;
75 } 77 }
76
77 if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
78 ieee80211_queue_work(wl->hw, &wl->irq_work);
79 set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
80 spin_unlock_irqrestore(&wl->wl_lock, flags); 78 spin_unlock_irqrestore(&wl->wl_lock, flags);
81 79
82 return IRQ_HANDLED; 80 return IRQ_WAKE_THREAD;
83} 81}
84 82
85static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) 83static void wl1271_sdio_disable_interrupts(struct wl1271 *wl)
@@ -106,8 +104,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
106 int ret; 104 int ret;
107 struct sdio_func *func = wl_to_func(wl); 105 struct sdio_func *func = wl_to_func(wl);
108 106
109 sdio_claim_host(func);
110
111 if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { 107 if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
112 ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); 108 ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
113 wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", 109 wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
@@ -123,8 +119,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
123 wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); 119 wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
124 } 120 }
125 121
126 sdio_release_host(func);
127
128 if (ret) 122 if (ret)
129 wl1271_error("sdio read failed (%d)", ret); 123 wl1271_error("sdio read failed (%d)", ret);
130} 124}
@@ -135,8 +129,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
135 int ret; 129 int ret;
136 struct sdio_func *func = wl_to_func(wl); 130 struct sdio_func *func = wl_to_func(wl);
137 131
138 sdio_claim_host(func);
139
140 if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { 132 if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
141 sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); 133 sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
142 wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", 134 wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x",
@@ -152,8 +144,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
152 ret = sdio_memcpy_toio(func, addr, buf, len); 144 ret = sdio_memcpy_toio(func, addr, buf, len);
153 } 145 }
154 146
155 sdio_release_host(func);
156
157 if (ret) 147 if (ret)
158 wl1271_error("sdio write failed (%d)", ret); 148 wl1271_error("sdio write failed (%d)", ret);
159} 149}
@@ -163,14 +153,18 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
163 struct sdio_func *func = wl_to_func(wl); 153 struct sdio_func *func = wl_to_func(wl);
164 int ret; 154 int ret;
165 155
166 /* Power up the card */ 156 /* Make sure the card will not be powered off by runtime PM */
167 ret = pm_runtime_get_sync(&func->dev); 157 ret = pm_runtime_get_sync(&func->dev);
168 if (ret < 0) 158 if (ret < 0)
169 goto out; 159 goto out;
170 160
161 /* Runtime PM might be disabled, so power up the card manually */
162 ret = mmc_power_restore_host(func->card->host);
163 if (ret < 0)
164 goto out;
165
171 sdio_claim_host(func); 166 sdio_claim_host(func);
172 sdio_enable_func(func); 167 sdio_enable_func(func);
173 sdio_release_host(func);
174 168
175out: 169out:
176 return ret; 170 return ret;
@@ -179,12 +173,17 @@ out:
179static int wl1271_sdio_power_off(struct wl1271 *wl) 173static int wl1271_sdio_power_off(struct wl1271 *wl)
180{ 174{
181 struct sdio_func *func = wl_to_func(wl); 175 struct sdio_func *func = wl_to_func(wl);
176 int ret;
182 177
183 sdio_claim_host(func);
184 sdio_disable_func(func); 178 sdio_disable_func(func);
185 sdio_release_host(func); 179 sdio_release_host(func);
186 180
187 /* Power down the card */ 181 /* Runtime PM might be disabled, so power off the card manually */
182 ret = mmc_power_save_host(func->card->host);
183 if (ret < 0)
184 return ret;
185
186 /* Let runtime PM know the card is powered off */
188 return pm_runtime_put_sync(&func->dev); 187 return pm_runtime_put_sync(&func->dev);
189} 188}
190 189
@@ -241,14 +240,14 @@ static int __devinit wl1271_probe(struct sdio_func *func,
241 wl->irq = wlan_data->irq; 240 wl->irq = wlan_data->irq;
242 wl->ref_clock = wlan_data->board_ref_clock; 241 wl->ref_clock = wlan_data->board_ref_clock;
243 242
244 ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); 243 ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
244 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
245 DRIVER_NAME, wl);
245 if (ret < 0) { 246 if (ret < 0) {
246 wl1271_error("request_irq() failed: %d", ret); 247 wl1271_error("request_irq() failed: %d", ret);
247 goto out_free; 248 goto out_free;
248 } 249 }
249 250
250 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
251
252 disable_irq(wl->irq); 251 disable_irq(wl->irq);
253 252
254 ret = wl1271_init_ieee80211(wl); 253 ret = wl1271_init_ieee80211(wl);
@@ -271,7 +270,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
271 out_irq: 270 out_irq:
272 free_irq(wl->irq, wl); 271 free_irq(wl->irq, wl);
273 272
274
275 out_free: 273 out_free:
276 wl1271_free_hw(wl); 274 wl1271_free_hw(wl);
277 275
@@ -345,3 +343,4 @@ MODULE_LICENSE("GPL");
345MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); 343MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
346MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); 344MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
347MODULE_FIRMWARE(WL1271_FW_NAME); 345MODULE_FIRMWARE(WL1271_FW_NAME);
346MODULE_FIRMWARE(WL1271_AP_FW_NAME);