aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/sdio-rx.c
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2009-05-07 04:02:39 -0400
committerInaky Perez-Gonzalez <inaky@linux.intel.com>2009-06-11 06:30:25 -0400
commit16820c166d3ad5973d388b5aa70ee7e535386657 (patch)
tree59ccd86e6530bbfc6aac3d55a4952f851c0bc3cc /drivers/net/wimax/i2400m/sdio-rx.c
parent6e053d6c79b3c1c9f6efc6563a811023c41be86a (diff)
wimax/i2400m/sdio: Move all the RX code to a unified, IRQ based receive routine
The current SDIO code was working in polling mode for boot-mode (firmware load) mode. This was causing issues on some hardware. Moved all the RX code to use a unified IRQ handler that based on the type of data the device is sending can discriminate and decide which is the right destination. As well, all the reads from the device are made to be at least the block size (256); the driver will ignore the rest when not needed. Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com> Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers/net/wimax/i2400m/sdio-rx.c')
-rw-r--r--drivers/net/wimax/i2400m/sdio-rx.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
index a3008b904f7d..321beadf6e47 100644
--- a/drivers/net/wimax/i2400m/sdio-rx.c
+++ b/drivers/net/wimax/i2400m/sdio-rx.c
@@ -69,6 +69,13 @@
69#define D_SUBMODULE rx 69#define D_SUBMODULE rx
70#include "sdio-debug-levels.h" 70#include "sdio-debug-levels.h"
71 71
72static const __le32 i2400m_ACK_BARKER[4] = {
73 __constant_cpu_to_le32(I2400M_ACK_BARKER),
74 __constant_cpu_to_le32(I2400M_ACK_BARKER),
75 __constant_cpu_to_le32(I2400M_ACK_BARKER),
76 __constant_cpu_to_le32(I2400M_ACK_BARKER)
77};
78
72 79
73/* 80/*
74 * Read and return the amount of bytes available for RX 81 * Read and return the amount of bytes available for RX
@@ -131,25 +138,35 @@ void i2400ms_rx(struct i2400ms *i2400ms)
131 ret = rx_size; 138 ret = rx_size;
132 goto error_get_size; 139 goto error_get_size;
133 } 140 }
141
134 ret = -ENOMEM; 142 ret = -ENOMEM;
135 skb = alloc_skb(rx_size, GFP_ATOMIC); 143 skb = alloc_skb(rx_size, GFP_ATOMIC);
136 if (NULL == skb) { 144 if (NULL == skb) {
137 dev_err(dev, "RX: unable to alloc skb\n"); 145 dev_err(dev, "RX: unable to alloc skb\n");
138 goto error_alloc_skb; 146 goto error_alloc_skb;
139 } 147 }
140
141 ret = sdio_memcpy_fromio(func, skb->data, 148 ret = sdio_memcpy_fromio(func, skb->data,
142 I2400MS_DATA_ADDR, rx_size); 149 I2400MS_DATA_ADDR, rx_size);
143 if (ret < 0) { 150 if (ret < 0) {
144 dev_err(dev, "RX: SDIO data read failed: %d\n", ret); 151 dev_err(dev, "RX: SDIO data read failed: %d\n", ret);
145 goto error_memcpy_fromio; 152 goto error_memcpy_fromio;
146 } 153 }
147 /* Check if device has reset */ 154
148 if (!memcmp(skb->data, i2400m_NBOOT_BARKER, 155 rmb(); /* make sure we get boot_mode from dev_reset_handle */
149 sizeof(i2400m_NBOOT_BARKER)) 156 if (i2400m->boot_mode == 1) {
150 || !memcmp(skb->data, i2400m_SBOOT_BARKER, 157 spin_lock(&i2400m->rx_lock);
151 sizeof(i2400m_SBOOT_BARKER))) { 158 i2400ms->bm_ack_size = rx_size;
159 spin_unlock(&i2400m->rx_lock);
160 memcpy(i2400m->bm_ack_buf, skb->data, rx_size);
161 wake_up(&i2400ms->bm_wfa_wq);
162 dev_err(dev, "RX: SDIO boot mode message\n");
163 kfree_skb(skb);
164 } else if (unlikely(!memcmp(skb->data, i2400m_NBOOT_BARKER,
165 sizeof(i2400m_NBOOT_BARKER))
166 || !memcmp(skb->data, i2400m_SBOOT_BARKER,
167 sizeof(i2400m_SBOOT_BARKER)))) {
152 ret = i2400m_dev_reset_handle(i2400m); 168 ret = i2400m_dev_reset_handle(i2400m);
169 dev_err(dev, "RX: SDIO reboot barker\n");
153 kfree_skb(skb); 170 kfree_skb(skb);
154 } else { 171 } else {
155 skb_put(skb, rx_size); 172 skb_put(skb, rx_size);
@@ -179,7 +196,6 @@ void i2400ms_irq(struct sdio_func *func)
179{ 196{
180 int ret; 197 int ret;
181 struct i2400ms *i2400ms = sdio_get_drvdata(func); 198 struct i2400ms *i2400ms = sdio_get_drvdata(func);
182 struct i2400m *i2400m = &i2400ms->i2400m;
183 struct device *dev = &func->dev; 199 struct device *dev = &func->dev;
184 int val; 200 int val;
185 201
@@ -194,10 +210,7 @@ void i2400ms_irq(struct sdio_func *func)
194 goto error_no_irq; 210 goto error_no_irq;
195 } 211 }
196 sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); 212 sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
197 if (WARN_ON(i2400m->boot_mode != 0)) 213 i2400ms_rx(i2400ms);
198 dev_err(dev, "RX: SW BUG? boot mode and IRQ is up?\n");
199 else
200 i2400ms_rx(i2400ms);
201error_no_irq: 214error_no_irq:
202 d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); 215 d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms);
203 return; 216 return;
@@ -214,8 +227,15 @@ int i2400ms_rx_setup(struct i2400ms *i2400ms)
214 int result; 227 int result;
215 struct sdio_func *func = i2400ms->func; 228 struct sdio_func *func = i2400ms->func;
216 struct device *dev = &func->dev; 229 struct device *dev = &func->dev;
230 struct i2400m *i2400m = &i2400ms->i2400m;
217 231
218 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); 232 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
233
234 init_waitqueue_head(&i2400ms->bm_wfa_wq);
235 spin_lock(&i2400m->rx_lock);
236 i2400ms->bm_wait_result = -EINPROGRESS;
237 spin_unlock(&i2400m->rx_lock);
238
219 sdio_claim_host(func); 239 sdio_claim_host(func);
220 result = sdio_claim_irq(func, i2400ms_irq); 240 result = sdio_claim_irq(func, i2400ms_irq);
221 if (result < 0) { 241 if (result < 0) {
@@ -245,8 +265,13 @@ void i2400ms_rx_release(struct i2400ms *i2400ms)
245 int result; 265 int result;
246 struct sdio_func *func = i2400ms->func; 266 struct sdio_func *func = i2400ms->func;
247 struct device *dev = &func->dev; 267 struct device *dev = &func->dev;
268 struct i2400m *i2400m = &i2400ms->i2400m;
248 269
249 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); 270 d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
271 spin_lock(&i2400m->rx_lock);
272 i2400ms->bm_ack_size = -EINTR;
273 spin_unlock(&i2400m->rx_lock);
274 wake_up_all(&i2400ms->bm_wfa_wq);
250 sdio_claim_host(func); 275 sdio_claim_host(func);
251 sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result); 276 sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result);
252 sdio_release_irq(func); 277 sdio_release_irq(func);