Commit a613bffd authored by James Ketrenos's avatar James Ketrenos

Catch ipw2200 up to equivelancy with v1.0.2

Removed unneeded parenthesis around numeric constant defines

Added support for iwspy

Put in fix for Ad-Hoc mode not passing through all packets (thanks to KKH)

Put in fix for fragmentation not working for fragment sizes between
441-464 bytes (thanks to Mohamed Abbas)

Fixed #592 problem of CONFIG_IEEE80211_WPA_MODULE not including WPA
support into the driver -- fixed as a result of no longer limiting WPAs
inclusion

Fixed #594 problem with user rates mask causing lack of association if
AP mandatory rate is masked out.  We now add back in as a supported rate
any mandatory rate.

Fixed #597 kernel oops due to calling dev_kfree_skb on an skb multiple times.

Added code to control LEDs that can be controlled through the wireless
NIC (vs. non-wireless HW interfaces) -- this is currently disabled by
default due to reports by some users of it hanging their laptop.

Added some more debug messages around fragmentation logic

Added locking around STATUS_HCMD_ACTIVE to prevent re-entry race
conditions

Moved ipw_adapter_restart to only execute on the priv->workqueue to
keep keyboard errors from occuring during adapter restart

Added CFG_BACKGROUND_SCAN to easily allow people to play with
background scanning implementations

Modified WPA logic to send WPA IE if one is set (vs. being based on
wpa_enabled)

Modified scan result logic to report WPA and RSN IEs if set (vs. being
based on wpa_enabled)

Fixed issues with endianess compatability between the host and
wireless adapter (thanks to York Liu and Yi Zhu)

Fixed problem with Ad-Hoc network creation causing a firmware error if
a scan was actively running (thanks to Mohamed Abbas)
Signed-off-by: default avatarJames Ketrenos <jketreno@linux.intel.com>
parent ea2b26e0
......@@ -32,7 +32,7 @@
#include "ipw2200.h"
#define IPW2200_VERSION "1.0.1"
#define IPW2200_VERSION "1.0.2"
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation"
#define DRV_VERSION IPW2200_VERSION
......@@ -49,6 +49,7 @@ static int mode = 0;
static u32 ipw_debug_level;
static int associate = 1;
static int auto_create = 1;
static int led = 0;
static int disable = 0;
static const char ipw_modes[] = {
'a', 'b', 'g', '?'
......@@ -637,6 +638,313 @@ static void ipw_init_ordinals(struct ipw_priv *priv)
}
u32 ipw_register_toggle(u32 reg)
{
reg &= ~CX2_START_STANDBY;
if (reg & CX2_GATE_ODMA)
reg &= ~CX2_GATE_ODMA;
if (reg & CX2_GATE_IDMA)
reg &= ~CX2_GATE_IDMA;
if (reg & CX2_GATE_ADMA)
reg &= ~CX2_GATE_ADMA;
return reg;
}
/*
* LED behavior:
* - On radio ON, turn on any LEDs that require to be on during start
* - On initialization, start unassociated blink
* - On association, disable unassociated blink
* - On disassociation, start unassociated blink
* - On radio OFF, turn off any LEDs started during radio on
*
*/
#define LD_TIME_LINK_ON 300
#define LD_TIME_LINK_OFF 2700
#define LD_TIME_ACT_ON 250
void ipw_led_link_on(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
/* If configured to not use LEDs, or nic_type is 1,
* then we don't toggle a LINK led */
if (priv->config & CFG_NO_LED || priv->nic_type == EEPROM_NIC_TYPE_1)
return;
spin_lock_irqsave(&priv->lock, flags);
if (!(priv->status & STATUS_RF_KILL_MASK) &&
!(priv->status & STATUS_LED_LINK_ON)) {
IPW_DEBUG_LED("Link LED On\n");
led = ipw_read_reg32(priv, CX2_EVENT_REG);
led |= priv->led_association_on;
led = ipw_register_toggle(led);
IPW_DEBUG_LED("Reg: 0x%08X\n", led);
ipw_write_reg32(priv, CX2_EVENT_REG, led);
priv->status |= STATUS_LED_LINK_ON;
/* If we aren't associated, schedule turning the LED off */
if (!(priv->status & STATUS_ASSOCIATED))
queue_delayed_work(priv->workqueue,
&priv->led_link_off,
LD_TIME_LINK_ON);
}
spin_unlock_irqrestore(&priv->lock, flags);
}
void ipw_led_link_off(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
/* If configured not to use LEDs, or nic type is 1,
* then we don't goggle the LINK led. */
if (priv->config & CFG_NO_LED || priv->nic_type == EEPROM_NIC_TYPE_1)
return;
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_LED_LINK_ON) {
led = ipw_read_reg32(priv, CX2_EVENT_REG);
led &= priv->led_association_off;
led = ipw_register_toggle(led);
IPW_DEBUG_LED("Reg: 0x%08X\n", led);
ipw_write_reg32(priv, CX2_EVENT_REG, led);
IPW_DEBUG_LED("Link LED Off\n");
priv->status &= ~STATUS_LED_LINK_ON;
/* If we aren't associated and the radio is on, schedule
* turning the LED on (blink while unassociated) */
if (!(priv->status & STATUS_RF_KILL_MASK) &&
!(priv->status & STATUS_ASSOCIATED))
queue_delayed_work(priv->workqueue, &priv->led_link_on,
LD_TIME_LINK_OFF);
}
spin_unlock_irqrestore(&priv->lock, flags);
}
void ipw_led_activity_on(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
if (priv->config & CFG_NO_LED)
return;
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_RF_KILL_MASK) {
spin_unlock_irqrestore(&priv->lock, flags);
return;
}
if (!(priv->status & STATUS_LED_ACT_ON)) {
led = ipw_read_reg32(priv, CX2_EVENT_REG);
led |= priv->led_activity_on;
led = ipw_register_toggle(led);
IPW_DEBUG_LED("Reg: 0x%08X\n", led);
ipw_write_reg32(priv, CX2_EVENT_REG, led);
IPW_DEBUG_LED("Activity LED On\n");
priv->status |= STATUS_LED_ACT_ON;
queue_delayed_work(priv->workqueue, &priv->led_act_off,
LD_TIME_ACT_ON);
} else {
/* Reschedule LED off for full time period */
cancel_delayed_work(&priv->led_act_off);
queue_delayed_work(priv->workqueue, &priv->led_act_off,
LD_TIME_ACT_ON);
}
spin_unlock_irqrestore(&priv->lock, flags);
}
void ipw_led_activity_off(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
if (priv->config & CFG_NO_LED)
return;
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_LED_ACT_ON) {
led = ipw_read_reg32(priv, CX2_EVENT_REG);
led &= priv->led_activity_off;
led = ipw_register_toggle(led);
IPW_DEBUG_LED("Reg: 0x%08X\n", led);
ipw_write_reg32(priv, CX2_EVENT_REG, led);
IPW_DEBUG_LED("Activity LED Off\n");
priv->status &= ~STATUS_LED_ACT_ON;
}
spin_unlock_irqrestore(&priv->lock, flags);
}
void ipw_led_band_on(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
/* Only nic type 1 supports mode LEDs */
if (priv->config & CFG_NO_LED || priv->nic_type != EEPROM_NIC_TYPE_1)
return;
spin_lock_irqsave(&priv->lock, flags);
led = ipw_read_reg32(priv, CX2_EVENT_REG);
if (priv->assoc_network->mode == IEEE_A) {
led |= priv->led_ofdm_on;
led &= priv->led_association_off;
IPW_DEBUG_LED("Mode LED On: 802.11a\n");
} else if (priv->assoc_network->mode == IEEE_G) {
led |= priv->led_ofdm_on;
led |= priv->led_association_on;
IPW_DEBUG_LED("Mode LED On: 802.11g\n");
} else {
led &= priv->led_ofdm_off;
led |= priv->led_association_on;
IPW_DEBUG_LED("Mode LED On: 802.11b\n");
}
led = ipw_register_toggle(led);
IPW_DEBUG_LED("Reg: 0x%08X\n", led);
ipw_write_reg32(priv, CX2_EVENT_REG, led);
spin_unlock_irqrestore(&priv->lock, flags);
}
void ipw_led_band_off(struct ipw_priv *priv)
{
unsigned long flags;
u32 led;
/* Only nic type 1 supports mode LEDs */
if (priv->config & CFG_NO_LED || priv->nic_type != EEPROM_NIC_TYPE_1)
return;
spin_lock_irqsave(&priv->lock, flags);
led = ipw_read_reg32(priv, CX2_EVENT_REG);
led &= priv->led_ofdm_off;
led &= priv->led_association_off;
led = ipw_register_toggle(led);
IPW_DEBUG_LED("Reg: 0x%08X\n", led);
ipw_write_reg32(priv, CX2_EVENT_REG, led);
spin_unlock_irqrestore(&priv->lock, flags);
}
void ipw_led_radio_on(struct ipw_priv *priv)
{
ipw_led_link_on(priv);
}
void ipw_led_radio_off(struct ipw_priv *priv)
{
ipw_led_activity_off(priv);
ipw_led_link_off(priv);
}
void ipw_led_link_up(struct ipw_priv *priv)
{
/* Set the Link Led on for all nic types */
ipw_led_link_on(priv);
}
void ipw_led_link_down(struct ipw_priv *priv)
{
ipw_led_activity_off(priv);
ipw_led_link_off(priv);
if (priv->status & STATUS_RF_KILL_MASK)
ipw_led_radio_off(priv);
}
void ipw_led_init(struct ipw_priv *priv)
{
priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE];
/* Set the default PINs for the link and activity leds */
priv->led_activity_on = CX2_ACTIVITY_LED;
priv->led_activity_off = ~(CX2_ACTIVITY_LED);
priv->led_association_on = CX2_ASSOCIATED_LED;
priv->led_association_off = ~(CX2_ASSOCIATED_LED);
/* Set the default PINs for the OFDM leds */
priv->led_ofdm_on = CX2_OFDM_LED;
priv->led_ofdm_off = ~(CX2_OFDM_LED);
switch (priv->nic_type) {
case EEPROM_NIC_TYPE_1:
/* In this NIC type, the LEDs are reversed.... */
priv->led_activity_on = CX2_ASSOCIATED_LED;
priv->led_activity_off = ~(CX2_ASSOCIATED_LED);
priv->led_association_on = CX2_ACTIVITY_LED;
priv->led_association_off = ~(CX2_ACTIVITY_LED);
if (!(priv->config & CFG_NO_LED))
ipw_led_band_on(priv);
/* And we don't blink link LEDs for this nic, so
* just return here */
return;
case EEPROM_NIC_TYPE_3:
case EEPROM_NIC_TYPE_2:
case EEPROM_NIC_TYPE_4:
case EEPROM_NIC_TYPE_0:
break;
default:
IPW_DEBUG_INFO("Unknown NIC type from EEPROM: %d\n",
priv->nic_type);
priv->nic_type = EEPROM_NIC_TYPE_0;
break;
}
if (!(priv->config & CFG_NO_LED)) {
if (priv->status & STATUS_ASSOCIATED)
ipw_led_link_on(priv);
else
ipw_led_link_off(priv);
}
}
void ipw_led_shutdown(struct ipw_priv *priv)
{
cancel_delayed_work(&priv->led_link_on);
cancel_delayed_work(&priv->led_link_off);
cancel_delayed_work(&priv->led_act_off);
ipw_led_activity_off(priv);
ipw_led_link_off(priv);
ipw_led_band_off(priv);
}
/*
* The following adds a new attribute to the sysfs representation
* of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/)
......@@ -648,8 +956,9 @@ static ssize_t show_debug_level(struct device_driver *d, char *buf)
{
return sprintf(buf, "0x%08X\n", ipw_debug_level);
}
static ssize_t store_debug_level(struct device_driver *d,
const char *buf, size_t count)
static ssize_t store_debug_level(struct device_driver *d, const char *buf,
size_t count)
{
char *p = (char *)buf;
u32 val;
......@@ -673,6 +982,82 @@ static ssize_t store_debug_level(struct device_driver *d,
static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
show_debug_level, store_debug_level);
static ssize_t show_scan_age(struct device *d, struct device_attribute *attr,
char *buf)
{
struct ipw_priv *priv = dev_get_drvdata(d);
return sprintf(buf, "%d\n", priv->ieee->scan_age);
}
static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
const char *buf, size_t count)
{
struct ipw_priv *priv = dev_get_drvdata(d);
struct net_device *dev = priv->net_dev;
char buffer[] = "00000000";
unsigned long len =
(sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1;
unsigned long val;
char *p = buffer;
IPW_DEBUG_INFO("enter\n");
strncpy(buffer, buf, len);
buffer[len] = 0;
if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
p++;
if (p[0] == 'x' || p[0] == 'X')
p++;
val = simple_strtoul(p, &p, 16);
} else
val = simple_strtoul(p, &p, 10);
if (p == buffer) {
IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name);
} else {
priv->ieee->scan_age = val;
IPW_DEBUG_INFO("set scan_age = %u\n", priv->ieee->scan_age);
}
IPW_DEBUG_INFO("exit\n");
return len;
}
static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age);
static ssize_t show_led(struct device *d, struct device_attribute *attr,
char *buf)
{
struct ipw_priv *priv = dev_get_drvdata(d);
return sprintf(buf, "%d\n", (priv->config & CFG_NO_LED) ? 0 : 1);
}
static ssize_t store_led(struct device *d, struct device_attribute *attr,
const char *buf, size_t count)
{
struct ipw_priv *priv = dev_get_drvdata(d);
IPW_DEBUG_INFO("enter\n");
if (count == 0)
return 0;
if (*buf == 0) {
IPW_DEBUG_LED("Disabling LED control.\n");
priv->config |= CFG_NO_LED;
ipw_led_shutdown(priv);
} else {
IPW_DEBUG_LED("Enabling LED control.\n");
priv->config &= ~CFG_NO_LED;
ipw_led_init(priv);
}
IPW_DEBUG_INFO("exit\n");
return count;
}
static DEVICE_ATTR(led, S_IWUSR | S_IRUGO, show_led, store_led);
static ssize_t show_status(struct device *d,
struct device_attribute *attr, char *buf)
{
......@@ -694,23 +1079,8 @@ static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL);
static ssize_t show_nic_type(struct device *d,
struct device_attribute *attr, char *buf)
{
struct ipw_priv *p = d->driver_data;
u8 type = p->eeprom[EEPROM_NIC_TYPE];
switch (type) {
case EEPROM_NIC_TYPE_STANDARD:
return sprintf(buf, "STANDARD\n");
case EEPROM_NIC_TYPE_DELL:
return sprintf(buf, "DELL\n");
case EEPROM_NIC_TYPE_FUJITSU:
return sprintf(buf, "FUJITSU\n");
case EEPROM_NIC_TYPE_IBM:
return sprintf(buf, "IBM\n");
case EEPROM_NIC_TYPE_HP:
return sprintf(buf, "HP\n");
}
return sprintf(buf, "UNKNOWN\n");
struct ipw_priv *priv = d->driver_data;
return sprintf(buf, "TYPE: %d\n", priv->nic_type);
}
static DEVICE_ATTR(nic_type, S_IRUGO, show_nic_type, NULL);
......@@ -955,9 +1325,8 @@ 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);
}
wake_up_interruptible(&priv->wait_command_queue);
queue_work(priv->workqueue, &priv->down);
} else {
......@@ -1081,11 +1450,9 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
IPW_DEBUG_RF_KILL("RF_KILL_DONE\n");
priv->status |= STATUS_RF_KILL_HW;
wake_up_interruptible(&priv->wait_command_queue);
netif_carrier_off(priv->net_dev);
netif_stop_queue(priv->net_dev);
priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
notify_wx_assoc_event(priv);
cancel_delayed_work(&priv->request_scan);
schedule_work(&priv->link_down);
queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
handled |= CX2_INTA_BIT_RF_KILL_DONE;
}
......@@ -1182,9 +1549,12 @@ static char *get_cmd_string(u8 cmd)
static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
{
int rc = 0;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_HCMD_ACTIVE) {
IPW_ERROR("Already sending a command\n");
spin_unlock_irqrestore(&priv->lock, flags);
return -1;
}
......@@ -1195,19 +1565,30 @@ static int ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len);
rc = ipw_queue_tx_hcmd(priv, cmd->cmd, &cmd->param, cmd->len, 0);
if (rc)
if (rc) {
priv->status &= ~STATUS_HCMD_ACTIVE;
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
spin_unlock_irqrestore(&priv->lock, flags);
rc = wait_event_interruptible_timeout(priv->wait_command_queue,
!(priv->
status & STATUS_HCMD_ACTIVE),
HOST_COMPLETE_TIMEOUT);
if (rc == 0) {
IPW_DEBUG_INFO("Command completion failed out after %dms.\n",
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_HCMD_ACTIVE) {
IPW_DEBUG_INFO("Command completion failed out after "
"%dms.\n",
1000 * (HOST_COMPLETE_TIMEOUT / HZ));
priv->status &= ~STATUS_HCMD_ACTIVE;
spin_unlock_irqrestore(&priv->lock, flags);
return -EIO;
}
spin_unlock_irqrestore(&priv->lock, flags);
}
if (priv->status & STATUS_RF_KILL_MASK) {
IPW_DEBUG_INFO("Command aborted due to RF Kill Switch\n");
return -EIO;
......@@ -1304,6 +1685,11 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
return 0;
}
/*
* NOTE: This must be executed from our workqueue as it results in udelay
* being called which may corrupt the keyboard if executed on default
* workqueue
*/
static void ipw_adapter_restart(void *adapter)
{
struct ipw_priv *priv = adapter;
......@@ -1327,7 +1713,7 @@ static void ipw_scan_check(void *data)
IPW_DEBUG_SCAN("Scan completion watchdog resetting "
"adapter (%dms).\n",
IPW_SCAN_CHECK_WATCHDOG / 100);
ipw_adapter_restart(priv);
queue_work(priv->workqueue, &priv->adapter_restart);
}
}
......@@ -1400,12 +1786,25 @@ static int ipw_send_associate(struct ipw_priv *priv,
.len = sizeof(*associate)
};
struct ipw_associate tmp_associate;
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);
if (!priv || !associate) {
IPW_ERROR("Invalid args\n");
return -1;
}
memcpy(&cmd.param, associate, sizeof(*associate));
memcpy(&cmd.param, &tmp_associate, sizeof(*associate));
if (ipw_send_cmd(priv, &cmd)) {
IPW_ERROR("failed to send ASSOCIATE command\n");
return -1;
......@@ -1706,7 +2105,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv)
/* read entire contents of eeprom into private buffer */
for (i = 0; i < 128; i++)
eeprom[i] = eeprom_read_u16(priv, (u8) i);
eeprom[i] = le16_to_cpu(eeprom_read_u16(priv, (u8) i));
/*
If the data looks correct, then copy it to our private
......@@ -2001,6 +2400,9 @@ static void ipw_remove_current_network(struct ipw_priv *priv)
{
struct list_head *element, *safe;
struct ieee80211_network *network = NULL;
unsigned long flags;
spin_lock_irqsave(&priv->ieee->lock, flags);
list_for_each_safe(element, safe, &priv->ieee->network_list) {
network = list_entry(element, struct ieee80211_network, list);
if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
......@@ -2009,6 +2411,7 @@ static void ipw_remove_current_network(struct ipw_priv *priv)
&priv->ieee->network_free_list);
}
}
spin_unlock_irqrestore(&priv->ieee->lock, flags);
}
/**
......@@ -2158,7 +2561,8 @@ 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, CX2_BASEBAND_CONTROL_STORE, image[i]);
ipw_write_reg16(priv, CX2_BASEBAND_CONTROL_STORE,
cpu_to_le16(image[i]));
/* enable DINO */
ipw_write_reg8(priv, CX2_BASEBAND_CONTROL_STATUS, 0);
......@@ -2181,7 +2585,8 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
for (i = 0; i < ARRAY_SIZE(response_buffer); i++)
response_buffer[i] =
ipw_read_reg32(priv, CX2_BASEBAND_RX_FIFO_READ);
le32_to_cpu(ipw_read_reg32(priv,
CX2_BASEBAND_RX_FIFO_READ));
memcpy(&priv->dino_alive, response_buffer,
sizeof(priv->dino_alive));
if (priv->dino_alive.alive_command == 1
......@@ -2250,13 +2655,14 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len)
* offeset*/
/* Dma loading */
rc = ipw_fw_dma_add_buffer(priv, shared_phys + offset,
chunk->address, chunk->length);
le32_to_cpu(chunk->address),
le32_to_cpu(chunk->length));
if (rc) {
IPW_DEBUG_INFO("dmaAddBuffer Failed\n");
goto out;
}
offset += chunk->length;
offset += le32_to_cpu(chunk->length);
} while (offset < len);
/* Run the DMA and wait for the answer */
......@@ -2351,14 +2757,17 @@ static int ipw_init_nic(struct ipw_priv *priv)
static int ipw_reset_nic(struct ipw_priv *priv)
{
int rc = 0;
unsigned long flags;
IPW_DEBUG_TRACE(">>\n");
rc = ipw_init_nic(priv);
spin_lock_irqsave(&priv->lock, flags);
/* Clear the 'host command active' bit... */
priv->status &= ~STATUS_HCMD_ACTIVE;
wake_up_interruptible(&priv->wait_command_queue);
spin_unlock_irqrestore(&priv->lock, flags);
IPW_DEBUG_TRACE("<<\n");
return rc;
......@@ -2378,17 +2787,18 @@ static int ipw_get_fw(struct ipw_priv *priv,
}
header = (struct fw_header *)(*fw)->data;
if (IPW_FW_MAJOR(header->version) != IPW_FW_MAJOR_VERSION) {
if (IPW_FW_MAJOR(le32_to_cpu(header->version)) != IPW_FW_MAJOR_VERSION) {
IPW_ERROR("'%s' firmware version not compatible (%d != %d)\n",
name,
IPW_FW_MAJOR(header->version), IPW_FW_MAJOR_VERSION);
IPW_FW_MAJOR(le32_to_cpu(header->version)),
IPW_FW_MAJOR_VERSION);
return -EINVAL;
}
IPW_DEBUG_INFO("Loading firmware '%s' file v%d.%d (%zd bytes)\n",
name,
IPW_FW_MAJOR(header->version),
IPW_FW_MINOR(header->version),
IPW_FW_MAJOR(le32_to_cpu(header->version)),
IPW_FW_MINOR(le32_to_cpu(header->version)),
(*fw)->size - sizeof(struct fw_header));
return 0;
}
......@@ -2414,6 +2824,7 @@ static inline void ipw_rx_queue_reset(struct ipw_priv *priv,
pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr,
CX2_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
dev_kfree_skb(rxq->pool[i].skb);
rxq->pool[i].skb = NULL;
}
list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
}
......@@ -2769,16 +3180,18 @@ static void ipw_queue_tx_free_tfd(struct ipw_priv *priv,
return;
/* sanity check */
if (bd->u.data.num_chunks > NUM_TFD_CHUNKS) {
IPW_ERROR("Too many chunks: %i\n", bd->u.data.num_chunks);
if (le32_to_cpu(bd->u.data.num_chunks) > NUM_TFD_CHUNKS) {
IPW_ERROR("Too many chunks: %i\n",
le32_to_cpu(bd->u.data.num_chunks));
/** @todo issue fatal error, it is quite serious situation */
return;
}
/* unmap chunks if any */
for (i = 0; i < bd->u.data.num_chunks; i++) {
pci_unmap_single(dev, bd->u.data.chunk_ptr[i],
bd->u.data.chunk_len[i], PCI_DMA_TODEVICE);
for (i = 0; i < le32_to_cpu(bd->u.data.num_chunks); i++) {
pci_unmap_single(dev, le32_to_cpu(bd->u.data.chunk_ptr[i]),
le16_to_cpu(bd->u.data.chunk_len[i]),
PCI_DMA_TODEVICE);
if (txq->txb[txq->q.last_used]) {
ieee80211_txb_free(txq->txb[txq->q.last_used]);
txq->txb[txq->q.last_used] = NULL;
......@@ -2841,10 +3254,9 @@ static void inline __maybe_wake_tx(struct ipw_priv *priv)
switch (priv->port_type) {
case DCR_TYPE_MU_BSS:
case DCR_TYPE_MU_IBSS:
if (!(priv->status & STATUS_ASSOCIATED)) {
if (!(priv->status & STATUS_ASSOCIATED))
return;
}
}
netif_wake_queue(priv->net_dev);
}
......@@ -3307,8 +3719,13 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
IPW_DL_STATE,
"Missed beacon: %d - disassociate\n", missed_count);
priv->status &= ~STATUS_ROAMING;
if (priv->status & STATUS_SCANNING)
if (priv->status & STATUS_SCANNING) {
IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF |
IPW_DL_STATE,
"Aborting scan with missed beacon.\n");
queue_work(priv->workqueue, &priv->abort_scan);
}
queue_work(priv->workqueue, &priv->disassociate);
return;
}
......@@ -3342,6 +3759,8 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
* stuck (only if we aren't roaming --
* otherwise we'll never scan more than 2 or 3
* channels..) */
IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF |
IPW_DL_STATE, "Aborting scan with missed beacon.\n");
queue_work(priv->workqueue, &priv->abort_scan);
}
......@@ -3356,6 +3775,8 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
static inline void ipw_rx_notification(struct ipw_priv *priv,
struct ipw_rx_notification *notif)
{
notif->size = le16_to_cpu(notif->size);
IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, notif->size);
switch (notif->subtype) {
......@@ -3400,29 +3821,8 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
priv->status &= ~STATUS_ASSOCIATING;
priv->status |= STATUS_ASSOCIATED;
netif_carrier_on(priv->net_dev);
if (netif_queue_stopped(priv->net_dev)) {
IPW_DEBUG_NOTIF
("waking queue\n");
netif_wake_queue(priv->net_dev);
} else {
IPW_DEBUG_NOTIF
("starting queue\n");
netif_start_queue(priv->
net_dev);
}
ipw_reset_stats(priv);
/* Ensure the rate is updated immediately */
priv->last_rate =
ipw_get_current_rate(priv);
schedule_work(&priv->gather_stats);
notify_wx_assoc_event(priv);
schedule_work(&priv->link_up);
/* queue_delayed_work(priv->workqueue,
&priv->request_scan,
SCAN_ASSOCIATED_INTERVAL);
*/
break;
}
......@@ -3455,12 +3855,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
STATUS_AUTH |
STATUS_ASSOCIATED);
netif_carrier_off(priv->
net_dev);
netif_stop_queue(priv->net_dev);
queue_work(priv->workqueue,
&priv->request_scan);
notify_wx_assoc_event(priv);
schedule_work(&priv->link_down);
break;
}
......@@ -3506,31 +3901,8 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
STATUS_ASSOCIATING |
STATUS_ASSOCIATED | STATUS_AUTH);
netif_stop_queue(priv->net_dev);
if (!(priv->status & STATUS_ROAMING)) {
netif_carrier_off(priv->
net_dev);
notify_wx_assoc_event(priv);
/* Cancel any queued work ... */
cancel_delayed_work(&priv->
request_scan);
cancel_delayed_work(&priv->
adhoc_check);
schedule_work(&priv->link_down);
/* Queue up another scan... */
queue_work(priv->workqueue,
&priv->request_scan);
cancel_delayed_work(&priv->
gather_stats);
} else {
priv->status |= STATUS_ROAMING;
queue_work(priv->workqueue,
&priv->request_scan);
}
ipw_reset_stats(priv);
break;
}
......@@ -3576,11 +3948,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
STATUS_AUTH |
STATUS_ASSOCIATED);
netif_carrier_off(priv->net_dev);
netif_stop_queue(priv->net_dev);
queue_work(priv->workqueue,
&priv->request_scan);
notify_wx_assoc_event(priv);
schedule_work(&priv->link_down);
break;
case CMAS_TX_AUTH_SEQ_1:
......@@ -3682,6 +4050,10 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
} else if (priv->status & STATUS_SCAN_PENDING)
queue_work(priv->workqueue,
&priv->request_scan);
else if (priv->config & CFG_BACKGROUND_SCAN
&& priv->status & STATUS_ASSOCIATED)
queue_delayed_work(priv->workqueue,
&priv->request_scan, HZ);
priv->ieee->scans++;
break;
......@@ -3690,13 +4062,13 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
case HOST_NOTIFICATION_STATUS_FRAG_LENGTH:{
struct notif_frag_length *x = &notif->u.frag_len;
if (notif->size == sizeof(*x)) {
IPW_ERROR("Frag length: %d\n", x->frag_length);
} else {
if (notif->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));
}
break;
}
......@@ -3722,11 +4094,9 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
case HOST_NOTIFICATION_DINO_CONFIG_RESPONSE:{
IPW_ERROR("Dino config\n");
if (priv->hcmd
&& priv->hcmd->cmd == HOST_CMD_DINO_CONFIG) {
/* TODO: Do anything special? */
} else {
&& priv->hcmd->cmd != HOST_CMD_DINO_CONFIG)
IPW_ERROR("Unexpected DINO_CONFIG_RESPONSE\n");
}
break;
}
......@@ -3739,8 +4109,11 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
break;
}
if (x->state == HOST_NOTIFICATION_STATUS_BEACON_MISSING)
ipw_handle_missed_beacon(priv, x->number);
if (le32_to_cpu(x->state) ==
HOST_NOTIFICATION_STATUS_BEACON_MISSING)
ipw_handle_missed_beacon(priv,
le32_to_cpu(x->
number));
break;
}
......@@ -3779,7 +4152,8 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
case HOST_NOTIFICATION_NOISE_STATS:{
if (notif->size == sizeof(u32)) {
priv->last_noise =
(u8) (notif->u.noise.value & 0xff);
(u8) (le32_to_cpu(notif->u.noise.value) &
0xff);
average_add(&priv->average_noise,
priv->last_noise);
break;
......@@ -3896,9 +4270,8 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
priv->tx_packets++;
}
done:
if (ipw_queue_space(q) > q->low_mark && qindex >= 0) {
if (ipw_queue_space(q) > q->low_mark && qindex >= 0)
__maybe_wake_tx(priv);
}
used = q->first_empty - q->last_used;
if (used < 0)
used += q->n_bd;
......@@ -4217,13 +4590,16 @@ static int ipw_compatible_rates(struct ipw_priv *priv,
num_rates = min(network->rates_len, (u8) IPW_MAX_RATES);
rates->num_rates = 0;
for (i = 0; i < num_rates; i++) {
if (!ipw_is_rate_in_mask
(priv, network->mode, network->rates[i])) {
if (!ipw_is_rate_in_mask(priv, network->mode,
network->rates[i])) {
if (network->rates[i] & IEEE80211_BASIC_RATE_MASK) {
IPW_DEBUG_SCAN
("Basic rate %02X masked: 0x%08X\n",
network->rates[i], priv->rates_mask);
return 0;
IPW_DEBUG_SCAN("Adding masked mandatory "
"rate %02X\n",
network->rates[i]);
rates->supported_rates[rates->num_rates++] =
network->rates[i];
continue;
}
IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n",
......@@ -4234,16 +4610,18 @@ static int ipw_compatible_rates(struct ipw_priv *priv,
rates->supported_rates[rates->num_rates++] = network->rates[i];
}
num_rates =
min(network->rates_ex_len, (u8) (IPW_MAX_RATES - num_rates));
num_rates = min(network->rates_ex_len,
(u8) (IPW_MAX_RATES - num_rates));
for (i = 0; i < num_rates; i++) {
if (!ipw_is_rate_in_mask
(priv, network->mode, network->rates_ex[i])) {
if (!ipw_is_rate_in_mask(priv, network->mode,
network->rates_ex[i])) {
if (network->rates_ex[i] & IEEE80211_BASIC_RATE_MASK) {
IPW_DEBUG_SCAN
("Basic rate %02X masked: 0x%08X\n",
network->rates_ex[i], priv->rates_mask);
return 0;
IPW_DEBUG_SCAN("Adding masked mandatory "
"rate %02X\n",
network->rates_ex[i]);
rates->supported_rates[rates->num_rates++] =
network->rates[i];
continue;
}
IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n",
......@@ -4531,9 +4909,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
* FW fatal error.
*/
network->mode = is_valid_channel(priv->ieee->mode, priv->channel);
if (network->mode) {
network->channel = priv->channel;
} else {
if (!network->mode) {
IPW_WARNING("Overriding invalid channel\n");
if (priv->ieee->mode & IEEE_A) {
network->mode = IEEE_A;
......@@ -4572,10 +4948,8 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
network->beacon_interval = 100; /* Default */
network->listen_interval = 10; /* Default */
network->atim_window = 0; /* Default */
#ifdef CONFIG_IEEE80211_WPA
network->wpa_ie_len = 0;
network->rsn_ie_len = 0;
#endif /* CONFIG_IEEE80211_WPA */
}
static void ipw_send_wep_keys(struct ipw_priv *priv)
......@@ -4593,9 +4967,9 @@ static void ipw_send_wep_keys(struct ipw_priv *priv)
for (i = 0; i < 4; i++) {
key->key_index = i;
if (!(priv->sec.flags & (1 << i))) {
if (!(priv->sec.flags & (1 << i)))
key->key_size = 0;
} else {
else {
key->key_size = priv->sec.key_sizes[i];
memcpy(key->key, priv->sec.keys[i], key->key_size);
}
......@@ -4752,9 +5126,10 @@ static int ipw_request_scan(struct ipw_priv *priv)
}
if (priv->status & STATUS_SCANNING) {
IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n");
IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n");
// IPW_DEBUG_HC("Concurrent scan requested. Aborting first.\n");
priv->status |= STATUS_SCAN_PENDING;
ipw_abort_scan(priv);
// ipw_abort_scan(priv);
return 0;
}
......@@ -4772,11 +5147,12 @@ static int ipw_request_scan(struct ipw_priv *priv)
memset(&scan, 0, sizeof(scan));
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = 20;
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = 20;
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 20;
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = cpu_to_le16(20);
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] =
cpu_to_le16(20);
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20);
scan.full_scan_index = ieee80211_get_scans(priv->ieee);
scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
#ifdef CONFIG_IPW_MONITOR
if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
......@@ -4798,7 +5174,8 @@ static int ipw_request_scan(struct ipw_priv *priv)
ipw_set_scan_type(&scan, channel_index,
IPW_SCAN_PASSIVE_FULL_DWELL_SCAN);
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = 2000;
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
cpu_to_le16(2000);
} else {
#endif /* CONFIG_IPW_MONITOR */
/* If we are roaming, then make this a directed scan for the current
......@@ -4807,7 +5184,7 @@ static int ipw_request_scan(struct ipw_priv *priv)
if ((priv->status & STATUS_ROAMING)
|| (!(priv->status & STATUS_ASSOCIATED)
&& (priv->config & CFG_STATIC_ESSID)
&& (scan.full_scan_index % 2))) {
&& (le32_to_cpu(scan.full_scan_index) % 2))) {
err = ipw_send_ssid(priv, priv->essid, priv->essid_len);
if (err) {
IPW_DEBUG_HC
......@@ -4882,7 +5259,6 @@ static int ipw_request_scan(struct ipw_priv *priv)
/* Support for wpa_supplicant. Will be replaced with WEXT once
* they get WPA support. */
#ifdef CONFIG_IEEE80211_WPA
/* following definitions must match definitions in driver_ipw.c */
......@@ -4959,6 +5335,7 @@ static int ipw_wpa_enable(struct ipw_priv *priv, int value)
} else {
sec.level = SEC_LEVEL_0;
sec.enabled = 0;
ieee->wpa_ie_len = 0;
}
if (ieee->set_security)
......@@ -4999,6 +5376,8 @@ static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value)
static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value)
{
struct ipw_priv *priv = ieee80211_priv(dev);
struct ieee80211_crypt_data *crypt;
unsigned long flags;
int ret = 0;
switch (name) {
......@@ -5007,7 +5386,22 @@ static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value)
break;
case IPW_PARAM_TKIP_COUNTERMEASURES:
priv->ieee->tkip_countermeasures = value;
crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) {
IPW_WARNING("Can't set TKIP countermeasures: "
"crypt not set!\n");
break;
}
flags = crypt->ops->get_flags(crypt->priv);
if (value)
flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
else
flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
crypt->ops->set_flags(flags, crypt->priv);
break;
case IPW_PARAM_DROP_UNENCRYPTED:
......@@ -5313,7 +5707,6 @@ static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p)
kfree(param);
return ret;
}
#endif /* CONFIG_IEEE80211_WPA */
static int ipw_associate_network(struct ipw_priv *priv,
struct ieee80211_network *network,
......@@ -5346,13 +5739,11 @@ static int ipw_associate_network(struct ipw_priv *priv,
if (priv->capability & CAP_PRIVACY_ON)
ipw_send_wep_keys(priv);
#ifdef CONFIG_IEEE80211_WPA
if (priv->ieee->wpa_enabled) {
if (priv->ieee->wpa_ie_len) {
priv->assoc_request.policy_support = 0x02; /* RSN active */
ipw_set_rsn_capa(priv, priv->ieee->wpa_ie,
priv->ieee->wpa_ie_len);
}
#endif
/*
* It is valid for our ieee device to support multiple modes, but
......@@ -5511,12 +5902,15 @@ static void ipw_roam(void *data)
if (priv->status & STATUS_ASSOCIATED) {
/* First pass through ROAM process -- look for a better
* network */
unsigned long flags;
u8 rssi = priv->assoc_network->stats.rssi;
priv->assoc_network->stats.rssi = -128;
spin_lock_irqsave(&priv->ieee->lock, flags);
list_for_each_entry(network, &priv->ieee->network_list, list) {
if (network != priv->assoc_network)
ipw_best_network(priv, &match, network, 1);
}
spin_unlock_irqrestore(&priv->ieee->lock, flags);
priv->assoc_network->stats.rssi = rssi;
if (match.network == priv->assoc_network) {
......@@ -5549,6 +5943,7 @@ static void ipw_associate(void *data)
};
struct ipw_supported_rates *rates;
struct list_head *element;
unsigned long flags;
if (!(priv->config & CFG_ASSOCIATE) &&
!(priv->config & (CFG_STATIC_ESSID |
......@@ -5557,6 +5952,8 @@ static void ipw_associate(void *data)
return;
}
/* Protect our use of the network_list */
spin_lock_irqsave(&priv->ieee->lock, flags);
list_for_each_entry(network, &priv->ieee->network_list, list)
ipw_best_network(priv, &match, network, 0);
......@@ -5567,6 +5964,7 @@ static void ipw_associate(void *data)
priv->ieee->iw_mode == IW_MODE_ADHOC &&
priv->config & CFG_ADHOC_CREATE &&
priv->config & CFG_STATIC_ESSID &&
priv->config & CFG_STATIC_CHANNEL &&
!list_empty(&priv->ieee->network_free_list)) {
element = priv->ieee->network_free_list.next;
network = list_entry(element, struct ieee80211_network, list);
......@@ -5575,12 +5973,14 @@ static void ipw_associate(void *data)
list_del(element);
list_add_tail(&network->list, &priv->ieee->network_list);
}
spin_unlock_irqrestore(&priv->ieee->lock, flags);
/* If we reached the end of the list, then we don't have any valid
* matching APs */
if (!network) {
ipw_debug_config(priv);
if (!(priv->status & STATUS_SCANNING))
queue_delayed_work(priv->workqueue, &priv->request_scan,
SCAN_INTERVAL);
......@@ -5601,7 +6001,7 @@ static inline void ipw_handle_data_packet(struct ipw_priv *priv,
/* We only process data packets if the
* interface is open */
if (unlikely((pkt->u.frame.length + IPW_RX_FRAME_SIZE) >
if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) >
skb_tailroom(rxb->skb))) {
priv->ieee->stats.rx_errors++;
priv->wstats.discard.misc++;
......@@ -5618,14 +6018,16 @@ static inline void ipw_handle_data_packet(struct ipw_priv *priv,
skb_reserve(rxb->skb, offsetof(struct ipw_rx_packet, u.frame.data));
/* Set the size of the skb to the size of the frame */
skb_put(rxb->skb, pkt->u.frame.length);
skb_put(rxb->skb, le16_to_cpu(pkt->u.frame.length));
IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
if (!ieee80211_rx(priv->ieee, rxb->skb, stats))
priv->ieee->stats.rx_errors++;
else /* ieee80211_rx succeeded, so it now owns the SKB */
else { /* ieee80211_rx succeeded, so it now owns the SKB */
rxb->skb = NULL;
ipw_led_activity_on(priv);
}
}
static inline int is_network_packet(struct ipw_priv *priv,
......@@ -5634,23 +6036,29 @@ static inline int is_network_packet(struct ipw_priv *priv,
/* Filter incoming packets to determine if they are targetted toward
* this network, discarding packets coming from ourselves */
switch (priv->ieee->iw_mode) {
case IW_MODE_ADHOC:
case IW_MODE_ADHOC: /* Header: Dest. | Source | BSSID */
/* {broad,multi}cast packets to our IBSS go through */
if (is_broadcast_ether_addr(header->addr1) ||
is_multicast_ether_addr(header->addr1))
return !memcmp(header->addr3, priv->bssid, ETH_ALEN);
else
return memcmp(header->addr1, priv->net_dev->dev_addr,
/* packets to our adapter go through */
return !memcmp(header->addr1, priv->net_dev->dev_addr,
ETH_ALEN);
break;
case IW_MODE_INFRA:
if (is_broadcast_ether_addr(header->addr3) ||
is_multicast_ether_addr(header->addr3))
return !memcmp(header->addr1, priv->bssid, ETH_ALEN);
else
return memcmp(header->addr3, priv->net_dev->dev_addr,
case IW_MODE_INFRA: /* Header: Dest. | AP{BSSID} | Source */
/* {broad,multi}cast packets to our IBSS go through */
if (is_broadcast_ether_addr(header->addr1) ||
is_multicast_ether_addr(header->addr1))
return !memcmp(header->addr2, priv->bssid, ETH_ALEN);
/* packets to our adapter go through */
return !memcmp(header->addr1, priv->net_dev->dev_addr,
ETH_ALEN);
break;
}
return 1;
}
......@@ -5695,7 +6103,7 @@ static void ipw_rx(struct ipw_priv *priv)
struct ieee80211_rx_stats stats = {
.rssi = pkt->u.frame.rssi_dbm -
IPW_RSSI_TO_DBM,
.signal = pkt->u.frame.signal,
/* .signal = le16_to_cpu(pkt->u.frame.signal), */
.rate = pkt->u.frame.rate,
.mac_time = jiffies,
.received_channel =
......@@ -5705,7 +6113,7 @@ static void ipw_rx(struct ipw_priv *priv)
control & (1 << 0)) ?
IEEE80211_24GHZ_BAND :
IEEE80211_52GHZ_BAND,
.len = pkt->u.frame.length,
.len = le16_to_cpu(pkt->u.frame.length),
};
if (stats.rssi != 0)
......@@ -5746,9 +6154,10 @@ static void ipw_rx(struct ipw_priv *priv)
}
IPW_DEBUG_RX("Frame: len=%u\n",
pkt->u.frame.length);
le16_to_cpu(pkt->u.frame.length));
if (pkt->u.frame.length < frame_hdr_len(header)) {
if (le16_to_cpu(pkt->u.frame.length) <
frame_hdr_len(header)) {
IPW_DEBUG_DROP
("Received packet is too small. "
"Dropping.\n");
......@@ -5757,19 +6166,20 @@ static void ipw_rx(struct ipw_priv *priv)
break;
}
switch (WLAN_FC_GET_TYPE(header->frame_ctl)) {
switch (WLAN_FC_GET_TYPE
(le16_to_cpu(header->frame_ctl))) {
case IEEE80211_FTYPE_MGMT:
ieee80211_rx_mgt(priv->ieee, header,
&stats);
if (priv->ieee->iw_mode == IW_MODE_ADHOC
&&
((WLAN_FC_GET_STYPE
(header->frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP)
(le16_to_cpu(header->frame_ctl))
== IEEE80211_STYPE_PROBE_RESP)
||
(WLAN_FC_GET_STYPE
(header->frame_ctl) ==
IEEE80211_STYPE_BEACON))
(le16_to_cpu(header->frame_ctl))
== IEEE80211_STYPE_BEACON))
&& !memcmp(header->addr3,
priv->bssid, ETH_ALEN))
ipw_add_station(priv,
......@@ -5852,7 +6262,9 @@ static int ipw_wx_get_name(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
if (!(priv->status & STATUS_ASSOCIATED))
if (priv->status & STATUS_RF_KILL_MASK) {
strcpy(wrqu->name, "radio off");
} else if (!(priv->status & STATUS_ASSOCIATED))
strcpy(wrqu->name, "unassociated");
else
snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
......@@ -5892,9 +6304,8 @@ static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
IPW_DEBUG_ASSOC("Disassociating due to channel change.\n");
ipw_disassociate(priv);
} else {
} else if (!(priv->status & (STATUS_SCANNING)))
ipw_associate(priv);
}
return 0;
}
......@@ -5986,9 +6397,8 @@ static int ipw_wx_set_mode(struct net_device *dev,
#ifdef CONFIG_PM
/* Free the existing firmware and reset the fw_loaded
* flag so ipw_load() will bring in the new firmawre */
if (fw_loaded) {
if (fw_loaded)
fw_loaded = 0;
}
release_firmware(bootfw);
release_firmware(ucode);
......@@ -5997,7 +6407,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
#endif
priv->ieee->iw_mode = wrqu->mode;
ipw_adapter_restart(priv);
queue_work(priv->workqueue, &priv->adapter_restart);
return err;
}
......@@ -6149,9 +6559,8 @@ static int ipw_wx_set_wap(struct net_device *dev,
if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
IPW_DEBUG_ASSOC("Disassociating due to BSSID change.\n");
ipw_disassociate(priv);
} else {
} else if (!(priv->status & (STATUS_SCANNING)))
ipw_associate(priv);
}
return 0;
}
......@@ -6220,9 +6629,8 @@ static int ipw_wx_set_essid(struct net_device *dev,
if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
IPW_DEBUG_ASSOC("Disassociating due to ESSID change.\n");
ipw_disassociate(priv);
} else {
} else if (!(priv->status & (STATUS_SCANNING)))
ipw_associate(priv);
}
return 0;
}
......@@ -6383,11 +6791,11 @@ static int ipw_wx_set_rate(struct net_device *dev,
if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) {
IPW_DEBUG_ASSOC("Disassociating due to RATE change.\n");
ipw_disassociate(priv);
}
} else {
} else if (!(priv->status & (STATUS_SCANNING))) {
/* We are not yet associated, so kick one off... */
ipw_associate(priv);
}
}
return 0;
}
......@@ -6635,11 +7043,10 @@ static int ipw_wx_get_power(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
if (!(priv->power_mode & IPW_POWER_ENABLED)) {
if (!(priv->power_mode & IPW_POWER_ENABLED))
wrqu->power.disabled = 1;
} else {
else
wrqu->power.disabled = 0;
}
IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode);
......@@ -6764,6 +7171,9 @@ static int ipw_wx_set_wireless_mode(struct net_device *dev,
} else
ipw_send_supported_rates(priv, &priv->rates);
/* Update the band LEDs */
ipw_led_band_on(priv);
IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n",
mode & IEEE_A ? 'a' : '.',
mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.');
......@@ -6870,7 +7280,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
if (enable) {
if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
priv->net_dev->type = ARPHRD_IEEE80211;
ipw_adapter_restart(priv);
queue_work(priv->workqueue, &priv->adapter_restart);
}
ipw_set_channel(priv, parms[1]);
......@@ -6878,7 +7288,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
if (priv->ieee->iw_mode != IW_MODE_MONITOR)
return 0;
priv->net_dev->type = ARPHRD_ETHER;
ipw_adapter_restart(priv);
queue_work(priv->workqueue, &priv->adapter_restart);
}
return 0;
}
......@@ -6889,7 +7299,7 @@ static int ipw_wx_reset(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
IPW_DEBUG_WX("RESET\n");
ipw_adapter_restart(priv);
queue_work(priv->workqueue, &priv->adapter_restart);
return 0;
}
#endif // CONFIG_IPW_MONITOR
......@@ -6925,6 +7335,10 @@ static iw_handler ipw_wx_handlers[] = {
IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode,
IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power,
IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power,
IW_IOCTL(SIOCSIWSPY) = iw_handler_set_spy,
IW_IOCTL(SIOCGIWSPY) = iw_handler_get_spy,
IW_IOCTL(SIOCSIWTHRSPY) = iw_handler_set_thrspy,
IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy,
};
#define IPW_PRIV_SET_POWER SIOCIWFIRSTPRIV
......@@ -6993,6 +7407,8 @@ static struct iw_handler_def ipw_wx_handler_def = {
.private_args = ipw_priv_args,
};
static struct iw_public_data ipw_wx_data;
/*
* Get wireless statistics.
* Called by /proc/net/wireless
......@@ -7057,7 +7473,7 @@ static inline void init_sys_config(struct ipw_sys_config *sys_config)
sys_config->dot11g_auto_detection = 0;
sys_config->enable_cts_to_self = 0;
sys_config->bt_coexist_collision_thr = 0;
sys_config->pass_noise_stats_to_host = 1;
sys_config->pass_noise_stats_to_host = 0; //1 -- fix for 256
}
static int ipw_net_open(struct net_device *dev)
......@@ -7131,7 +7547,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
tfd->control_flags.control_bits = TFD_NEED_IRQ_MASK;
tfd->u.data.cmd_id = DINO_CMD_TX;
tfd->u.data.len = txb->payload_size;
tfd->u.data.len = cpu_to_le16(txb->payload_size);
remaining_bytes = txb->payload_size;
if (unlikely(!unicast))
tfd->u.data.tx_flags = DCT_FLAG_NO_WEP;
......@@ -7149,8 +7565,14 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len);
/* payload */
tfd->u.data.num_chunks = min((u8) (NUM_TFD_CHUNKS - 2), txb->nr_frags);
for (i = 0; i < tfd->u.data.num_chunks; i++) {
tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2),
txb->nr_frags));
IPW_DEBUG_FRAG("%i fragments being sent as %i chunks.\n",
txb->nr_frags, le32_to_cpu(tfd->u.data.num_chunks));
for (i = 0; i < le32_to_cpu(tfd->u.data.num_chunks); i++) {
IPW_DEBUG_FRAG("Adding fragment %i of %i (%d bytes).\n",
i, le32_to_cpu(tfd->u.data.num_chunks),
txb->fragments[i]->len - hdr_len);
IPW_DEBUG_TX("Dumping TX packet frag %i of %i (%d bytes):\n",
i, tfd->u.data.num_chunks,
txb->fragments[i]->len - hdr_len);
......@@ -7158,11 +7580,13 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
txb->fragments[i]->len - hdr_len);
tfd->u.data.chunk_ptr[i] =
pci_map_single(priv->pci_dev,
cpu_to_le32(pci_map_single
(priv->pci_dev,
txb->fragments[i]->data + hdr_len,
txb->fragments[i]->len - hdr_len,
PCI_DMA_TODEVICE);
tfd->u.data.chunk_len[i] = txb->fragments[i]->len - hdr_len;
PCI_DMA_TODEVICE));
tfd->u.data.chunk_len[i] =
cpu_to_le16(txb->fragments[i]->len - hdr_len);
}
if (i != txb->nr_frags) {
......@@ -7177,7 +7601,7 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
remaining_bytes);
skb = alloc_skb(remaining_bytes, GFP_ATOMIC);
if (skb != NULL) {
tfd->u.data.chunk_len[i] = remaining_bytes;
tfd->u.data.chunk_len[i] = cpu_to_le16(remaining_bytes);
for (j = i; j < txb->nr_frags; j++) {
int size = txb->fragments[j]->len - hdr_len;
printk(KERN_INFO "Adding frag %d %d...\n",
......@@ -7188,10 +7612,14 @@ static inline void ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb)
dev_kfree_skb_any(txb->fragments[i]);
txb->fragments[i] = skb;
tfd->u.data.chunk_ptr[i] =
pci_map_single(priv->pci_dev, skb->data,
cpu_to_le32(pci_map_single
(priv->pci_dev, skb->data,
tfd->u.data.chunk_len[i],
PCI_DMA_TODEVICE);
tfd->u.data.num_chunks++;
PCI_DMA_TODEVICE));
tfd->u.data.num_chunks =
cpu_to_le32(le32_to_cpu(tfd->u.data.num_chunks) +
1);
}
}
......@@ -7227,6 +7655,7 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
}
ipw_tx_skb(priv, txb);
ipw_led_activity_on(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
......@@ -7260,7 +7689,7 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p)
memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
printk(KERN_INFO "%s: Setting MAC to " MAC_FMT "\n",
priv->net_dev->name, MAC_ARG(priv->mac_addr));
ipw_adapter_restart(priv);
queue_work(priv->workqueue, &priv->adapter_restart);
return 0;
}
......@@ -7414,6 +7843,46 @@ static void ipw_rf_kill(void *adapter)
spin_unlock_irqrestore(&priv->lock, flags);
}
void ipw_link_up(struct ipw_priv *priv)
{
netif_carrier_on(priv->net_dev);
if (netif_queue_stopped(priv->net_dev)) {
IPW_DEBUG_NOTIF("waking queue\n");
netif_wake_queue(priv->net_dev);
} else {
IPW_DEBUG_NOTIF("starting queue\n");
netif_start_queue(priv->net_dev);
}
ipw_reset_stats(priv);
/* Ensure the rate is updated immediately */
priv->last_rate = ipw_get_current_rate(priv);
ipw_gather_stats(priv);
ipw_led_link_up(priv);
notify_wx_assoc_event(priv);
if (priv->config & CFG_BACKGROUND_SCAN)
queue_delayed_work(priv->workqueue, &priv->request_scan, HZ);
}
void ipw_link_down(struct ipw_priv *priv)
{
ipw_led_link_down(priv);
netif_carrier_off(priv->net_dev);
netif_stop_queue(priv->net_dev);
notify_wx_assoc_event(priv);
/* Cancel any queued work ... */
cancel_delayed_work(&priv->request_scan);
cancel_delayed_work(&priv->adhoc_check);
cancel_delayed_work(&priv->gather_stats);
ipw_reset_stats(priv);
/* Queue up another scan... */
queue_work(priv->workqueue, &priv->request_scan);
}
static int ipw_setup_deferred_work(struct ipw_priv *priv)
{
int ret = 0;
......@@ -7436,6 +7905,13 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv)
INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_abort_scan, priv);
INIT_WORK(&priv->roam, ipw_roam, priv);
INIT_WORK(&priv->scan_check, ipw_scan_check, priv);
INIT_WORK(&priv->link_up, (void (*)(void *))ipw_link_up, priv);
INIT_WORK(&priv->link_down, (void (*)(void *))ipw_link_down, priv);
INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_led_link_on, priv);
INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_led_link_off,
priv);
INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_led_activity_off,
priv);
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
ipw_irq_tasklet, (unsigned long)priv);
......@@ -7636,8 +8112,9 @@ static int ipw_up(struct ipw_priv *priv)
rc = ipw_config(priv);
if (!rc) {
IPW_DEBUG_INFO("Configured device on count %i\n", i);
ipw_led_init(priv);
ipw_led_radio_on(priv);
priv->notif_missed_beacons = 0;
netif_start_queue(priv->net_dev);
return 0;
} else {
IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n",
......@@ -7675,11 +8152,12 @@ static void ipw_down(struct ipw_priv *priv)
netif_stop_queue(priv->net_dev);
ipw_stop_nic(priv);
ipw_led_radio_off(priv);
}
static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
#ifdef CONFIG_IEEE80211_WPA
struct iwreq *wrq = (struct iwreq *)rq;
int ret = -1;
switch (cmd) {
......@@ -7691,8 +8169,6 @@ static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EOPNOTSUPP;
}
#endif /* CONFIG_IEEE80211_WPA */
return -EOPNOTSUPP;
}
......@@ -7739,7 +8215,7 @@ static struct pci_device_id card_ids[] = {
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x104f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x4220, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */
{PCI_VENDOR_ID_INTEL, 0x4221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* 2225BG */
{PCI_VENDOR_ID_INTEL, 0x4221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */
{PCI_VENDOR_ID_INTEL, 0x4223, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
{PCI_VENDOR_ID_INTEL, 0x4224, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
......@@ -7764,6 +8240,8 @@ static struct attribute *ipw_sysfs_entries[] = {
&dev_attr_eeprom_delay.attr,
&dev_attr_ucode_version.attr,
&dev_attr_rtc.attr,
&dev_attr_scan_age.attr,
&dev_attr_led.attr,
NULL
};
......@@ -7789,6 +8267,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv = ieee80211_priv(net_dev);
priv->ieee = netdev_priv(net_dev);
priv->net_dev = net_dev;
priv->pci_dev = pdev;
#ifdef CONFIG_IPW_DEBUG
......@@ -7843,6 +8322,12 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Initialize module parameter values here */
/* We default to disabling the LED code as right now it causes
* too many systems to lock up... */
if (!led)
priv->config |= CFG_NO_LED;
if (associate)
priv->config |= CFG_ASSOCIATE;
else
......@@ -7893,11 +8378,6 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->adapter = IPW_2915ABG;
priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B;
} else {
if (priv->pci_dev->device == 0x4221)
printk(KERN_INFO DRV_NAME
": Detected Intel PRO/Wireless 2225BG Network "
"Connection\n");
else
printk(KERN_INFO DRV_NAME
": Detected Intel PRO/Wireless 2200BG Network "
"Connection\n");
......@@ -7933,6 +8413,9 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_MODULE_OWNER(net_dev);
SET_NETDEV_DEV(net_dev, &pdev->dev);
ipw_wx_data.spy_data = &priv->ieee->spy_data;
ipw_wx_data.ieee80211 = priv->ieee;
priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit;
priv->ieee->set_security = shim__set_security;
......@@ -7944,6 +8427,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
net_dev->set_multicast_list = ipw_net_set_multicast_list;
net_dev->set_mac_address = ipw_net_set_mac_address;
net_dev->get_wireless_stats = ipw_get_wireless_stats;
net_dev->wireless_data = &ipw_wx_data;
net_dev->wireless_handlers = &ipw_wx_handler_def;
net_dev->ethtool_ops = &ipw_ethtool_ops;
net_dev->irq = pdev->irq;
......@@ -7960,12 +8444,12 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = register_netdev(net_dev);
if (err) {
IPW_ERROR("failed to register network device\n");
goto out_remove_group;
goto out_remove_sysfs;
}
return 0;
out_remove_group:
out_remove_sysfs:
sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
out_release_irq:
free_irq(pdev->irq, priv);
......@@ -8005,9 +8489,10 @@ static void ipw_pci_remove(struct pci_dev *pdev)
}
ipw_tx_queue_free(priv);
ipw_led_shutdown(priv);
/* ipw_down will ensure that there is no more pending work
* in the workqueue's, so we can safely remove them now. */
if (priv->workqueue) {
cancel_delayed_work(&priv->adhoc_check);
cancel_delayed_work(&priv->gather_stats);
cancel_delayed_work(&priv->request_scan);
......@@ -8015,7 +8500,6 @@ static void ipw_pci_remove(struct pci_dev *pdev)
cancel_delayed_work(&priv->scan_check);
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
}
free_irq(pdev->irq, priv);
iounmap(priv->hw_base);
......@@ -8138,6 +8622,10 @@ MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
module_param(auto_create, int, 0444);
MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
module_param(led, int, 0444);
MODULE_PARM_DESC(auto_create,
"enable led control on some systems (default 0 off)\n");
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
......
......@@ -403,9 +403,9 @@ struct clx2_tx_queue {
#define RX_FREE_BUFFERS 32
#define RX_LOW_WATERMARK 8
#define SUP_RATE_11A_MAX_NUM_CHANNELS (8)
#define SUP_RATE_11B_MAX_NUM_CHANNELS (4)
#define SUP_RATE_11G_MAX_NUM_CHANNELS (12)
#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
// Used for passing to driver number of successes and failures per rate
struct rate_histogram {
......@@ -890,6 +890,9 @@ struct ipw_cmd {
#define STATUS_SCANNING (1<<21)
#define STATUS_SCAN_ABORTING (1<<22)
#define STATUS_LED_LINK_ON (1<<24)
#define STATUS_LED_ACT_ON (1<<25)
#define STATUS_INDIRECT_BYTE (1<<28) /* sysfs entry configured for access */
#define STATUS_INDIRECT_DWORD (1<<29) /* sysfs entry configured for access */
#define STATUS_DIRECT_DWORD (1<<30) /* sysfs entry configured for access */
......@@ -905,6 +908,8 @@ struct ipw_cmd {
#define CFG_ASSOCIATE (1<<6)
#define CFG_FIXED_RATE (1<<7)
#define CFG_ADHOC_CREATE (1<<8)
#define CFG_NO_LED (1<<9)
#define CFG_BACKGROUND_SCAN (1<<10)
#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */
#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */
......@@ -1046,9 +1051,24 @@ struct ipw_priv {
struct work_struct abort_scan;
struct work_struct roam;
struct work_struct scan_check;
struct work_struct link_up;
struct work_struct link_down;
struct tasklet_struct irq_tasklet;
/* LED related variables and work_struct */
u8 nic_type;
u32 led_activity_on;
u32 led_activity_off;
u32 led_association_on;
u32 led_association_off;
u32 led_ofdm_on;
u32 led_ofdm_off;
struct work_struct led_link_on;
struct work_struct led_link_off;
struct work_struct led_act_off;
#define IPW_2200BG 1
#define IPW_2915ABG 2
u8 adapter;
......@@ -1126,6 +1146,8 @@ do { if (ipw_debug_level & (level)) \
#define IPW_DL_RF_KILL (1<<17)
#define IPW_DL_FW_ERRORS (1<<18)
#define IPW_DL_LED (1<<19)
#define IPW_DL_ORD (1<<20)
#define IPW_DL_FRAG (1<<21)
......@@ -1151,6 +1173,7 @@ do { if (ipw_debug_level & (level)) \
#define IPW_DEBUG_TX(f, a...) IPW_DEBUG(IPW_DL_TX, f, ## a)
#define IPW_DEBUG_ISR(f, a...) IPW_DEBUG(IPW_DL_ISR, f, ## a)
#define IPW_DEBUG_MANAGEMENT(f, a...) IPW_DEBUG(IPW_DL_MANAGE, f, ## a)
#define IPW_DEBUG_LED(f, a...) IPW_DEBUG(IPW_DL_LED, f, ## a)
#define IPW_DEBUG_WEP(f, a...) IPW_DEBUG(IPW_DL_WEP, f, ## a)
#define IPW_DEBUG_HC(f, a...) IPW_DEBUG(IPW_DL_HOST_COMMAND, f, ## a)
#define IPW_DEBUG_FRAG(f, a...) IPW_DEBUG(IPW_DL_FRAG, f, ## a)
......@@ -1268,25 +1291,25 @@ do { if (ipw_debug_level & (level)) \
#define CX2_DMA_I_DMA_CONTROL 0x003000A4
#define CX2_DMA_I_CB_BASE 0x003000A0
#define CX2_TX_CMD_QUEUE_BD_BASE (0x00000200)
#define CX2_TX_CMD_QUEUE_BD_SIZE (0x00000204)
#define CX2_TX_QUEUE_0_BD_BASE (0x00000208)
#define CX2_TX_CMD_QUEUE_BD_BASE 0x00000200
#define CX2_TX_CMD_QUEUE_BD_SIZE 0x00000204
#define CX2_TX_QUEUE_0_BD_BASE 0x00000208
#define CX2_TX_QUEUE_0_BD_SIZE (0x0000020C)
#define CX2_TX_QUEUE_1_BD_BASE (0x00000210)
#define CX2_TX_QUEUE_1_BD_SIZE (0x00000214)
#define CX2_TX_QUEUE_2_BD_BASE (0x00000218)
#define CX2_TX_QUEUE_1_BD_BASE 0x00000210
#define CX2_TX_QUEUE_1_BD_SIZE 0x00000214
#define CX2_TX_QUEUE_2_BD_BASE 0x00000218
#define CX2_TX_QUEUE_2_BD_SIZE (0x0000021C)
#define CX2_TX_QUEUE_3_BD_BASE (0x00000220)
#define CX2_TX_QUEUE_3_BD_SIZE (0x00000224)
#define CX2_RX_BD_BASE (0x00000240)
#define CX2_RX_BD_SIZE (0x00000244)
#define CX2_RFDS_TABLE_LOWER (0x00000500)
#define CX2_TX_CMD_QUEUE_READ_INDEX (0x00000280)
#define CX2_TX_QUEUE_0_READ_INDEX (0x00000284)
#define CX2_TX_QUEUE_1_READ_INDEX (0x00000288)
#define CX2_TX_QUEUE_3_BD_BASE 0x00000220
#define CX2_TX_QUEUE_3_BD_SIZE 0x00000224
#define CX2_RX_BD_BASE 0x00000240
#define CX2_RX_BD_SIZE 0x00000244
#define CX2_RFDS_TABLE_LOWER 0x00000500
#define CX2_TX_CMD_QUEUE_READ_INDEX 0x00000280
#define CX2_TX_QUEUE_0_READ_INDEX 0x00000284
#define CX2_TX_QUEUE_1_READ_INDEX 0x00000288
#define CX2_TX_QUEUE_2_READ_INDEX (0x0000028C)
#define CX2_TX_QUEUE_3_READ_INDEX (0x00000290)
#define CX2_TX_QUEUE_3_READ_INDEX 0x00000290
#define CX2_RX_READ_INDEX (0x000002A0)
#define CX2_TX_CMD_QUEUE_WRITE_INDEX (0x00000F80)
......@@ -1333,15 +1356,15 @@ do { if (ipw_debug_level & (level)) \
#define EEPROM_HW_VERSION (GET_EEPROM_ADDR(0x72,LSB)) /* 2 bytes */
/* NIC type as found in the one byte EEPROM_NIC_TYPE offset*/
#define EEPROM_NIC_TYPE_STANDARD 0
#define EEPROM_NIC_TYPE_DELL 1
#define EEPROM_NIC_TYPE_FUJITSU 2
#define EEPROM_NIC_TYPE_IBM 3
#define EEPROM_NIC_TYPE_HP 4
#define EEPROM_NIC_TYPE_0 0
#define EEPROM_NIC_TYPE_1 1
#define EEPROM_NIC_TYPE_2 2
#define EEPROM_NIC_TYPE_3 3
#define EEPROM_NIC_TYPE_4 4
#define FW_MEM_REG_LOWER_BOUND 0x00300000
#define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40)
#define CX2_EVENT_REG (FW_MEM_REG_LOWER_BOUND + 0x04)
#define EEPROM_BIT_SK (1<<0)
#define EEPROM_BIT_CS (1<<1)
#define EEPROM_BIT_DI (1<<2)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment