diff options
-rw-r--r-- | drivers/net/wireless/ipw2200.c | 56 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2200.h | 3 |
2 files changed, 49 insertions, 10 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 2119a79dcc86..feb8fcbab2d5 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -1740,8 +1740,10 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) | |||
1740 | if (disable_radio) { | 1740 | if (disable_radio) { |
1741 | priv->status |= STATUS_RF_KILL_SW; | 1741 | priv->status |= STATUS_RF_KILL_SW; |
1742 | 1742 | ||
1743 | if (priv->workqueue) | 1743 | if (priv->workqueue) { |
1744 | cancel_delayed_work(&priv->request_scan); | 1744 | cancel_delayed_work(&priv->request_scan); |
1745 | cancel_delayed_work(&priv->scan_event); | ||
1746 | } | ||
1745 | queue_work(priv->workqueue, &priv->down); | 1747 | queue_work(priv->workqueue, &priv->down); |
1746 | } else { | 1748 | } else { |
1747 | priv->status &= ~STATUS_RF_KILL_SW; | 1749 | priv->status &= ~STATUS_RF_KILL_SW; |
@@ -1992,6 +1994,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1992 | wake_up_interruptible(&priv->wait_command_queue); | 1994 | wake_up_interruptible(&priv->wait_command_queue); |
1993 | priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); | 1995 | priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); |
1994 | cancel_delayed_work(&priv->request_scan); | 1996 | cancel_delayed_work(&priv->request_scan); |
1997 | cancel_delayed_work(&priv->scan_event); | ||
1995 | schedule_work(&priv->link_down); | 1998 | schedule_work(&priv->link_down); |
1996 | queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); | 1999 | queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); |
1997 | handled |= IPW_INTA_BIT_RF_KILL_DONE; | 2000 | handled |= IPW_INTA_BIT_RF_KILL_DONE; |
@@ -4343,6 +4346,37 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, | |||
4343 | IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count); | 4346 | IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count); |
4344 | } | 4347 | } |
4345 | 4348 | ||
4349 | static void ipw_scan_event(struct work_struct *work) | ||
4350 | { | ||
4351 | union iwreq_data wrqu; | ||
4352 | |||
4353 | struct ipw_priv *priv = | ||
4354 | container_of(work, struct ipw_priv, scan_event.work); | ||
4355 | |||
4356 | wrqu.data.length = 0; | ||
4357 | wrqu.data.flags = 0; | ||
4358 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); | ||
4359 | } | ||
4360 | |||
4361 | static void handle_scan_event(struct ipw_priv *priv) | ||
4362 | { | ||
4363 | /* Only userspace-requested scan completion events go out immediately */ | ||
4364 | if (!priv->user_requested_scan) { | ||
4365 | if (!delayed_work_pending(&priv->scan_event)) | ||
4366 | queue_delayed_work(priv->workqueue, &priv->scan_event, | ||
4367 | round_jiffies(msecs_to_jiffies(4000))); | ||
4368 | } else { | ||
4369 | union iwreq_data wrqu; | ||
4370 | |||
4371 | priv->user_requested_scan = 0; | ||
4372 | cancel_delayed_work(&priv->scan_event); | ||
4373 | |||
4374 | wrqu.data.length = 0; | ||
4375 | wrqu.data.flags = 0; | ||
4376 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); | ||
4377 | } | ||
4378 | } | ||
4379 | |||
4346 | /** | 4380 | /** |
4347 | * Handle host notification packet. | 4381 | * Handle host notification packet. |
4348 | * Called from interrupt routine | 4382 | * Called from interrupt routine |
@@ -4705,14 +4739,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4705 | * on how the scan was initiated. User space can just | 4739 | * on how the scan was initiated. User space can just |
4706 | * sync on periodic scan to get fresh data... | 4740 | * sync on periodic scan to get fresh data... |
4707 | * Jean II */ | 4741 | * Jean II */ |
4708 | if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) { | 4742 | if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) |
4709 | union iwreq_data wrqu; | 4743 | handle_scan_event(priv); |
4710 | |||
4711 | wrqu.data.length = 0; | ||
4712 | wrqu.data.flags = 0; | ||
4713 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, | ||
4714 | &wrqu, NULL); | ||
4715 | } | ||
4716 | break; | 4744 | break; |
4717 | } | 4745 | } |
4718 | 4746 | ||
@@ -9490,6 +9518,10 @@ static int ipw_wx_set_scan(struct net_device *dev, | |||
9490 | struct ipw_priv *priv = ieee80211_priv(dev); | 9518 | struct ipw_priv *priv = ieee80211_priv(dev); |
9491 | struct iw_scan_req *req = (struct iw_scan_req *)extra; | 9519 | struct iw_scan_req *req = (struct iw_scan_req *)extra; |
9492 | 9520 | ||
9521 | mutex_lock(&priv->mutex); | ||
9522 | priv->user_requested_scan = 1; | ||
9523 | mutex_unlock(&priv->mutex); | ||
9524 | |||
9493 | if (wrqu->data.length == sizeof(struct iw_scan_req)) { | 9525 | if (wrqu->data.length == sizeof(struct iw_scan_req)) { |
9494 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 9526 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
9495 | ipw_request_direct_scan(priv, req->essid, | 9527 | ipw_request_direct_scan(priv, req->essid, |
@@ -10668,6 +10700,7 @@ static void ipw_link_up(struct ipw_priv *priv) | |||
10668 | } | 10700 | } |
10669 | 10701 | ||
10670 | cancel_delayed_work(&priv->request_scan); | 10702 | cancel_delayed_work(&priv->request_scan); |
10703 | cancel_delayed_work(&priv->scan_event); | ||
10671 | ipw_reset_stats(priv); | 10704 | ipw_reset_stats(priv); |
10672 | /* Ensure the rate is updated immediately */ | 10705 | /* Ensure the rate is updated immediately */ |
10673 | priv->last_rate = ipw_get_current_rate(priv); | 10706 | priv->last_rate = ipw_get_current_rate(priv); |
@@ -10705,7 +10738,8 @@ static void ipw_link_down(struct ipw_priv *priv) | |||
10705 | if (!(priv->status & STATUS_EXIT_PENDING)) { | 10738 | if (!(priv->status & STATUS_EXIT_PENDING)) { |
10706 | /* Queue up another scan... */ | 10739 | /* Queue up another scan... */ |
10707 | queue_delayed_work(priv->workqueue, &priv->request_scan, 0); | 10740 | queue_delayed_work(priv->workqueue, &priv->request_scan, 0); |
10708 | } | 10741 | } else |
10742 | cancel_delayed_work(&priv->scan_event); | ||
10709 | } | 10743 | } |
10710 | 10744 | ||
10711 | static void ipw_bg_link_down(struct work_struct *work) | 10745 | static void ipw_bg_link_down(struct work_struct *work) |
@@ -10735,6 +10769,7 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) | |||
10735 | INIT_WORK(&priv->up, ipw_bg_up); | 10769 | INIT_WORK(&priv->up, ipw_bg_up); |
10736 | INIT_WORK(&priv->down, ipw_bg_down); | 10770 | INIT_WORK(&priv->down, ipw_bg_down); |
10737 | INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); | 10771 | INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); |
10772 | INIT_DELAYED_WORK(&priv->scan_event, ipw_scan_event); | ||
10738 | INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan); | 10773 | INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan); |
10739 | INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); | 10774 | INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); |
10740 | INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); | 10775 | INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); |
@@ -11766,6 +11801,7 @@ static void ipw_pci_remove(struct pci_dev *pdev) | |||
11766 | cancel_delayed_work(&priv->adhoc_check); | 11801 | cancel_delayed_work(&priv->adhoc_check); |
11767 | cancel_delayed_work(&priv->gather_stats); | 11802 | cancel_delayed_work(&priv->gather_stats); |
11768 | cancel_delayed_work(&priv->request_scan); | 11803 | cancel_delayed_work(&priv->request_scan); |
11804 | cancel_delayed_work(&priv->scan_event); | ||
11769 | cancel_delayed_work(&priv->rf_kill); | 11805 | cancel_delayed_work(&priv->rf_kill); |
11770 | cancel_delayed_work(&priv->scan_check); | 11806 | cancel_delayed_work(&priv->scan_check); |
11771 | destroy_workqueue(priv->workqueue); | 11807 | destroy_workqueue(priv->workqueue); |
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 9c973b96bb42..bec8e37a1738 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h | |||
@@ -1287,6 +1287,8 @@ struct ipw_priv { | |||
1287 | 1287 | ||
1288 | struct iw_public_data wireless_data; | 1288 | struct iw_public_data wireless_data; |
1289 | 1289 | ||
1290 | int user_requested_scan; | ||
1291 | |||
1290 | struct workqueue_struct *workqueue; | 1292 | struct workqueue_struct *workqueue; |
1291 | 1293 | ||
1292 | struct delayed_work adhoc_check; | 1294 | struct delayed_work adhoc_check; |
@@ -1295,6 +1297,7 @@ struct ipw_priv { | |||
1295 | struct work_struct system_config; | 1297 | struct work_struct system_config; |
1296 | struct work_struct rx_replenish; | 1298 | struct work_struct rx_replenish; |
1297 | struct delayed_work request_scan; | 1299 | struct delayed_work request_scan; |
1300 | struct delayed_work scan_event; | ||
1298 | struct work_struct request_passive_scan; | 1301 | struct work_struct request_passive_scan; |
1299 | struct work_struct adapter_restart; | 1302 | struct work_struct adapter_restart; |
1300 | struct delayed_work rf_kill; | 1303 | struct delayed_work rf_kill; |