aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ipw2200.c56
-rw-r--r--drivers/net/wireless/ipw2200.h3
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
4349static 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
4361static 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
10711static void ipw_bg_link_down(struct work_struct *work) 10745static 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;