aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/cw1200/cw1200_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/cw1200/cw1200_spi.c')
-rw-r--r--drivers/net/wireless/cw1200/cw1200_spi.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c
index d06376014bcd..f5e6b489ed32 100644
--- a/drivers/net/wireless/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/cw1200/cw1200_spi.c
@@ -40,7 +40,9 @@ struct hwbus_priv {
40 struct cw1200_common *core; 40 struct cw1200_common *core;
41 const struct cw1200_platform_data_spi *pdata; 41 const struct cw1200_platform_data_spi *pdata;
42 spinlock_t lock; /* Serialize all bus operations */ 42 spinlock_t lock; /* Serialize all bus operations */
43 wait_queue_head_t wq;
43 int claimed; 44 int claimed;
45 int irq_disabled;
44}; 46};
45 47
46#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2) 48#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2)
@@ -197,8 +199,11 @@ static void cw1200_spi_lock(struct hwbus_priv *self)
197{ 199{
198 unsigned long flags; 200 unsigned long flags;
199 201
202 DECLARE_WAITQUEUE(wait, current);
203
200 might_sleep(); 204 might_sleep();
201 205
206 add_wait_queue(&self->wq, &wait);
202 spin_lock_irqsave(&self->lock, flags); 207 spin_lock_irqsave(&self->lock, flags);
203 while (1) { 208 while (1) {
204 set_current_state(TASK_UNINTERRUPTIBLE); 209 set_current_state(TASK_UNINTERRUPTIBLE);
@@ -211,6 +216,7 @@ static void cw1200_spi_lock(struct hwbus_priv *self)
211 set_current_state(TASK_RUNNING); 216 set_current_state(TASK_RUNNING);
212 self->claimed = 1; 217 self->claimed = 1;
213 spin_unlock_irqrestore(&self->lock, flags); 218 spin_unlock_irqrestore(&self->lock, flags);
219 remove_wait_queue(&self->wq, &wait);
214 220
215 return; 221 return;
216} 222}
@@ -222,6 +228,8 @@ static void cw1200_spi_unlock(struct hwbus_priv *self)
222 spin_lock_irqsave(&self->lock, flags); 228 spin_lock_irqsave(&self->lock, flags);
223 self->claimed = 0; 229 self->claimed = 0;
224 spin_unlock_irqrestore(&self->lock, flags); 230 spin_unlock_irqrestore(&self->lock, flags);
231 wake_up(&self->wq);
232
225 return; 233 return;
226} 234}
227 235
@@ -230,6 +238,8 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id)
230 struct hwbus_priv *self = dev_id; 238 struct hwbus_priv *self = dev_id;
231 239
232 if (self->core) { 240 if (self->core) {
241 disable_irq_nosync(self->func->irq);
242 self->irq_disabled = 1;
233 cw1200_irq_handler(self->core); 243 cw1200_irq_handler(self->core);
234 return IRQ_HANDLED; 244 return IRQ_HANDLED;
235 } else { 245 } else {
@@ -263,13 +273,22 @@ exit:
263 273
264static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self) 274static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self)
265{ 275{
266 int ret = 0;
267
268 pr_debug("SW IRQ unsubscribe\n"); 276 pr_debug("SW IRQ unsubscribe\n");
269 disable_irq_wake(self->func->irq); 277 disable_irq_wake(self->func->irq);
270 free_irq(self->func->irq, self); 278 free_irq(self->func->irq, self);
271 279
272 return ret; 280 return 0;
281}
282
283static int cw1200_spi_irq_enable(struct hwbus_priv *self, int enable)
284{
285 /* Disables are handled by the interrupt handler */
286 if (enable && self->irq_disabled) {
287 enable_irq(self->func->irq);
288 self->irq_disabled = 0;
289 }
290
291 return 0;
273} 292}
274 293
275static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) 294static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata)
@@ -349,6 +368,7 @@ static struct hwbus_ops cw1200_spi_hwbus_ops = {
349 .unlock = cw1200_spi_unlock, 368 .unlock = cw1200_spi_unlock,
350 .align_size = cw1200_spi_align_size, 369 .align_size = cw1200_spi_align_size,
351 .power_mgmt = cw1200_spi_pm, 370 .power_mgmt = cw1200_spi_pm,
371 .irq_enable = cw1200_spi_irq_enable,
352}; 372};
353 373
354/* Probe Function to be called by SPI stack when device is discovered */ 374/* Probe Function to be called by SPI stack when device is discovered */
@@ -400,6 +420,8 @@ static int cw1200_spi_probe(struct spi_device *func)
400 420
401 spi_set_drvdata(func, self); 421 spi_set_drvdata(func, self);
402 422
423 init_waitqueue_head(&self->wq);
424
403 status = cw1200_spi_irq_subscribe(self); 425 status = cw1200_spi_irq_subscribe(self);
404 426
405 status = cw1200_core_probe(&cw1200_spi_hwbus_ops, 427 status = cw1200_core_probe(&cw1200_spi_hwbus_ops,