Commit 5bcbc3fc authored by Ronald Wahl's avatar Ronald Wahl Committed by John W. Linville

carl9170: fix sleep in softirq context

This patch fixes the following bug:

usb 1-1.1: restart device (8)
BUG: sleeping function called from invalid context at drivers/usb/core/urb.c:654
in_atomic(): 1, irqs_disabled(): 0, pid: 0, name: swapper
 (usb_poison_urb+0x1c/0xf8)
 (usb_poison_anchored_urbs+0x48/0x78)
 (carl9170_usb_handle_tx_err+0x128/0x150)
 (carl9170_usb_reset+0xc/0x20)
 (carl9170_handle_command_response+0x298/0xea8)
 (carl9170_usb_tasklet+0x68/0x184)
 (tasklet_hi_action+0x84/0xdc)

this only happens if the device is plugged in an USB port,
the driver is loaded but inactive (e.g. the wlan interface
is down). If the device is active everything is fine.
Signed-off-by: default avatarRonald Wahl <ronald.wahl@raritan.com>
Signed-off-by: default avatarChristian Lamparter <chunkeey@googlemail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9c371f99
...@@ -303,6 +303,7 @@ struct ar9170 { ...@@ -303,6 +303,7 @@ struct ar9170 {
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ]; unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ]; unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
bool needs_full_reset; bool needs_full_reset;
bool force_usb_reset;
atomic_t pending_restarts; atomic_t pending_restarts;
/* interface mode settings */ /* interface mode settings */
......
...@@ -465,27 +465,26 @@ static void carl9170_restart_work(struct work_struct *work) ...@@ -465,27 +465,26 @@ static void carl9170_restart_work(struct work_struct *work)
{ {
struct ar9170 *ar = container_of(work, struct ar9170, struct ar9170 *ar = container_of(work, struct ar9170,
restart_work); restart_work);
int err; int err = -EIO;
ar->usedkeys = 0; ar->usedkeys = 0;
ar->filter_state = 0; ar->filter_state = 0;
carl9170_cancel_worker(ar); carl9170_cancel_worker(ar);
mutex_lock(&ar->mutex); mutex_lock(&ar->mutex);
err = carl9170_usb_restart(ar); if (!ar->force_usb_reset) {
if (net_ratelimit()) { err = carl9170_usb_restart(ar);
if (err) { if (net_ratelimit()) {
dev_err(&ar->udev->dev, "Failed to restart device " if (err)
" (%d).\n", err); dev_err(&ar->udev->dev, "Failed to restart device (%d).\n", err);
} else { else
dev_info(&ar->udev->dev, "device restarted " dev_info(&ar->udev->dev, "device restarted successfully.\n");
"successfully.\n");
} }
} }
carl9170_zap_queues(ar); carl9170_zap_queues(ar);
mutex_unlock(&ar->mutex); mutex_unlock(&ar->mutex);
if (!err) {
if (!err && !ar->force_usb_reset) {
ar->restart_counter++; ar->restart_counter++;
atomic_set(&ar->pending_restarts, 0); atomic_set(&ar->pending_restarts, 0);
...@@ -526,10 +525,10 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r) ...@@ -526,10 +525,10 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
if (!ar->registered) if (!ar->registered)
return; return;
if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset) if (!IS_ACCEPTING_CMD(ar) || ar->needs_full_reset)
ieee80211_queue_work(ar->hw, &ar->restart_work); ar->force_usb_reset = true;
else
carl9170_usb_reset(ar); ieee80211_queue_work(ar->hw, &ar->restart_work);
/* /*
* At this point, the device instance might have vanished/disabled. * At this point, the device instance might have vanished/disabled.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment