aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2008-06-02 17:51:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-09 15:50:16 -0400
commitea177305b321a4127e448b88de20d5792682ace1 (patch)
tree8623f4068d433f9aa0685e87080965427816c67e
parent24b95685ffcdb3dc28f64b9e8af6ea3e8360fbc5 (diff)
ipw2200: queue direct scans
When another scan is in progress, a direct scan gets dropped on the floor. However, that direct scan is usually the scan that's really needed by userspace, and gets stomped on by all the broadcast scans the ipw2200 driver issues internally. Make sure the direct scan happens eventually, and as a bonus ensure that the passive scan worker is cleaned up when appropriate. The change of request_passive_scan form a struct work to struct delayed_work is only to make the set_wx_scan() code a bit simpler, it's still only used with a delay of 0 to match previous behavior. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ipw2200.c176
-rw-r--r--drivers/net/wireless/ipw2200.h6
2 files changed, 87 insertions, 95 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 729336774828..6e704608947c 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -1753,6 +1753,8 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
1753 1753
1754 if (priv->workqueue) { 1754 if (priv->workqueue) {
1755 cancel_delayed_work(&priv->request_scan); 1755 cancel_delayed_work(&priv->request_scan);
1756 cancel_delayed_work(&priv->request_direct_scan);
1757 cancel_delayed_work(&priv->request_passive_scan);
1756 cancel_delayed_work(&priv->scan_event); 1758 cancel_delayed_work(&priv->scan_event);
1757 } 1759 }
1758 queue_work(priv->workqueue, &priv->down); 1760 queue_work(priv->workqueue, &priv->down);
@@ -2005,6 +2007,8 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
2005 wake_up_interruptible(&priv->wait_command_queue); 2007 wake_up_interruptible(&priv->wait_command_queue);
2006 priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); 2008 priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
2007 cancel_delayed_work(&priv->request_scan); 2009 cancel_delayed_work(&priv->request_scan);
2010 cancel_delayed_work(&priv->request_direct_scan);
2011 cancel_delayed_work(&priv->request_passive_scan);
2008 cancel_delayed_work(&priv->scan_event); 2012 cancel_delayed_work(&priv->scan_event);
2009 schedule_work(&priv->link_down); 2013 schedule_work(&priv->link_down);
2010 queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); 2014 queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
@@ -4712,6 +4716,12 @@ static void ipw_rx_notification(struct ipw_priv *priv,
4712 priv->status &= ~STATUS_SCAN_FORCED; 4716 priv->status &= ~STATUS_SCAN_FORCED;
4713#endif /* CONFIG_IPW2200_MONITOR */ 4717#endif /* CONFIG_IPW2200_MONITOR */
4714 4718
4719 /* Do queued direct scans first */
4720 if (priv->status & STATUS_DIRECT_SCAN_PENDING) {
4721 queue_delayed_work(priv->workqueue,
4722 &priv->request_direct_scan, 0);
4723 }
4724
4715 if (!(priv->status & (STATUS_ASSOCIATED | 4725 if (!(priv->status & (STATUS_ASSOCIATED |
4716 STATUS_ASSOCIATING | 4726 STATUS_ASSOCIATING |
4717 STATUS_ROAMING | 4727 STATUS_ROAMING |
@@ -6267,7 +6277,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
6267 } 6277 }
6268} 6278}
6269 6279
6270static int ipw_request_scan_helper(struct ipw_priv *priv, int type) 6280static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct)
6271{ 6281{
6272 struct ipw_scan_request_ext scan; 6282 struct ipw_scan_request_ext scan;
6273 int err = 0, scan_type; 6283 int err = 0, scan_type;
@@ -6278,22 +6288,31 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type)
6278 6288
6279 mutex_lock(&priv->mutex); 6289 mutex_lock(&priv->mutex);
6280 6290
6291 if (direct && (priv->direct_scan_ssid_len == 0)) {
6292 IPW_DEBUG_HC("Direct scan requested but no SSID to scan for\n");
6293 priv->status &= ~STATUS_DIRECT_SCAN_PENDING;
6294 goto done;
6295 }
6296
6281 if (priv->status & STATUS_SCANNING) { 6297 if (priv->status & STATUS_SCANNING) {
6282 IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); 6298 IPW_DEBUG_HC("Concurrent scan requested. Queuing.\n");
6283 priv->status |= STATUS_SCAN_PENDING; 6299 priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING :
6300 STATUS_SCAN_PENDING;
6284 goto done; 6301 goto done;
6285 } 6302 }
6286 6303
6287 if (!(priv->status & STATUS_SCAN_FORCED) && 6304 if (!(priv->status & STATUS_SCAN_FORCED) &&
6288 priv->status & STATUS_SCAN_ABORTING) { 6305 priv->status & STATUS_SCAN_ABORTING) {
6289 IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); 6306 IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n");
6290 priv->status |= STATUS_SCAN_PENDING; 6307 priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING :
6308 STATUS_SCAN_PENDING;
6291 goto done; 6309 goto done;
6292 } 6310 }
6293 6311
6294 if (priv->status & STATUS_RF_KILL_MASK) { 6312 if (priv->status & STATUS_RF_KILL_MASK) {
6295 IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n"); 6313 IPW_DEBUG_HC("Queuing scan due to RF Kill activation\n");
6296 priv->status |= STATUS_SCAN_PENDING; 6314 priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING :
6315 STATUS_SCAN_PENDING;
6297 goto done; 6316 goto done;
6298 } 6317 }
6299 6318
@@ -6321,6 +6340,7 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type)
6321 cpu_to_le16(20); 6340 cpu_to_le16(20);
6322 6341
6323 scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); 6342 scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
6343 scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20);
6324 6344
6325#ifdef CONFIG_IPW2200_MONITOR 6345#ifdef CONFIG_IPW2200_MONITOR
6326 if (priv->ieee->iw_mode == IW_MODE_MONITOR) { 6346 if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
@@ -6360,13 +6380,23 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type)
6360 cpu_to_le16(2000); 6380 cpu_to_le16(2000);
6361 } else { 6381 } else {
6362#endif /* CONFIG_IPW2200_MONITOR */ 6382#endif /* CONFIG_IPW2200_MONITOR */
6363 /* If we are roaming, then make this a directed scan for the 6383 /* Honor direct scans first, otherwise if we are roaming make
6364 * current network. Otherwise, ensure that every other scan 6384 * this a direct scan for the current network. Finally,
6365 * is a fast channel hop scan */ 6385 * ensure that every other scan is a fast channel hop scan */
6366 if ((priv->status & STATUS_ROAMING) 6386 if (direct) {
6367 || (!(priv->status & STATUS_ASSOCIATED) 6387 err = ipw_send_ssid(priv, priv->direct_scan_ssid,
6368 && (priv->config & CFG_STATIC_ESSID) 6388 priv->direct_scan_ssid_len);
6369 && (le32_to_cpu(scan.full_scan_index) % 2))) { 6389 if (err) {
6390 IPW_DEBUG_HC("Attempt to send SSID command "
6391 "failed\n");
6392 goto done;
6393 }
6394
6395 scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN;
6396 } else if ((priv->status & STATUS_ROAMING)
6397 || (!(priv->status & STATUS_ASSOCIATED)
6398 && (priv->config & CFG_STATIC_ESSID)
6399 && (le32_to_cpu(scan.full_scan_index) % 2))) {
6370 err = ipw_send_ssid(priv, priv->essid, priv->essid_len); 6400 err = ipw_send_ssid(priv, priv->essid, priv->essid_len);
6371 if (err) { 6401 if (err) {
6372 IPW_DEBUG_HC("Attempt to send SSID command " 6402 IPW_DEBUG_HC("Attempt to send SSID command "
@@ -6391,7 +6421,12 @@ send_request:
6391 } 6421 }
6392 6422
6393 priv->status |= STATUS_SCANNING; 6423 priv->status |= STATUS_SCANNING;
6394 priv->status &= ~STATUS_SCAN_PENDING; 6424 if (direct) {
6425 priv->status &= ~STATUS_DIRECT_SCAN_PENDING;
6426 priv->direct_scan_ssid_len = 0;
6427 } else
6428 priv->status &= ~STATUS_SCAN_PENDING;
6429
6395 queue_delayed_work(priv->workqueue, &priv->scan_check, 6430 queue_delayed_work(priv->workqueue, &priv->scan_check,
6396 IPW_SCAN_CHECK_WATCHDOG); 6431 IPW_SCAN_CHECK_WATCHDOG);
6397done: 6432done:
@@ -6402,15 +6437,22 @@ done:
6402static void ipw_request_passive_scan(struct work_struct *work) 6437static void ipw_request_passive_scan(struct work_struct *work)
6403{ 6438{
6404 struct ipw_priv *priv = 6439 struct ipw_priv *priv =
6405 container_of(work, struct ipw_priv, request_passive_scan); 6440 container_of(work, struct ipw_priv, request_passive_scan.work);
6406 ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); 6441 ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE, 0);
6407} 6442}
6408 6443
6409static void ipw_request_scan(struct work_struct *work) 6444static void ipw_request_scan(struct work_struct *work)
6410{ 6445{
6411 struct ipw_priv *priv = 6446 struct ipw_priv *priv =
6412 container_of(work, struct ipw_priv, request_scan.work); 6447 container_of(work, struct ipw_priv, request_scan.work);
6413 ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); 6448 ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE, 0);
6449}
6450
6451static void ipw_request_direct_scan(struct work_struct *work)
6452{
6453 struct ipw_priv *priv =
6454 container_of(work, struct ipw_priv, request_direct_scan.work);
6455 ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE, 1);
6414} 6456}
6415 6457
6416static void ipw_bg_abort_scan(struct work_struct *work) 6458static void ipw_bg_abort_scan(struct work_struct *work)
@@ -9477,99 +9519,38 @@ static int ipw_wx_get_retry(struct net_device *dev,
9477 return 0; 9519 return 0;
9478} 9520}
9479 9521
9480static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
9481 int essid_len)
9482{
9483 struct ipw_scan_request_ext scan;
9484 int err = 0, scan_type;
9485
9486 if (!(priv->status & STATUS_INIT) ||
9487 (priv->status & STATUS_EXIT_PENDING))
9488 return 0;
9489
9490 mutex_lock(&priv->mutex);
9491
9492 if (priv->status & STATUS_RF_KILL_MASK) {
9493 IPW_DEBUG_HC("Aborting scan due to RF kill activation\n");
9494 priv->status |= STATUS_SCAN_PENDING;
9495 goto done;
9496 }
9497
9498 IPW_DEBUG_HC("starting request direct scan!\n");
9499
9500 if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
9501 /* We should not sleep here; otherwise we will block most
9502 * of the system (for instance, we hold rtnl_lock when we
9503 * get here).
9504 */
9505 err = -EAGAIN;
9506 goto done;
9507 }
9508 memset(&scan, 0, sizeof(scan));
9509
9510 if (priv->config & CFG_SPEED_SCAN)
9511 scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] =
9512 cpu_to_le16(30);
9513 else
9514 scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] =
9515 cpu_to_le16(20);
9516
9517 scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] =
9518 cpu_to_le16(20);
9519 scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
9520 scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20);
9521
9522 scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
9523
9524 err = ipw_send_ssid(priv, essid, essid_len);
9525 if (err) {
9526 IPW_DEBUG_HC("Attempt to send SSID command failed\n");
9527 goto done;
9528 }
9529 scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN;
9530
9531 ipw_add_scan_channels(priv, &scan, scan_type);
9532
9533 err = ipw_send_scan_request_ext(priv, &scan);
9534 if (err) {
9535 IPW_DEBUG_HC("Sending scan command failed: %08X\n", err);
9536 goto done;
9537 }
9538
9539 priv->status |= STATUS_SCANNING;
9540
9541 done:
9542 mutex_unlock(&priv->mutex);
9543 return err;
9544}
9545
9546static int ipw_wx_set_scan(struct net_device *dev, 9522static int ipw_wx_set_scan(struct net_device *dev,
9547 struct iw_request_info *info, 9523 struct iw_request_info *info,
9548 union iwreq_data *wrqu, char *extra) 9524 union iwreq_data *wrqu, char *extra)
9549{ 9525{
9550 struct ipw_priv *priv = ieee80211_priv(dev); 9526 struct ipw_priv *priv = ieee80211_priv(dev);
9551 struct iw_scan_req *req = (struct iw_scan_req *)extra; 9527 struct iw_scan_req *req = (struct iw_scan_req *)extra;
9528 struct delayed_work *work = NULL;
9552 9529
9553 mutex_lock(&priv->mutex); 9530 mutex_lock(&priv->mutex);
9531
9554 priv->user_requested_scan = 1; 9532 priv->user_requested_scan = 1;
9555 mutex_unlock(&priv->mutex);
9556 9533
9557 if (wrqu->data.length == sizeof(struct iw_scan_req)) { 9534 if (wrqu->data.length == sizeof(struct iw_scan_req)) {
9558 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { 9535 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
9559 ipw_request_direct_scan(priv, req->essid, 9536 int len = min((int)req->essid_len,
9560 req->essid_len); 9537 (int)sizeof(priv->direct_scan_ssid));
9561 return 0; 9538 memcpy(priv->direct_scan_ssid, req->essid, len);
9562 } 9539 priv->direct_scan_ssid_len = len;
9563 if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { 9540 work = &priv->request_direct_scan;
9564 queue_work(priv->workqueue, 9541 } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
9565 &priv->request_passive_scan); 9542 work = &priv->request_passive_scan;
9566 return 0;
9567 } 9543 }
9544 } else {
9545 /* Normal active broadcast scan */
9546 work = &priv->request_scan;
9568 } 9547 }
9569 9548
9549 mutex_unlock(&priv->mutex);
9550
9570 IPW_DEBUG_WX("Start scan\n"); 9551 IPW_DEBUG_WX("Start scan\n");
9571 9552
9572 queue_delayed_work(priv->workqueue, &priv->request_scan, 0); 9553 queue_delayed_work(priv->workqueue, work, 0);
9573 9554
9574 return 0; 9555 return 0;
9575} 9556}
@@ -10731,6 +10712,8 @@ static void ipw_link_up(struct ipw_priv *priv)
10731 } 10712 }
10732 10713
10733 cancel_delayed_work(&priv->request_scan); 10714 cancel_delayed_work(&priv->request_scan);
10715 cancel_delayed_work(&priv->request_direct_scan);
10716 cancel_delayed_work(&priv->request_passive_scan);
10734 cancel_delayed_work(&priv->scan_event); 10717 cancel_delayed_work(&priv->scan_event);
10735 ipw_reset_stats(priv); 10718 ipw_reset_stats(priv);
10736 /* Ensure the rate is updated immediately */ 10719 /* Ensure the rate is updated immediately */
@@ -10761,6 +10744,8 @@ static void ipw_link_down(struct ipw_priv *priv)
10761 10744
10762 /* Cancel any queued work ... */ 10745 /* Cancel any queued work ... */
10763 cancel_delayed_work(&priv->request_scan); 10746 cancel_delayed_work(&priv->request_scan);
10747 cancel_delayed_work(&priv->request_direct_scan);
10748 cancel_delayed_work(&priv->request_passive_scan);
10764 cancel_delayed_work(&priv->adhoc_check); 10749 cancel_delayed_work(&priv->adhoc_check);
10765 cancel_delayed_work(&priv->gather_stats); 10750 cancel_delayed_work(&priv->gather_stats);
10766 10751
@@ -10800,8 +10785,9 @@ static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv)
10800 INIT_WORK(&priv->up, ipw_bg_up); 10785 INIT_WORK(&priv->up, ipw_bg_up);
10801 INIT_WORK(&priv->down, ipw_bg_down); 10786 INIT_WORK(&priv->down, ipw_bg_down);
10802 INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); 10787 INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan);
10788 INIT_DELAYED_WORK(&priv->request_direct_scan, ipw_request_direct_scan);
10789 INIT_DELAYED_WORK(&priv->request_passive_scan, ipw_request_passive_scan);
10803 INIT_DELAYED_WORK(&priv->scan_event, ipw_scan_event); 10790 INIT_DELAYED_WORK(&priv->scan_event, ipw_scan_event);
10804 INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan);
10805 INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); 10791 INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats);
10806 INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); 10792 INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan);
10807 INIT_WORK(&priv->roam, ipw_bg_roam); 10793 INIT_WORK(&priv->roam, ipw_bg_roam);
@@ -11835,6 +11821,8 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
11835 cancel_delayed_work(&priv->adhoc_check); 11821 cancel_delayed_work(&priv->adhoc_check);
11836 cancel_delayed_work(&priv->gather_stats); 11822 cancel_delayed_work(&priv->gather_stats);
11837 cancel_delayed_work(&priv->request_scan); 11823 cancel_delayed_work(&priv->request_scan);
11824 cancel_delayed_work(&priv->request_direct_scan);
11825 cancel_delayed_work(&priv->request_passive_scan);
11838 cancel_delayed_work(&priv->scan_event); 11826 cancel_delayed_work(&priv->scan_event);
11839 cancel_delayed_work(&priv->rf_kill); 11827 cancel_delayed_work(&priv->rf_kill);
11840 cancel_delayed_work(&priv->scan_check); 11828 cancel_delayed_work(&priv->scan_check);
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index cd3295b66dd6..d4ab28b73b32 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -1037,6 +1037,7 @@ struct ipw_cmd { /* XXX */
1037#define STATUS_DISASSOC_PENDING (1<<12) 1037#define STATUS_DISASSOC_PENDING (1<<12)
1038#define STATUS_STATE_PENDING (1<<13) 1038#define STATUS_STATE_PENDING (1<<13)
1039 1039
1040#define STATUS_DIRECT_SCAN_PENDING (1<<19)
1040#define STATUS_SCAN_PENDING (1<<20) 1041#define STATUS_SCAN_PENDING (1<<20)
1041#define STATUS_SCANNING (1<<21) 1042#define STATUS_SCANNING (1<<21)
1042#define STATUS_SCAN_ABORTING (1<<22) 1043#define STATUS_SCAN_ABORTING (1<<22)
@@ -1292,6 +1293,8 @@ struct ipw_priv {
1292 struct iw_public_data wireless_data; 1293 struct iw_public_data wireless_data;
1293 1294
1294 int user_requested_scan; 1295 int user_requested_scan;
1296 u8 direct_scan_ssid[IW_ESSID_MAX_SIZE];
1297 u8 direct_scan_ssid_len;
1295 1298
1296 struct workqueue_struct *workqueue; 1299 struct workqueue_struct *workqueue;
1297 1300
@@ -1301,8 +1304,9 @@ struct ipw_priv {
1301 struct work_struct system_config; 1304 struct work_struct system_config;
1302 struct work_struct rx_replenish; 1305 struct work_struct rx_replenish;
1303 struct delayed_work request_scan; 1306 struct delayed_work request_scan;
1307 struct delayed_work request_direct_scan;
1308 struct delayed_work request_passive_scan;
1304 struct delayed_work scan_event; 1309 struct delayed_work scan_event;
1305 struct work_struct request_passive_scan;
1306 struct work_struct adapter_restart; 1310 struct work_struct adapter_restart;
1307 struct delayed_work rf_kill; 1311 struct delayed_work rf_kill;
1308 struct work_struct up; 1312 struct work_struct up;