From: John W. Linville <linville@redhat.com> Date: Wed, 13 Aug 2008 12:36:06 -0400 Subject: [wireless] update ipw2x00 driver to 2.6.25 Message-id: 20080813163606.GD18695@redhat.com O-Subject: [RHEL5 patch 2/3] Update ipw2x00 driver to match version from 2.6.25 Bugzilla: 448762 This patch updates the ipw2100 and ipw2200 drivers to match what was current in 2.6.25. BZ448762 Tested against the related drivers by me with good results. diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 3591257..0e8cf04 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -162,6 +162,9 @@ that only one external action is invoked at a time. #include <linux/firmware.h> #include <linux/acpi.h> #include <linux/ctype.h> +#if 0 /* Not in RHEL5... */ +#include <linux/latency.h> +#endif #include "ipw2100.h" @@ -678,7 +681,8 @@ static void schedule_reset(struct ipw2100_priv *priv) queue_delayed_work(priv->workqueue, &priv->reset_work, priv->reset_backoff * HZ); else - queue_work(priv->workqueue, &priv->reset_work); + queue_delayed_work(priv->workqueue, &priv->reset_work, + 0); if (priv->reset_backoff < MAX_RESET_BACKOFF) priv->reset_backoff++; @@ -1265,7 +1269,7 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv) IPW2100_INTA_FATAL_ERROR | IPW2100_INTA_PARITY_ERROR); } - } while (i--); + } while (--i); /* Clear out any pending INTAs since we aren't supposed to have * interrupts enabled at this point... */ @@ -1337,7 +1341,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv) if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED) break; - } while (i--); + } while (--i); priv->status &= ~STATUS_RESET_PENDING; @@ -1696,6 +1700,13 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) return 0; } +#if 0 /* Not in RHEL5... */ + /* the ipw2100 hardware really doesn't want power management delays + * longer than 175usec + */ + modify_acceptable_latency("ipw2100", 175); +#endif + /* If the interrupt is enabled, turn it off... */ spin_lock_irqsave(&priv->low_lock, flags); ipw2100_disable_interrupts(priv); @@ -1761,7 +1772,8 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) if (priv->stop_rf_kill) { priv->stop_rf_kill = 0; - queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies_relative(HZ)); } deferred = 1; @@ -1848,12 +1860,8 @@ static void ipw2100_down(struct ipw2100_priv *priv) ipw2100_disable_interrupts(priv); spin_unlock_irqrestore(&priv->low_lock, flags); -#ifdef ACPI_CSTATE_LIMIT_DEFINED - if (priv->config & CFG_C3_DISABLED) { - IPW_DEBUG_INFO(": Resetting C3 transitions.\n"); - acpi_set_cstate_limit(priv->cstate_limit); - priv->config &= ~CFG_C3_DISABLED; - } +#if 0 /* Not in RHEL5... */ + modify_acceptable_latency("ipw2100", INFINITE_LATENCY); #endif /* We have to signal any supplicant if we are disassociating */ @@ -2063,9 +2071,9 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) return; if (priv->status & STATUS_SECURITY_UPDATED) - queue_work(priv->workqueue, &priv->security_work); + queue_delayed_work(priv->workqueue, &priv->security_work, 0); - queue_work(priv->workqueue, &priv->wx_event_work); + queue_delayed_work(priv->workqueue, &priv->wx_event_work, 0); } static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) @@ -2076,18 +2084,31 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) /* RF_KILL is now enabled (else we wouldn't be here) */ priv->status |= STATUS_RF_KILL_HW; -#ifdef ACPI_CSTATE_LIMIT_DEFINED - if (priv->config & CFG_C3_DISABLED) { - IPW_DEBUG_INFO(": Resetting C3 transitions.\n"); - acpi_set_cstate_limit(priv->cstate_limit); - priv->config &= ~CFG_C3_DISABLED; - } -#endif - /* Make sure the RF Kill check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies_relative(HZ)); +} + +static void send_scan_event(void *data) +{ + struct ipw2100_priv *priv = data; + union iwreq_data wrqu; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); +} + +static void ipw2100_scan_event_later(struct ipw2100_priv *priv) +{ + send_scan_event(priv); +} + +static void ipw2100_scan_event_now(struct ipw2100_priv *priv) +{ + send_scan_event(priv); } static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) @@ -2096,6 +2117,18 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) /* Age the scan results... */ priv->ieee->scans++; priv->status &= ~STATUS_SCANNING; + + /* Only userspace-requested scan completion events go out immediately */ + if (!priv->user_requested_scan) { + if (!delayed_work_pending(&priv->scan_event_later)) + queue_delayed_work(priv->workqueue, + &priv->scan_event_later, + round_jiffies_relative(msecs_to_jiffies(4000))); + } else { + priv->user_requested_scan = 0; + cancel_delayed_work(&priv->scan_event_later); + queue_work(priv->workqueue, &priv->scan_event_now); + } } #ifdef CONFIG_IPW2100_DEBUG @@ -2314,23 +2347,10 @@ static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) u32 match, reg; int j; #endif -#ifdef ACPI_CSTATE_LIMIT_DEFINED - int limit; -#endif IPW_DEBUG_INFO(": PCI latency error detected at 0x%04zX.\n", i * sizeof(struct ipw2100_status)); -#ifdef ACPI_CSTATE_LIMIT_DEFINED - IPW_DEBUG_INFO(": Disabling C3 transitions.\n"); - limit = acpi_get_cstate_limit(); - if (limit > 2) { - priv->cstate_limit = limit; - acpi_set_cstate_limit(2); - priv->config |= CFG_C3_DISABLED; - } -#endif - #ifdef IPW2100_DEBUG_C3 /* Halt the fimrware so we can get a good image */ write_register(priv->net_dev, IPW_REG_RESET_REG, @@ -2488,9 +2508,9 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i, ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ - ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total hdr+data */ + ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct ipw_rt_hdr)); /* total hdr+data */ - ipw_rt->rt_hdr.it_present = 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL; + ipw_rt->rt_hdr.it_present = cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); ipw_rt->rt_dbmsignal = status->rssi + IPW2100_RSSI_TO_DBM; @@ -2537,7 +2557,7 @@ static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) #ifdef CONFIG_IPW2100_MONITOR return 0; #else - switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) { + switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) { case IEEE80211_FTYPE_MGMT: case IEEE80211_FTYPE_CTL: return 0; @@ -2656,7 +2676,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv) #endif if (stats.len < sizeof(struct ieee80211_hdr_3addr)) break; - switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) { + switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) { case IEEE80211_FTYPE_MGMT: ieee80211_rx_mgt(priv->ieee, &u->rx_data.header, &stats); @@ -4064,9 +4084,7 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr, __LINE__); out += sprintf(out, "ESSID: %s\n", essid); - out += sprintf(out, "BSSID: %02x:%02x:%02x:%02x:%02x:%02x\n", - bssid[0], bssid[1], bssid[2], - bssid[3], bssid[4], bssid[5]); + out += sprintf(out, "BSSID: " MAC_FMT "\n", MAC_ARG(bssid)); out += sprintf(out, "Channel: %d\n", chan); return out - buf; @@ -4222,7 +4240,8 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies_relative(HZ)); } else schedule_reset(priv); } @@ -4363,6 +4382,7 @@ static void ipw2100_kill_workqueue(struct ipw2100_priv *priv) cancel_delayed_work(&priv->wx_event_work); cancel_delayed_work(&priv->hang_check); cancel_delayed_work(&priv->rf_kill); + cancel_delayed_work(&priv->scan_event_later); destroy_workqueue(priv->workqueue); priv->workqueue = NULL; } @@ -4639,19 +4659,19 @@ static void ipw2100_rx_free(struct ipw2100_priv *priv) static int ipw2100_read_mac_address(struct ipw2100_priv *priv) { u32 length = ETH_ALEN; - u8 mac[ETH_ALEN]; + u8 addr[ETH_ALEN]; int err; - err = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ADAPTER_MAC, mac, &length); + err = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ADAPTER_MAC, addr, &length); if (err) { IPW_DEBUG_INFO("MAC address read failed\n"); return -EIO; } - IPW_DEBUG_INFO("card MAC is %02X:%02X:%02X:%02X:%02X:%02X\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - memcpy(priv->net_dev->dev_addr, mac, ETH_ALEN); + memcpy(priv->net_dev->dev_addr, addr, ETH_ALEN); + IPW_DEBUG_INFO("card MAC is " MAC_FMT "\n", + MAC_ARG(priv->net_dev->dev_addr)); return 0; } @@ -4979,6 +4999,7 @@ int ipw2100_set_fragmentation_threshold(struct ipw2100_priv *priv, } #endif +#if 0 /* Not in RHEL5... */ static int ipw2100_set_short_retry(struct ipw2100_priv *priv, u32 retry) { struct host_command cmd = { @@ -5018,6 +5039,7 @@ static int ipw2100_set_long_retry(struct ipw2100_priv *priv, u32 retry) return 0; } +#endif static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid, int batch_mode) @@ -5031,9 +5053,8 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid, #ifdef CONFIG_IPW2100_DEBUG if (bssid != NULL) - IPW_DEBUG_HC("MANDATORY_BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n", - bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], - bssid[5]); + IPW_DEBUG_HC("MANDATORY_BSSID: " MAC_FMT "\n", + MAC_ARG(bssid)); else IPW_DEBUG_HC("MANDATORY_BSSID: <clear>\n"); #endif @@ -5953,7 +5974,8 @@ static void ipw2100_rf_kill(void *adapter) if (rf_kill_active(priv)) { IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n"); if (!priv->stop_rf_kill) - queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); + queue_delayed_work(priv->workqueue, &priv->rf_kill, + round_jiffies_relative(HZ)); goto exit_unlock; } @@ -6019,7 +6041,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, * ends up causing problems. So, we just handle * the WX extensions through the ipw2100_ioctl interface */ - /* memset() puts everything to 0, so we only have explicitely set + /* memset() puts everything to 0, so we only have explicitly set * those values that need to be something else */ /* If power management is turned on, default to AUTO mode */ @@ -6095,13 +6117,17 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, priv->workqueue = create_workqueue(DRV_NAME); INIT_WORK(&priv->reset_work, - (void (*)(void *))ipw2100_reset_adapter, priv); + (void (*)(void *))ipw2100_reset_adapter, priv); INIT_WORK(&priv->security_work, - (void (*)(void *))ipw2100_security_work, priv); + (void (*)(void *))ipw2100_security_work, priv); INIT_WORK(&priv->wx_event_work, - (void (*)(void *))ipw2100_wx_event_work, priv); + (void (*)(void *))ipw2100_wx_event_work, priv); INIT_WORK(&priv->hang_check, ipw2100_hang_check, priv); INIT_WORK(&priv->rf_kill, ipw2100_rf_kill, priv); + INIT_WORK(&priv->scan_event_now, + (void (*)(void *))ipw2100_scan_event_now, priv); + INIT_WORK(&priv->scan_event_later, + (void (*)(void *))ipw2100_scan_event_later, priv); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw2100_irq_tasklet, (unsigned long)priv); @@ -6223,8 +6249,6 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, IPW_DEBUG_INFO("Attempting to register device...\n"); - SET_MODULE_OWNER(dev); - printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2100 Network Connection\n"); @@ -6528,6 +6552,9 @@ static int __init ipw2100_init(void) if (ret) goto out; +#if 0 /* Not in RHEL5... */ + set_acceptable_latency("ipw2100", INFINITE_LATENCY); +#endif #ifdef CONFIG_IPW2100_DEBUG ipw2100_debug_level = debug; ret = driver_create_file(&ipw2100_pci_driver.driver, @@ -6549,6 +6576,9 @@ static void __exit ipw2100_exit(void) &driver_attr_debug_level); #endif pci_unregister_driver(&ipw2100_pci_driver); +#if 0 /* Not in RHEL5... */ + remove_acceptable_latency("ipw2100"); +#endif } module_init(ipw2100_init); @@ -6563,8 +6593,7 @@ static const long ipw2100_frequencies[] = { 2472, 2484 }; -#define FREQ_COUNT (sizeof(ipw2100_frequencies) / \ - sizeof(ipw2100_frequencies[0])) +#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies) static const long ipw2100_rates_11b[] = { 1000000, @@ -6901,13 +6930,8 @@ static int ipw2100_wx_set_wap(struct net_device *dev, err = ipw2100_set_mandatory_bssid(priv, wrqu->ap_addr.sa_data, 0); - IPW_DEBUG_WX("SET BSSID -> %02X:%02X:%02X:%02X:%02X:%02X\n", - wrqu->ap_addr.sa_data[0] & 0xff, - wrqu->ap_addr.sa_data[1] & 0xff, - wrqu->ap_addr.sa_data[2] & 0xff, - wrqu->ap_addr.sa_data[3] & 0xff, - wrqu->ap_addr.sa_data[4] & 0xff, - wrqu->ap_addr.sa_data[5] & 0xff); + IPW_DEBUG_WX("SET BSSID -> " MAC_FMT "\n", + MAC_ARG(wrqu->ap_addr.sa_data)); done: mutex_unlock(&priv->action_mutex); @@ -7319,6 +7343,7 @@ static int ipw2100_wx_get_frag(struct net_device *dev, return 0; } +#if 0 /* Not in RHEL5... */ static int ipw2100_wx_set_retry(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -7394,6 +7419,7 @@ static int ipw2100_wx_get_retry(struct net_device *dev, return 0; } +#endif static int ipw2100_wx_set_scan(struct net_device *dev, struct iw_request_info *info, @@ -7409,6 +7435,8 @@ static int ipw2100_wx_set_scan(struct net_device *dev, } IPW_DEBUG_WX("Initiating scan...\n"); + + priv->user_requested_scan = 1; if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { IPW_DEBUG_WX("Start scan failed.\n"); @@ -7483,7 +7511,7 @@ static int ipw2100_wx_set_power(struct net_device *dev, switch (wrqu->power.flags & IW_POWER_MODE) { case IW_POWER_ON: /* If not specified */ case IW_POWER_MODE: /* If set all mask */ - case IW_POWER_ALL_R: /* If explicitely state all */ + case IW_POWER_ALL_R: /* If explicitly state all */ break; default: /* Otherwise we don't support it */ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", @@ -7549,11 +7577,10 @@ static int ipw2100_wx_set_genie(struct net_device *dev, return -EINVAL; if (wrqu->data.length) { - buf = kmalloc(wrqu->data.length, GFP_KERNEL); + buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - memcpy(buf, extra, wrqu->data.length); kfree(ieee->wpa_ie); ieee->wpa_ie = buf; ieee->wpa_ie_len = wrqu->data.length; @@ -7770,7 +7797,7 @@ static int ipw2100_wx_set_mlme(struct net_device *dev, { struct ipw2100_priv *priv = ieee80211_priv(dev); struct iw_mlme *mlme = (struct iw_mlme *)extra; - u16 reason; + __le16 reason; reason = cpu_to_le16(mlme->reason_code); @@ -7851,10 +7878,10 @@ static int ipw2100_wx_set_powermode(struct net_device *dev, goto done; } - if ((mode < 1) || (mode > POWER_MODES)) + if ((mode < 0) || (mode > POWER_MODES)) mode = IPW_POWER_AUTO; - if (priv->power_mode != mode) + if (IPW_POWER_LEVEL(priv->power_mode) != mode) err = ipw2100_set_power_mode(priv, mode); done: mutex_unlock(&priv->action_mutex); @@ -7885,7 +7912,7 @@ static int ipw2100_wx_get_powermode(struct net_device *dev, break; case IPW_POWER_AUTO: snprintf(extra, MAX_POWER_STRING, - "Power save level: %d (Auto)", 0); + "Power save level: %d (Auto)", level); break; default: timeout = timeout_duration[level - 1] / 1000; @@ -8038,8 +8065,13 @@ static iw_handler ipw2100_wx_handlers[] = { ipw2100_wx_get_frag, /* SIOCGIWFRAG */ ipw2100_wx_set_txpow, /* SIOCSIWTXPOW */ ipw2100_wx_get_txpow, /* SIOCGIWTXPOW */ +#if 0 /* Not in RHEL5... */ ipw2100_wx_set_retry, /* SIOCSIWRETRY */ ipw2100_wx_get_retry, /* SIOCGIWRETRY */ +#else + NULL, /* SIOCSIWRETRY */ + NULL, /* SIOCGIWRETRY */ +#endif ipw2100_wx_set_encode, /* SIOCSIWENCODE */ ipw2100_wx_get_encode, /* SIOCGIWENCODE */ ipw2100_wx_set_power, /* SIOCSIWPOWER */ @@ -8262,10 +8294,9 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev) static struct iw_handler_def ipw2100_wx_handler_def = { .standard = ipw2100_wx_handlers, - .num_standard = sizeof(ipw2100_wx_handlers) / sizeof(iw_handler), - .num_private = sizeof(ipw2100_private_handler) / sizeof(iw_handler), - .num_private_args = sizeof(ipw2100_private_args) / - sizeof(struct iw_priv_args), + .num_standard = ARRAY_SIZE(ipw2100_wx_handlers), + .num_private = ARRAY_SIZE(ipw2100_private_handler), + .num_private_args = ARRAY_SIZE(ipw2100_private_args), .private = (iw_handler *) ipw2100_private_handler, .private_args = (struct iw_priv_args *)ipw2100_private_args, .get_wireless_stats = ipw2100_wx_wireless_stats, diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index 55b7227..d8f4a9e 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -479,7 +479,6 @@ enum { #define CFG_ASSOCIATE (1<<6) #define CFG_FIXED_RATE (1<<7) #define CFG_ADHOC_CREATE (1<<8) -#define CFG_C3_DISABLED (1<<9) #define CFG_PASSIVE_SCAN (1<<10) #ifdef CONFIG_IPW2100_MONITOR #define CFG_CRC_CHECK (1<<11) @@ -508,7 +507,6 @@ struct ipw2100_priv { u8 bssid[ETH_ALEN]; u8 channel; int last_mode; - int cstate_limit; unsigned long connect_start; unsigned long last_reset; @@ -588,6 +586,10 @@ struct ipw2100_priv { struct work_struct wx_event_work; struct work_struct hang_check; struct work_struct rf_kill; + struct work_struct scan_event_now; + struct work_struct scan_event_later; + + int user_requested_scan; u32 interrupts; int tx_interrupts; diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index d7b70a0..a2ebb0f 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -70,7 +70,7 @@ #define VQ #endif -#define IPW2200_VERSION "1.2.0" VK VD VM VP VR VQ +#define IPW2200_VERSION "1.2.2" VK VD VM VP VR VQ #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" #define DRV_VERSION IPW2200_VERSION @@ -866,7 +866,7 @@ static void ipw_bg_led_link_on(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_led_link_on(data); + ipw_led_link_on(priv); mutex_unlock(&priv->mutex); } @@ -910,7 +910,7 @@ static void ipw_bg_led_link_off(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_led_link_off(data); + ipw_led_link_off(priv); mutex_unlock(&priv->mutex); } @@ -989,7 +989,7 @@ static void ipw_bg_led_activity_off(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_led_activity_off(data); + ipw_led_activity_off(priv); mutex_unlock(&priv->mutex); } @@ -1230,9 +1230,19 @@ static ssize_t show_event_log(struct device *d, { struct ipw_priv *priv = dev_get_drvdata(d); u32 log_len = ipw_get_event_log_len(priv); - struct ipw_event log[log_len]; + u32 log_size; + struct ipw_event *log; u32 len = 0, i; + /* not using min() because of its strict type checking */ + log_size = PAGE_SIZE / sizeof(*log) > log_len ? + sizeof(*log) * log_len : PAGE_SIZE; + log = kzalloc(log_size, GFP_KERNEL); + if (!log) { + IPW_ERROR("Unable to allocate memory for log\n"); + return 0; + } + log_len = log_size / sizeof(*log); ipw_capture_event_log(priv, log_len, log); len += snprintf(buf + len, PAGE_SIZE - len, "%08X", log_len); @@ -1241,6 +1251,7 @@ static ssize_t show_event_log(struct device *d, "\n%08X%08X%08X", log[i].time, log[i].event, log[i].data); len += snprintf(buf + len, PAGE_SIZE - len, "\n"); + kfree(log); return len; } @@ -1737,8 +1748,10 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) if (disable_radio) { priv->status |= STATUS_RF_KILL_SW; - if (priv->workqueue) + if (priv->workqueue) { cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->scan_event); + } queue_work(priv->workqueue, &priv->down); } else { priv->status &= ~STATUS_RF_KILL_SW; @@ -1748,7 +1761,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ cancel_delayed_work(&priv->rf_kill); queue_delayed_work(priv->workqueue, &priv->rf_kill, - 2 * HZ); + round_jiffies_relative(2 * HZ)); } else queue_work(priv->workqueue, &priv->up); } @@ -1989,6 +2002,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) wake_up_interruptible(&priv->wait_command_queue); priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->scan_event); schedule_work(&priv->link_down); queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); handled |= IPW_INTA_BIT_RF_KILL_DONE; @@ -2278,7 +2292,7 @@ static void ipw_bg_adapter_restart(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_adapter_restart(data); + ipw_adapter_restart(priv); mutex_unlock(&priv->mutex); } @@ -2299,7 +2313,7 @@ static void ipw_bg_scan_check(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_scan_check(data); + ipw_scan_check(priv); mutex_unlock(&priv->mutex); } @@ -2333,27 +2347,13 @@ static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) static int ipw_send_associate(struct ipw_priv *priv, struct ipw_associate *associate) { - struct ipw_associate tmp_associate; - if (!priv || !associate) { IPW_ERROR("Invalid args\n"); return -1; } - memcpy(&tmp_associate, associate, sizeof(*associate)); - tmp_associate.policy_support = - cpu_to_le16(tmp_associate.policy_support); - tmp_associate.assoc_tsf_msw = cpu_to_le32(tmp_associate.assoc_tsf_msw); - tmp_associate.assoc_tsf_lsw = cpu_to_le32(tmp_associate.assoc_tsf_lsw); - tmp_associate.capability = cpu_to_le16(tmp_associate.capability); - tmp_associate.listen_interval = - cpu_to_le16(tmp_associate.listen_interval); - tmp_associate.beacon_interval = - cpu_to_le16(tmp_associate.beacon_interval); - tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window); - - return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(tmp_associate), - &tmp_associate); + return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(*associate), + associate); } static int ipw_send_supported_rates(struct ipw_priv *priv, @@ -2384,14 +2384,13 @@ static int ipw_set_random_seed(struct ipw_priv *priv) static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) { + __le32 v = cpu_to_le32(phy_off); if (!priv) { IPW_ERROR("Invalid args\n"); return -1; } - phy_off = cpu_to_le32(phy_off); - return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off), - &phy_off); + return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(v), &v); } static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) @@ -2480,7 +2479,7 @@ static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) { - u32 param; + __le32 param; if (!priv) { IPW_ERROR("Invalid args\n"); @@ -2491,21 +2490,21 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) * level */ switch (mode) { case IPW_POWER_BATTERY: - param = IPW_POWER_INDEX_3; + param = cpu_to_le32(IPW_POWER_INDEX_3); break; case IPW_POWER_AC: - param = IPW_POWER_MODE_CAM; + param = cpu_to_le32(IPW_POWER_MODE_CAM); break; default: - param = mode; + param = cpu_to_le32(mode); break; } - param = cpu_to_le32(mode); return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param), ¶m); } +#if 0 /* Not in RHEL5... */ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) { struct ipw_retry_limit retry_limit = { @@ -2521,6 +2520,7 @@ static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) return ipw_send_cmd_pdu(priv, IPW_CMD_RETRY_LIMIT, sizeof(retry_limit), &retry_limit); } +#endif /* * The IPW device contains a Microwire compatible EEPROM that stores @@ -2635,13 +2635,13 @@ static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac) static void ipw_eeprom_init_sram(struct ipw_priv *priv) { int i; - u16 *eeprom = (u16 *) priv->eeprom; + __le16 *eeprom = (__le16 *) priv->eeprom; IPW_DEBUG_TRACE(">>\n"); /* read entire contents of eeprom into private buffer */ for (i = 0; i < 128; i++) - eeprom[i] = le16_to_cpu(eeprom_read_u16(priv, (u8) i)); + eeprom[i] = cpu_to_le16(eeprom_read_u16(priv, (u8) i)); /* If the data looks correct, then copy it to our private @@ -3021,17 +3021,17 @@ static void ipw_arc_release(struct ipw_priv *priv) } struct fw_chunk { - u32 address; - u32 length; + __le32 address; + __le32 length; }; static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) { int rc = 0, i, addr; u8 cr = 0; - u16 *image; + __le16 *image; - image = (u16 *) data; + image = (__le16 *) data; IPW_DEBUG_TRACE(">> \n"); @@ -3078,7 +3078,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) /* load new ipw uCode */ for (i = 0; i < len / 2; i++) ipw_write_reg16(priv, IPW_BASEBAND_CONTROL_STORE, - cpu_to_le16(image[i])); + le16_to_cpu(image[i])); /* enable DINO */ ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); @@ -3097,11 +3097,11 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) if (cr & DINO_RXFIFO_DATA) { /* alive_command_responce size is NOT multiple of 4 */ - u32 response_buffer[(sizeof(priv->dino_alive) + 3) / 4]; + __le32 response_buffer[(sizeof(priv->dino_alive) + 3) / 4]; for (i = 0; i < ARRAY_SIZE(response_buffer); i++) response_buffer[i] = - le32_to_cpu(ipw_read_reg32(priv, + cpu_to_le32(ipw_read_reg32(priv, IPW_BASEBAND_RX_FIFO_READ)); memcpy(&priv->dino_alive, response_buffer, sizeof(priv->dino_alive)); @@ -3362,7 +3362,6 @@ static void ipw_rx_queue_reset(struct ipw_priv *priv, /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; - rxq->processed = RX_QUEUE_SIZE - 1; rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); } @@ -3604,7 +3603,22 @@ static int ipw_load(struct ipw_priv *priv) * Driver allocates buffers of this size for Rx */ -static inline int ipw_queue_space(const struct clx2_queue *q) +/** + * ipw_rx_queue_space - Return number of free slots available in queue. + */ +static int ipw_rx_queue_space(const struct ipw_rx_queue *q) +{ + int s = q->read - q->write; + if (s <= 0) + s += RX_QUEUE_SIZE; + /* keep some buffer to not confuse full and empty queue */ + s -= 2; + if (s < 0) + s = 0; + return s; +} + +static inline int ipw_tx_queue_space(const struct clx2_queue *q) { int s = q->last_used - q->first_empty; if (s <= 0) @@ -3881,7 +3895,7 @@ static void ipw_bg_disassociate(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_disassociate(data); + ipw_disassociate(priv); mutex_unlock(&priv->mutex); } @@ -4147,7 +4161,7 @@ static void ipw_gather_stats(struct ipw_priv *priv) priv->last_missed_beacons = priv->missed_beacons; if (priv->assoc_request.beacon_interval) { missed_beacons_percent = missed_beacons_delta * - (HZ * priv->assoc_request.beacon_interval) / + (HZ * le16_to_cpu(priv->assoc_request.beacon_interval)) / (IPW_STATS_INTERVAL * 10); } else { missed_beacons_percent = 0; @@ -4258,7 +4272,7 @@ static void ipw_bg_gather_stats(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_gather_stats(data); + ipw_gather_stats(priv); mutex_unlock(&priv->mutex); } @@ -4314,8 +4328,8 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, if (!(priv->status & STATUS_ROAMING)) { priv->status |= STATUS_ROAMING; if (!(priv->status & STATUS_SCANNING)) - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); } return; } @@ -4333,6 +4347,36 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count); } +static void ipw_scan_event(void *data) +{ + union iwreq_data wrqu; + + struct ipw_priv *priv = data; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); +} + +static void handle_scan_event(struct ipw_priv *priv) +{ + /* Only userspace-requested scan completion events go out immediately */ + if (!priv->user_requested_scan) { + if (!delayed_work_pending(&priv->scan_event)) + queue_delayed_work(priv->workqueue, &priv->scan_event, + round_jiffies_relative(msecs_to_jiffies(4000))); + } else { + union iwreq_data wrqu; + + priv->user_requested_scan = 0; + cancel_delayed_work(&priv->scan_event); + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); + } +} + /** * Handle host notification packet. * Called from interrupt routine @@ -4340,9 +4384,10 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, static void ipw_rx_notification(struct ipw_priv *priv, struct ipw_rx_notification *notif) { + u16 size = le16_to_cpu(notif->size); notif->size = le16_to_cpu(notif->size); - IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, notif->size); + IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size); switch (notif->subtype) { case HOST_NOTIFICATION_STATUS_ASSOCIATED:{ @@ -4377,9 +4422,9 @@ static void ipw_rx_notification(struct ipw_priv *priv, workqueue, &priv-> adhoc_check, - priv-> + le16_to_cpu(priv-> assoc_request. - beacon_interval); + beacon_interval)); break; } @@ -4397,20 +4442,17 @@ static void ipw_rx_notification(struct ipw_priv *priv, if ((sizeof (struct ieee80211_assoc_response) - <= notif->size) - && (notif->size <= 2314)) { + <= size) + && (size <= 2314)) { struct ieee80211_rx_stats stats = { - .len = - notif-> - size - 1, + .len = size - 1, }; IPW_DEBUG_QOS ("QoS Associate " - "size %d\n", - notif->size); + "size %d\n", size); ieee80211_rx_mgt(priv-> ieee, (struct @@ -4437,7 +4479,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_DL_ASSOC, "deauthenticated: '%s' " MAC_FMT - ": (0x%04X) - %s \n", + ": (0x%04X) - %s\n", escape_essid(priv-> essid, priv-> @@ -4615,20 +4657,20 @@ static void ipw_rx_notification(struct ipw_priv *priv, struct notif_channel_result *x = ¬if->u.channel_result; - if (notif->size == sizeof(*x)) { + if (size == sizeof(*x)) { IPW_DEBUG_SCAN("Scan result for channel %d\n", x->channel_num); } else { IPW_DEBUG_SCAN("Scan result of wrong size %d " "(should be %zd)\n", - notif->size, sizeof(*x)); + size, sizeof(*x)); } break; } case HOST_NOTIFICATION_STATUS_SCAN_COMPLETED:{ struct notif_scan_complete *x = ¬if->u.scan_complete; - if (notif->size == sizeof(*x)) { + if (size == sizeof(*x)) { IPW_DEBUG_SCAN ("Scan completed: type %d, %d channels, " "%d status\n", x->scan_type, @@ -4636,7 +4678,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, } else { IPW_ERROR("Scan completed of wrong size %d " "(should be %zd)\n", - notif->size, sizeof(*x)); + size, sizeof(*x)); } priv->status &= @@ -4653,8 +4695,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { priv->status |= STATUS_SCAN_FORCED; - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); break; } priv->status &= ~STATUS_SCAN_FORCED; @@ -4677,12 +4719,13 @@ static void ipw_rx_notification(struct ipw_priv *priv, /* Don't schedule if we aborted the scan */ priv->status &= ~STATUS_ROAMING; } else if (priv->status & STATUS_SCAN_PENDING) - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); else if (priv->config & CFG_BACKGROUND_SCAN && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, - &priv->request_scan, HZ); + &priv->request_scan, + round_jiffies_relative(HZ)); /* Send an empty event to user space. * We don't send the received data on the event because @@ -4693,27 +4736,21 @@ static void ipw_rx_notification(struct ipw_priv *priv, * on how the scan was initiated. User space can just * sync on periodic scan to get fresh data... * Jean II */ - if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) { - union iwreq_data wrqu; - - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(priv->net_dev, SIOCGIWSCAN, - &wrqu, NULL); - } + if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) + handle_scan_event(priv); break; } case HOST_NOTIFICATION_STATUS_FRAG_LENGTH:{ struct notif_frag_length *x = ¬if->u.frag_len; - if (notif->size == sizeof(*x)) + if (size == sizeof(*x)) IPW_ERROR("Frag length: %d\n", le16_to_cpu(x->frag_length)); else IPW_ERROR("Frag length of wrong size %d " "(should be %zd)\n", - notif->size, sizeof(*x)); + size, sizeof(*x)); break; } @@ -4721,7 +4758,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, struct notif_link_deterioration *x = ¬if->u.link_deterioration; - if (notif->size == sizeof(*x)) { + if (size == sizeof(*x)) { IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, "link deterioration: type %d, cnt %d\n", x->silence_notification_type, @@ -4731,7 +4768,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, } else { IPW_ERROR("Link Deterioration of wrong size %d " "(should be %zd)\n", - notif->size, sizeof(*x)); + size, sizeof(*x)); } break; } @@ -4747,10 +4784,10 @@ static void ipw_rx_notification(struct ipw_priv *priv, case HOST_NOTIFICATION_STATUS_BEACON_STATE:{ struct notif_beacon_state *x = ¬if->u.beacon_state; - if (notif->size != sizeof(*x)) { + if (size != sizeof(*x)) { IPW_ERROR ("Beacon state of wrong size %d (should " - "be %zd)\n", notif->size, sizeof(*x)); + "be %zd)\n", size, sizeof(*x)); break; } @@ -4765,7 +4802,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, case HOST_NOTIFICATION_STATUS_TGI_TX_KEY:{ struct notif_tgi_tx_key *x = ¬if->u.tgi_tx_key; - if (notif->size == sizeof(*x)) { + if (size == sizeof(*x)) { IPW_ERROR("TGi Tx Key: state 0x%02x sec type " "0x%02x station %d\n", x->key_state, x->security_type, @@ -4775,14 +4812,14 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_ERROR ("TGi Tx Key of wrong size %d (should be %zd)\n", - notif->size, sizeof(*x)); + size, sizeof(*x)); break; } case HOST_NOTIFICATION_CALIB_KEEP_RESULTS:{ struct notif_calibration *x = ¬if->u.calibration; - if (notif->size == sizeof(*x)) { + if (size == sizeof(*x)) { memcpy(&priv->calib, x, sizeof(*x)); IPW_DEBUG_INFO("TODO: Calibration\n"); break; @@ -4790,12 +4827,12 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_ERROR ("Calibration of wrong size %d (should be %zd)\n", - notif->size, sizeof(*x)); + size, sizeof(*x)); break; } case HOST_NOTIFICATION_NOISE_STATS:{ - if (notif->size == sizeof(u32)) { + if (size == sizeof(u32)) { priv->exp_avg_noise = exponential_average(priv->exp_avg_noise, (u8) (le32_to_cpu(notif->u.noise.value) & 0xff), @@ -4805,14 +4842,14 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_ERROR ("Noise stat is wrong size %d (should be %zd)\n", - notif->size, sizeof(u32)); + size, sizeof(u32)); break; } default: IPW_DEBUG_NOTIF("Unknown notification: " "subtype=%d,flags=0x%2x,size=%d\n", - notif->subtype, notif->flags, notif->size); + notif->subtype, notif->flags, size); } } @@ -4884,7 +4921,7 @@ static int ipw_queue_reset(struct ipw_priv *priv) /** * Reclaim Tx queue entries no more used by NIC. * - * When FW adwances 'R' index, all entries between old and + * When FW advances 'R' index, all entries between old and * new 'R' index need to be reclaimed. As result, some free space * forms. If there is enough free space (> low mark), wake Tx queue. * @@ -4914,7 +4951,7 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv, priv->tx_packets++; } done: - if ((ipw_queue_space(q) > q->low_mark) && + if ((ipw_tx_queue_space(q) > q->low_mark) && (qindex >= 0) && (priv->status & STATUS_ASSOCIATED) && netif_running(priv->net_dev)) netif_wake_queue(priv->net_dev); @@ -4932,7 +4969,7 @@ static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf, struct clx2_queue *q = &txq->q; struct tfd_frame *tfd; - if (ipw_queue_space(q) < (sync ? 1 : 2)) { + if (ipw_tx_queue_space(q) < (sync ? 1 : 2)) { IPW_ERROR("No space for Tx\n"); return -EBUSY; } @@ -5037,7 +5074,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv) spin_lock_irqsave(&rxq->lock, flags); write = rxq->write; - while ((rxq->write != rxq->processed) && (rxq->free_count)) { + while ((ipw_rx_queue_space(rxq) > 0) && (rxq->free_count)) { element = rxq->rx_free.next; rxb = list_entry(element, struct ipw_rx_mem_buffer, list); list_del(element); @@ -5105,7 +5142,7 @@ static void ipw_bg_rx_queue_replenish(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_rx_queue_replenish(data); + ipw_rx_queue_replenish(priv); mutex_unlock(&priv->mutex); } @@ -5153,7 +5190,6 @@ static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *priv) /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; - rxq->processed = RX_QUEUE_SIZE - 1; rxq->free_count = 0; return rxq; @@ -5401,7 +5437,7 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, if ((network->ssid_len != match->network->ssid_len) || memcmp(network->ssid, match->network->ssid, network->ssid_len)) { - IPW_DEBUG_MERGE("Netowrk '%s (" MAC_FMT ")' excluded " + IPW_DEBUG_MERGE("Network '%s (" MAC_FMT ")' excluded " "because of non-network ESSID.\n", escape_essid(network->ssid, network->ssid_len), @@ -5488,7 +5524,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, "because of the same BSSID match: " MAC_FMT ".\n", escape_essid(network->ssid, network->ssid_len), - MAC_ARG(network->bssid), MAC_ARG(priv->bssid)); + MAC_ARG(network->bssid), + MAC_ARG(priv->bssid)); return 0; } @@ -5613,7 +5650,7 @@ static int ipw_best_network(struct ipw_priv *priv, if ((network->ssid_len != match->network->ssid_len) || memcmp(network->ssid, match->network->ssid, network->ssid_len)) { - IPW_DEBUG_ASSOC("Netowrk '%s (" MAC_FMT ")' excluded " + IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " "because of non-network ESSID.\n", escape_essid(network->ssid, network->ssid_len), @@ -5991,14 +6028,14 @@ static void ipw_adhoc_check(void *data) } queue_delayed_work(priv->workqueue, &priv->adhoc_check, - priv->assoc_request.beacon_interval); + le16_to_cpu(priv->assoc_request.beacon_interval)); } static void ipw_bg_adhoc_check(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_adhoc_check(data); + ipw_adhoc_check(priv); mutex_unlock(&priv->mutex); } @@ -6345,19 +6382,21 @@ done: return err; } -static int ipw_request_passive_scan(struct ipw_priv *priv) { - return ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); +static void ipw_request_passive_scan(struct ipw_priv *priv) +{ + ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); } -static int ipw_request_scan(struct ipw_priv *priv) { - return ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); +static void ipw_request_scan(struct ipw_priv *priv) +{ + ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); } static void ipw_bg_abort_scan(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_abort_scan(data); + ipw_abort_scan(priv); mutex_unlock(&priv->mutex); } @@ -6701,7 +6740,7 @@ static int ipw_wx_set_mlme(struct net_device *dev, { struct ipw_priv *priv = ieee80211_priv(dev); struct iw_mlme *mlme = (struct iw_mlme *)extra; - u16 reason; + __le16 reason; reason = cpu_to_le16(mlme->reason_code); @@ -6838,7 +6877,7 @@ static int ipw_qos_activate(struct ipw_priv *priv, burst_duration = ipw_qos_get_burst_duration(priv); for (i = 0; i < QOS_QUEUE_NUM; i++) qos_parameters[QOS_PARAM_SET_ACTIVE].tx_op_limit[i] = - (u16)burst_duration; + cpu_to_le16(burst_duration); } else if (priv->ieee->iw_mode == IW_MODE_ADHOC) { if (type == IEEE_B) { IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n", @@ -6870,20 +6909,11 @@ static int ipw_qos_activate(struct ipw_priv *priv, burst_duration = ipw_qos_get_burst_duration(priv); for (i = 0; i < QOS_QUEUE_NUM; i++) qos_parameters[QOS_PARAM_SET_ACTIVE]. - tx_op_limit[i] = (u16)burst_duration; + tx_op_limit[i] = cpu_to_le16(burst_duration); } } IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n"); - for (i = 0; i < 3; i++) { - int j; - for (j = 0; j < QOS_QUEUE_NUM; j++) { - qos_parameters[i].cw_min[j] = cpu_to_le16(qos_parameters[i].cw_min[j]); - qos_parameters[i].cw_max[j] = cpu_to_le16(qos_parameters[i].cw_max[j]); - qos_parameters[i].tx_op_limit[j] = cpu_to_le16(qos_parameters[i].tx_op_limit[j]); - } - } - err = ipw_send_qos_params_command(priv, (struct ieee80211_qos_parameters *) &(qos_parameters[0])); @@ -7232,7 +7262,7 @@ static int ipw_associate_network(struct ipw_priv *priv, priv->assoc_request.auth_type = AUTH_OPEN; if (priv->ieee->wpa_ie_len) { - priv->assoc_request.policy_support = 0x02; /* RSN active */ + priv->assoc_request.policy_support = cpu_to_le16(0x02); /* RSN active */ ipw_set_rsn_capa(priv, priv->ieee->wpa_ie, priv->ieee->wpa_ie_len); } @@ -7249,7 +7279,7 @@ static int ipw_associate_network(struct ipw_priv *priv, else if (network->mode & priv->ieee->mode & IEEE_B) priv->assoc_request.ieee_mode = IPW_B_MODE; - priv->assoc_request.capability = network->capability; + priv->assoc_request.capability = cpu_to_le16(network->capability); if ((network->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && !(priv->config & CFG_PREAMBLE_LONG)) { priv->assoc_request.preamble_length = DCT_FLAG_SHORT_PREAMBLE; @@ -7258,13 +7288,13 @@ static int ipw_associate_network(struct ipw_priv *priv, /* Clear the short preamble if we won't be supporting it */ priv->assoc_request.capability &= - ~WLAN_CAPABILITY_SHORT_PREAMBLE; + ~cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); } /* Clear capability bits that aren't used in Ad Hoc */ if (priv->ieee->iw_mode == IW_MODE_ADHOC) priv->assoc_request.capability &= - ~WLAN_CAPABILITY_SHORT_SLOT_TIME; + ~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, " "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n", @@ -7286,7 +7316,7 @@ static int ipw_associate_network(struct ipw_priv *priv, '1' + priv->ieee->sec.active_key : '.', priv->capability & CAP_PRIVACY_ON ? '.' : ' '); - priv->assoc_request.beacon_interval = network->beacon_interval; + priv->assoc_request.beacon_interval = cpu_to_le16(network->beacon_interval); if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && (network->time_stamp[0] == 0) && (network->time_stamp[1] == 0)) { priv->assoc_request.assoc_type = HC_IBSS_START; @@ -7297,21 +7327,21 @@ static int ipw_associate_network(struct ipw_priv *priv, priv->assoc_request.assoc_type = HC_REASSOCIATE; else priv->assoc_request.assoc_type = HC_ASSOCIATE; - priv->assoc_request.assoc_tsf_msw = network->time_stamp[1]; - priv->assoc_request.assoc_tsf_lsw = network->time_stamp[0]; + priv->assoc_request.assoc_tsf_msw = cpu_to_le32(network->time_stamp[1]); + priv->assoc_request.assoc_tsf_lsw = cpu_to_le32(network->time_stamp[0]); } memcpy(priv->assoc_request.bssid, network->bssid, ETH_ALEN); if (priv->ieee->iw_mode == IW_MODE_ADHOC) { memset(&priv->assoc_request.dest, 0xFF, ETH_ALEN); - priv->assoc_request.atim_window = network->atim_window; + priv->assoc_request.atim_window = cpu_to_le16(network->atim_window); } else { memcpy(priv->assoc_request.dest, network->bssid, ETH_ALEN); priv->assoc_request.atim_window = 0; } - priv->assoc_request.listen_interval = network->listen_interval; + priv->assoc_request.listen_interval = cpu_to_le16(network->listen_interval); err = ipw_send_ssid(priv, priv->essid, priv->essid_len); if (err) { @@ -7444,7 +7474,7 @@ static void ipw_bg_roam(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_roam(data); + ipw_roam(priv); mutex_unlock(&priv->mutex); } @@ -7525,8 +7555,8 @@ static int ipw_associate(void *data) &priv->request_scan, SCAN_INTERVAL); else - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); } return 0; @@ -7541,7 +7571,7 @@ static void ipw_bg_associate(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_associate(data); + ipw_associate(priv); mutex_unlock(&priv->mutex); } @@ -7698,11 +7728,11 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ - ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total header+data */ + ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct ipw_rt_hdr)); /* total header+data */ /* Big bitfield of all the fields we provide in radiotap */ - ipw_rt->rt_hdr.it_present = - ((1 << IEEE80211_RADIOTAP_TSFT) | + ipw_rt->rt_hdr.it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_TSFT) | (1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL) | @@ -7731,7 +7761,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); } else { /* 802.11g */ ipw_rt->rt_chbitmask = - (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); + cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); } /* set the rate in multiples of 500k/s */ @@ -7912,14 +7942,14 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ - ipw_rt->rt_hdr.it_len = sizeof(*ipw_rt); /* total header+data */ + ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*ipw_rt)); /* total header+data */ /* Set the size of the skb to the size of the frame */ - skb_put(skb, ipw_rt->rt_hdr.it_len + len); + skb_put(skb, sizeof(*ipw_rt) + len); /* Big bitfield of all the fields we provide in radiotap */ - ipw_rt->rt_hdr.it_present = - ((1 << IEEE80211_RADIOTAP_TSFT) | + ipw_rt->rt_hdr.it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_TSFT) | (1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL) | @@ -7948,7 +7978,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); } else { /* 802.11g */ ipw_rt->rt_chbitmask = - (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); + cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); } /* set the rate in multiples of 500k/s */ @@ -8158,7 +8188,7 @@ static void ipw_handle_mgmt_packet(struct ipw_priv *priv, skb->dev = priv->ieee->dev; /* Point raw at the ieee80211_stats */ - skb->mac.raw = skb->data; + skb_reset_mac_header(skb); skb->pkt_type = PACKET_OTHERHOST; skb->protocol = __constant_htons(ETH_P_80211_STATS); @@ -8180,10 +8210,14 @@ static void ipw_rx(struct ipw_priv *priv) struct ieee80211_hdr_4addr *header; u32 r, w, i; u8 network_packet; + u8 fill_rx = 0; r = ipw_read32(priv, IPW_RX_READ_INDEX); w = ipw_read32(priv, IPW_RX_WRITE_INDEX); - i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE; + i = priv->rxq->read; + + if (ipw_rx_queue_space (priv->rxq) > (RX_QUEUE_SIZE / 2)) + fill_rx = 1; while (i != r) { rxb = priv->rxq->queue[i]; @@ -8355,11 +8389,17 @@ static void ipw_rx(struct ipw_priv *priv) list_add_tail(&rxb->list, &priv->rxq->rx_used); i = (i + 1) % RX_QUEUE_SIZE; + + /* If there are a lot of unsued frames, restock the Rx queue + * so the ucode won't assert */ + if (fill_rx) { + priv->rxq->read = i; + ipw_rx_queue_replenish(priv); + } } /* Backtrack one entry */ - priv->rxq->processed = (i ? i : RX_QUEUE_SIZE) - 1; - + priv->rxq->read = i; ipw_rx_queue_restock(priv); } @@ -8896,6 +8936,7 @@ static int ipw_wx_get_wap(struct net_device *dev, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); + /* If we are associated, trying to associate, or have a statically * configured BSSID then return that; otherwise return ANY */ mutex_lock(&priv->mutex); @@ -9317,6 +9358,7 @@ static int ipw_wx_get_frag(struct net_device *dev, return 0; } +#if 0 /* Not in RHEL5... */ static int ipw_wx_set_retry(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -9380,6 +9422,7 @@ static int ipw_wx_get_retry(struct net_device *dev, return 0; } +#endif static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, int essid_len) @@ -9454,6 +9497,10 @@ static int ipw_wx_set_scan(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); struct iw_scan_req *req = (struct iw_scan_req *)extra; + mutex_lock(&priv->mutex); + priv->user_requested_scan = 1; + mutex_unlock(&priv->mutex); + if (wrqu->data.length == sizeof(struct iw_scan_req)) { if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { ipw_request_direct_scan(priv, req->essid, @@ -9469,7 +9516,7 @@ static int ipw_wx_set_scan(struct net_device *dev, IPW_DEBUG_WX("Start scan\n"); - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, &priv->request_scan, 0); return 0; } @@ -9535,7 +9582,7 @@ static int ipw_wx_set_power(struct net_device *dev, switch (wrqu->power.flags & IW_POWER_MODE) { case IW_POWER_ON: /* If not specified */ case IW_POWER_MODE: /* If set all mask */ - case IW_POWER_ALL_R: /* If explicitely state all */ + case IW_POWER_ALL_R: /* If explicitly state all */ break; default: /* Otherwise we don't support it */ IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", @@ -9550,6 +9597,7 @@ static int ipw_wx_set_power(struct net_device *dev, priv->power_mode = IPW_POWER_ENABLED | IPW_POWER_BATTERY; else priv->power_mode = IPW_POWER_ENABLED | priv->power_mode; + err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); @@ -9586,22 +9634,19 @@ static int ipw_wx_set_powermode(struct net_device *dev, struct ipw_priv *priv = ieee80211_priv(dev); int mode = *(int *)extra; int err; + mutex_lock(&priv->mutex); - if ((mode < 1) || (mode > IPW_POWER_LIMIT)) { + if ((mode < 1) || (mode > IPW_POWER_LIMIT)) mode = IPW_POWER_AC; - priv->power_mode = mode; - } else { - priv->power_mode = IPW_POWER_ENABLED | mode; - } - if (priv->power_mode != mode) { + if (IPW_POWER_LEVEL(priv->power_mode) != mode) { err = ipw_send_power_mode(priv, mode); - if (err) { IPW_DEBUG_WX("failed setting power mode.\n"); mutex_unlock(&priv->mutex); return err; } + priv->power_mode = IPW_POWER_ENABLED | mode; } mutex_unlock(&priv->mutex); return 0; @@ -9908,8 +9953,10 @@ static iw_handler ipw_wx_handlers[] = { IW_IOCTL(SIOCGIWFRAG) = ipw_wx_get_frag, IW_IOCTL(SIOCSIWTXPOW) = ipw_wx_set_txpow, IW_IOCTL(SIOCGIWTXPOW) = ipw_wx_get_txpow, +#if 0 /* Not in RHEL5... */ IW_IOCTL(SIOCSIWRETRY) = ipw_wx_set_retry, IW_IOCTL(SIOCGIWRETRY) = ipw_wx_get_retry, +#endif IW_IOCTL(SIOCSIWENCODE) = ipw_wx_set_encode, IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode, IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power, @@ -10128,7 +10175,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, if (id == IPW_INVALID_STATION) { IPW_WARNING("Attempt to send data to " "invalid cell: " MAC_FMT "\n", - MAC_ARG(hdr->addr1)); + hdr->addr1[0], hdr->addr1[1], + hdr->addr1[2], hdr->addr1[3], + hdr->addr1[4], hdr->addr1[5]); goto drop; } } @@ -10270,7 +10319,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, tfd->u.data.chunk_ptr[i] = cpu_to_le32(pci_map_single (priv->pci_dev, skb->data, - tfd->u.data.chunk_len[i], + remaining_bytes, PCI_DMA_TODEVICE)); tfd->u.data.num_chunks = @@ -10283,7 +10332,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); ipw_write32(priv, q->reg_w, q->first_empty); - if (ipw_queue_space(q) < q->high_mark) + if (ipw_tx_queue_space(q) < q->high_mark) netif_stop_queue(priv->net_dev); return NETDEV_TX_OK; @@ -10304,7 +10353,7 @@ static int ipw_net_is_queue_full(struct net_device *dev, int pri) struct clx2_tx_queue *txq = &priv->txq[0]; #endif /* CONFIG_IPW2200_QOS */ - if (ipw_queue_space(&txq->q) < txq->q.high_mark) + if (ipw_tx_queue_space(&txq->q) < txq->q.high_mark) return 1; return 0; @@ -10365,26 +10414,26 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION; rt_hdr->it_pad = 0; rt_hdr->it_present = 0; /* after all, it's just an idea */ - rt_hdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL); + rt_hdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CHANNEL); - *(u16*)skb_put(dst, sizeof(u16)) = cpu_to_le16( + *(__le16*)skb_put(dst, sizeof(u16)) = cpu_to_le16( ieee80211chan2mhz(priv->channel)); if (priv->channel > 14) /* 802.11a */ - *(u16*)skb_put(dst, sizeof(u16)) = + *(__le16*)skb_put(dst, sizeof(u16)) = cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ); else if (priv->ieee->mode == IEEE_B) /* 802.11b */ - *(u16*)skb_put(dst, sizeof(u16)) = + *(__le16*)skb_put(dst, sizeof(u16)) = cpu_to_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ); else /* 802.11g */ - *(u16*)skb_put(dst, sizeof(u16)) = + *(__le16*)skb_put(dst, sizeof(u16)) = cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); - rt_hdr->it_len = dst->len; + rt_hdr->it_len = cpu_to_le16(dst->len); - memcpy(skb_put(dst, len), src->data, len); + skb_copy_from_linear_data(src, skb_put(dst, len), len); if (!ieee80211_rx(priv->prom_priv->ieee, dst, &dummystats)) dev_kfree_skb_any(dst); @@ -10444,6 +10493,7 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p) { struct ipw_priv *priv = ieee80211_priv(dev); struct sockaddr *addr = p; + if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; mutex_lock(&priv->mutex); @@ -10537,7 +10587,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs) spin_lock(&priv->irq_lock); if (!(priv->status & STATUS_INT_ENABLED)) { - /* Shared IRQ */ + /* IRQ is disabled */ goto none; } @@ -10610,7 +10660,7 @@ static void ipw_bg_rf_kill(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_rf_kill(data); + ipw_rf_kill(priv); mutex_unlock(&priv->mutex); } @@ -10630,6 +10680,7 @@ static void ipw_link_up(struct ipw_priv *priv) } cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->scan_event); ipw_reset_stats(priv); /* Ensure the rate is updated immediately */ priv->last_rate = ipw_get_current_rate(priv); @@ -10645,7 +10696,7 @@ static void ipw_bg_link_up(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_link_up(data); + ipw_link_up(priv); mutex_unlock(&priv->mutex); } @@ -10665,19 +10716,20 @@ static void ipw_link_down(struct ipw_priv *priv) if (!(priv->status & STATUS_EXIT_PENDING)) { /* Queue up another scan... */ - queue_work(priv->workqueue, &priv->request_scan); - } + queue_delayed_work(priv->workqueue, &priv->request_scan, 0); + } else + cancel_delayed_work(&priv->scan_event); } static void ipw_bg_link_down(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_link_down(data); + ipw_link_down(priv); mutex_unlock(&priv->mutex); } -static int ipw_setup_deferred_work(struct ipw_priv *priv) +static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv) { int ret = 0; @@ -10692,31 +10744,26 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv); INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart, priv); INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv); - INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv); - INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); + INIT_WORK(&priv->up, ipw_bg_up, priv); + INIT_WORK(&priv->down, ipw_bg_down, priv); INIT_WORK(&priv->request_scan, - (void (*)(void *))ipw_request_scan, priv); + (void (*)(void *))ipw_request_scan, priv); + INIT_WORK(&priv->scan_event, ipw_scan_event, priv); INIT_WORK(&priv->request_passive_scan, - (void (*)(void *))ipw_request_passive_scan, priv); - INIT_WORK(&priv->gather_stats, - (void (*)(void *))ipw_bg_gather_stats, priv); - INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); + (void (*)(void *))ipw_request_passive_scan, priv); + INIT_WORK(&priv->gather_stats, ipw_bg_gather_stats, priv); + INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan, priv); INIT_WORK(&priv->roam, ipw_bg_roam, priv); INIT_WORK(&priv->scan_check, ipw_bg_scan_check, priv); - INIT_WORK(&priv->link_up, (void (*)(void *))ipw_bg_link_up, priv); - INIT_WORK(&priv->link_down, (void (*)(void *))ipw_bg_link_down, priv); - INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_bg_led_link_on, - priv); - INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_bg_led_link_off, - priv); - INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_bg_led_activity_off, - priv); - INIT_WORK(&priv->merge_networks, - (void (*)(void *))ipw_merge_adhoc_network, priv); + INIT_WORK(&priv->link_up, ipw_bg_link_up, priv); + INIT_WORK(&priv->link_down, ipw_bg_link_down, priv); + INIT_WORK(&priv->led_link_on, ipw_bg_led_link_on, priv); + INIT_WORK(&priv->led_link_off, ipw_bg_led_link_off, priv); + INIT_WORK(&priv->led_act_off, ipw_bg_led_activity_off, priv); + INIT_WORK(&priv->merge_networks, ipw_merge_adhoc_network, priv); #ifdef CONFIG_IPW2200_QOS - INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, - priv); + INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate, priv); #endif /* CONFIG_IPW2200_QOS */ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) @@ -10795,9 +10842,9 @@ static void shim__set_security(struct net_device *dev, #if 0 if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) && (((priv->assoc_request.capability & - WLAN_CAPABILITY_PRIVACY) && !sec->enabled) || + cpu_to_le16(WLAN_CAPABILITY_PRIVACY)) && !sec->enabled) || (!(priv->assoc_request.capability & - WLAN_CAPABILITY_PRIVACY) && sec->enabled))) { + cpu_to_le16(WLAN_CAPABILITY_PRIVACY)) && sec->enabled))) { IPW_DEBUG_ASSOC("Disassociating due to capability " "change.\n"); ipw_disassociate(priv); @@ -11248,7 +11295,8 @@ static int ipw_up(struct ipw_priv *priv) /* If configure to try and auto-associate, kick * off a scan. */ - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); return 0; } @@ -11273,7 +11321,7 @@ static void ipw_bg_up(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_up(data); + ipw_up(priv); mutex_unlock(&priv->mutex); } @@ -11344,7 +11392,7 @@ static void ipw_bg_down(void *data) { struct ipw_priv *priv = data; mutex_lock(&priv->mutex); - ipw_down(data); + ipw_down(priv); mutex_unlock(&priv->mutex); } @@ -11497,6 +11545,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) priv->prom_priv->priv = priv; strcpy(priv->prom_net_dev->name, "rtap%d"); + memcpy(priv->prom_net_dev->dev_addr, priv->mac_addr, ETH_ALEN); priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; priv->prom_net_dev->open = ipw_prom_open; @@ -11530,7 +11579,8 @@ static void ipw_prom_free(struct ipw_priv *priv) #endif -static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit ipw_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { int err = 0; struct net_device *net_dev; @@ -11611,7 +11661,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_destroy_workqueue; } - SET_MODULE_OWNER(net_dev); SET_NETDEV_DEV(net_dev, &pdev->dev); mutex_lock(&priv->mutex); @@ -11698,7 +11747,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; } -static void ipw_pci_remove(struct pci_dev *pdev) +static void __devexit ipw_pci_remove(struct pci_dev *pdev) { struct ipw_priv *priv = pci_get_drvdata(pdev); struct list_head *p, *q; @@ -11732,6 +11781,7 @@ static void ipw_pci_remove(struct pci_dev *pdev) cancel_delayed_work(&priv->adhoc_check); cancel_delayed_work(&priv->gather_stats); cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->scan_event); cancel_delayed_work(&priv->rf_kill); cancel_delayed_work(&priv->scan_check); destroy_workqueue(priv->workqueue); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index dad5eed..3a5bc30 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -45,7 +45,6 @@ #include <linux/firmware.h> #include <linux/wireless.h> -#include <linux/dma-mapping.h> #include <linux/jiffies.h> #include <asm/io.h> @@ -268,25 +267,25 @@ enum connection_manager_assoc_states { #define CW_MIN_CCK 31 #define CW_MAX_CCK 1023 -#define QOS_TX0_CW_MIN_OFDM CW_MIN_OFDM -#define QOS_TX1_CW_MIN_OFDM CW_MIN_OFDM -#define QOS_TX2_CW_MIN_OFDM ( (CW_MIN_OFDM + 1) / 2 - 1 ) -#define QOS_TX3_CW_MIN_OFDM ( (CW_MIN_OFDM + 1) / 4 - 1 ) +#define QOS_TX0_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) +#define QOS_TX1_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) +#define QOS_TX2_CW_MIN_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/2 - 1) +#define QOS_TX3_CW_MIN_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/4 - 1) -#define QOS_TX0_CW_MIN_CCK CW_MIN_CCK -#define QOS_TX1_CW_MIN_CCK CW_MIN_CCK -#define QOS_TX2_CW_MIN_CCK ( (CW_MIN_CCK + 1) / 2 - 1 ) -#define QOS_TX3_CW_MIN_CCK ( (CW_MIN_CCK + 1) / 4 - 1 ) +#define QOS_TX0_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) +#define QOS_TX1_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) +#define QOS_TX2_CW_MIN_CCK cpu_to_le16((CW_MIN_CCK + 1)/2 - 1) +#define QOS_TX3_CW_MIN_CCK cpu_to_le16((CW_MIN_CCK + 1)/4 - 1) -#define QOS_TX0_CW_MAX_OFDM CW_MAX_OFDM -#define QOS_TX1_CW_MAX_OFDM CW_MAX_OFDM -#define QOS_TX2_CW_MAX_OFDM CW_MIN_OFDM -#define QOS_TX3_CW_MAX_OFDM ( (CW_MIN_OFDM + 1) / 2 - 1 ) +#define QOS_TX0_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) +#define QOS_TX1_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) +#define QOS_TX2_CW_MAX_OFDM cpu_to_le16(CW_MIN_OFDM) +#define QOS_TX3_CW_MAX_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/2 - 1) -#define QOS_TX0_CW_MAX_CCK CW_MAX_CCK -#define QOS_TX1_CW_MAX_CCK CW_MAX_CCK -#define QOS_TX2_CW_MAX_CCK CW_MIN_CCK -#define QOS_TX3_CW_MAX_CCK ( (CW_MIN_CCK + 1) / 2 - 1 ) +#define QOS_TX0_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) +#define QOS_TX1_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) +#define QOS_TX2_CW_MAX_CCK cpu_to_le16(CW_MIN_CCK) +#define QOS_TX3_CW_MAX_CCK cpu_to_le16((CW_MIN_CCK + 1)/2 - 1) #define QOS_TX0_AIFS (3 - QOS_AIFSN_MIN_VALUE) #define QOS_TX1_AIFS (7 - QOS_AIFSN_MIN_VALUE) @@ -300,33 +299,33 @@ enum connection_manager_assoc_states { #define QOS_TX0_TXOP_LIMIT_CCK 0 #define QOS_TX1_TXOP_LIMIT_CCK 0 -#define QOS_TX2_TXOP_LIMIT_CCK 6016 -#define QOS_TX3_TXOP_LIMIT_CCK 3264 +#define QOS_TX2_TXOP_LIMIT_CCK cpu_to_le16(6016) +#define QOS_TX3_TXOP_LIMIT_CCK cpu_to_le16(3264) #define QOS_TX0_TXOP_LIMIT_OFDM 0 #define QOS_TX1_TXOP_LIMIT_OFDM 0 -#define QOS_TX2_TXOP_LIMIT_OFDM 3008 -#define QOS_TX3_TXOP_LIMIT_OFDM 1504 +#define QOS_TX2_TXOP_LIMIT_OFDM cpu_to_le16(3008) +#define QOS_TX3_TXOP_LIMIT_OFDM cpu_to_le16(1504) -#define DEF_TX0_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX1_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX2_CW_MIN_OFDM CW_MIN_OFDM -#define DEF_TX3_CW_MIN_OFDM CW_MIN_OFDM +#define DEF_TX0_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) +#define DEF_TX1_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) +#define DEF_TX2_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) +#define DEF_TX3_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) -#define DEF_TX0_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX1_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX2_CW_MIN_CCK CW_MIN_CCK -#define DEF_TX3_CW_MIN_CCK CW_MIN_CCK +#define DEF_TX0_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) +#define DEF_TX1_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) +#define DEF_TX2_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) +#define DEF_TX3_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) -#define DEF_TX0_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX1_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX2_CW_MAX_OFDM CW_MAX_OFDM -#define DEF_TX3_CW_MAX_OFDM CW_MAX_OFDM +#define DEF_TX0_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) +#define DEF_TX1_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) +#define DEF_TX2_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) +#define DEF_TX3_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) -#define DEF_TX0_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX1_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX2_CW_MAX_CCK CW_MAX_CCK -#define DEF_TX3_CW_MAX_CCK CW_MAX_CCK +#define DEF_TX0_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) +#define DEF_TX1_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) +#define DEF_TX2_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) +#define DEF_TX3_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) #define DEF_TX0_AIFS 0 #define DEF_TX1_AIFS 0 @@ -389,18 +388,18 @@ struct clx2_queue { } __attribute__ ((packed)); struct machdr32 { - u16 frame_ctl; + __le16 frame_ctl; u16 duration; // watch out for endians! u8 addr1[MACADRR_BYTE_LEN]; u8 addr2[MACADRR_BYTE_LEN]; u8 addr3[MACADRR_BYTE_LEN]; u16 seq_ctrl; // more endians! u8 addr4[MACADRR_BYTE_LEN]; - u16 qos_ctrl; + __le16 qos_ctrl; } __attribute__ ((packed)); struct machdr30 { - u16 frame_ctl; + __le16 frame_ctl; u16 duration; // watch out for endians! u8 addr1[MACADRR_BYTE_LEN]; u8 addr2[MACADRR_BYTE_LEN]; @@ -410,17 +409,17 @@ struct machdr30 { } __attribute__ ((packed)); struct machdr26 { - u16 frame_ctl; + __le16 frame_ctl; u16 duration; // watch out for endians! u8 addr1[MACADRR_BYTE_LEN]; u8 addr2[MACADRR_BYTE_LEN]; u8 addr3[MACADRR_BYTE_LEN]; u16 seq_ctrl; // more endians! - u16 qos_ctrl; + __le16 qos_ctrl; } __attribute__ ((packed)); struct machdr24 { - u16 frame_ctl; + __le16 frame_ctl; u16 duration; // watch out for endians! u8 addr1[MACADRR_BYTE_LEN]; u8 addr2[MACADRR_BYTE_LEN]; @@ -467,15 +466,15 @@ struct tfd_command { struct tfd_data { /* Header */ - u32 work_area_ptr; + __le32 work_area_ptr; u8 station_number; /* 0 for BSS */ u8 reserved1; - u16 reserved2; + __le16 reserved2; /* Tx Parameters */ u8 cmd_id; u8 seq_num; - u16 len; + __le16 len; u8 priority; u8 tx_flags; u8 tx_flags_ext; @@ -483,11 +482,11 @@ struct tfd_data { u8 wepkey[DCT_WEP_KEY_FIELD_LENGTH]; u8 rate; u8 antenna; - u16 next_packet_duration; - u16 next_frag_len; - u16 back_off_counter; //////txop; + __le16 next_packet_duration; + __le16 next_frag_len; + __le16 back_off_counter; //////txop; u8 retrylimit; - u16 cwcurrent; + __le16 cwcurrent; u8 reserved3; /* 802.11 MAC Header */ @@ -499,9 +498,9 @@ struct tfd_data { } tfd; /* Payload DMA info */ - u32 num_chunks; - u32 chunk_ptr[NUM_TFD_CHUNKS]; - u16 chunk_len[NUM_TFD_CHUNKS]; + __le32 num_chunks; + __le32 chunk_ptr[NUM_TFD_CHUNKS]; + __le16 chunk_len[NUM_TFD_CHUNKS]; } __attribute__ ((packed)); struct txrx_control_flags { @@ -548,14 +547,14 @@ struct clx2_tx_queue { // Used for passing to driver number of successes and failures per rate struct rate_histogram { union { - u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; + __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; + __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; + __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; } success; union { - u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; + __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; + __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; + __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; } failed; } __attribute__ ((packed)); @@ -603,13 +602,13 @@ struct notif_scan_complete { } __attribute__ ((packed)); struct notif_frag_length { - u16 frag_length; - u16 reserved; + __le16 frag_length; + __le16 reserved; } __attribute__ ((packed)); struct notif_beacon_state { - u32 state; - u32 number; + __le32 state; + __le32 number; } __attribute__ ((packed)); struct notif_tgi_tx_key { @@ -628,7 +627,7 @@ struct notif_link_deterioration { u8 modulation; struct rate_histogram histogram; u8 silence_notification_type; /* SILENCE_OVER/UNDER_THRESH */ - u16 silence_count; + __le16 silence_count; } __attribute__ ((packed)); struct notif_association { @@ -646,14 +645,14 @@ struct notif_calibration { } __attribute__ ((packed)); struct notif_noise { - u32 value; + __le32 value; } __attribute__ ((packed)); struct ipw_rx_notification { u8 reserved[8]; u8 subtype; u8 flags; - u16 size; + __le16 size; union { struct notif_association assoc; struct notif_authenticate auth; @@ -670,7 +669,7 @@ struct ipw_rx_notification { } __attribute__ ((packed)); struct ipw_rx_frame { - u32 reserved1; + __le32 reserved1; u8 parent_tsf[4]; // fw_use[0] is boolean for OUR_TSF_IS_GREATER u8 received_channel; // The channel that this frame was received on. // Note that for .11b this does not have to be @@ -681,14 +680,14 @@ struct ipw_rx_frame { u8 rssi; u8 agc; u8 rssi_dbm; - u16 signal; - u16 noise; + __le16 signal; + __le16 noise; u8 antennaAndPhy; u8 control; // control bit should be on in bg u8 rtscts_rate; // rate of rts or cts (in rts cts sequence rate // is identical) u8 rtscts_seen; // 0x1 RTS seen ; 0x2 CTS seen - u16 length; + __le16 length; u8 data[0]; } __attribute__ ((packed)); @@ -828,14 +827,14 @@ struct ipw_tgi_tx_key { u8 station_index; u8 flags; u8 key[16]; - u32 tx_counter[2]; + __le32 tx_counter[2]; } __attribute__ ((packed)); #define IPW_SCAN_CHANNELS 54 struct ipw_scan_request { u8 scan_type; - u16 dwell_time; + __le16 dwell_time; u8 channels_list[IPW_SCAN_CHANNELS]; u8 channels_reserved[3]; } __attribute__ ((packed)); @@ -850,11 +849,11 @@ enum { }; struct ipw_scan_request_ext { - u32 full_scan_index; + __le32 full_scan_index; u8 channels_list[IPW_SCAN_CHANNELS]; u8 scan_type[IPW_SCAN_CHANNELS / 2]; u8 reserved; - u16 dwell_time[IPW_SCAN_TYPES]; + __le16 dwell_time[IPW_SCAN_TYPES]; } __attribute__ ((packed)); static inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index) @@ -882,20 +881,20 @@ struct ipw_associate { u8 auth_type:4, auth_key:4; u8 assoc_type; u8 reserved; - u16 policy_support; + __le16 policy_support; u8 preamble_length; u8 ieee_mode; u8 bssid[ETH_ALEN]; - u32 assoc_tsf_msw; - u32 assoc_tsf_lsw; - u16 capability; - u16 listen_interval; - u16 beacon_interval; + __le32 assoc_tsf_msw; + __le32 assoc_tsf_lsw; + __le16 capability; + __le16 listen_interval; + __le16 beacon_interval; u8 dest[ETH_ALEN]; - u16 atim_window; + __le16 atim_window; u8 smr; u8 reserved1; - u16 reserved2; + __le16 reserved2; } __attribute__ ((packed)); struct ipw_supported_rates { @@ -907,13 +906,13 @@ struct ipw_supported_rates { } __attribute__ ((packed)); struct ipw_rts_threshold { - u16 rts_threshold; - u16 reserved; + __le16 rts_threshold; + __le16 reserved; } __attribute__ ((packed)); struct ipw_frag_threshold { - u16 frag_threshold; - u16 reserved; + __le16 frag_threshold; + __le16 reserved; } __attribute__ ((packed)); struct ipw_retry_limit { @@ -932,7 +931,7 @@ struct ipw_dino_config { struct ipw_aironet_info { u8 id; u8 length; - u16 reserved; + __le16 reserved; } __attribute__ ((packed)); struct ipw_rx_key { @@ -978,12 +977,12 @@ struct ipw_tx_power { struct ipw_rsn_capabilities { u8 id; u8 length; - u16 version; + __le16 version; } __attribute__ ((packed)); struct ipw_sensitivity_calib { - u16 beacon_rssi_raw; - u16 reserved; + __le16 beacon_rssi_raw; + __le16 reserved; } __attribute__ ((packed)); /** @@ -1157,8 +1156,8 @@ struct ipw_rt_hdr { u64 rt_tsf; /* TSF */ u8 rt_flags; /* radiotap packet flags */ u8 rt_rate; /* rate in 500kb/s */ - u16 rt_channel; /* channel in mhz */ - u16 rt_chbitmask; /* channel bitfield */ + __le16 rt_channel; /* channel in mhz */ + __le16 rt_chbitmask; /* channel bitfield */ s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ s8 rt_dbmnoise; u8 rt_antenna; /* antenna number */ @@ -1288,6 +1287,8 @@ struct ipw_priv { struct iw_public_data wireless_data; + int user_requested_scan; + struct workqueue_struct *workqueue; struct work_struct adhoc_check; @@ -1296,6 +1297,7 @@ struct ipw_priv { struct work_struct system_config; struct work_struct rx_replenish; struct work_struct request_scan; + struct work_struct scan_event; struct work_struct request_passive_scan; struct work_struct adapter_restart; struct work_struct rf_kill; @@ -1757,7 +1759,7 @@ enum { #define HC_IBSS_RECONF 4 #define HC_DISASSOC_QUIET 5 -#define HC_QOS_SUPPORT_ASSOC 0x01 +#define HC_QOS_SUPPORT_ASSOC cpu_to_le16(0x01) #define IPW_RATE_CAPABILITIES 1 #define IPW_RATE_CONNECT 0