Portions of this file are based on the Host AP project,
Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- <jkmaline@cc.hut.fi>
- Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ <j@w1.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
Portions of ipw2100_mod_firmware_load, ipw2100_do_mod_firmware_load, and
ipw2100_fw_load are loosely based on drivers/sound/sound_firmware.c
#include <linux/firmware.h>
#include <linux/acpi.h>
#include <linux/ctype.h>
-#include <linux/latency.h>
+#include <linux/pm_qos_params.h>
#include "ipw2100.h"
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... */
if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)
break;
- } while (i--);
+ } while (--i);
priv->status &= ~STATUS_RESET_PENDING;
/* the ipw2100 hardware really doesn't want power management delays
* longer than 175usec
*/
- modify_acceptable_latency("ipw2100", 175);
+ pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
/* If the interrupt is enabled, turn it off... */
spin_lock_irqsave(&priv->low_lock, flags);
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;
ipw2100_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->low_lock, flags);
- modify_acceptable_latency("ipw2100", INFINITE_LATENCY);
-
-#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
+ pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
+ PM_QOS_DEFAULT_VALUE);
/* We have to signal any supplicant if we are disassociating */
if (associated)
u32 chan;
char *txratename;
u8 bssid[ETH_ALEN];
+ DECLARE_MAC_BUF(mac);
/*
* TBD: BSSID is usually 00:00:00:00:00:00 here and not
}
IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID="
- MAC_FMT ")\n",
+ "%s)\n",
priv->net_dev->name, escape_essid(essid, essid_len),
- txratename, chan, MAC_ARG(bssid));
+ txratename, chan, print_mac(mac, bssid));
/* now we copy read ssid into dev */
if (!(priv->config & CFG_STATIC_ESSID)) {
static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
{
+ DECLARE_MAC_BUF(mac);
+
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
- "disassociated: '%s' " MAC_FMT " \n",
+ "disassociated: '%s' %s \n",
escape_essid(priv->essid, priv->essid_len),
- MAC_ARG(priv->bssid));
+ print_mac(mac, priv->bssid));
priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
/* 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 work_struct *work)
+{
+ send_scan_event(container_of(work, struct ipw2100_priv,
+ scan_event_later.work));
+}
+
+static void ipw2100_scan_event_now(struct work_struct *work)
+{
+ send_scan_event(container_of(work, struct ipw2100_priv,
+ scan_event_now));
}
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
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,
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;
#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;
#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);
char *out = buf;
int length;
int ret;
+ DECLARE_MAC_BUF(mac);
if (priv->status & STATUS_RF_KILL_MASK)
return 0;
__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: %s\n", print_mac(mac, bssid));
out += sprintf(out, "Channel: %d\n", chan);
return out - buf;
/* 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);
}
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;
}
static int ipw2100_read_mac_address(struct ipw2100_priv *priv)
{
u32 length = ETH_ALEN;
- u8 mac[ETH_ALEN];
+ u8 addr[ETH_ALEN];
+ DECLARE_MAC_BUF(mac);
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 %s\n",
+ print_mac(mac, priv->net_dev->dev_addr));
return 0;
}
int err;
#ifdef CONFIG_IPW2100_DEBUG
+ DECLARE_MAC_BUF(mac);
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: %s\n",
+ print_mac(mac, bssid));
else
IPW_DEBUG_HC("MANDATORY_BSSID: <clear>\n");
#endif
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;
}
* 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 */
INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work);
INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check);
INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill);
+ INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now);
+ INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later);
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
ipw2100_irq_tasklet, (unsigned long)priv);
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");
if (ret)
goto out;
- set_acceptable_latency("ipw2100", INFINITE_LATENCY);
+ pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
+ PM_QOS_DEFAULT_VALUE);
#ifdef CONFIG_IPW2100_DEBUG
ipw2100_debug_level = debug;
ret = driver_create_file(&ipw2100_pci_driver.driver,
&driver_attr_debug_level);
#endif
pci_unregister_driver(&ipw2100_pci_driver);
- remove_acceptable_latency("ipw2100");
+ pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
}
module_init(ipw2100_init);
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,
static const unsigned char off[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+ DECLARE_MAC_BUF(mac);
// sanity checks
if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
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 -> %s\n",
+ print_mac(mac, wrqu->ap_addr.sa_data));
done:
mutex_unlock(&priv->action_mutex);
*/
struct ipw2100_priv *priv = ieee80211_priv(dev);
+ DECLARE_MAC_BUF(mac);
/* If we are associated, trying to associate, or have a statically
* configured BSSID then return that; otherwise return ANY */
} else
memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
- IPW_DEBUG_WX("Getting WAP BSSID: " MAC_FMT "\n",
- MAC_ARG(wrqu->ap_addr.sa_data));
+ IPW_DEBUG_WX("Getting WAP BSSID: %s\n",
+ print_mac(mac, wrqu->ap_addr.sa_data));
return 0;
}
}
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");
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",
{
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);
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);
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;
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,