aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/cw1200/cw1200_spi.c19
-rw-r--r--drivers/net/wireless/cw1200/fwio.c2
-rw-r--r--drivers/net/wireless/cw1200/hwbus.h1
-rw-r--r--drivers/net/wireless/cw1200/hwio.c15
4 files changed, 33 insertions, 4 deletions
diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c
index d06376014bcd..c31580ba883b 100644
--- a/drivers/net/wireless/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/cw1200/cw1200_spi.c
@@ -41,6 +41,7 @@ struct hwbus_priv {
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 int claimed; 43 int claimed;
44 int irq_disabled;
44}; 45};
45 46
46#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2) 47#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2)
@@ -230,6 +231,8 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id)
230 struct hwbus_priv *self = dev_id; 231 struct hwbus_priv *self = dev_id;
231 232
232 if (self->core) { 233 if (self->core) {
234 disable_irq_nosync(self->func->irq);
235 self->irq_disabled = 1;
233 cw1200_irq_handler(self->core); 236 cw1200_irq_handler(self->core);
234 return IRQ_HANDLED; 237 return IRQ_HANDLED;
235 } else { 238 } else {
@@ -263,13 +266,22 @@ exit:
263 266
264static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self) 267static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self)
265{ 268{
266 int ret = 0;
267
268 pr_debug("SW IRQ unsubscribe\n"); 269 pr_debug("SW IRQ unsubscribe\n");
269 disable_irq_wake(self->func->irq); 270 disable_irq_wake(self->func->irq);
270 free_irq(self->func->irq, self); 271 free_irq(self->func->irq, self);
271 272
272 return ret; 273 return 0;
274}
275
276static int cw1200_spi_irq_enable(struct hwbus_priv *self, int enable)
277{
278 /* Disables are handled by the interrupt handler */
279 if (enable && self->irq_disabled) {
280 enable_irq(self->func->irq);
281 self->irq_disabled = 0;
282 }
283
284 return 0;
273} 285}
274 286
275static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) 287static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata)
@@ -349,6 +361,7 @@ static struct hwbus_ops cw1200_spi_hwbus_ops = {
349 .unlock = cw1200_spi_unlock, 361 .unlock = cw1200_spi_unlock,
350 .align_size = cw1200_spi_align_size, 362 .align_size = cw1200_spi_align_size,
351 .power_mgmt = cw1200_spi_pm, 363 .power_mgmt = cw1200_spi_pm,
364 .irq_enable = cw1200_spi_irq_enable,
352}; 365};
353 366
354/* Probe Function to be called by SPI stack when device is discovered */ 367/* Probe Function to be called by SPI stack when device is discovered */
diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c
index acdff0f7f952..0b2061bbc68b 100644
--- a/drivers/net/wireless/cw1200/fwio.c
+++ b/drivers/net/wireless/cw1200/fwio.c
@@ -485,7 +485,7 @@ int cw1200_load_firmware(struct cw1200_common *priv)
485 485
486 /* Enable interrupt signalling */ 486 /* Enable interrupt signalling */
487 priv->hwbus_ops->lock(priv->hwbus_priv); 487 priv->hwbus_ops->lock(priv->hwbus_priv);
488 ret = __cw1200_irq_enable(priv, 1); 488 ret = __cw1200_irq_enable(priv, 2);
489 priv->hwbus_ops->unlock(priv->hwbus_priv); 489 priv->hwbus_ops->unlock(priv->hwbus_priv);
490 if (ret < 0) 490 if (ret < 0)
491 goto unsubscribe; 491 goto unsubscribe;
diff --git a/drivers/net/wireless/cw1200/hwbus.h b/drivers/net/wireless/cw1200/hwbus.h
index 8b2fc831c3de..51dfb3a90735 100644
--- a/drivers/net/wireless/cw1200/hwbus.h
+++ b/drivers/net/wireless/cw1200/hwbus.h
@@ -28,6 +28,7 @@ struct hwbus_ops {
28 void (*unlock)(struct hwbus_priv *self); 28 void (*unlock)(struct hwbus_priv *self);
29 size_t (*align_size)(struct hwbus_priv *self, size_t size); 29 size_t (*align_size)(struct hwbus_priv *self, size_t size);
30 int (*power_mgmt)(struct hwbus_priv *self, bool suspend); 30 int (*power_mgmt)(struct hwbus_priv *self, bool suspend);
31 int (*irq_enable)(struct hwbus_priv *self, int enable);
31}; 32};
32 33
33#endif /* CW1200_HWBUS_H */ 34#endif /* CW1200_HWBUS_H */
diff --git a/drivers/net/wireless/cw1200/hwio.c b/drivers/net/wireless/cw1200/hwio.c
index ff230b7aeedd..41bd7615ccaa 100644
--- a/drivers/net/wireless/cw1200/hwio.c
+++ b/drivers/net/wireless/cw1200/hwio.c
@@ -273,6 +273,21 @@ int __cw1200_irq_enable(struct cw1200_common *priv, int enable)
273 u16 val16; 273 u16 val16;
274 int ret; 274 int ret;
275 275
276 /* We need to do this hack because the SPI layer can sleep on I/O
277 and the general path involves I/O to the device in interrupt
278 context.
279
280 However, the initial enable call needs to go to the hardware.
281
282 We don't worry about shutdown because we do a full reset which
283 clears the interrupt enabled bits.
284 */
285 if (priv->hwbus_ops->irq_enable) {
286 ret = priv->hwbus_ops->irq_enable(priv->hwbus_priv, enable);
287 if (ret || enable < 2)
288 return ret;
289 }
290
276 if (HIF_8601_SILICON == priv->hw_type) { 291 if (HIF_8601_SILICON == priv->hw_type) {
277 ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32); 292 ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
278 if (ret < 0) { 293 if (ret < 0) {