Skip to content

Commit

Permalink
carl9170: fix sleep in softirq context
Browse files Browse the repository at this point in the history
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: Ronald Wahl <ronald.wahl@raritan.com>
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Ronald Wahl authored and John W. Linville committed Oct 8, 2012
1 parent 9c371f9 commit 5bcbc3f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/carl9170/carl9170.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ struct ar9170 {
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
bool needs_full_reset;
bool force_usb_reset;
atomic_t pending_restarts;

/* interface mode settings */
Expand Down
29 changes: 14 additions & 15 deletions drivers/net/wireless/ath/carl9170/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,27 +465,26 @@ static void carl9170_restart_work(struct work_struct *work)
{
struct ar9170 *ar = container_of(work, struct ar9170,
restart_work);
int err;
int err = -EIO;

ar->usedkeys = 0;
ar->filter_state = 0;
carl9170_cancel_worker(ar);

mutex_lock(&ar->mutex);
err = carl9170_usb_restart(ar);
if (net_ratelimit()) {
if (err) {
dev_err(&ar->udev->dev, "Failed to restart device "
" (%d).\n", err);
} else {
dev_info(&ar->udev->dev, "device restarted "
"successfully.\n");
if (!ar->force_usb_reset) {
err = carl9170_usb_restart(ar);
if (net_ratelimit()) {
if (err)
dev_err(&ar->udev->dev, "Failed to restart device (%d).\n", err);
else
dev_info(&ar->udev->dev, "device restarted successfully.\n");
}
}

carl9170_zap_queues(ar);
mutex_unlock(&ar->mutex);
if (!err) {

if (!err && !ar->force_usb_reset) {
ar->restart_counter++;
atomic_set(&ar->pending_restarts, 0);

Expand Down Expand Up @@ -526,10 +525,10 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
if (!ar->registered)
return;

if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset)
ieee80211_queue_work(ar->hw, &ar->restart_work);
else
carl9170_usb_reset(ar);
if (!IS_ACCEPTING_CMD(ar) || ar->needs_full_reset)
ar->force_usb_reset = true;

ieee80211_queue_work(ar->hw, &ar->restart_work);

/*
* At this point, the device instance might have vanished/disabled.
Expand Down

0 comments on commit 5bcbc3f

Please sign in to comment.