diff options
author | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-10-19 03:24:56 -0400 |
---|---|---|
committer | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-11-03 15:49:36 -0500 |
commit | c931ceeb780560ff652a8f9875f88778439ee87e (patch) | |
tree | ca754722967ff1b9a4660ef38b0eae3d36f38a58 /drivers/net | |
parent | 55a662d6468005ec3cd799fbd8d0ad03dfae6d2a (diff) |
wimax/i2400m: introduce i2400m_reset(), stopping TX and carrier
Currently the i2400m driver was resetting by just calling
i2400m->bus_reset(). However, this was missing stopping the TX queue
and downing the carrier. This was causing, for the corner case of the
driver reseting a device that refuses to go out of idle mode, that a
few packets would be queued and more than one reset would go through,
making the recovery a wee bit messy.
To avoid introducing the same cleanup in all the bus-specific driver,
introduced a i2400m_reset() function that takes care of house cleaning
and then calling the bus-level reset implementation.
The bulk of the changes in all files are just to rename the call from
i2400m->bus_reset() to i2400m_reset().
Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wimax/i2400m/control.c | 4 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/debugfs.c | 2 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/driver.c | 22 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/fw.c | 4 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/i2400m.h | 1 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/netdev.c | 8 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/rx.c | 4 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/sdio.c | 9 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/usb.c | 2 |
9 files changed, 35 insertions, 21 deletions
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index b69fd8834c78..944945540391 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c | |||
@@ -54,7 +54,7 @@ | |||
54 | * i2400m_set_init_config() | 54 | * i2400m_set_init_config() |
55 | * i2400m_cmd_get_state() | 55 | * i2400m_cmd_get_state() |
56 | * i2400m_dev_shutdown() Called by i2400m_dev_stop() | 56 | * i2400m_dev_shutdown() Called by i2400m_dev_stop() |
57 | * i2400m->bus_reset() | 57 | * i2400m_reset() |
58 | * | 58 | * |
59 | * i2400m_{cmd,get,set}_*() | 59 | * i2400m_{cmd,get,set}_*() |
60 | * i2400m_msg_to_dev() | 60 | * i2400m_msg_to_dev() |
@@ -343,7 +343,7 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m, | |||
343 | /* Huh? just in case, shut it down */ | 343 | /* Huh? just in case, shut it down */ |
344 | dev_err(dev, "HW BUG? unknown state %u: shutting down\n", | 344 | dev_err(dev, "HW BUG? unknown state %u: shutting down\n", |
345 | i2400m_state); | 345 | i2400m_state); |
346 | i2400m->bus_reset(i2400m, I2400M_RT_WARM); | 346 | i2400m_reset(i2400m, I2400M_RT_WARM); |
347 | break; | 347 | break; |
348 | }; | 348 | }; |
349 | d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n", | 349 | d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n", |
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c index 9b81af3f80a9..b1aec3e1892f 100644 --- a/drivers/net/wimax/i2400m/debugfs.c +++ b/drivers/net/wimax/i2400m/debugfs.c | |||
@@ -214,7 +214,7 @@ int debugfs_i2400m_reset_set(void *data, u64 val) | |||
214 | case I2400M_RT_WARM: | 214 | case I2400M_RT_WARM: |
215 | case I2400M_RT_COLD: | 215 | case I2400M_RT_COLD: |
216 | case I2400M_RT_BUS: | 216 | case I2400M_RT_BUS: |
217 | result = i2400m->bus_reset(i2400m, rt); | 217 | result = i2400m_reset(i2400m, rt); |
218 | if (result >= 0) | 218 | if (result >= 0) |
219 | result = 0; | 219 | result = 0; |
220 | default: | 220 | default: |
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index cc58a864bd06..96a615fe09de 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c | |||
@@ -255,7 +255,7 @@ int i2400m_op_reset(struct wimax_dev *wimax_dev) | |||
255 | mutex_lock(&i2400m->init_mutex); | 255 | mutex_lock(&i2400m->init_mutex); |
256 | i2400m->reset_ctx = &ctx; | 256 | i2400m->reset_ctx = &ctx; |
257 | mutex_unlock(&i2400m->init_mutex); | 257 | mutex_unlock(&i2400m->init_mutex); |
258 | result = i2400m->bus_reset(i2400m, I2400M_RT_WARM); | 258 | result = i2400m_reset(i2400m, I2400M_RT_WARM); |
259 | if (result < 0) | 259 | if (result < 0) |
260 | goto out; | 260 | goto out; |
261 | result = wait_for_completion_timeout(&ctx.completion, 4*HZ); | 261 | result = wait_for_completion_timeout(&ctx.completion, 4*HZ); |
@@ -710,7 +710,7 @@ out_unlock: | |||
710 | mutex_unlock(&i2400m->init_mutex); | 710 | mutex_unlock(&i2400m->init_mutex); |
711 | if (result == -EUCLEAN) { | 711 | if (result == -EUCLEAN) { |
712 | /* ops, need to clean up [w/ init_mutex not held] */ | 712 | /* ops, need to clean up [w/ init_mutex not held] */ |
713 | result = i2400m->bus_reset(i2400m, I2400M_RT_BUS); | 713 | result = i2400m_reset(i2400m, I2400M_RT_BUS); |
714 | if (result >= 0) | 714 | if (result >= 0) |
715 | result = -ENODEV; | 715 | result = -ENODEV; |
716 | } | 716 | } |
@@ -815,6 +815,24 @@ void i2400m_init(struct i2400m *i2400m) | |||
815 | EXPORT_SYMBOL_GPL(i2400m_init); | 815 | EXPORT_SYMBOL_GPL(i2400m_init); |
816 | 816 | ||
817 | 817 | ||
818 | int i2400m_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) | ||
819 | { | ||
820 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
821 | |||
822 | /* | ||
823 | * Make sure we stop TXs and down the carrier before | ||
824 | * resetting; this is needed to avoid things like | ||
825 | * i2400m_wake_tx() scheduling stuff in parallel. | ||
826 | */ | ||
827 | if (net_dev->reg_state == NETREG_REGISTERED) { | ||
828 | netif_tx_disable(net_dev); | ||
829 | netif_carrier_off(net_dev); | ||
830 | } | ||
831 | return i2400m->bus_reset(i2400m, rt); | ||
832 | } | ||
833 | EXPORT_SYMBOL_GPL(i2400m_reset); | ||
834 | |||
835 | |||
818 | /** | 836 | /** |
819 | * i2400m_setup - bus-generic setup function for the i2400m device | 837 | * i2400m_setup - bus-generic setup function for the i2400m device |
820 | * | 838 | * |
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index fda54bfdf70e..64cdfeb299ca 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c | |||
@@ -130,7 +130,7 @@ | |||
130 | * i2400m_fw_dnload | 130 | * i2400m_fw_dnload |
131 | * i2400m_bootrom_init | 131 | * i2400m_bootrom_init |
132 | * i2400m_bm_cmd | 132 | * i2400m_bm_cmd |
133 | * i2400m->bus_reset | 133 | * i2400m_reset |
134 | * i2400m_dnload_init | 134 | * i2400m_dnload_init |
135 | * i2400m_dnload_init_signed | 135 | * i2400m_dnload_init_signed |
136 | * i2400m_dnload_init_nonsigned | 136 | * i2400m_dnload_init_nonsigned |
@@ -902,7 +902,7 @@ do_reboot: | |||
902 | d_printf(4, dev, "device reboot: reboot command [%d # left]\n", | 902 | d_printf(4, dev, "device reboot: reboot command [%d # left]\n", |
903 | count); | 903 | count); |
904 | if ((flags & I2400M_BRI_NO_REBOOT) == 0) | 904 | if ((flags & I2400M_BRI_NO_REBOOT) == 0) |
905 | i2400m->bus_reset(i2400m, I2400M_RT_WARM); | 905 | i2400m_reset(i2400m, I2400M_RT_WARM); |
906 | result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack), | 906 | result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack), |
907 | I2400M_BM_CMD_RAW); | 907 | I2400M_BM_CMD_RAW); |
908 | flags &= ~I2400M_BRI_NO_REBOOT; | 908 | flags &= ~I2400M_BRI_NO_REBOOT; |
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 5eee985f2926..04df9bbe340f 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
@@ -717,6 +717,7 @@ unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr) | |||
717 | * Driver / device setup and internal functions | 717 | * Driver / device setup and internal functions |
718 | */ | 718 | */ |
719 | extern void i2400m_init(struct i2400m *); | 719 | extern void i2400m_init(struct i2400m *); |
720 | extern int i2400m_reset(struct i2400m *, enum i2400m_reset_type); | ||
720 | extern void i2400m_netdev_setup(struct net_device *net_dev); | 721 | extern void i2400m_netdev_setup(struct net_device *net_dev); |
721 | extern int i2400m_sysfs_setup(struct device_driver *); | 722 | extern int i2400m_sysfs_setup(struct device_driver *); |
722 | extern void i2400m_sysfs_release(struct device_driver *); | 723 | extern void i2400m_sysfs_release(struct device_driver *); |
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index e7d1a51ee3fe..f67af4291f8c 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c | |||
@@ -171,8 +171,9 @@ void i2400m_wake_tx_work(struct work_struct *ws) | |||
171 | result = 0; | 171 | result = 0; |
172 | if (result < 0) { | 172 | if (result < 0) { |
173 | dev_err(dev, "WAKE&TX: device didn't get out of idle: " | 173 | dev_err(dev, "WAKE&TX: device didn't get out of idle: " |
174 | "%d\n", result); | 174 | "%d - resetting\n", result); |
175 | goto error; | 175 | i2400m_reset(i2400m, I2400M_RT_BUS); |
176 | goto error; | ||
176 | } | 177 | } |
177 | result = wait_event_timeout(i2400m->state_wq, | 178 | result = wait_event_timeout(i2400m->state_wq, |
178 | i2400m->state != I2400M_SS_IDLE, 5 * HZ); | 179 | i2400m->state != I2400M_SS_IDLE, 5 * HZ); |
@@ -180,7 +181,8 @@ void i2400m_wake_tx_work(struct work_struct *ws) | |||
180 | result = -ETIMEDOUT; | 181 | result = -ETIMEDOUT; |
181 | if (result < 0) { | 182 | if (result < 0) { |
182 | dev_err(dev, "WAKE&TX: error waiting for device to exit IDLE: " | 183 | dev_err(dev, "WAKE&TX: error waiting for device to exit IDLE: " |
183 | "%d\n", result); | 184 | "%d - resetting\n", result); |
185 | i2400m_reset(i2400m, I2400M_RT_BUS); | ||
184 | goto error; | 186 | goto error; |
185 | } | 187 | } |
186 | msleep(20); /* device still needs some time or it drops it */ | 188 | msleep(20); /* device still needs some time or it drops it */ |
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index 64a44ca00675..e3d2a9de023c 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c | |||
@@ -828,7 +828,7 @@ void i2400m_roq_queue(struct i2400m *i2400m, struct i2400m_roq *roq, | |||
828 | dev_err(dev, "SW BUG? queue nsn %d (lbn %u ws %u)\n", | 828 | dev_err(dev, "SW BUG? queue nsn %d (lbn %u ws %u)\n", |
829 | nsn, lbn, roq->ws); | 829 | nsn, lbn, roq->ws); |
830 | i2400m_roq_log_dump(i2400m, roq); | 830 | i2400m_roq_log_dump(i2400m, roq); |
831 | i2400m->bus_reset(i2400m, I2400M_RT_WARM); | 831 | i2400m_reset(i2400m, I2400M_RT_WARM); |
832 | } else { | 832 | } else { |
833 | __i2400m_roq_queue(i2400m, roq, skb, lbn, nsn); | 833 | __i2400m_roq_queue(i2400m, roq, skb, lbn, nsn); |
834 | i2400m_roq_log_add(i2400m, roq, I2400M_RO_TYPE_PACKET, | 834 | i2400m_roq_log_add(i2400m, roq, I2400M_RO_TYPE_PACKET, |
@@ -894,7 +894,7 @@ void i2400m_roq_queue_update_ws(struct i2400m *i2400m, struct i2400m_roq *roq, | |||
894 | dev_err(dev, "SW BUG? queue_update_ws nsn %u (sn %u ws %u)\n", | 894 | dev_err(dev, "SW BUG? queue_update_ws nsn %u (sn %u ws %u)\n", |
895 | nsn, sn, roq->ws); | 895 | nsn, sn, roq->ws); |
896 | i2400m_roq_log_dump(i2400m, roq); | 896 | i2400m_roq_log_dump(i2400m, roq); |
897 | i2400m->bus_reset(i2400m, I2400M_RT_WARM); | 897 | i2400m_reset(i2400m, I2400M_RT_WARM); |
898 | } else { | 898 | } else { |
899 | /* if the queue is empty, don't bother as we'd queue | 899 | /* if the queue is empty, don't bother as we'd queue |
900 | * it and inmediately unqueue it -- just deliver it */ | 900 | * it and inmediately unqueue it -- just deliver it */ |
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index ec178928914e..20ab22ec291b 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c | |||
@@ -43,7 +43,7 @@ | |||
43 | * i2400m_release() | 43 | * i2400m_release() |
44 | * free_netdev(net_dev) | 44 | * free_netdev(net_dev) |
45 | * | 45 | * |
46 | * i2400ms_bus_reset() Called by i2400m->bus_reset | 46 | * i2400ms_bus_reset() Called by i2400m_reset |
47 | * __i2400ms_reset() | 47 | * __i2400ms_reset() |
48 | * __i2400ms_send_barker() | 48 | * __i2400ms_send_barker() |
49 | */ | 49 | */ |
@@ -342,13 +342,6 @@ int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) | |||
342 | sizeof(i2400m_COLD_BOOT_BARKER)); | 342 | sizeof(i2400m_COLD_BOOT_BARKER)); |
343 | else if (rt == I2400M_RT_BUS) { | 343 | else if (rt == I2400M_RT_BUS) { |
344 | do_bus_reset: | 344 | do_bus_reset: |
345 | /* call netif_tx_disable() before sending IOE disable, | ||
346 | * so that all the tx from network layer are stopped | ||
347 | * while IOE is being reset. Make sure it is called | ||
348 | * only after register_netdev() was issued. | ||
349 | */ | ||
350 | if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED) | ||
351 | netif_tx_disable(i2400m->wimax_dev.net_dev); | ||
352 | 345 | ||
353 | i2400ms_bus_release(i2400m); | 346 | i2400ms_bus_release(i2400m); |
354 | 347 | ||
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 418db12b0cd7..5e079408f16e 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c | |||
@@ -58,7 +58,7 @@ | |||
58 | * i2400mu_rx_release() | 58 | * i2400mu_rx_release() |
59 | * i2400mu_tx_release() | 59 | * i2400mu_tx_release() |
60 | * | 60 | * |
61 | * i2400mu_bus_reset() Called by i2400m->bus_reset | 61 | * i2400mu_bus_reset() Called by i2400m_reset |
62 | * __i2400mu_reset() | 62 | * __i2400mu_reset() |
63 | * __i2400mu_send_barker() | 63 | * __i2400mu_send_barker() |
64 | * usb_reset_device() | 64 | * usb_reset_device() |