aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-07 23:36:03 -0400
committerInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-19 02:56:25 -0400
commita8ee303cae6fbdaa639afa50b9d03ce6f0c7d7da (patch)
tree91c3a39faff5efe635e31be76dbce03609695a4d
parent097acbeff98178e01c2f6adb2259ab4d811340cc (diff)
wimax/i2400m: SDIO: fix oops on reset when TXing on uninitialized data
Currently the SDIO part of the TX resources were initialized/released with bus_dev_{start,stop}. The generic code's TX subsystem is destroyed afterwards, so there is a window from the bus-TX destruction to the generic-TX destruction where the generic-TX code might call into bus-TX to do transactions. The SDIO code cannot really cope with this (whereas in USB, how it is laid out, it correctly ignores it). In any case, it made no sense for the SDIO TX code to be in i2400m->bus_dev_start/stop(), so moved to i2400m->bus_setup/release(), which also takes care of the oops. Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
-rw-r--r--drivers/net/wimax/i2400m/sdio.c43
1 files changed, 9 insertions, 34 deletions
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index 14e66f06f235..ec178928914e 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -46,15 +46,6 @@
46 * i2400ms_bus_reset() Called by i2400m->bus_reset 46 * i2400ms_bus_reset() Called by i2400m->bus_reset
47 * __i2400ms_reset() 47 * __i2400ms_reset()
48 * __i2400ms_send_barker() 48 * __i2400ms_send_barker()
49 *
50 * i2400ms_bus_dev_start() Called by i2400m_dev_start() [who is
51 * i2400ms_tx_setup() called by i2400m_setup()]
52 * i2400ms_rx_setup()
53 *
54 * i2400ms_bus_dev_stop() Called by i2400m_dev_stop() [who is
55 * i2400ms_rx_release() is called by i2400m_release()]
56 * i2400ms_tx_release()
57 *
58 */ 49 */
59 50
60#include <linux/debugfs.h> 51#include <linux/debugfs.h>
@@ -191,12 +182,17 @@ int i2400ms_bus_setup(struct i2400m *i2400m)
191 goto error_func_enable; 182 goto error_func_enable;
192 } 183 }
193 184
185 result = i2400ms_tx_setup(i2400ms);
186 if (result < 0)
187 goto error_tx_setup;
194 result = i2400ms_rx_setup(i2400ms); 188 result = i2400ms_rx_setup(i2400ms);
195 if (result < 0) 189 if (result < 0)
196 goto error_rx_setup; 190 goto error_rx_setup;
197 return 0; 191 return 0;
198 192
199error_rx_setup: 193error_rx_setup:
194 i2400ms_tx_release(i2400ms);
195error_tx_setup:
200 sdio_claim_host(func); 196 sdio_claim_host(func);
201 sdio_disable_func(func); 197 sdio_disable_func(func);
202 sdio_release_host(func); 198 sdio_release_host(func);
@@ -218,6 +214,7 @@ void i2400ms_bus_release(struct i2400m *i2400m)
218 struct sdio_func *func = i2400ms->func; 214 struct sdio_func *func = i2400ms->func;
219 215
220 i2400ms_rx_release(i2400ms); 216 i2400ms_rx_release(i2400ms);
217 i2400ms_tx_release(i2400ms);
221 sdio_claim_host(func); 218 sdio_claim_host(func);
222 sdio_disable_func(func); 219 sdio_disable_func(func);
223 sdio_release_host(func); 220 sdio_release_host(func);
@@ -235,36 +232,14 @@ void i2400ms_bus_release(struct i2400m *i2400m)
235static 232static
236int i2400ms_bus_dev_start(struct i2400m *i2400m) 233int i2400ms_bus_dev_start(struct i2400m *i2400m)
237{ 234{
238 int result;
239 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); 235 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
240 struct sdio_func *func = i2400ms->func; 236 struct sdio_func *func = i2400ms->func;
241 struct device *dev = &func->dev; 237 struct device *dev = &func->dev;
242 238
243 d_fnstart(3, dev, "(i2400m %p)\n", i2400m); 239 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
244 msleep(200); 240 msleep(200);
245 result = i2400ms_tx_setup(i2400ms); 241 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, 0);
246 if (result < 0) 242 return 0;
247 goto error_tx_setup;
248 d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
249 return result;
250
251error_tx_setup:
252 i2400ms_tx_release(i2400ms);
253 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
254 return result;
255}
256
257
258static
259void i2400ms_bus_dev_stop(struct i2400m *i2400m)
260{
261 struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
262 struct sdio_func *func = i2400ms->func;
263 struct device *dev = &func->dev;
264
265 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
266 i2400ms_tx_release(i2400ms);
267 d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
268} 243}
269 244
270 245
@@ -506,7 +481,7 @@ int i2400ms_probe(struct sdio_func *func,
506 i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX; 481 i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
507 i2400m->bus_setup = i2400ms_bus_setup; 482 i2400m->bus_setup = i2400ms_bus_setup;
508 i2400m->bus_dev_start = i2400ms_bus_dev_start; 483 i2400m->bus_dev_start = i2400ms_bus_dev_start;
509 i2400m->bus_dev_stop = i2400ms_bus_dev_stop; 484 i2400m->bus_dev_stop = NULL;
510 i2400m->bus_release = i2400ms_bus_release; 485 i2400m->bus_release = i2400ms_bus_release;
511 i2400m->bus_tx_kick = i2400ms_bus_tx_kick; 486 i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
512 i2400m->bus_reset = i2400ms_bus_reset; 487 i2400m->bus_reset = i2400ms_bus_reset;