diff options
Diffstat (limited to 'drivers/net/wimax/i2400m/driver.c')
| -rw-r--r-- | drivers/net/wimax/i2400m/driver.c | 115 |
1 files changed, 23 insertions, 92 deletions
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index cdedab46ba2..9c78090e72f 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c @@ -92,54 +92,6 @@ MODULE_PARM_DESC(barkers, "signal; values are appended to a list--setting one value " "as zero cleans the existing list and starts a new one."); -static -struct i2400m_work *__i2400m_work_setup( - struct i2400m *i2400m, void (*fn)(struct work_struct *), - gfp_t gfp_flags, const void *pl, size_t pl_size) -{ - struct i2400m_work *iw; - - iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags); - if (iw == NULL) - return NULL; - iw->i2400m = i2400m_get(i2400m); - iw->pl_size = pl_size; - memcpy(iw->pl, pl, pl_size); - INIT_WORK(&iw->ws, fn); - return iw; -} - - -/* - * Schedule i2400m's specific work on the system's queue. - * - * Used for a few cases where we really need it; otherwise, identical - * to i2400m_queue_work(). - * - * Returns < 0 errno code on error, 1 if ok. - * - * If it returns zero, something really bad happened, as it means the - * works struct was already queued, but we have just allocated it, so - * it should not happen. - */ -static int i2400m_schedule_work(struct i2400m *i2400m, - void (*fn)(struct work_struct *), gfp_t gfp_flags, - const void *pl, size_t pl_size) -{ - int result; - struct i2400m_work *iw; - - result = -ENOMEM; - iw = __i2400m_work_setup(i2400m, fn, gfp_flags, pl, pl_size); - if (iw != NULL) { - result = schedule_work(&iw->ws); - if (WARN_ON(result == 0)) - result = -ENXIO; - } - return result; -} - - /* * WiMAX stack operation: relay a message from user space * @@ -270,7 +222,6 @@ int i2400m_check_mac_addr(struct i2400m *i2400m) struct sk_buff *skb; const struct i2400m_tlv_detailed_device_info *ddi; struct net_device *net_dev = i2400m->wimax_dev.net_dev; - const unsigned char zeromac[ETH_ALEN] = { 0 }; d_fnstart(3, dev, "(i2400m %p)\n", i2400m); skb = i2400m_get_device_info(i2400m); @@ -280,7 +231,7 @@ int i2400m_check_mac_addr(struct i2400m *i2400m) result); goto error; } - /* Extract MAC addresss */ + /* Extract MAC address */ ddi = (void *) skb->data; BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address)); d_printf(2, dev, "GET DEVICE INFO: mac addr %pM\n", @@ -292,7 +243,7 @@ int i2400m_check_mac_addr(struct i2400m *i2400m) "to that of boot mode's\n"); dev_warn(dev, "device reports %pM\n", ddi->mac_address); dev_warn(dev, "boot mode reported %pM\n", net_dev->perm_addr); - if (!memcmp(zeromac, ddi->mac_address, sizeof(zeromac))) + if (is_zero_ether_addr(ddi->mac_address)) dev_err(dev, "device reports an invalid MAC address, " "not updating\n"); else { @@ -549,26 +500,23 @@ int i2400m_pm_notifier(struct notifier_block *notifier, */ int i2400m_pre_reset(struct i2400m *i2400m) { - int result; struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(i2400m %p)\n", i2400m); d_printf(1, dev, "pre-reset shut down\n"); - result = 0; mutex_lock(&i2400m->init_mutex); if (i2400m->updown) { netif_tx_disable(i2400m->wimax_dev.net_dev); __i2400m_dev_stop(i2400m); - result = 0; /* down't set updown to zero -- this way * post_reset can restore properly */ } mutex_unlock(&i2400m->init_mutex); if (i2400m->bus_release) i2400m->bus_release(i2400m); - d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); - return result; + d_fnend(3, dev, "(i2400m %p) = 0\n", i2400m); + return 0; } EXPORT_SYMBOL_GPL(i2400m_pre_reset); @@ -648,17 +596,11 @@ EXPORT_SYMBOL_GPL(i2400m_post_reset); static void __i2400m_dev_reset_handle(struct work_struct *ws) { - int result; - struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); - const char *reason; - struct i2400m *i2400m = iw->i2400m; + struct i2400m *i2400m = container_of(ws, struct i2400m, reset_ws); + const char *reason = i2400m->reset_reason; struct device *dev = i2400m_dev(i2400m); struct i2400m_reset_ctx *ctx = i2400m->reset_ctx; - - if (WARN_ON(iw->pl_size != sizeof(reason))) - reason = "SW BUG: reason n/a"; - else - memcpy(&reason, iw->pl, sizeof(reason)); + int result; d_fnstart(3, dev, "(ws %p i2400m %p reason %s)\n", ws, i2400m, reason); @@ -708,7 +650,7 @@ void __i2400m_dev_reset_handle(struct work_struct *ws) if (result == -EUCLEAN) { /* * We come here because the reset during operational mode - * wasn't successully done and need to proceed to a bus + * wasn't successfully done and need to proceed to a bus * reset. For the dev_reset_handle() to be able to handle * the reset event later properly, we restore boot_mode back * to the state before previous reset. ie: just like we are @@ -733,8 +675,6 @@ void __i2400m_dev_reset_handle(struct work_struct *ws) } } out: - i2400m_put(i2400m); - kfree(iw); d_fnend(3, dev, "(ws %p i2400m %p reason %s) = void\n", ws, i2400m, reason); } @@ -754,8 +694,8 @@ out: */ int i2400m_dev_reset_handle(struct i2400m *i2400m, const char *reason) { - return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle, - GFP_ATOMIC, &reason, sizeof(reason)); + i2400m->reset_reason = reason; + return schedule_work(&i2400m->reset_ws); } EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle); @@ -768,14 +708,9 @@ EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle); static void __i2400m_error_recovery(struct work_struct *ws) { - struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); - struct i2400m *i2400m = iw->i2400m; + struct i2400m *i2400m = container_of(ws, struct i2400m, recovery_ws); i2400m_reset(i2400m, I2400M_RT_BUS); - - i2400m_put(i2400m); - kfree(iw); - return; } /* @@ -805,26 +740,17 @@ void __i2400m_error_recovery(struct work_struct *ws) */ void i2400m_error_recovery(struct i2400m *i2400m) { - struct device *dev = i2400m_dev(i2400m); - - if (atomic_add_return(1, &i2400m->error_recovery) == 1) { - if (i2400m_schedule_work(i2400m, __i2400m_error_recovery, - GFP_ATOMIC, NULL, 0) < 0) { - dev_err(dev, "run out of memory for " - "scheduling an error recovery ?\n"); - atomic_dec(&i2400m->error_recovery); - } - } else + if (atomic_add_return(1, &i2400m->error_recovery) == 1) + schedule_work(&i2400m->recovery_ws); + else atomic_dec(&i2400m->error_recovery); - return; } EXPORT_SYMBOL_GPL(i2400m_error_recovery); /* * Alloc the command and ack buffers for boot mode * - * Get the buffers needed to deal with boot mode messages. These - * buffers need to be allocated before the sdio recieve irq is setup. + * Get the buffers needed to deal with boot mode messages. */ static int i2400m_bm_buf_alloc(struct i2400m *i2400m) @@ -886,6 +812,10 @@ void i2400m_init(struct i2400m *i2400m) mutex_init(&i2400m->init_mutex); /* wake_tx_ws is initialized in i2400m_tx_setup() */ + + INIT_WORK(&i2400m->reset_ws, __i2400m_dev_reset_handle); + INIT_WORK(&i2400m->recovery_ws, __i2400m_error_recovery); + atomic_set(&i2400m->bus_reset_retries, 0); i2400m->alive = 0; @@ -962,7 +892,7 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) result = i2400m_read_mac_addr(i2400m); if (result < 0) goto error_read_mac_addr; - random_ether_addr(i2400m->src_mac_addr); + eth_random_addr(i2400m->src_mac_addr); i2400m->pm_notifier.notifier_call = i2400m_pm_notifier; register_pm_notifier(&i2400m->pm_notifier); @@ -1040,6 +970,9 @@ void i2400m_release(struct i2400m *i2400m) i2400m_dev_stop(i2400m); + cancel_work_sync(&i2400m->reset_ws); + cancel_work_sync(&i2400m->recovery_ws); + i2400m_debugfs_rm(i2400m); sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, &i2400m_dev_attr_group); @@ -1083,8 +1016,6 @@ module_init(i2400m_driver_init); static void __exit i2400m_driver_exit(void) { - /* for scheds i2400m_dev_reset_handle() */ - flush_scheduled_work(); i2400m_barker_db_exit(); } module_exit(i2400m_driver_exit); |
