diff options
author | Dan Williams <dcbw@redhat.com> | 2007-10-10 12:28:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2007-10-18 15:38:24 -0400 |
commit | d20c678a450a25c1c12925f60c1b4cc040acc17d (patch) | |
tree | c8209bd0394e5cfb5e7726b07d683dad255abda5 | |
parent | 3ba72b25211217de195e3f528dd36132b38a205b (diff) |
[PATCH] ipw2100: send WEXT scan events
ipw2100 wasn't sending WEXT scan events at all on scan completion. And
like ipw2200, the driver aggressively auto-scans, requiring
non-user-requested scan events to be batched together and sent at
specific intervals instead of many times per seconds.
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ipw2100.c | 39 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2100.h | 4 |
2 files changed, 43 insertions, 0 deletions
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 2d46a16c0945..2fa8eed86dc1 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c | |||
@@ -2105,12 +2105,46 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) | |||
2105 | queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); | 2105 | queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); |
2106 | } | 2106 | } |
2107 | 2107 | ||
2108 | static void send_scan_event(void *data) | ||
2109 | { | ||
2110 | struct ipw2100_priv *priv = data; | ||
2111 | union iwreq_data wrqu; | ||
2112 | |||
2113 | wrqu.data.length = 0; | ||
2114 | wrqu.data.flags = 0; | ||
2115 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); | ||
2116 | } | ||
2117 | |||
2118 | static void ipw2100_scan_event_later(struct work_struct *work) | ||
2119 | { | ||
2120 | send_scan_event(container_of(work, struct ipw2100_priv, | ||
2121 | scan_event_later.work)); | ||
2122 | } | ||
2123 | |||
2124 | static void ipw2100_scan_event_now(struct work_struct *work) | ||
2125 | { | ||
2126 | send_scan_event(container_of(work, struct ipw2100_priv, | ||
2127 | scan_event_now)); | ||
2128 | } | ||
2129 | |||
2108 | static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) | 2130 | static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) |
2109 | { | 2131 | { |
2110 | IPW_DEBUG_SCAN("scan complete\n"); | 2132 | IPW_DEBUG_SCAN("scan complete\n"); |
2111 | /* Age the scan results... */ | 2133 | /* Age the scan results... */ |
2112 | priv->ieee->scans++; | 2134 | priv->ieee->scans++; |
2113 | priv->status &= ~STATUS_SCANNING; | 2135 | priv->status &= ~STATUS_SCANNING; |
2136 | |||
2137 | /* Only userspace-requested scan completion events go out immediately */ | ||
2138 | if (!priv->user_requested_scan) { | ||
2139 | if (!delayed_work_pending(&priv->scan_event_later)) | ||
2140 | queue_delayed_work(priv->workqueue, | ||
2141 | &priv->scan_event_later, | ||
2142 | round_jiffies(msecs_to_jiffies(4000))); | ||
2143 | } else { | ||
2144 | priv->user_requested_scan = 0; | ||
2145 | cancel_delayed_work(&priv->scan_event_later); | ||
2146 | queue_work(priv->workqueue, &priv->scan_event_now); | ||
2147 | } | ||
2114 | } | 2148 | } |
2115 | 2149 | ||
2116 | #ifdef CONFIG_IPW2100_DEBUG | 2150 | #ifdef CONFIG_IPW2100_DEBUG |
@@ -4378,6 +4412,7 @@ static void ipw2100_kill_workqueue(struct ipw2100_priv *priv) | |||
4378 | cancel_delayed_work(&priv->wx_event_work); | 4412 | cancel_delayed_work(&priv->wx_event_work); |
4379 | cancel_delayed_work(&priv->hang_check); | 4413 | cancel_delayed_work(&priv->hang_check); |
4380 | cancel_delayed_work(&priv->rf_kill); | 4414 | cancel_delayed_work(&priv->rf_kill); |
4415 | cancel_delayed_work(&priv->scan_event_later); | ||
4381 | destroy_workqueue(priv->workqueue); | 4416 | destroy_workqueue(priv->workqueue); |
4382 | priv->workqueue = NULL; | 4417 | priv->workqueue = NULL; |
4383 | } | 4418 | } |
@@ -6121,6 +6156,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6121 | INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); | 6156 | INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); |
6122 | INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); | 6157 | INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); |
6123 | INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); | 6158 | INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); |
6159 | INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now); | ||
6160 | INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later); | ||
6124 | 6161 | ||
6125 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 6162 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
6126 | ipw2100_irq_tasklet, (unsigned long)priv); | 6163 | ipw2100_irq_tasklet, (unsigned long)priv); |
@@ -7425,6 +7462,8 @@ static int ipw2100_wx_set_scan(struct net_device *dev, | |||
7425 | } | 7462 | } |
7426 | 7463 | ||
7427 | IPW_DEBUG_WX("Initiating scan...\n"); | 7464 | IPW_DEBUG_WX("Initiating scan...\n"); |
7465 | |||
7466 | priv->user_requested_scan = 1; | ||
7428 | if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { | 7467 | if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { |
7429 | IPW_DEBUG_WX("Start scan failed.\n"); | 7468 | IPW_DEBUG_WX("Start scan failed.\n"); |
7430 | 7469 | ||
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index de7d384d38af..1ee3348aedd9 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h | |||
@@ -588,6 +588,10 @@ struct ipw2100_priv { | |||
588 | struct delayed_work wx_event_work; | 588 | struct delayed_work wx_event_work; |
589 | struct delayed_work hang_check; | 589 | struct delayed_work hang_check; |
590 | struct delayed_work rf_kill; | 590 | struct delayed_work rf_kill; |
591 | struct work_struct scan_event_now; | ||
592 | struct delayed_work scan_event_later; | ||
593 | |||
594 | int user_requested_scan; | ||
591 | 595 | ||
592 | u32 interrupts; | 596 | u32 interrupts; |
593 | int tx_interrupts; | 597 | int tx_interrupts; |