diff options
Diffstat (limited to 'drivers/net/wireless/ipw2100.c')
-rw-r--r-- | drivers/net/wireless/ipw2100.c | 72 |
1 files changed, 41 insertions, 31 deletions
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 2d46a16c0945..a6c7904de282 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c | |||
@@ -1858,14 +1858,6 @@ static void ipw2100_down(struct ipw2100_priv *priv) | |||
1858 | 1858 | ||
1859 | modify_acceptable_latency("ipw2100", INFINITE_LATENCY); | 1859 | modify_acceptable_latency("ipw2100", INFINITE_LATENCY); |
1860 | 1860 | ||
1861 | #ifdef ACPI_CSTATE_LIMIT_DEFINED | ||
1862 | if (priv->config & CFG_C3_DISABLED) { | ||
1863 | IPW_DEBUG_INFO(": Resetting C3 transitions.\n"); | ||
1864 | acpi_set_cstate_limit(priv->cstate_limit); | ||
1865 | priv->config &= ~CFG_C3_DISABLED; | ||
1866 | } | ||
1867 | #endif | ||
1868 | |||
1869 | /* We have to signal any supplicant if we are disassociating */ | 1861 | /* We have to signal any supplicant if we are disassociating */ |
1870 | if (associated) | 1862 | if (associated) |
1871 | wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); | 1863 | wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); |
@@ -2091,26 +2083,52 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) | |||
2091 | /* RF_KILL is now enabled (else we wouldn't be here) */ | 2083 | /* RF_KILL is now enabled (else we wouldn't be here) */ |
2092 | priv->status |= STATUS_RF_KILL_HW; | 2084 | priv->status |= STATUS_RF_KILL_HW; |
2093 | 2085 | ||
2094 | #ifdef ACPI_CSTATE_LIMIT_DEFINED | ||
2095 | if (priv->config & CFG_C3_DISABLED) { | ||
2096 | IPW_DEBUG_INFO(": Resetting C3 transitions.\n"); | ||
2097 | acpi_set_cstate_limit(priv->cstate_limit); | ||
2098 | priv->config &= ~CFG_C3_DISABLED; | ||
2099 | } | ||
2100 | #endif | ||
2101 | |||
2102 | /* Make sure the RF Kill check timer is running */ | 2086 | /* Make sure the RF Kill check timer is running */ |
2103 | priv->stop_rf_kill = 0; | 2087 | priv->stop_rf_kill = 0; |
2104 | cancel_delayed_work(&priv->rf_kill); | 2088 | cancel_delayed_work(&priv->rf_kill); |
2105 | queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); | 2089 | queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); |
2106 | } | 2090 | } |
2107 | 2091 | ||
2092 | static void send_scan_event(void *data) | ||
2093 | { | ||
2094 | struct ipw2100_priv *priv = data; | ||
2095 | union iwreq_data wrqu; | ||
2096 | |||
2097 | wrqu.data.length = 0; | ||
2098 | wrqu.data.flags = 0; | ||
2099 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); | ||
2100 | } | ||
2101 | |||
2102 | static void ipw2100_scan_event_later(struct work_struct *work) | ||
2103 | { | ||
2104 | send_scan_event(container_of(work, struct ipw2100_priv, | ||
2105 | scan_event_later.work)); | ||
2106 | } | ||
2107 | |||
2108 | static void ipw2100_scan_event_now(struct work_struct *work) | ||
2109 | { | ||
2110 | send_scan_event(container_of(work, struct ipw2100_priv, | ||
2111 | scan_event_now)); | ||
2112 | } | ||
2113 | |||
2108 | static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) | 2114 | static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) |
2109 | { | 2115 | { |
2110 | IPW_DEBUG_SCAN("scan complete\n"); | 2116 | IPW_DEBUG_SCAN("scan complete\n"); |
2111 | /* Age the scan results... */ | 2117 | /* Age the scan results... */ |
2112 | priv->ieee->scans++; | 2118 | priv->ieee->scans++; |
2113 | priv->status &= ~STATUS_SCANNING; | 2119 | priv->status &= ~STATUS_SCANNING; |
2120 | |||
2121 | /* Only userspace-requested scan completion events go out immediately */ | ||
2122 | if (!priv->user_requested_scan) { | ||
2123 | if (!delayed_work_pending(&priv->scan_event_later)) | ||
2124 | queue_delayed_work(priv->workqueue, | ||
2125 | &priv->scan_event_later, | ||
2126 | round_jiffies(msecs_to_jiffies(4000))); | ||
2127 | } else { | ||
2128 | priv->user_requested_scan = 0; | ||
2129 | cancel_delayed_work(&priv->scan_event_later); | ||
2130 | queue_work(priv->workqueue, &priv->scan_event_now); | ||
2131 | } | ||
2114 | } | 2132 | } |
2115 | 2133 | ||
2116 | #ifdef CONFIG_IPW2100_DEBUG | 2134 | #ifdef CONFIG_IPW2100_DEBUG |
@@ -2329,23 +2347,10 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) | |||
2329 | u32 match, reg; | 2347 | u32 match, reg; |
2330 | int j; | 2348 | int j; |
2331 | #endif | 2349 | #endif |
2332 | #ifdef ACPI_CSTATE_LIMIT_DEFINED | ||
2333 | int limit; | ||
2334 | #endif | ||
2335 | 2350 | ||
2336 | IPW_DEBUG_INFO(": PCI latency error detected at 0x%04zX.\n", | 2351 | IPW_DEBUG_INFO(": PCI latency error detected at 0x%04zX.\n", |
2337 | i * sizeof(struct ipw2100_status)); | 2352 | i * sizeof(struct ipw2100_status)); |
2338 | 2353 | ||
2339 | #ifdef ACPI_CSTATE_LIMIT_DEFINED | ||
2340 | IPW_DEBUG_INFO(": Disabling C3 transitions.\n"); | ||
2341 | limit = acpi_get_cstate_limit(); | ||
2342 | if (limit > 2) { | ||
2343 | priv->cstate_limit = limit; | ||
2344 | acpi_set_cstate_limit(2); | ||
2345 | priv->config |= CFG_C3_DISABLED; | ||
2346 | } | ||
2347 | #endif | ||
2348 | |||
2349 | #ifdef IPW2100_DEBUG_C3 | 2354 | #ifdef IPW2100_DEBUG_C3 |
2350 | /* Halt the fimrware so we can get a good image */ | 2355 | /* Halt the fimrware so we can get a good image */ |
2351 | write_register(priv->net_dev, IPW_REG_RESET_REG, | 2356 | write_register(priv->net_dev, IPW_REG_RESET_REG, |
@@ -4378,6 +4383,7 @@ static void ipw2100_kill_workqueue(struct ipw2100_priv *priv) | |||
4378 | cancel_delayed_work(&priv->wx_event_work); | 4383 | cancel_delayed_work(&priv->wx_event_work); |
4379 | cancel_delayed_work(&priv->hang_check); | 4384 | cancel_delayed_work(&priv->hang_check); |
4380 | cancel_delayed_work(&priv->rf_kill); | 4385 | cancel_delayed_work(&priv->rf_kill); |
4386 | cancel_delayed_work(&priv->scan_event_later); | ||
4381 | destroy_workqueue(priv->workqueue); | 4387 | destroy_workqueue(priv->workqueue); |
4382 | priv->workqueue = NULL; | 4388 | priv->workqueue = NULL; |
4383 | } | 4389 | } |
@@ -6041,7 +6047,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6041 | * ends up causing problems. So, we just handle | 6047 | * ends up causing problems. So, we just handle |
6042 | * the WX extensions through the ipw2100_ioctl interface */ | 6048 | * the WX extensions through the ipw2100_ioctl interface */ |
6043 | 6049 | ||
6044 | /* memset() puts everything to 0, so we only have explicitely set | 6050 | /* memset() puts everything to 0, so we only have explicitly set |
6045 | * those values that need to be something else */ | 6051 | * those values that need to be something else */ |
6046 | 6052 | ||
6047 | /* If power management is turned on, default to AUTO mode */ | 6053 | /* If power management is turned on, default to AUTO mode */ |
@@ -6121,6 +6127,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); | 6127 | INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); |
6122 | INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); | 6128 | INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); |
6123 | INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); | 6129 | INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); |
6130 | INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now); | ||
6131 | INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later); | ||
6124 | 6132 | ||
6125 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 6133 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
6126 | ipw2100_irq_tasklet, (unsigned long)priv); | 6134 | ipw2100_irq_tasklet, (unsigned long)priv); |
@@ -7425,6 +7433,8 @@ static int ipw2100_wx_set_scan(struct net_device *dev, | |||
7425 | } | 7433 | } |
7426 | 7434 | ||
7427 | IPW_DEBUG_WX("Initiating scan...\n"); | 7435 | IPW_DEBUG_WX("Initiating scan...\n"); |
7436 | |||
7437 | priv->user_requested_scan = 1; | ||
7428 | if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { | 7438 | if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { |
7429 | IPW_DEBUG_WX("Start scan failed.\n"); | 7439 | IPW_DEBUG_WX("Start scan failed.\n"); |
7430 | 7440 | ||
@@ -7499,7 +7509,7 @@ static int ipw2100_wx_set_power(struct net_device *dev, | |||
7499 | switch (wrqu->power.flags & IW_POWER_MODE) { | 7509 | switch (wrqu->power.flags & IW_POWER_MODE) { |
7500 | case IW_POWER_ON: /* If not specified */ | 7510 | case IW_POWER_ON: /* If not specified */ |
7501 | case IW_POWER_MODE: /* If set all mask */ | 7511 | case IW_POWER_MODE: /* If set all mask */ |
7502 | case IW_POWER_ALL_R: /* If explicitely state all */ | 7512 | case IW_POWER_ALL_R: /* If explicitly state all */ |
7503 | break; | 7513 | break; |
7504 | default: /* Otherwise we don't support it */ | 7514 | default: /* Otherwise we don't support it */ |
7505 | IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", | 7515 | IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", |