aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/sdio-rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wimax/i2400m/sdio-rx.c')
-rw-r--r--drivers/net/wimax/i2400m/sdio-rx.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
index 321beadf6e47..8adf6c9b6f8f 100644
--- a/drivers/net/wimax/i2400m/sdio-rx.c
+++ b/drivers/net/wimax/i2400m/sdio-rx.c
@@ -53,6 +53,7 @@
53 * i2400ms_irq() 53 * i2400ms_irq()
54 * i2400ms_rx() 54 * i2400ms_rx()
55 * __i2400ms_rx_get_size() 55 * __i2400ms_rx_get_size()
56 * i2400m_is_boot_barker()
56 * i2400m_rx() 57 * i2400m_rx()
57 * 58 *
58 * i2400ms_rx_setup() 59 * i2400ms_rx_setup()
@@ -138,6 +139,11 @@ void i2400ms_rx(struct i2400ms *i2400ms)
138 ret = rx_size; 139 ret = rx_size;
139 goto error_get_size; 140 goto error_get_size;
140 } 141 }
142 /*
143 * Hardware quirk: make sure to clear the INTR status register
144 * AFTER getting the data transfer size.
145 */
146 sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
141 147
142 ret = -ENOMEM; 148 ret = -ENOMEM;
143 skb = alloc_skb(rx_size, GFP_ATOMIC); 149 skb = alloc_skb(rx_size, GFP_ATOMIC);
@@ -153,25 +159,34 @@ void i2400ms_rx(struct i2400ms *i2400ms)
153 } 159 }
154 160
155 rmb(); /* make sure we get boot_mode from dev_reset_handle */ 161 rmb(); /* make sure we get boot_mode from dev_reset_handle */
156 if (i2400m->boot_mode == 1) { 162 if (unlikely(i2400m->boot_mode == 1)) {
157 spin_lock(&i2400m->rx_lock); 163 spin_lock(&i2400m->rx_lock);
158 i2400ms->bm_ack_size = rx_size; 164 i2400ms->bm_ack_size = rx_size;
159 spin_unlock(&i2400m->rx_lock); 165 spin_unlock(&i2400m->rx_lock);
160 memcpy(i2400m->bm_ack_buf, skb->data, rx_size); 166 memcpy(i2400m->bm_ack_buf, skb->data, rx_size);
161 wake_up(&i2400ms->bm_wfa_wq); 167 wake_up(&i2400ms->bm_wfa_wq);
162 dev_err(dev, "RX: SDIO boot mode message\n"); 168 d_printf(5, dev, "RX: SDIO boot mode message\n");
163 kfree_skb(skb); 169 kfree_skb(skb);
164 } else if (unlikely(!memcmp(skb->data, i2400m_NBOOT_BARKER, 170 goto out;
165 sizeof(i2400m_NBOOT_BARKER)) 171 }
166 || !memcmp(skb->data, i2400m_SBOOT_BARKER, 172 ret = -EIO;
167 sizeof(i2400m_SBOOT_BARKER)))) { 173 if (unlikely(rx_size < sizeof(__le32))) {
168 ret = i2400m_dev_reset_handle(i2400m); 174 dev_err(dev, "HW BUG? only %zu bytes received\n", rx_size);
175 goto error_bad_size;
176 }
177 if (likely(i2400m_is_d2h_barker(skb->data))) {
178 skb_put(skb, rx_size);
179 i2400m_rx(i2400m, skb);
180 } else if (unlikely(i2400m_is_boot_barker(i2400m,
181 skb->data, rx_size))) {
182 ret = i2400m_dev_reset_handle(i2400m, "device rebooted");
169 dev_err(dev, "RX: SDIO reboot barker\n"); 183 dev_err(dev, "RX: SDIO reboot barker\n");
170 kfree_skb(skb); 184 kfree_skb(skb);
171 } else { 185 } else {
172 skb_put(skb, rx_size); 186 i2400m_unknown_barker(i2400m, skb->data, rx_size);
173 i2400m_rx(i2400m, skb); 187 kfree_skb(skb);
174 } 188 }
189out:
175 d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms); 190 d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms);
176 return; 191 return;
177 192
@@ -179,6 +194,7 @@ error_memcpy_fromio:
179 kfree_skb(skb); 194 kfree_skb(skb);
180error_alloc_skb: 195error_alloc_skb:
181error_get_size: 196error_get_size:
197error_bad_size:
182 d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret); 198 d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret);
183 return; 199 return;
184} 200}
@@ -209,7 +225,6 @@ void i2400ms_irq(struct sdio_func *func)
209 dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n"); 225 dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n");
210 goto error_no_irq; 226 goto error_no_irq;
211 } 227 }
212 sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
213 i2400ms_rx(i2400ms); 228 i2400ms_rx(i2400ms);
214error_no_irq: 229error_no_irq:
215 d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); 230 d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms);
@@ -234,6 +249,13 @@ int i2400ms_rx_setup(struct i2400ms *i2400ms)
234 init_waitqueue_head(&i2400ms->bm_wfa_wq); 249 init_waitqueue_head(&i2400ms->bm_wfa_wq);
235 spin_lock(&i2400m->rx_lock); 250 spin_lock(&i2400m->rx_lock);
236 i2400ms->bm_wait_result = -EINPROGRESS; 251 i2400ms->bm_wait_result = -EINPROGRESS;
252 /*
253 * Before we are about to enable the RX interrupt, make sure
254 * bm_ack_size is cleared to -EINPROGRESS which indicates
255 * no RX interrupt happened yet or the previous interrupt
256 * has been handled, we are ready to take the new interrupt
257 */
258 i2400ms->bm_ack_size = -EINPROGRESS;
237 spin_unlock(&i2400m->rx_lock); 259 spin_unlock(&i2400m->rx_lock);
238 260
239 sdio_claim_host(func); 261 sdio_claim_host(func);