aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-05-15 00:52:37 -0700
committerDavid S. Miller <davem@davemloft.net>2008-05-15 00:52:37 -0700
commitf42a44494bcdf03fc851c03d438464d59c0ceaf5 (patch)
tree986ea7b54e9fc79a64863fd7e92eabd99ffd37a3
parent63fe46da9c380b3f2bbdf3765044649517cc717c (diff)
parentef85ad541f9a6ccd3f89ec73f92b2d6f45a9d3e8 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
-rw-r--r--drivers/net/wireless/adm8211.c7
-rw-r--r--drivers/net/wireless/airo.c57
-rw-r--r--drivers/net/wireless/arlan-main.c40
-rw-r--r--drivers/net/wireless/arlan.h1
-rw-r--r--drivers/net/wireless/ath5k/base.c25
-rw-r--r--drivers/net/wireless/ath5k/hw.c6
-rw-r--r--drivers/net/wireless/atmel.c46
-rw-r--r--drivers/net/wireless/b43/b43.h16
-rw-r--r--drivers/net/wireless/b43/lo.c4
-rw-r--r--drivers/net/wireless/b43/main.c16
-rw-r--r--drivers/net/wireless/b43/nphy.c2
-rw-r--r--drivers/net/wireless/b43/phy.c51
-rw-r--r--drivers/net/wireless/b43/xmit.c5
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h17
-rw-r--r--drivers/net/wireless/b43legacy/main.c15
-rw-r--r--drivers/net/wireless/b43legacy/phy.c14
-rw-r--r--drivers/net/wireless/b43legacy/radio.c12
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c4
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig4
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-rs.c36
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c661
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c51
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h48
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c220
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h22
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c44
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h101
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c422
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c61
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c373
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c58
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c1135
-rw-r--r--drivers/net/wireless/libertas/cmd.c32
-rw-r--r--drivers/net/wireless/libertas/cmd.h1
-rw-r--r--drivers/net/wireless/libertas/main.c12
-rw-r--r--drivers/net/wireless/p54/p54common.c7
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c5
-rw-r--r--drivers/net/wireless/rtl8180_dev.c9
-rw-r--r--drivers/net/wireless/rtl8187_dev.c10
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c29
-rw-r--r--include/linux/ieee80211.h32
-rw-r--r--include/net/mac80211.h47
-rw-r--r--net/ieee80211/ieee80211_rx.c2
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/debugfs_sta.c17
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/key.c4
-rw-r--r--net/mac80211/main.c41
-rw-r--r--net/mac80211/mesh_hwmp.c2
-rw-r--r--net/mac80211/mesh_plink.c88
-rw-r--r--net/mac80211/mlme.c71
-rw-r--r--net/mac80211/rx.c214
-rw-r--r--net/mac80211/sta_info.c14
-rw-r--r--net/mac80211/sta_info.h74
-rw-r--r--net/mac80211/tkip.c145
-rw-r--r--net/mac80211/tx.c30
-rw-r--r--net/mac80211/wext.c28
-rw-r--r--net/wireless/core.c33
-rw-r--r--net/wireless/radiotap.c16
71 files changed, 2529 insertions, 2126 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index d93a1de77eb..7af5d8851f6 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -445,9 +445,9 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
struct ieee80211_rx_status rx_status = {0};
if (priv->pdev->revision < ADM8211_REV_CA)
- rx_status.ssi = rssi;
+ rx_status.signal = rssi;
else
- rx_status.ssi = 100 - rssi;
+ rx_status.signal = 100 - rssi;
rx_status.rate_idx = rate;
@@ -1893,9 +1893,10 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
+ dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
dev->channel_change_time = 1000;
- dev->max_rssi = 100; /* FIXME: find better value */
+ dev->max_signal = 100; /* FIXME: find better value */
dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 45f47c1c0a3..8a78283e860 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1148,7 +1148,6 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
static void airo_networks_free(struct airo_info *ai);
struct airo_info {
- struct net_device_stats stats;
struct net_device *dev;
struct list_head dev_list;
/* Note, we can have MAX_FIDS outstanding. FIDs are 16-bits, so we
@@ -1924,7 +1923,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
if (npacks >= MAXTXQ - 1) {
netif_stop_queue (dev);
if (npacks > MAXTXQ) {
- ai->stats.tx_fifo_errors++;
+ dev->stats.tx_fifo_errors++;
return 1;
}
skb_queue_tail (&ai->txq, skb);
@@ -2044,13 +2043,13 @@ static void get_tx_error(struct airo_info *ai, s32 fid)
bap_read(ai, &status, 2, BAP0);
}
if (le16_to_cpu(status) & 2) /* Too many retries */
- ai->stats.tx_aborted_errors++;
+ ai->dev->stats.tx_aborted_errors++;
if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */
- ai->stats.tx_heartbeat_errors++;
+ ai->dev->stats.tx_heartbeat_errors++;
if (le16_to_cpu(status) & 8) /* Aid fail */
{ }
if (le16_to_cpu(status) & 0x10) /* MAC disabled */
- ai->stats.tx_carrier_errors++;
+ ai->dev->stats.tx_carrier_errors++;
if (le16_to_cpu(status) & 0x20) /* Association lost */
{ }
/* We produce a TXDROP event only for retry or lifetime
@@ -2102,7 +2101,7 @@ static void airo_end_xmit(struct net_device *dev) {
for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++);
} else {
priv->fids[fid] &= 0xffff;
- priv->stats.tx_window_errors++;
+ dev->stats.tx_window_errors++;
}
if (i < MAX_FIDS / 2)
netif_wake_queue(dev);
@@ -2128,7 +2127,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
netif_stop_queue(dev);
if (i == MAX_FIDS / 2) {
- priv->stats.tx_fifo_errors++;
+ dev->stats.tx_fifo_errors++;
return 1;
}
}
@@ -2167,7 +2166,7 @@ static void airo_end_xmit11(struct net_device *dev) {
for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++);
} else {
priv->fids[fid] &= 0xffff;
- priv->stats.tx_window_errors++;
+ dev->stats.tx_window_errors++;
}
if (i < MAX_FIDS)
netif_wake_queue(dev);
@@ -2199,7 +2198,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
netif_stop_queue(dev);
if (i == MAX_FIDS) {
- priv->stats.tx_fifo_errors++;
+ dev->stats.tx_fifo_errors++;
return 1;
}
}
@@ -2219,8 +2218,9 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
return 0;
}
-static void airo_read_stats(struct airo_info *ai)
+static void airo_read_stats(struct net_device *dev)
{
+ struct airo_info *ai = dev->priv;
StatsRid stats_rid;
__le32 *vals = stats_rid.vals;
@@ -2232,23 +2232,24 @@ static void airo_read_stats(struct airo_info *ai)
readStatsRid(ai, &stats_rid, RID_STATS, 0);
up(&ai->sem);
- ai->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) +
+ dev->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) +
le32_to_cpu(vals[45]);
- ai->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) +
+ dev->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) +
le32_to_cpu(vals[41]);
- ai->stats.rx_bytes = le32_to_cpu(vals[92]);
- ai->stats.tx_bytes = le32_to_cpu(vals[91]);
- ai->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) +
+ dev->stats.rx_bytes = le32_to_cpu(vals[92]);
+ dev->stats.tx_bytes = le32_to_cpu(vals[91]);
+ dev->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) +
le32_to_cpu(vals[3]) + le32_to_cpu(vals[4]);
- ai->stats.tx_errors = le32_to_cpu(vals[42]) + ai->stats.tx_fifo_errors;
- ai->stats.multicast = le32_to_cpu(vals[43]);
- ai->stats.collisions = le32_to_cpu(vals[89]);
+ dev->stats.tx_errors = le32_to_cpu(vals[42]) +
+ dev->stats.tx_fifo_errors;
+ dev->stats.multicast = le32_to_cpu(vals[43]);
+ dev->stats.collisions = le32_to_cpu(vals[89]);
/* detailed rx_errors: */
- ai->stats.rx_length_errors = le32_to_cpu(vals[3]);
- ai->stats.rx_crc_errors = le32_to_cpu(vals[4]);
- ai->stats.rx_frame_errors = le32_to_cpu(vals[2]);
- ai->stats.rx_fifo_errors = le32_to_cpu(vals[0]);
+ dev->stats.rx_length_errors = le32_to_cpu(vals[3]);
+ dev->stats.rx_crc_errors = le32_to_cpu(vals[4]);
+ dev->stats.rx_frame_errors = le32_to_cpu(vals[2]);
+ dev->stats.rx_fifo_errors = le32_to_cpu(vals[0]);
}
static struct net_device_stats *airo_get_stats(struct net_device *dev)
@@ -2261,10 +2262,10 @@ static struct net_device_stats *airo_get_stats(struct net_device *dev)
set_bit(JOB_STATS, &local->jobs);
wake_up_interruptible(&local->thr_wait);
} else
- airo_read_stats(local);
+ airo_read_stats(dev);
}
- return &local->stats;
+ return &dev->stats;
}
static void airo_set_promisc(struct airo_info *ai) {
@@ -3092,7 +3093,7 @@ static int airo_thread(void *data) {
else if (test_bit(JOB_XMIT11, &ai->jobs))
airo_end_xmit11(dev);
else if (test_bit(JOB_STATS, &ai->jobs))
- airo_read_stats(ai);
+ airo_read_stats(dev);
else if (test_bit(JOB_WSTATS, &ai->jobs))
airo_read_wireless_stats(ai);
else if (test_bit(JOB_PROMISC, &ai->jobs))
@@ -3288,7 +3289,7 @@ static irqreturn_t airo_interrupt(int irq, void *dev_id)
skb = dev_alloc_skb( len + hdrlen + 2 + 2 );
if ( !skb ) {
- apriv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
goto badrx;
}
skb_reserve(skb, 2); /* This way the IP header is aligned */
@@ -3556,7 +3557,7 @@ static void mpi_receive_802_3(struct airo_info *ai)
skb = dev_alloc_skb(len);
if (!skb) {
- ai->stats.rx_dropped++;
+ ai->dev->stats.rx_dropped++;
goto badrx;
}
buffer = skb_put(skb,len);
@@ -3649,7 +3650,7 @@ void mpi_receive_802_11 (struct airo_info *ai)
skb = dev_alloc_skb( len + hdrlen + 2 );
if ( !skb ) {
- ai->stats.rx_dropped++;
+ ai->dev->stats.rx_dropped++;
goto badrx;
}
buffer = (u16*)skb_put (skb, len + hdrlen);
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c
index dbdfc9e39d2..dec5e874a54 100644
--- a/drivers/net/wireless/arlan-main.c
+++ b/drivers/net/wireless/arlan-main.c
@@ -125,7 +125,7 @@ static inline int arlan_drop_tx(struct net_device *dev)
{
struct arlan_private *priv = netdev_priv(dev);
- priv->stats.tx_errors++;
+ dev->stats.tx_errors++;
if (priv->Conf->tx_delay_ms)
{
priv->tx_done_delayed = jiffies + priv->Conf->tx_delay_ms * HZ / 1000 + 1;
@@ -1269,7 +1269,7 @@ static void arlan_tx_done_interrupt(struct net_device *dev, int status)
{
IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
printk("arlan intr: transmit OK\n");
- priv->stats.tx_packets++;
+ dev->stats.tx_packets++;
priv->bad = 0;
priv->reset = 0;
priv->retransmissions = 0;
@@ -1496,7 +1496,7 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short
if (skb == NULL)
{
printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name);
- priv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
break;
}
skb_reserve(skb, 2);
@@ -1536,14 +1536,14 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short
}
netif_rx(skb);
dev->last_rx = jiffies;
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += pkt_len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
}
break;
default:
printk(KERN_ERR "arlan intr: received unknown status\n");
- priv->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
break;
}
ARLAN_DEBUG_EXIT("arlan_rx_interrupt");
@@ -1719,23 +1719,23 @@ static struct net_device_stats *arlan_statistics(struct net_device *dev)
/* Update the statistics from the device registers. */
- READSHM(priv->stats.collisions, arlan->numReTransmissions, u_int);
- READSHM(priv->stats.rx_crc_errors, arlan->numCRCErrors, u_int);
- READSHM(priv->stats.rx_dropped, arlan->numFramesDiscarded, u_int);
- READSHM(priv->stats.rx_fifo_errors, arlan->numRXBufferOverflows, u_int);
- READSHM(priv->stats.rx_frame_errors, arlan->numReceiveFramesLost, u_int);
- READSHM(priv->stats.rx_over_errors, arlan->numRXOverruns, u_int);
- READSHM(priv->stats.rx_packets, arlan->numDatagramsReceived, u_int);
- READSHM(priv->stats.tx_aborted_errors, arlan->numAbortErrors, u_int);
- READSHM(priv->stats.tx_carrier_errors, arlan->numStatusTimeouts, u_int);
- READSHM(priv->stats.tx_dropped, arlan->numDatagramsDiscarded, u_int);
- READSHM(priv->stats.tx_fifo_errors, arlan->numTXUnderruns, u_int);
- READSHM(priv->stats.tx_packets, arlan->numDatagramsTransmitted, u_int);
- READSHM(priv->stats.tx_window_errors, arlan->numHoldOffs, u_int);
+ READSHM(dev->stats.collisions, arlan->numReTransmissions, u_int);
+ READSHM(dev->stats.rx_crc_errors, arlan->numCRCErrors, u_int);
+ READSHM(dev->stats.rx_dropped, arlan->numFramesDiscarded, u_int);
+ READSHM(dev->stats.rx_fifo_errors, arlan->numRXBufferOverflows, u_int);
+ READSHM(dev->stats.rx_frame_errors, arlan->numReceiveFramesLost, u_int);
+ READSHM(dev->stats.rx_over_errors, arlan->numRXOverruns, u_int);
+ READSHM(dev->stats.rx_packets, arlan->numDatagramsReceived, u_int);
+ READSHM(dev->stats.tx_aborted_errors, arlan->numAbortErrors, u_int);
+ READSHM(dev->stats.tx_carrier_errors, arlan->numStatusTimeouts, u_int);
+ READSHM(dev->stats.tx_dropped, arlan->numDatagramsDiscarded, u_int);
+ READSHM(dev->stats.tx_fifo_errors, arlan->numTXUnderruns, u_int);
+ READSHM(dev->stats.tx_packets, arlan->numDatagramsTransmitted, u_int);
+ READSHM(dev->stats.tx_window_errors, arlan->numHoldOffs, u_int);
ARLAN_DEBUG_EXIT("arlan_statistics");
- return &priv->stats;
+ return &dev->stats;
}
diff --git a/drivers/net/wireless/arlan.h b/drivers/net/wireless/arlan.h
index 3ed1df75900..fb3ad51a1ca 100644
--- a/drivers/net/wireless/arlan.h
+++ b/drivers/net/wireless/arlan.h
@@ -330,7 +330,6 @@ struct TxParam
#define TX_RING_SIZE 2
/* Information that need to be kept for each board. */
struct arlan_private {
- struct net_device_stats stats;
struct arlan_shmem __iomem * card;
struct arlan_shmem * conf;
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 3201c160434..c76ada17878 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -458,13 +458,11 @@ ath5k_pci_probe(struct pci_dev *pdev,
/* Initialize driver private data */
SET_IEEE80211_DEV(hw, &pdev->dev);
- hw->flags = IEEE80211_HW_RX_INCLUDES_FCS;
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_NOISE_DBM;
hw->extra_tx_headroom = 2;
hw->channel_change_time = 5000;
- /* these names are misleading */
- hw->max_rssi = -110; /* signal in dBm */
- hw->max_noise = -110; /* noise in dBm */
- hw->max_signal = 100; /* we will provide a percentage based on rssi */
sc = hw->priv;
sc->hw = hw;
sc->pdev = pdev;
@@ -1787,6 +1785,8 @@ ath5k_tasklet_rx(unsigned long data)
spin_lock(&sc->rxbuflock);
do {
+ rxs.flag = 0;
+
if (unlikely(list_empty(&sc->rxbuf))) {
ATH5K_WARN(sc, "empty rx buf pool\n");
break;
@@ -1893,20 +1893,9 @@ accept:
rxs.freq = sc->curchan->center_freq;
rxs.band = sc->curband->band;
- /*
- * signal quality:
- * the names here are misleading and the usage of these
- * values by iwconfig makes it even worse
- */
- /* noise floor in dBm, from the last noise calibration */
rxs.noise = sc->ah->ah_noise_floor;
- /* signal level in dBm */
- rxs.ssi = rxs.noise + rs.rs_rssi;
- /*
- * "signal" is actually displayed as Link Quality by iwconfig
- * we provide a percentage based on rssi (assuming max rssi 64)
- */
- rxs.signal = rs.rs_rssi * 100 / 64;
+ rxs.signal = rxs.noise + rs.rs_rssi;
+ rxs.qual = rs.rs_rssi * 100 / 64;
rxs.antenna = rs.rs_antenna;
rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
index 5fb1ae6ad3e..77990b56860 100644
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -4119,6 +4119,7 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
rs->rs_status = 0;
+ rs->rs_phyerr = 0;
/*
* Key table status
@@ -4145,7 +4146,7 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
if (rx_status->rx_status_1 &
AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
rs->rs_status |= AR5K_RXERR_PHY;
- rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
+ rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
}
@@ -4193,6 +4194,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
rs->rs_status = 0;
+ rs->rs_phyerr = 0;
/*
* Key table status
@@ -4215,7 +4217,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
if (rx_status->rx_status_1 &
AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
rs->rs_status |= AR5K_RXERR_PHY;
- rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1,
+ rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
}
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index ef2da4023d6..f978a9d5190 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -433,7 +433,6 @@ struct atmel_private {
struct net_device *dev;
struct device *sys_dev;
struct iw_statistics wstats;
- struct net_device_stats stats; // device stats
spinlock_t irqlock, timerlock; // spinlocks
enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
enum {
@@ -694,9 +693,9 @@ static void tx_done_irq(struct atmel_private *priv)
if (type == TX_PACKET_TYPE_DATA) {
if (status == TX_STATUS_SUCCESS)
- priv->stats.tx_packets++;
+ priv->dev->stats.tx_packets++;
else
- priv->stats.tx_errors++;
+ priv->dev->stats.tx_errors++;
netif_wake_queue(priv->dev);
}
}
@@ -792,13 +791,13 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) {
- priv->stats.tx_errors++;
+ dev->stats.tx_errors++;
dev_kfree_skb(skb);
return 0;
}
if (priv->station_state != STATION_STATE_READY) {
- priv->stats.tx_errors++;
+ dev->stats.tx_errors++;
dev_kfree_skb(skb);
return 0;
}
@@ -815,7 +814,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
initial + 18 (+30-12) */
if (!(buff = find_tx_buff(priv, len + 18))) {
- priv->stats.tx_dropped++;
+ dev->stats.tx_dropped++;
spin_unlock_irqrestore(&priv->irqlock, flags);
spin_unlock_bh(&priv->timerlock);
netif_stop_queue(dev);
@@ -851,7 +850,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
/* low bit of first byte of destination tells us if broadcast */
tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA);
dev->trans_start = jiffies;
- priv->stats.tx_bytes += len;
+ dev->stats.tx_bytes += len;
spin_unlock_irqrestore(&priv->irqlock, flags);
spin_unlock_bh(&priv->timerlock);
@@ -895,7 +894,7 @@ static void fast_rx_path(struct atmel_private *priv,
}
if (!(skb = dev_alloc_skb(msdu_size + 14))) {
- priv->stats.rx_dropped++;
+ priv->dev->stats.rx_dropped++;
return;
}
@@ -908,7 +907,7 @@ static void fast_rx_path(struct atmel_private *priv,
crc = crc32_le(crc, skbp + 12, msdu_size);
atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + 30 + msdu_size, 4);
if ((crc ^ 0xffffffff) != netcrc) {
- priv->stats.rx_crc_errors++;
+ priv->dev->stats.rx_crc_errors++;
dev_kfree_skb(skb);
return;
}
@@ -924,8 +923,8 @@ static void fast_rx_path(struct atmel_private *priv,
skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
- priv->stats.rx_bytes += 12 + msdu_size;
- priv->stats.rx_packets++;
+ priv->dev->stats.rx_bytes += 12 + msdu_size;
+ priv->dev->stats.rx_packets++;
}
/* Test to see if the packet in card memory at packet_loc has a valid CRC
@@ -991,7 +990,7 @@ static void frag_rx_path(struct atmel_private *priv,
crc = crc32_le(crc, &priv->rx_buf[12], msdu_size);
atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
if ((crc ^ 0xffffffff) != netcrc) {
- priv->stats.rx_crc_errors++;
+ priv->dev->stats.rx_crc_errors++;
memset(priv->frag_source, 0xff, 6);
}
}
@@ -1009,7 +1008,7 @@ static void frag_rx_path(struct atmel_private *priv,
msdu_size);
atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
if ((crc ^ 0xffffffff) != netcrc) {
- priv->stats.rx_crc_errors++;
+ priv->dev->stats.rx_crc_errors++;
memset(priv->frag_source, 0xff, 6);
more_frags = 1; /* don't send broken assembly */
}
@@ -1021,7 +1020,7 @@ static void frag_rx_path(struct atmel_private *priv,
if (!more_frags) { /* last one */
memset(priv->frag_source, 0xff, 6);
if (!(skb = dev_alloc_skb(priv->frag_len + 14))) {
- priv->stats.rx_dropped++;
+ priv->dev->stats.rx_dropped++;
} else {
skb_reserve(skb, 2);
memcpy(skb_put(skb, priv->frag_len + 12),
@@ -1031,8 +1030,8 @@ static void frag_rx_path(struct atmel_private *priv,
skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
- priv->stats.rx_bytes += priv->frag_len + 12;
- priv->stats.rx_packets++;
+ priv->dev->stats.rx_bytes += priv->frag_len + 12;
+ priv->dev->stats.rx_packets++;
}
}
} else
@@ -1057,7 +1056,7 @@ static void rx_done_irq(struct atmel_private *priv)
if (status == 0xc1) /* determined by experiment */
priv->wstats.discard.nwid++;
else
- priv->stats.rx_errors++;
+ priv->dev->stats.rx_errors++;
goto next;
}
@@ -1065,7 +1064,7 @@ static void rx_done_irq(struct atmel_private *priv)
rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
if (msdu_size < 30) {
- priv->stats.rx_errors++;
+ priv->dev->stats.rx_errors++;
goto next;
}
@@ -1123,7 +1122,7 @@ static void rx_done_irq(struct atmel_private *priv)
msdu_size -= 4;
crc = crc32_le(crc, (unsigned char *)&priv->rx_buf, msdu_size);
if ((crc ^ 0xffffffff) != (*((u32 *)&priv->rx_buf[msdu_size]))) {
- priv->stats.rx_crc_errors++;
+ priv->dev->stats.rx_crc_errors++;
goto next;
}
}
@@ -1250,12 +1249,6 @@ static irqreturn_t service_interrupt(int irq, void *dev_id)
}
}
-static struct net_device_stats *atmel_get_stats(struct net_device *dev)
-{
- struct atmel_private *priv = netdev_priv(dev);
- return &priv->stats;
-}
-
static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
@@ -1518,8 +1511,6 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
priv->crc_ok_cnt = priv->crc_ko_cnt = 0;
} else
priv->probe_crc = 0;
- memset(&priv->stats, 0, sizeof(priv->stats));
- memset(&priv->wstats, 0, sizeof(priv->wstats));
priv->last_qual = jiffies;
priv->last_beacon_timestamp = 0;
memset(priv->frag_source, 0xff, sizeof(priv->frag_source));
@@ -1568,7 +1559,6 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
dev->change_mtu = atmel_change_mtu;
dev->set_mac_address = atmel_set_mac_address;
dev->hard_start_xmit = start_tx;
- dev->get_stats = atmel_get_stats;
dev->wireless_handlers = (struct iw_handler_def *)&atmel_handler_def;
dev->do_ioctl = atmel_ioctl;
dev->irq = irq;
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 7d034df250b..0c2bc061e8f 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -939,22 +939,6 @@ static inline bool __b43_warn_on_dummy(bool x) { return x; }
# define B43_WARN_ON(x) __b43_warn_on_dummy(unlikely(!!(x)))
#endif
-/** Limit a value between two limits */
-#ifdef limit_value
-# undef limit_value
-#endif
-#define limit_value(value, min, max) \
- ({ \
- typeof(value) __value = (value); \
- typeof(value) __min = (min); \
- typeof(value) __max = (max); \
- if (__value < __min) \
- __value = __min; \
- else if (__value > __max) \
- __value = __max; \
- __value; \
- })
-
/* Convert an integer to a Q5.2 value */
#define INT_TO_Q52(i) ((i) << 2)
/* Convert a Q5.2 value to an integer (precision loss!) */
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index 4ce1e356120..9c854d6aae3 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -199,7 +199,7 @@ static void lo_measure_txctl_values(struct b43_wldev *dev)
if (lb_gain > 10) {
radio_pctl_reg = 0;
pga = abs(10 - lb_gain) / 6;
- pga = limit_value(pga, 0, 15);
+ pga = clamp_val(pga, 0, 15);
} else {
int cmp_val;
int tmp;
@@ -321,7 +321,7 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
phy->lna_lod_gain = 1;
trsw_rx_gain -= 8;
}
- trsw_rx_gain = limit_value(trsw_rx_gain, 0, 0x2D);
+ trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D);
phy->pga_gain = trsw_rx_gain / 3;
if (phy->pga_gain >= 5) {
phy->pga_gain -= 5;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index c6e79a15d3c..fc23ba5309b 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1182,10 +1182,10 @@ static void handle_irq_noise(struct b43_wldev *dev)
/* Get the noise samples. */
B43_WARN_ON(dev->noisecalc.nr_samples >= 8);
i = dev->noisecalc.nr_samples;
- noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]];
dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]];
dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]];
@@ -4466,10 +4466,10 @@ static int b43_wireless_init(struct ssb_device *dev)
/* fill hw info */
hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
- IEEE80211_HW_RX_INCLUDES_FCS;
- hw->max_signal = 100;
- hw->max_rssi = -110;
- hw->max_noise = -110;
+ IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_NOISE_DBM;
+
hw->queues = b43_modparam_qos ? 4 : 1;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
diff --git a/drivers/net/wireless/b43/nphy.c b/drivers/net/wireless/b43/nphy.c
index 8695eb22347..644eed993be 100644
--- a/drivers/net/wireless/b43/nphy.c
+++ b/drivers/net/wireless/b43/nphy.c
@@ -29,8 +29,6 @@
#include "nphy.h"
#include "tables_nphy.h"
-#include <linux/delay.h>
-
void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
{//TODO
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
index 8b3c24da8db..305d4cd6fd0 100644
--- a/drivers/net/wireless/b43/phy.c
+++ b/drivers/net/wireless/b43/phy.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/types.h>
+#include <linux/bitrev.h>
#include "b43.h"
#include "phy.h"
@@ -83,25 +84,9 @@ const u8 b43_radio_channel_codes_bg[] = {
72, 84,
};
+#define bitrev4(tmp) (bitrev8(tmp) >> 4)
static void b43_phy_initg(struct b43_wldev *dev);
-/* Reverse the bits of a 4bit value.
- * Example: 1101 is flipped 1011
- */
-static u16 flip_4bit(u16 value)
-{
- u16 flipped = 0x0000;
-
- B43_WARN_ON(value & ~0x000F);
-
- flipped |= (value & 0x0001) << 3;
- flipped |= (value & 0x0002) << 1;
- flipped |= (value & 0x0004) >> 1;
- flipped |= (value & 0x0008) >> 3;
-
- return flipped;
-}
-
static void generate_rfatt_list(struct b43_wldev *dev,
struct b43_rfatt_list *list)
{
@@ -1415,7 +1400,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
* Essentially, what we do here is resetting all NRSSI LT
- * entries to -32 (see the limit_value() in nrssi_hw_update())
+ * entries to -32 (see the clamp_val() in nrssi_hw_update())
*/
b43_nrssi_hw_update(dev, 0xFFFF); //FIXME?
b43_calc_nrssi_threshold(dev);
@@ -1477,13 +1462,13 @@ static s8 b43_phy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
switch (phy->type) {
case B43_PHYTYPE_A:
tmp += 0x80;
- tmp = limit_value(tmp, 0x00, 0xFF);
+ tmp = clamp_val(tmp, 0x00, 0xFF);
dbm = phy->tssi2dbm[tmp];
//TODO: There's a FIXME on the specs
break;
case B43_PHYTYPE_B:
case B43_PHYTYPE_G:
- tmp = limit_value(tmp, 0x00, 0x3F);
+ tmp = clamp_val(tmp, 0x00, 0x3F);
dbm = phy->tssi2dbm[tmp];
break;
default:
@@ -1542,8 +1527,8 @@ void b43_put_attenuation_into_ranges(struct b43_wldev *dev,
break;
}
- *_rfatt = limit_value(rfatt, rf_min, rf_max);
- *_bbatt = limit_value(bbatt, bb_min, bb_max);
+ *_rfatt = clamp_val(rfatt, rf_min, rf_max);
+ *_bbatt = clamp_val(bbatt, bb_min, bb_max);
}
/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
@@ -1638,7 +1623,7 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
/* Get desired power (in Q5.2) */
desired_pwr = INT_TO_Q52(phy->power_level);
/* And limit it. max_pwr already is Q5.2 */
- desired_pwr = limit_value(desired_pwr, 0, max_pwr);
+ desired_pwr = clamp_val(desired_pwr, 0, max_pwr);
if (b43_debug(dev, B43_DBG_XMITPOWER)) {
b43dbg(dev->wl,
"Current TX power output: " Q52_FMT
@@ -1748,7 +1733,7 @@ static inline
f = q;
i++;
} while (delta >= 2);
- entry[index] = limit_value(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128);
+ entry[index] = clamp_val(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128);
return 0;
}
@@ -2274,7 +2259,7 @@ void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
for (i = 0; i < 64; i++) {
tmp = b43_nrssi_hw_read(dev, i);
tmp -= val;
- tmp = limit_value(tmp, -32, 31);
+ tmp = clamp_val(tmp, -32, 31);
b43_nrssi_hw_write(dev, i, tmp);
}
}
@@ -2291,7 +2276,7 @@ void b43_nrssi_mem_update(struct b43_wldev *dev)
tmp = (i - delta) * phy->nrssislope;
tmp /= 0x10000;
tmp += 0x3A;
- tmp = limit_value(tmp, 0, 0x3F);
+ tmp = clamp_val(tmp, 0, 0x3F);
phy->nrssi_lt[i] = tmp;
}
}
@@ -2728,7 +2713,7 @@ void b43_calc_nrssi_threshold(struct b43_wldev *dev)
} else
threshold = phy->nrssi[1] - 5;
- threshold = limit_value(threshold, 0, 0x3E);
+ threshold = clamp_val(threshold, 0, 0x3E);
b43_phy_read(dev, 0x0020); /* dummy read */
b43_phy_write(dev, 0x0020,
(((u16) threshold) << 8) | 0x001C);
@@ -2779,7 +2764,7 @@ void b43_calc_nrssi_threshold(struct b43_wldev *dev)
else
a += 32;
a = a >> 6;
- a = limit_value(a, -31, 31);
+ a = clamp_val(a, -31, 31);
b = b * (phy->nrssi[1] - phy->nrssi[0]);
b += (phy->nrssi[0] << 6);
@@ -2788,7 +2773,7 @@ void b43_calc_nrssi_threshold(struct b43_wldev *dev)
else
b += 32;
b = b >> 6;
- b = limit_value(b, -31, 31);
+ b = clamp_val(b, -31, 31);
tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000;
tmp_u16 |= ((u32) b & 0x0000003F);
@@ -2891,13 +2876,13 @@ b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode)
}
radio_stacksave(0x0078);
tmp = (b43_radio_read16(dev, 0x0078) & 0x001E);
- flipped = flip_4bit(tmp);
+ B43_WARN_ON(tmp > 15);
+ flipped = bitrev4(tmp);
if (flipped < 10 && flipped >= 8)
flipped = 7;
else if (flipped >= 10)
flipped -= 3;
- flipped = flip_4bit(flipped);
- flipped = (flipped << 1) | 0x0020;
+ flipped = (bitrev4(flipped) << 1) | 0x0020;
b43_radio_write16(dev, 0x0078, flipped);
b43_calc_nrssi_threshold(dev);
@@ -3530,7 +3515,7 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
tmp1 >>= 9;
for (i = 0; i < 16; i++) {
- radio78 = ((flip_4bit(i) << 1) | 0x20);
+ radio78 = (bitrev4(i) << 1) | 0x0020;
b43_radio_write16(dev, 0x78, radio78);
udelay(10);
for (j = 0; j < 16; j++) {
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 88491947a20..afce9338d83 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -581,12 +581,11 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
// and also find out what the maximum possible value is.
// Fill status.ssi and status.signal fields.
} else {
- status.ssi = b43_rssi_postprocess(dev, rxhdr->jssi,
+ status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
(phystat0 & B43_RX_PHYST0_OFDM),
(phystat0 & B43_RX_PHYST0_GAINCTL),
(phystat3 & B43_RX_PHYST3_TRSTATE));
- /* the next line looks wrong, but is what mac80211 wants */
- status.signal = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
+ status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
}
if (phystat0 & B43_RX_PHYST0_OFDM)
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index ded3cd31b3d..c40078e1fff 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -823,23 +823,6 @@ void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...)
# define b43legacydbg(wl, fmt...) do { /* nothing */ } while (0)
#endif /* DEBUG */
-
-/** Limit a value between two limits */
-#ifdef limit_value
-# undef limit_value
-#endif
-#define limit_value(value, min, max) \
- ({ \
- typeof(value) __value = (value); \
- typeof(value) __min = (min); \
- typeof(value) __max = (max); \
- if (__value < __min) \
- __value = __min; \
- else if (__value > __max) \
- __value = __max; \
- __value; \
- })
-
/* Macros for printing a value in Q5.2 format */
#define Q52_FMT "%u.%u"
#define Q52_ARG(q52) ((q52) / 4), (((q52) & 3) * 100 / 4)
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1ccc51e90a8..7755c59e080 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -846,10 +846,10 @@ static void handle_irq_noise(struct b43legacy_wldev *dev)
/* Get the noise samples. */
B43legacy_WARN_ON(dev->noisecalc.nr_samples >= 8);
i = dev->noisecalc.nr_samples;
- noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]];
dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]];
dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]];
@@ -3718,10 +3718,9 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
/* fill hw info */
hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
- IEEE80211_HW_RX_INCLUDES_FCS;
- hw->max_signal = 100;
- hw->max_rssi = -110;
- hw->max_noise = -110;
+ IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_NOISE_DBM;
hw->queues = 1; /* FIXME: hardware has more queues */
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 8e5c09b8187..768cccb9b1b 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -1088,7 +1088,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
* Essentially, what we do here is resetting all NRSSI LT
- * entries to -32 (see the limit_value() in nrssi_hw_update())
+ * entries to -32 (see the clamp_val() in nrssi_hw_update())
*/
b43legacy_nrssi_hw_update(dev, 0xFFFF);
b43legacy_calc_nrssi_threshold(dev);
@@ -1756,7 +1756,7 @@ static s8 b43legacy_phy_estimate_power_out(struct b43legacy_wldev *dev, s8 tssi)
switch (phy->type) {
case B43legacy_PHYTYPE_B:
case B43legacy_PHYTYPE_G:
- tmp = limit_value(tmp, 0x00, 0x3F);
+ tmp = clamp_val(tmp, 0x00, 0x3F);
dbm = phy->tssi2dbm[tmp];
break;
default:
@@ -1859,7 +1859,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
/* find the desired power in Q5.2 - power_level is in dBm
* and limit it - max_pwr is already in Q5.2 */
- desired_pwr = limit_value(phy->power_level << 2, 0, max_pwr);
+ desired_pwr = clamp_val(phy->power_level << 2, 0, max_pwr);
if (b43legacy_debug(dev, B43legacy_DBG_XMITPOWER))
b43legacydbg(dev->wl, "Current TX power output: " Q52_FMT
" dBm, Desired TX power output: " Q52_FMT
@@ -1905,7 +1905,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
radio_attenuation++;
}
}
- baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+ baseband_attenuation = clamp_val(baseband_attenuation, 0, 11);
txpower = phy->txctl1;
if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
@@ -1933,8 +1933,8 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
}
/* Save the control values */
phy->txctl1 = txpower;
- baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
- radio_attenuation = limit_value(radio_attenuation, 0, 9);
+ baseband_attenuation = clamp_val(baseband_attenuation, 0, 11);
+ radio_attenuation = clamp_val(radio_attenuation, 0, 9);
phy->rfatt = radio_attenuation;
phy->bbatt = baseband_attenuation;
@@ -1979,7 +1979,7 @@ s8 b43legacy_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
f = q;
i++;
} while (delta >= 2);
- entry[index] = limit_value(b43legacy_tssi2dbm_ad(m1 * f, 8192),
+ entry[index] = clamp_val(b43legacy_tssi2dbm_ad(m1 * f, 8192),
-127, 128);
return 0;
}
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index 955832e8654..2df545cfad1 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -357,7 +357,7 @@ void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val)
for (i = 0; i < 64; i++) {
tmp = b43legacy_nrssi_hw_read(dev, i);
tmp -= val;
- tmp = limit_value(tmp, -32, 31);
+ tmp = clamp_val(tmp, -32, 31);
b43legacy_nrssi_hw_write(dev, i, tmp);
}
}
@@ -375,7 +375,7 @@ void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev)
tmp = (i - delta) * phy->nrssislope;
tmp /= 0x10000;
tmp += 0x3A;
- tmp = limit_value(tmp, 0, 0x3F);
+ tmp = clamp_val(tmp, 0, 0x3F);
phy->nrssi_lt[i] = tmp;
}
}
@@ -839,7 +839,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
} else
threshold = phy->nrssi[1] - 5;
- threshold = limit_value(threshold, 0, 0x3E);
+ threshold = clamp_val(threshold, 0, 0x3E);
b43legacy_phy_read(dev, 0x0020); /* dummy read */
b43legacy_phy_write(dev, 0x0020, (((u16)threshold) << 8)
| 0x001C);
@@ -892,7 +892,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
else
a += 32;
a = a >> 6;
- a = limit_value(a, -31, 31);
+ a = clamp_val(a, -31, 31);
b = b * (phy->nrssi[1] - phy->nrssi[0]);
b += (phy->nrssi[0] << 6);
@@ -901,7 +901,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
else
b += 32;
b = b >> 6;
- b = limit_value(b, -31, 31);
+ b = clamp_val(b, -31, 31);
tmp_u16 = b43legacy_phy_read(dev, 0x048A) & 0xF000;
tmp_u16 |= ((u32)b & 0x0000003F);
@@ -1905,7 +1905,7 @@ void b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower)
u16 dac;
u16 ilt;
- txpower = limit_value(txpower, 0, 63);
+ txpower = clamp_val(txpower, 0, 63);
pamp = b43legacy_get_txgain_freq_power_amp(txpower);
pamp <<= 5;
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index fc83dab6e2c..bed9e041d6c 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -532,12 +532,12 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
}
}
- status.ssi = b43legacy_rssi_postprocess(dev, jssi,
+ status.signal = b43legacy_rssi_postprocess(dev, jssi,
(phystat0 & B43legacy_RX_PHYST0_OFDM),
(phystat0 & B43legacy_RX_PHYST0_GAINCTL),
(phystat3 & B43legacy_RX_PHYST3_TRSTATE));
status.noise = dev->stats.link_noise;
- status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI;
+ status.qual = (jssi * 100) / B43legacy_RX_MAX_SSI;
/* change to support A PHY */
if (phystat0 & B43legacy_RX_PHYST0_OFDM)
status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 995dd537083..5f3e849043f 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -96,13 +96,13 @@ config IWLWIFI_DEBUG
control which debug output is sent to the kernel log by setting the
value in
- /sys/bus/pci/drivers/${DRIVER}/debug_level
+ /sys/class/net/wlan0/device/debug_level
This entry will only exist if this option is enabled.
To set a value, simply echo an 8-byte hex value to the same file:
- % echo 0x43fff > /sys/bus/pci/drivers/${DRIVER}/debug_level
+ % echo 0x43fff > /sys/class/net/wlan0/device/debug_level
You can find the list of debug mask values in:
drivers/net/wireless/iwlwifi/iwl-4965-debug.h
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index b0b2b5ebfa6..5c73eede719 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_IWLCORE) += iwlcore.o
iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
+iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
@@ -10,7 +11,7 @@ iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o
iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o
obj-$(CONFIG_IWL4965) += iwl4965.o
-iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o
+iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o
ifeq ($(CONFIG_IWL5000),y)
iwl4965-objs += iwl-5000.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 9df48b33f0c..ad4e7b74ca2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -520,7 +520,7 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
{
/* First cache any information we need before we overwrite
* the information provided in the skb from the hardware */
- s8 signal = stats->ssi;
+ s8 signal = stats->signal;
s8 noise = 0;
int rate = stats->rate_idx;
u64 tsf = stats->mactime;
@@ -693,7 +693,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
}
/* Convert 3945's rssi indicator to dBm */
- rx_status.ssi = rx_stats->rssi - IWL_RSSI_OFFSET;
+ rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET;
/* Set default noise value to -127 */
if (priv->last_rx_noise == 0)
@@ -712,21 +712,21 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
* Calculate rx_status.signal (quality indicator in %) based on SNR. */
if (rx_stats_noise_diff) {
snr = rx_stats_sig_avg / rx_stats_noise_diff;
- rx_status.noise = rx_status.ssi -
+ rx_status.noise = rx_status.signal -
iwl3945_calc_db_from_ratio(snr);
- rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi,
+ rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal,
rx_status.noise);
/* If noise info not available, calculate signal quality indicator (%)
* using just the dBm signal level. */
} else {
rx_status.noise = priv->last_rx_noise;
- rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, 0);
+ rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0);
}
IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n",
- rx_status.ssi, rx_status.noise, rx_status.signal,
+ rx_status.signal, rx_status.noise, rx_status.qual,
rx_stats_sig_avg, rx_stats_noise_diff);
header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
@@ -736,8 +736,8 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n",
network_packet ? '*' : ' ',
le16_to_cpu(rx_hdr->channel),
- rx_status.ssi, rx_status.ssi,
- rx_status.ssi, rx_status.rate_idx);
+ rx_status.signal, rx_status.signal,
+ rx_status.noise, rx_status.rate_idx);
#ifdef CONFIG_IWL3945_DEBUG
if (iwl3945_debug_level & (IWL_DL_RX))
@@ -748,7 +748,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
if (network_packet) {
priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
priv->last_tsf = le64_to_cpu(rx_end->timestamp);
- priv->last_rx_rssi = rx_status.ssi;
+ priv->last_rx_rssi = rx_status.signal;
priv->last_rx_noise = rx_status.noise;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index fb96c62ad0f..9fdc1405e85 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -886,6 +886,7 @@ struct iwl3945_priv {
struct work_struct report_work;
struct work_struct request_scan;
struct work_struct beacon_update;
+ struct work_struct set_monitor;
struct tasklet_struct irq_tasklet;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index 29749e2a8ff..ee55b283226 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -829,7 +829,7 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags)
#define IWL49_NUM_QUEUES 16
/**
- * struct iwl4965_tfd_frame_data
+ * struct iwl_tfd_frame_data
*
* Describes up to 2 buffers containing (contiguous) portions of a Tx frame.
* Each buffer must be on dword boundary.
@@ -848,7 +848,7 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags)
* 31-20: Tx buffer 2 length (bytes)
* 19- 0: Tx buffer 2 address bits [35:16]
*/
-struct iwl4965_tfd_frame_data {
+struct iwl_tfd_frame_data {
__le32 tb1_addr;
__le32 val1;
@@ -878,7 +878,7 @@ struct iwl4965_tfd_frame_data {
/**
- * struct iwl4965_tfd_frame
+ * struct iwl_tfd_frame
*
* Transmit Frame Descriptor (TFD)
*
@@ -905,7 +905,7 @@ struct iwl4965_tfd_frame_data {
*
* A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
*/
-struct iwl4965_tfd_frame {
+struct iwl_tfd_frame {
__le32 val0;
/* __le32 rsvd1:24; */
/* __le32 num_tbs:5; */
@@ -914,7 +914,7 @@ struct iwl4965_tfd_frame {
#define IWL_num_tbs_SYM val0
/* __le32 rsvd2:1; */
/* __le32 padding:2; */
- struct iwl4965_tfd_frame_data pa[10];
+ struct iwl_tfd_frame_data pa[10];
__le32 reserved;
} __attribute__ ((packed));
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 24dee00b0e8..8e3660ebba7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -360,9 +360,9 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
unsigned long state;
DECLARE_MAC_BUF(mac);
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_lock_bh(&sta->lock);
state = sta->ampdu_mlme.tid_state_tx[tid];
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
if (state == HT_AGG_STATE_IDLE &&
rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
@@ -662,7 +662,8 @@ static u16 rs_get_supported_rates(struct iwl4965_lq_sta *lq_sta,
}
}
-static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type)
+static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask,
+ int rate_type)
{
u8 high = IWL_RATE_INVALID;
u8 low = IWL_RATE_INVALID;
@@ -763,7 +764,8 @@ static u32 rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta,
goto out;
}
- high_low = rs_get_adjacent_rate(scale_index, rate_mask, tbl->lq_type);
+ high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask,
+ tbl->lq_type);
low = high_low & 0xff;
if (low == IWL_RATE_INVALID)
@@ -990,7 +992,7 @@ out:
* These control how long we stay using same modulation mode before
* searching for a new mode.
*/
-static void rs_set_stay_in_table(u8 is_legacy,
+static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy,
struct iwl4965_lq_sta *lq_sta)
{
IWL_DEBUG_RATE("we are staying in the same table\n");
@@ -1079,7 +1081,8 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
new_rate = high = low = start_hi = IWL_RATE_INVALID;
for (; ;) {
- high_low = rs_get_adjacent_rate(rate, rate_mask, tbl->lq_type);
+ high_low = rs_get_adjacent_rate(priv, rate, rate_mask,
+ tbl->lq_type);
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;
@@ -1565,7 +1568,9 @@ static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta)
int i;
int active_tbl;
int flush_interval_passed = 0;
+ struct iwl_priv *priv;
+ priv = lq_sta->drv;
active_tbl = lq_sta->active_tbl;
tbl = &(lq_sta->lq_info[active_tbl]);
@@ -1838,7 +1843,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
/* (Else) not in search of better modulation mode, try for better
* starting rate, while staying in this mode. */
- high_low = rs_get_adjacent_rate(index, rate_scale_index_msk,
+ high_low = rs_get_adjacent_rate(priv, index, rate_scale_index_msk,
tbl->lq_type);
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;
@@ -1998,7 +2003,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
(lq_sta->action_counter >= 1)) {
lq_sta->action_counter = 0;
IWL_DEBUG_RATE("LQ: STAY in legacy table\n");
- rs_set_stay_in_table(1, lq_sta);
+ rs_set_stay_in_table(priv, 1, lq_sta);
}
/* If we're in an HT mode, and all 3 mode switch actions
@@ -2015,7 +2020,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
}
#endif /*CONFIG_IWL4965_HT */
lq_sta->action_counter = 0;
- rs_set_stay_in_table(0, lq_sta);
+ rs_set_stay_in_table(priv, 0, lq_sta);
}
/*
@@ -2169,11 +2174,13 @@ out:
rcu_read_unlock();
}
-static void *rs_alloc_sta(void *priv, gfp_t gfp)
+static void *rs_alloc_sta(void *priv_rate, gfp_t gfp)
{
struct iwl4965_lq_sta *lq_sta;
+ struct iwl_priv *priv;
int i, j;
+ priv = (struct iwl_priv *)priv_rate;
IWL_DEBUG_RATE("create station rate scale window\n");
lq_sta = kzalloc(sizeof(struct iwl4965_lq_sta), gfp);
@@ -2443,10 +2450,12 @@ static void rs_clear(void *priv_rate)
IWL_DEBUG_RATE("leave\n");
}
-static void rs_free_sta(void *priv, void *priv_sta)
+static void rs_free_sta(void *priv_rate, void *priv_sta)
{
struct iwl4965_lq_sta *lq_sta = priv_sta;
+ struct iwl_priv *priv;
+ priv = (struct iwl_priv *)priv_rate;
IWL_DEBUG_RATE("enter\n");
kfree(lq_sta);
IWL_DEBUG_RATE("leave\n");
@@ -2462,6 +2471,9 @@ static int open_file_generic(struct inode *inode, struct file *file)
static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta,
u32 *rate_n_flags, int index)
{
+ struct iwl_priv *priv;
+
+ priv = lq_sta->drv;
if (lq_sta->dbg_fixed_rate) {
if (index < 12) {
*rate_n_flags = lq_sta->dbg_fixed_rate;
@@ -2481,10 +2493,12 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
struct iwl4965_lq_sta *lq_sta = file->private_data;
+ struct iwl_priv *priv;
char buf[64];
int buf_size;
u32 parsed_rate;
+ priv = lq_sta->drv;
memset(buf, 0, sizeof(buf));
buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 5d675e39bab..17847f981e1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -50,11 +50,10 @@ static struct iwl_mod_params iwl4965_mod_params = {
.num_of_queues = IWL49_NUM_QUEUES,
.enable_qos = 1,
.amsdu_size_8K = 1,
+ .restart_fw = 1,
/* the rest are 0 by default */
};
-static void iwl4965_hw_card_show_info(struct iwl_priv *priv);
-
#ifdef CONFIG_IWL4965_HT
static const u16 default_tid_to_tx_fifo[] = {
@@ -224,6 +223,102 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
return 0;
}
+/**
+ * iwl4965_set_ucode_ptrs - Set uCode address location
+ *
+ * Tell initialization uCode where to find runtime uCode.
+ *
+ * BSM registers initially contain pointers to initialization uCode.
+ * We need to replace them to load runtime uCode inst and data,
+ * and to save runtime data when powering down.
+ */
+static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
+{
+ dma_addr_t pinst;
+ dma_addr_t pdata;
+ unsigned long flags;
+ int ret = 0;
+
+ /* bits 35:4 for 4965 */
+ pinst = priv->ucode_code.p_addr >> 4;
+ pdata = priv->ucode_data_backup.p_addr >> 4;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = iwl_grab_nic_access(priv);
+ if (ret) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+ }
+
+ /* Tell bootstrap uCode where to find image to load */
+ iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+ iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+ iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+ priv->ucode_data.len);
+
+ /* Inst bytecount must be last to set up, bit 31 signals uCode
+ * that all new ptr/size info is in place */
+ iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+ priv->ucode_code.len | BSM_DRAM_INST_LOAD);
+ iwl_release_nic_access(priv);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ IWL_DEBUG_INFO("Runtime uCode pointers are set.\n");
+
+ return ret;
+}
+
+/**
+ * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
+ *
+ * Called after REPLY_ALIVE notification received from "initialize" uCode.
+ *
+ * The 4965 "initialize" ALIVE reply contains calibration data for:
+ * Voltage, temperature, and MIMO tx gain correction, now stored in priv
+ * (3945 does not contain this data).
+ *
+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
+*/
+static void iwl4965_init_alive_start(struct iwl_priv *priv)
+{
+ /* Check alive response for "valid" sign from uCode */
+ if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
+ /* We had an error bringing up the hardware, so take it
+ * all the way back down so we can try again */
+ IWL_DEBUG_INFO("Initialize Alive failed.\n");
+ goto restart;
+ }
+
+ /* Bootstrap uCode has loaded initialize uCode ... verify inst image.
+ * This is a paranoid check, because we would not have gotten the
+ * "initialize" alive if code weren't properly loaded. */
+ if (iwl_verify_ucode(priv)) {
+ /* Runtime instruction load was bad;
+ * take it all the way back down so we can try again */
+ IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
+ goto restart;
+ }
+
+ /* Calculate temperature */
+ priv->temperature = iwl4965_get_temperature(priv);
+
+ /* Send pointers to protocol/runtime uCode image ... init code will
+ * load and launch runtime uCode, which will send us another "Alive"
+ * notification. */
+ IWL_DEBUG_INFO("Initialization Alive received.\n");
+ if (iwl4965_set_ucode_ptrs(priv)) {
+ /* Runtime instruction load won't happen;
+ * take it all the way back down so we can try again */
+ IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n");
+ goto restart;
+ }
+ return;
+
+restart:
+ queue_work(priv->workqueue, &priv->restart);
+}
+
static int is_fat_channel(__le32 rxon_flags)
{
return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) ||
@@ -372,178 +467,31 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
return ret;
}
-static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
+static int iwl4965_disable_tx_fifo(struct iwl_priv *priv)
{
- int ret;
unsigned long flags;
- unsigned int rb_size;
+ int ret;
spin_lock_irqsave(&priv->lock, flags);
+
ret = iwl_grab_nic_access(priv);
- if (ret) {
+ if (unlikely(ret)) {
+ IWL_ERROR("Tx fifo reset failed");
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
- if (priv->cfg->mod_params->amsdu_size_8K)
- rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
- else
- rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
-
- /* Stop Rx DMA */
- iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-
- /* Reset driver's Rx queue write index */
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-
- /* Tell device where to find RBD circular buffer in DRAM */
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- rxq->dma_addr >> 8);
-
- /* Tell device where in DRAM to update its Rx status */
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
- (priv->shared_phys +
- offsetof(struct iwl4965_shared, rb_closed)) >> 4);
-
- /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
- iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
- FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
- FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
- rb_size |
- /* 0x10 << 4 | */
- (RX_QUEUE_SIZE_LOG <<
- FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
-
- /*
- * iwl_write32(priv,CSR_INT_COAL_REG,0);
- */
-
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-/* Tell 4965 where to find the "keep warm" buffer */
-static int iwl4965_kw_init(struct iwl_priv *priv)
-{
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_nic_access(priv);
- if (rc)
- goto out;
-
- iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG,
- priv->kw.dma_addr >> 4);
+ iwl_write_prph(priv, IWL49_SCD_TXFACT, 0);
iwl_release_nic_access(priv);
-out:
spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
-}
-
-static int iwl4965_kw_alloc(struct iwl_priv *priv)
-{
- struct pci_dev *dev = priv->pci_dev;
- struct iwl4965_kw *kw = &priv->kw;
-
- kw->size = IWL4965_KW_SIZE; /* TBW need set somewhere else */
- kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr);
- if (!kw->v_addr)
- return -ENOMEM;
return 0;
}
-/**
- * iwl4965_kw_free - Free the "keep warm" buffer
- */
-static void iwl4965_kw_free(struct iwl_priv *priv)
-{
- struct pci_dev *dev = priv->pci_dev;
- struct iwl4965_kw *kw = &priv->kw;
-
- if (kw->v_addr) {
- pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr);
- memset(kw, 0, sizeof(*kw));
- }
-}
-
-/**
- * iwl4965_txq_ctx_reset - Reset TX queue context
- * Destroys all DMA structures and initialise them again
- *
- * @param priv
- * @return error code
- */
-static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
-{
- int rc = 0;
- int txq_id, slots_num;
- unsigned long flags;
-
- iwl4965_kw_free(priv);
-
- /* Free all tx/cmd queues and keep-warm buffer */
- iwl4965_hw_txq_ctx_free(priv);
-
- /* Alloc keep-warm buffer */
- rc = iwl4965_kw_alloc(priv);
- if (rc) {
- IWL_ERROR("Keep Warm allocation failed");
- goto error_kw;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- rc = iwl_grab_nic_access(priv);
- if (unlikely(rc)) {
- IWL_ERROR("TX reset failed");
- spin_unlock_irqrestore(&priv->lock, flags);
- goto error_reset;
- }
-
- /* Turn off all Tx DMA channels */
- iwl_write_prph(priv, IWL49_SCD_TXFACT, 0);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Tell 4965 where to find the keep-warm buffer */
- rc = iwl4965_kw_init(priv);
- if (rc) {
- IWL_ERROR("kw_init failed\n");
- goto error_reset;
- }
-
- /* Alloc and init all (default 16) Tx queues,
- * including the command queue (#4) */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
- txq_id);
- if (rc) {
- IWL_ERROR("Tx %d queue init failed\n", txq_id);
- goto error;
- }
- }
-
- return rc;
-
- error:
- iwl4965_hw_txq_ctx_free(priv);
- error_reset:
- iwl4965_kw_free(priv);
- error_kw:
- return rc;
-}
static int iwl4965_apm_init(struct iwl_priv *priv)
{
- unsigned long flags;
int ret = 0;
- spin_lock_irqsave(&priv->lock, flags);
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
@@ -575,7 +523,6 @@ static int iwl4965_apm_init(struct iwl_priv *priv)
iwl_release_nic_access(priv);
out:
- spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
@@ -621,59 +568,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-
-int iwl4965_hw_nic_init(struct iwl_priv *priv)
-{
- unsigned long flags;
- struct iwl4965_rx_queue *rxq = &priv->rxq;
- int ret;
-
- /* nic_init */
- priv->cfg->ops->lib->apm_ops.init(priv);
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
-
- priv->cfg->ops->lib->apm_ops.config(priv);
-
- iwl4965_hw_card_show_info(priv);
-
- /* end nic_init */
-
- /* Allocate the RX queue, or reset if it is already allocated */
- if (!rxq->bd) {
- ret = iwl4965_rx_queue_alloc(priv);
- if (ret) {
- IWL_ERROR("Unable to initialize Rx queue\n");
- return -ENOMEM;
- }
- } else
- iwl4965_rx_queue_reset(priv, rxq);
-
- iwl4965_rx_replenish(priv);
-
- iwl4965_rx_init(priv, rxq);
-
- spin_lock_irqsave(&priv->lock, flags);
-
- rxq->need_update = 1;
- iwl4965_rx_queue_update_write_ptr(priv, rxq);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Allocate and init all Tx and Command queues */
- ret = iwl4965_txq_ctx_reset(priv);
- if (ret)
- return ret;
-
- set_bit(STATUS_INIT, &priv->status);
-
- return 0;
-}
-
int iwl4965_hw_nic_stop_master(struct iwl_priv *priv)
{
int rc = 0;
@@ -734,7 +628,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
}
/* Deallocate memory for all Tx queues */
- iwl4965_hw_txq_ctx_free(priv);
+ iwl_hw_txq_ctx_free(priv);
}
int iwl4965_hw_nic_reset(struct iwl_priv *priv)
@@ -984,7 +878,7 @@ static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
* NOTE: Acquire priv->lock before calling this function !
*/
static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq,
+ struct iwl_tx_queue *txq,
int tx_fifo_id, int scd_retry)
{
int txq_id = txq->q.id;
@@ -1188,82 +1082,6 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
return 0;
}
-/**
- * iwl4965_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv)
-{
- int txq_id;
-
- /* Tx queues */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- iwl4965_tx_queue_free(priv, &priv->txq[txq_id]);
-
- /* Keep-warm buffer */
- iwl4965_kw_free(priv);
-}
-
-/**
- * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
- *
- * Does NOT advance any TFD circular buffer read/write indexes
- * Does NOT free the TFD itself (which is within circular buffer)
- */
-int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
-{
- struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0];
- struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
- struct pci_dev *dev = priv->pci_dev;
- int i;
- int counter = 0;
- int index, is_odd;
-
- /* Host command buffers stay mapped in memory, nothing to clean */
- if (txq->q.id == IWL_CMD_QUEUE_NUM)
- return 0;
-
- /* Sanity check on number of chunks */
- counter = IWL_GET_BITS(*bd, num_tbs);
- if (counter > MAX_NUM_OF_TBS) {
- IWL_ERROR("Too many chunks: %i\n", counter);
- /* @todo issue fatal error, it is quite serious situation */
- return 0;
- }
-
- /* Unmap chunks, if any.
- * TFD info for odd chunks is different format than for even chunks. */
- for (i = 0; i < counter; i++) {
- index = i / 2;
- is_odd = i & 0x1;
-
- if (is_odd)
- pci_unmap_single(
- dev,
- IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
- (IWL_GET_BITS(bd->pa[index],
- tb2_addr_hi20) << 16),
- IWL_GET_BITS(bd->pa[index], tb2_len),
- PCI_DMA_TODEVICE);
-
- else if (i > 0)
- pci_unmap_single(dev,
- le32_to_cpu(bd->pa[index].tb1_addr),
- IWL_GET_BITS(bd->pa[index], tb1_len),
- PCI_DMA_TODEVICE);
-
- /* Free SKB, if any, for this chunk */
- if (txq->txb[txq->q.read_ptr].skb[i]) {
- struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i];
-
- dev_kfree_skb(skb);
- txq->txb[txq->q.read_ptr].skb[i] = NULL;
- }
- }
- return 0;
-}
-
/* set card power command */
static int iwl4965_set_power(struct iwl_priv *priv,
void *cmd)
@@ -2186,7 +2004,7 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
}
-int iwl4965_hw_get_rx_read(struct iwl_priv *priv)
+static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv)
{
struct iwl4965_shared *s = priv->shared_virt;
return le32_to_cpu(s->rb_closed) & 0xFFF;
@@ -2229,46 +2047,11 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
return (sizeof(*tx_beacon_cmd) + frame_size);
}
-/*
- * Tell 4965 where to find circular buffer of Tx Frame Descriptors for
- * given Tx queue, and enable the DMA channel used for that queue.
- *
- * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
- * channels supported in hardware.
- */
-int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
-{
- int rc;
- unsigned long flags;
- int txq_id = txq->q.id;
-
- spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_nic_access(priv);
- if (rc) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
-
- /* Circular buffer (TFD queue in DRAM) physical base address */
- iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
- txq->q.dma_addr >> 8);
-
- /* Enable DMA channel, using same id as for TFD queue */
- iwl_write_direct32(
- priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
- FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
- FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
- iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
dma_addr_t addr, u16 len)
{
int index, is_odd;
- struct iwl4965_tfd_frame *tfd = ptr;
+ struct iwl_tfd_frame *tfd = ptr;
u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs);
/* Each TFD can point to a maximum 20 Tx buffers */
@@ -2298,18 +2081,6 @@ int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
return 0;
}
-static void iwl4965_hw_card_show_info(struct iwl_priv *priv)
-{
- u16 hw_version = iwl_eeprom_query16(priv, EEPROM_4965_BOARD_REVISION);
-
- IWL_DEBUG_INFO("4965ABGN HW Version %u.%u.%u\n",
- ((hw_version >> 8) & 0x0F),
- ((hw_version >> 8) >> 4), (hw_version & 0x00FF));
-
- IWL_DEBUG_INFO("4965ABGN PBA Number %.16s\n",
- &priv->eeprom[EEPROM_4965_BOARD_PBA]);
-}
-
static int iwl4965_alloc_shared_mem(struct iwl_priv *priv)
{
priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
@@ -2320,6 +2091,8 @@ static int iwl4965_alloc_shared_mem(struct iwl_priv *priv)
memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared));
+ priv->rb_closed_offset = offsetof(struct iwl4965_shared, rb_closed);
+
return 0;
}
@@ -2336,7 +2109,7 @@ static void iwl4965_free_shared_mem(struct iwl_priv *priv)
* iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq,
+ struct iwl_tx_queue *txq,
u16 byte_cnt)
{
int len;
@@ -2516,9 +2289,10 @@ static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
priv->last_rx_noise);
}
-void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
+void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
int change;
s32 temp;
@@ -2588,7 +2362,7 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv,
struct ieee80211_rx_status *stats,
u32 ampdu_status)
{
- s8 signal = stats->ssi;
+ s8 signal = stats->signal;
s8 noise = 0;
int rate = stats->rate_idx;
u64 tsf = stats->mactime;
@@ -2742,7 +2516,7 @@ static int iwl4965_set_decrypted_flag(struct iwl_priv *priv,
return 0;
}
-static u32 iwl4965_translate_rx_status(u32 decrypt_in)
+static u32 iwl4965_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
{
u32 decrypt_out = 0;
@@ -2803,10 +2577,10 @@ static u32 iwl4965_translate_rx_status(u32 decrypt_in)
static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
int include_phy,
- struct iwl4965_rx_mem_buffer *rxb,
+ struct iwl_rx_mem_buffer *rxb,
struct ieee80211_rx_status *stats)
{
- struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
(struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
struct ieee80211_hdr *hdr;
@@ -2843,7 +2617,9 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
rx_start->byte_count = amsdu->byte_count;
rx_end = (__le32 *) (((u8 *) hdr) + len);
}
- if (len > priv->hw_params.max_pkt_size || len < 16) {
+ /* In monitor mode allow 802.11 ACk frames (10 bytes) */
+ if (len > priv->hw_params.max_pkt_size ||
+ len < ((priv->iw_mode == IEEE80211_IF_TYPE_MNTR) ? 10 : 16)) {
IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
return;
}
@@ -2854,7 +2630,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
if (!include_phy) {
/* New status scheme, need to translate */
ampdu_status_legacy = ampdu_status;
- ampdu_status = iwl4965_translate_rx_status(ampdu_status);
+ ampdu_status = iwl4965_translate_rx_status(priv, ampdu_status);
}
/* start from MAC */
@@ -2886,7 +2662,8 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
}
/* Calc max signal level (dBm) among 3 possible receivers */
-static int iwl4965_calc_rssi(struct iwl4965_rx_phy_res *rx_resp)
+static int iwl4965_calc_rssi(struct iwl_priv *priv,
+ struct iwl4965_rx_phy_res *rx_resp)
{
/* data from PHY/DSP regarding signal strength, etc.,
* contents are always there, not configurable by host. */
@@ -2930,7 +2707,7 @@ static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
}
static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
@@ -2963,7 +2740,7 @@ static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
* proper operation with 4965.
*/
static void iwl4965_dbg_report_frame(struct iwl_priv *priv,
- struct iwl4965_rx_packet *pkt,
+ struct iwl_rx_packet *pkt,
struct ieee80211_hdr *header, int group100)
{
u32 to_us;
@@ -2990,7 +2767,7 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv,
struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
u8 *data = IWL_RX_DATA(pkt);
- if (likely(!(iwl_debug_level & IWL_DL_RX)))
+ if (likely(!(priv->debug_level & IWL_DL_RX)))
return;
/* MAC header */
@@ -3093,11 +2870,11 @@ static void iwl4965_dbg_report_frame(struct iwl_priv *priv,
}
}
if (print_dump)
- iwl_print_hex_dump(IWL_DL_RX, data, length);
+ iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
}
#else
static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv,
- struct iwl4965_rx_packet *pkt,
+ struct iwl_rx_packet *pkt,
struct ieee80211_hdr *header,
int group100)
{
@@ -3109,11 +2886,11 @@ static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv,
/* Called for REPLY_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
struct ieee80211_hdr *header;
struct ieee80211_rx_status rx_status;
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
/* Use phy data (Rx signal strength, etc.) contained within
* this rx packet for legacy frames,
* or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
@@ -3186,7 +2963,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
/* Find max signal strength (dBm) among 3 antenna/receiver chains */
- rx_status.ssi = iwl4965_calc_rssi(rx_start);
+ rx_status.signal = iwl4965_calc_rssi(priv, rx_start);
/* Meaningful noise values are available only from beacon statistics,
* which are gathered only when associated, and indicate noise
@@ -3195,11 +2972,11 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
if (iwl_is_associated(priv) &&
!test_bit(STATUS_SCANNING, &priv->status)) {
rx_status.noise = priv->last_rx_noise;
- rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi,
+ rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal,
rx_status.noise);
} else {
rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
- rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, 0);
+ rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal, 0);
}
/* Reset beacon noise level if not associated. */
@@ -3211,12 +2988,19 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
iwl4965_dbg_report_frame(priv, pkt, header, 1);
IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
- rx_status.ssi, rx_status.noise, rx_status.signal,
+ rx_status.signal, rx_status.noise, rx_status.signal,
(unsigned long long)rx_status.mactime);
+
+ if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
+ iwl4965_handle_data_packet(priv, 1, include_phy,
+ rxb, &rx_status);
+ return;
+ }
+
network_packet = iwl4965_is_network_packet(priv, header);
if (network_packet) {
- priv->last_rx_rssi = rx_status.ssi;
+ priv->last_rx_rssi = rx_status.signal;
priv->last_beacon_time = priv->ucode_beacon_time;
priv->last_tsf = le64_to_cpu(rx_start->timestamp);
}
@@ -3278,19 +3062,19 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
* This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
priv->last_phy_res[0] = 1;
memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
sizeof(struct iwl4965_rx_phy_res));
}
static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_missed_beacon_notif *missed_beacon;
missed_beacon = &pkt->u.missed_beacon;
@@ -3322,7 +3106,7 @@ static void iwl4965_sta_modify_enable_tid_tx(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
}
/**
@@ -3332,7 +3116,7 @@ static void iwl4965_sta_modify_enable_tid_tx(struct iwl_priv *priv,
* ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
*/
static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl4965_ht_agg *agg,
+ struct iwl_ht_agg *agg,
struct iwl4965_compressed_ba_resp*
ba_resp)
@@ -3449,7 +3233,7 @@ int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
{
struct iwl4965_queue *q = &priv->txq[txq_id].q;
u8 *addr = priv->stations[sta_id].sta.sta.addr;
- struct iwl4965_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
+ struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
switch (priv->stations[sta_id].tid[tid].agg.state) {
case IWL_EMPTYING_HW_QUEUE_DELBA:
@@ -3495,13 +3279,13 @@ static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
* of frames sent via aggregation.
*/
static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
int index;
- struct iwl4965_tx_queue *txq = NULL;
- struct iwl4965_ht_agg *agg;
+ struct iwl_tx_queue *txq = NULL;
+ struct iwl_ht_agg *agg;
DECLARE_MAC_BUF(mac);
/* "flow" corresponds to Tx queue */
@@ -3547,13 +3331,16 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
* block-ack window (we assume that they've been successfully
* transmitted ... if not, it's too late anyway). */
if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
+ /* calculate mac80211 ampdu sw queue to wake */
+ int ampdu_q =
+ scd_flow - IWL_BACK_QUEUE_FIRST_ID + priv->hw->queues;
int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index);
priv->stations[ba_resp->sta_id].
tid[ba_resp->tid].tfds_in_queue -= freed;
if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
priv->mac80211_registered &&
agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
- ieee80211_wake_queue(priv->hw, scd_flow);
+ ieee80211_wake_queue(priv->hw, ampdu_q);
iwl4965_check_empty_hw_queue(priv, ba_resp->sta_id,
ba_resp->tid, scd_flow);
}
@@ -3714,103 +3501,6 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
#ifdef CONFIG_IWL4965_HT
-static u8 iwl4965_is_channel_extension(struct iwl_priv *priv,
- enum ieee80211_band band,
- u16 channel, u8 extension_chan_offset)
-{
- const struct iwl_channel_info *ch_info;
-
- ch_info = iwl_get_channel_info(priv, band, channel);
- if (!is_channel_valid(ch_info))
- return 0;
-
- if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)
- return 0;
-
- if ((ch_info->fat_extension_channel == extension_chan_offset) ||
- (ch_info->fat_extension_channel == HT_IE_EXT_CHANNEL_MAX))
- return 1;
-
- return 0;
-}
-
-static u8 iwl4965_is_fat_tx_allowed(struct iwl_priv *priv,
- struct ieee80211_ht_info *sta_ht_inf)
-{
- struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
-
- if ((!iwl_ht_conf->is_ht) ||
- (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
- (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE))
- return 0;
-
- if (sta_ht_inf) {
- if ((!sta_ht_inf->ht_supported) ||
- (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH)))
- return 0;
- }
-
- return (iwl4965_is_channel_extension(priv, priv->band,
- iwl_ht_conf->control_channel,
- iwl_ht_conf->extension_chan_offset));
-}
-
-void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
-{
- struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
- u32 val;
-
- if (!ht_info->is_ht)
- return;
-
- /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */
- if (iwl4965_is_fat_tx_allowed(priv, NULL))
- rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK;
- else
- rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
- RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
-
- if (le16_to_cpu(rxon->channel) != ht_info->control_channel) {
- IWL_DEBUG_ASSOC("control diff than current %d %d\n",
- le16_to_cpu(rxon->channel),
- ht_info->control_channel);
- rxon->channel = cpu_to_le16(ht_info->control_channel);
- return;
- }
-
- /* Note: control channel is opposite of extension channel */
- switch (ht_info->extension_chan_offset) {
- case IWL_EXT_CHANNEL_OFFSET_ABOVE:
- rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
- break;
- case IWL_EXT_CHANNEL_OFFSET_BELOW:
- rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
- break;
- case IWL_EXT_CHANNEL_OFFSET_NONE:
- default:
- rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
- break;
- }
-
- val = ht_info->ht_protection;
-
- rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS);
-
- iwl_set_rxon_chain(priv);
-
- IWL_DEBUG_ASSOC("supported HT rate 0x%X 0x%X 0x%X "
- "rxon flags 0x%X operation mode :0x%X "
- "extension channel offset 0x%x "
- "control chan %d\n",
- ht_info->supp_mcs_set[0],
- ht_info->supp_mcs_set[1],
- ht_info->supp_mcs_set[2],
- le32_to_cpu(rxon->flags), ht_info->ht_protection,
- ht_info->extension_chan_offset,
- ht_info->control_channel);
- return;
-}
-
void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
struct ieee80211_ht_info *sta_ht_inf)
{
@@ -3846,7 +3536,7 @@ void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
sta_flags |= cpu_to_le32(
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
- if (iwl4965_is_fat_tx_allowed(priv, sta_ht_inf))
+ if (iwl_is_fat_tx_allowed(priv, sta_ht_inf))
sta_flags |= STA_FLG_FAT_EN_MSK;
else
sta_flags &= ~STA_FLG_FAT_EN_MSK;
@@ -3874,7 +3564,7 @@ static int iwl4965_rx_agg_start(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta,
+ return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
CMD_ASYNC);
}
@@ -3895,7 +3585,7 @@ static int iwl4965_rx_agg_stop(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta,
+ return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
CMD_ASYNC);
}
@@ -3925,7 +3615,7 @@ static int iwl4965_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra,
int ssn = -1;
int ret = 0;
unsigned long flags;
- struct iwl4965_tid_data *tid_data;
+ struct iwl_tid_data *tid_data;
DECLARE_MAC_BUF(mac);
if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
@@ -3978,7 +3668,7 @@ static int iwl4965_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid)
{
struct iwl_priv *priv = hw->priv;
int tx_fifo_id, txq_id, sta_id, ssn = -1;
- struct iwl4965_tid_data *tid_data;
+ struct iwl_tid_data *tid_data;
int ret, write_ptr, read_ptr;
unsigned long flags;
DECLARE_MAC_BUF(mac);
@@ -4060,9 +3750,26 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
}
return 0;
}
-
#endif /* CONFIG_IWL4965_HT */
+
+static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
+{
+ struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data;
+ addsta->mode = cmd->mode;
+ memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
+ memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
+ addsta->station_flags = cmd->station_flags;
+ addsta->station_flags_msk = cmd->station_flags_msk;
+ addsta->tid_disable_tx = cmd->tid_disable_tx;
+ addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
+ addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
+ addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
+ addsta->reserved1 = __constant_cpu_to_le16(0);
+ addsta->reserved2 = __constant_cpu_to_le32(0);
+
+ return (u16)sizeof(struct iwl4965_addsta_cmd);
+}
/* Set up 4965-specific Rx frame reply handlers */
static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
{
@@ -4106,6 +3813,7 @@ static struct iwl_hcmd_ops iwl4965_hcmd = {
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.enqueue_hcmd = iwl4965_enqueue_hcmd,
+ .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
.chain_noise_reset = iwl4965_chain_noise_reset,
.gain_computation = iwl4965_gain_computation,
@@ -4116,11 +3824,13 @@ static struct iwl_lib_ops iwl4965_lib = {
.set_hw_params = iwl4965_hw_set_hw_params,
.alloc_shared_mem = iwl4965_alloc_shared_mem,
.free_shared_mem = iwl4965_free_shared_mem,
+ .shared_mem_rx_idx = iwl4965_shared_mem_rx_idx,
.txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
- .hw_nic_init = iwl4965_hw_nic_init,
+ .disable_tx_fifo = iwl4965_disable_tx_fifo,
.rx_handler_setup = iwl4965_rx_handler_setup,
.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
.alive_notify = iwl4965_alive_notify,
+ .init_alive_start = iwl4965_init_alive_start,
.load_ucode = iwl4965_load_bsm,
.apm_ops = {
.init = iwl4965_apm_init,
@@ -4183,4 +3893,5 @@ module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444);
MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444);
MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
-
+module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444);
+MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error");
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 0d8ef63f871..b5e28b81179 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -86,7 +86,7 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
return ret;
}
-static void iwl5000_nic_init(struct iwl_priv *priv)
+static void iwl5000_nic_config(struct iwl_priv *priv)
{
unsigned long flags;
u16 radio_cfg;
@@ -362,6 +362,8 @@ static int iwl5000_alloc_shared_mem(struct iwl_priv *priv)
memset(priv->shared_virt, 0, sizeof(struct iwl5000_shared));
+ priv->rb_closed_offset = offsetof(struct iwl5000_shared, rb_closed);
+
return 0;
}
@@ -374,11 +376,17 @@ static void iwl5000_free_shared_mem(struct iwl_priv *priv)
priv->shared_phys);
}
+static int iwl5000_shared_mem_rx_idx(struct iwl_priv *priv)
+{
+ struct iwl5000_shared *s = priv->shared_virt;
+ return le32_to_cpu(s->rb_closed) & 0xFFF;
+}
+
/**
* iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq,
+ struct iwl_tx_queue *txq,
u16 byte_cnt)
{
struct iwl5000_shared *shared_data = priv->shared_virt;
@@ -422,10 +430,40 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
}
}
+static u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
+{
+ u16 size = (u16)sizeof(struct iwl_addsta_cmd);
+ memcpy(data, cmd, size);
+ return size;
+}
+
+
+static int iwl5000_disable_tx_fifo(struct iwl_priv *priv)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ ret = iwl_grab_nic_access(priv);
+ if (unlikely(ret)) {
+ IWL_ERROR("Tx fifo reset failed");
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+ }
+
+ iwl_write_prph(priv, IWL50_SCD_TXFACT, 0);
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
static struct iwl_hcmd_ops iwl5000_hcmd = {
};
static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
+ .build_addsta_hcmd = iwl5000_build_addsta_hcmd,
#ifdef CONFIG_IWL5000_RUN_TIME_CALIB
.gain_computation = iwl5000_gain_computation,
.chain_noise_reset = iwl5000_chain_noise_reset,
@@ -436,10 +474,12 @@ static struct iwl_lib_ops iwl5000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
.alloc_shared_mem = iwl5000_alloc_shared_mem,
.free_shared_mem = iwl5000_free_shared_mem,
+ .shared_mem_rx_idx = iwl5000_shared_mem_rx_idx,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
+ .disable_tx_fifo = iwl5000_disable_tx_fifo,
.apm_ops = {
.init = iwl5000_apm_init,
- .config = iwl5000_nic_init,
+ .config = iwl5000_nic_config,
.set_pwr_src = iwl4965_set_pwr_src,
},
.eeprom_ops = {
@@ -470,6 +510,7 @@ static struct iwl_mod_params iwl50_mod_params = {
.num_of_queues = IWL50_NUM_QUEUES,
.enable_qos = 1,
.amsdu_size_8K = 1,
+ .restart_fw = 1,
/* the rest are 0 by default */
};
@@ -515,5 +556,5 @@ module_param_named(qos_enable50, iwl50_mod_params.enable_qos, int, 0444);
MODULE_PARM_DESC(qos_enable50, "enable all 50XX QoS functionality");
module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444);
MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series");
-
-
+module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444);
+MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error");
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 5afa7b79b59..d16a853f376 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -769,6 +769,20 @@ struct iwl4965_keyinfo {
u8 key[16]; /* 16-byte unicast decryption key */
} __attribute__ ((packed));
+/* 5000 */
+struct iwl_keyinfo {
+ __le16 key_flags;
+ u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
+ u8 reserved1;
+ __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
+ u8 key_offset;
+ u8 reserved2;
+ u8 key[16]; /* 16-byte unicast decryption key */
+ __le64 tx_secur_seq_cnt;
+ __le64 hw_tkip_mic_rx_key;
+ __le64 hw_tkip_mic_tx_key;
+} __attribute__ ((packed));
+
/**
* struct sta_id_modify
* @addr[ETH_ALEN]: station's MAC address
@@ -844,6 +858,38 @@ struct iwl4965_addsta_cmd {
__le32 reserved2;
} __attribute__ ((packed));
+/* 5000 */
+struct iwl_addsta_cmd {
+ u8 mode; /* 1: modify existing, 0: add new station */
+ u8 reserved[3];
+ struct sta_id_modify sta;
+ struct iwl_keyinfo key;
+ __le32 station_flags; /* STA_FLG_* */
+ __le32 station_flags_msk; /* STA_FLG_* */
+
+ /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+ * corresponding to bit (e.g. bit 5 controls TID 5).
+ * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+ __le16 tid_disable_tx;
+
+ __le16 reserved1;
+
+ /* TID for which to add block-ack support.
+ * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+ u8 add_immediate_ba_tid;
+
+ /* TID for which to remove block-ack support.
+ * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+ u8 remove_immediate_ba_tid;
+
+ /* Starting Sequence Number for added block-ack support.
+ * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+ __le16 add_immediate_ba_ssn;
+
+ __le32 reserved2;
+} __attribute__ ((packed));
+
+
#define ADD_STA_SUCCESS_MSK 0x1
#define ADD_STA_NO_ROOM_IN_TABLE 0x2
#define ADD_STA_NO_BLOCK_ACK_RESOURCE 0x4
@@ -2731,7 +2777,7 @@ struct iwl4965_led_cmd {
*
*****************************************************************************/
-struct iwl4965_rx_packet {
+struct iwl_rx_packet {
__le32 len;
struct iwl_cmd_header hdr;
union {
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index c4b5c1a100f..d3cbad2bf87 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -46,11 +46,6 @@ MODULE_VERSION(IWLWIFI_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");
-#ifdef CONFIG_IWLWIFI_DEBUG
-u32 iwl_debug_level;
-EXPORT_SYMBOL(iwl_debug_level);
-#endif
-
#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
IWL_RATE_SISO_##s##M_PLCP, \
@@ -121,6 +116,100 @@ void iwl_hw_detect(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_hw_detect);
+/* Tell nic where to find the "keep warm" buffer */
+int iwl_kw_init(struct iwl_priv *priv)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = iwl_grab_nic_access(priv);
+ if (ret)
+ goto out;
+
+ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG,
+ priv->kw.dma_addr >> 4);
+ iwl_release_nic_access(priv);
+out:
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+}
+
+int iwl_kw_alloc(struct iwl_priv *priv)
+{
+ struct pci_dev *dev = priv->pci_dev;
+ struct iwl_kw *kw = &priv->kw;
+
+ kw->size = IWL_KW_SIZE;
+ kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr);
+ if (!kw->v_addr)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * iwl_kw_free - Free the "keep warm" buffer
+ */
+void iwl_kw_free(struct iwl_priv *priv)
+{
+ struct pci_dev *dev = priv->pci_dev;
+ struct iwl_kw *kw = &priv->kw;
+
+ if (kw->v_addr) {
+ pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr);
+ memset(kw, 0, sizeof(*kw));
+ }
+}
+
+int iwl_hw_nic_init(struct iwl_priv *priv)
+{
+ unsigned long flags;
+ struct iwl_rx_queue *rxq = &priv->rxq;
+ int ret;
+
+ /* nic_init */
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->cfg->ops->lib->apm_ops.init(priv);
+ iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
+
+ priv->cfg->ops->lib->apm_ops.config(priv);
+
+ /* Allocate the RX queue, or reset if it is already allocated */
+ if (!rxq->bd) {
+ ret = iwl_rx_queue_alloc(priv);
+ if (ret) {
+ IWL_ERROR("Unable to initialize Rx queue\n");
+ return -ENOMEM;
+ }
+ } else
+ iwl_rx_queue_reset(priv, rxq);
+
+ iwl_rx_replenish(priv);
+
+ iwl_rx_init(priv, rxq);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ rxq->need_update = 1;
+ iwl_rx_queue_update_write_ptr(priv, rxq);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Allocate and init all Tx and Command queues */
+ ret = iwl_txq_ctx_reset(priv);
+ if (ret)
+ return ret;
+
+ set_bit(STATUS_INIT, &priv->status);
+
+ return 0;
+}
+EXPORT_SYMBOL(iwl_hw_nic_init);
+
/**
* iwlcore_clear_stations_table - Clear the driver's station table
*
@@ -259,6 +348,12 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
if (priv->hw_params.tx_chains_num >= 3)
ht_info->supp_mcs_set[2] = 0xFF;
}
+#else
+static inline void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
+ struct ieee80211_ht_info *ht_info,
+ enum ieee80211_band band)
+{
+}
#endif /* CONFIG_IWL4965_HT */
static void iwlcore_init_hw_rates(struct iwl_priv *priv,
@@ -428,6 +523,105 @@ static u8 is_single_rx_stream(struct iwl_priv *priv)
(priv->current_ht_config.supp_mcs_set[2] == 0)) ||
priv->ps_mode == IWL_MIMO_PS_STATIC;
}
+static u8 iwl_is_channel_extension(struct iwl_priv *priv,
+ enum ieee80211_band band,
+ u16 channel, u8 extension_chan_offset)
+{
+ const struct iwl_channel_info *ch_info;
+
+ ch_info = iwl_get_channel_info(priv, band, channel);
+ if (!is_channel_valid(ch_info))
+ return 0;
+
+ if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)
+ return 0;
+
+ if ((ch_info->fat_extension_channel == extension_chan_offset) ||
+ (ch_info->fat_extension_channel == HT_IE_EXT_CHANNEL_MAX))
+ return 1;
+
+ return 0;
+}
+
+u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
+ struct ieee80211_ht_info *sta_ht_inf)
+{
+ struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
+
+ if ((!iwl_ht_conf->is_ht) ||
+ (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
+ (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE))
+ return 0;
+
+ if (sta_ht_inf) {
+ if ((!sta_ht_inf->ht_supported) ||
+ (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH)))
+ return 0;
+ }
+
+ return iwl_is_channel_extension(priv, priv->band,
+ iwl_ht_conf->control_channel,
+ iwl_ht_conf->extension_chan_offset);
+}
+EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
+
+void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
+{
+ struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
+ u32 val;
+
+ if (!ht_info->is_ht)
+ return;
+
+ /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */
+ if (iwl_is_fat_tx_allowed(priv, NULL))
+ rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK;
+ else
+ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
+ RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
+
+ if (le16_to_cpu(rxon->channel) != ht_info->control_channel) {
+ IWL_DEBUG_ASSOC("control diff than current %d %d\n",
+ le16_to_cpu(rxon->channel),
+ ht_info->control_channel);
+ rxon->channel = cpu_to_le16(ht_info->control_channel);
+ return;
+ }
+
+ /* Note: control channel is opposite of extension channel */
+ switch (ht_info->extension_chan_offset) {
+ case IWL_EXT_CHANNEL_OFFSET_ABOVE:
+ rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+ break;
+ case IWL_EXT_CHANNEL_OFFSET_BELOW:
+ rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+ break;
+ case IWL_EXT_CHANNEL_OFFSET_NONE:
+ default:
+ rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
+ break;
+ }
+
+ val = ht_info->ht_protection;
+
+ rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS);
+
+ iwl_set_rxon_chain(priv);
+
+ IWL_DEBUG_ASSOC("supported HT rate 0x%X 0x%X 0x%X "
+ "rxon flags 0x%X operation mode :0x%X "
+ "extension channel offset 0x%x "
+ "control chan %d\n",
+ ht_info->supp_mcs_set[0],
+ ht_info->supp_mcs_set[1],
+ ht_info->supp_mcs_set[2],
+ le32_to_cpu(rxon->flags), ht_info->ht_protection,
+ ht_info->extension_chan_offset,
+ ht_info->control_channel);
+ return;
+}
+EXPORT_SYMBOL(iwl_set_rxon_ht);
+
#else
static inline u8 is_single_rx_stream(struct iwl_priv *priv)
{
@@ -552,18 +746,10 @@ static void iwlcore_init_hw(struct iwl_priv *priv)
struct ieee80211_hw *hw = priv->hw;
hw->rate_control_algorithm = "iwl-4965-rs";
- /* Tell mac80211 and its clients (e.g. Wireless Extensions)
- * the range of signal quality values that we'll provide.
- * Negative values for level/noise indicate that we'll provide dBm.
- * For WE, at least, non-0 values here *enable* display of values
- * in app (iwconfig). */
- hw->max_rssi = -20; /* signal level, negative indicates dBm */
- hw->max_noise = -20; /* noise level, negative indicates dBm */
- hw->max_signal = 100; /* link quality indication (%) */
-
- /* Tell mac80211 our Tx characteristics */
- hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
-
+ /* Tell mac80211 our characteristics */
+ hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_NOISE_DBM;
/* Default value; 4 EDCA QOS priorities */
hw->queues = 4;
#ifdef CONFIG_IWL4965_HT
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 369f1821584..e139c8ffa9a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -87,6 +87,7 @@ struct iwl_hcmd_ops {
};
struct iwl_hcmd_utils_ops {
int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+ u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data);
#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
void (*gain_computation)(struct iwl_priv *priv,
u32 *average_noise,
@@ -102,13 +103,16 @@ struct iwl_lib_ops {
/* ucode shared memory */
int (*alloc_shared_mem)(struct iwl_priv *priv);
void (*free_shared_mem)(struct iwl_priv *priv);
+ int (*shared_mem_rx_idx)(struct iwl_priv *priv);
void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq,
+ struct iwl_tx_queue *txq,
u16 byte_cnt);
/* setup Rx handler */
void (*rx_handler_setup)(struct iwl_priv *priv);
- /* nic init */
- int (*hw_nic_init)(struct iwl_priv *priv);
+ /* nic Tx fifo handling */
+ int (*disable_tx_fifo)(struct iwl_priv *priv);
+ /* alive notification after init uCode load */
+ void (*init_alive_start)(struct iwl_priv *priv);
/* alive notification */
int (*alive_notify)(struct iwl_priv *priv);
/* check validity of rtc data address */
@@ -145,6 +149,7 @@ struct iwl_mod_params {
int enable_qos; /* def: 1 = use quality of service */
int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
int antenna; /* def: 0 = both antennas (use diversity) */
+ int restart_fw; /* def: 1 = restart firmware */
};
struct iwl_cfg {
@@ -172,6 +177,39 @@ int iwl_set_rxon_channel(struct iwl_priv *priv,
u16 channel);
void iwlcore_free_geos(struct iwl_priv *priv);
int iwl_setup(struct iwl_priv *priv);
+void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
+u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
+ struct ieee80211_ht_info *sta_ht_inf);
+int iwl_hw_nic_init(struct iwl_priv *priv);
+
+/* "keep warm" functions */
+int iwl_kw_init(struct iwl_priv *priv);
+int iwl_kw_alloc(struct iwl_priv *priv);
+void iwl_kw_free(struct iwl_priv *priv);
+
+/*****************************************************
+* RX
+******************************************************/
+void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+int iwl_rx_queue_alloc(struct iwl_priv *priv);
+void iwl_rx_handle(struct iwl_priv *priv);
+int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
+ struct iwl_rx_queue *q);
+void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+void iwl_rx_replenish(struct iwl_priv *priv);
+int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+/* FIXME: remove when TX is moved to iwl core */
+int iwl_rx_queue_restock(struct iwl_priv *priv);
+int iwl_rx_queue_space(const struct iwl_rx_queue *q);
+void iwl_rx_allocate(struct iwl_priv *priv);
+
+/*****************************************************
+* TX
+******************************************************/
+int iwl_txq_ctx_reset(struct iwl_priv *priv);
+/* FIXME: remove when free Tx is fully merged into iwlcore */
+int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
@@ -265,4 +303,5 @@ static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
return priv->cfg->ops->hcmd->rxon_assoc(priv);
}
+
#endif /* __iwl_core_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index c60724c21db..2f24594c5fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -30,26 +30,16 @@
#define __iwl_debug_h__
#ifdef CONFIG_IWLWIFI_DEBUG
-extern u32 iwl_debug_level;
#define IWL_DEBUG(level, fmt, args...) \
-do { if (iwl_debug_level & (level)) \
- printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+do { if (priv->debug_level & (level)) \
+ dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \
in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
#define IWL_DEBUG_LIMIT(level, fmt, args...) \
-do { if ((iwl_debug_level & (level)) && net_ratelimit()) \
- printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+do { if ((priv->debug_level & (level)) && net_ratelimit()) \
+ dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \
in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
-static inline void iwl_print_hex_dump(int level, void *p, u32 len)
-{
- if (!(iwl_debug_level & level))
- return;
-
- print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
- p, len, 1);
-}
-
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_debugfs {
const char *name;
@@ -57,6 +47,7 @@ struct iwl_debugfs {
struct dentry *dir_data;
struct dir_data_files{
struct dentry *file_sram;
+ struct dentry *file_eeprom;
struct dentry *file_stations;
struct dentry *file_rx_statistics;
struct dentry *file_tx_statistics;
@@ -76,9 +67,6 @@ static inline void IWL_DEBUG(int level, const char *fmt, ...)
static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
{
}
-static inline void iwl_print_hex_dump(int level, void *p, u32 len)
-{
-}
#endif /* CONFIG_IWLWIFI_DEBUG */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 30914453de1..ad25806dfaf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -206,7 +206,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
- struct iwl4965_station_entry *station;
+ struct iwl_station_entry *station;
int max_sta = priv->hw_params.max_stations;
char *buf;
int i, j, pos = 0;
@@ -277,8 +277,48 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
return ret;
}
+static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
+ char __user *user_buf,
+ size_t count,
+ loff_t *ppos)
+{
+ ssize_t ret;
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0, ofs = 0, buf_size = 0;
+ const u8 *ptr;
+ char *buf;
+ size_t eeprom_len = priv->cfg->eeprom_size;
+ buf_size = 4 * eeprom_len + 256;
+
+ if (eeprom_len % 16) {
+ IWL_ERROR("EEPROM size is not multiple of 16.\n");
+ return -ENODATA;
+ }
+
+ /* 4 characters for byte 0xYY */
+ buf = kzalloc(buf_size, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERROR("Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ ptr = priv->eeprom;
+ for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
+ pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
+ hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
+ buf_size - pos, 0);
+ pos += strlen(buf);
+ if (buf_size - pos > 0)
+ buf[pos++] = '\n';
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
DEBUGFS_READ_WRITE_FILE_OPS(sram);
+DEBUGFS_READ_FILE_OPS(eeprom);
DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics);
@@ -304,6 +344,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
}
DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
+ DEBUGFS_ADD_FILE(eeprom, data);
DEBUGFS_ADD_FILE(sram, data);
DEBUGFS_ADD_FILE(stations, data);
DEBUGFS_ADD_FILE(rx_statistics, data);
@@ -327,6 +368,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
if (!(priv->dbgfs))
return;
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 78aba21bc18..5dccc5a8fa9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -91,7 +91,7 @@ extern struct iwl_cfg iwl5350_agn_cfg;
#define DEFAULT_SHORT_RETRY_LIMIT 7U
#define DEFAULT_LONG_RETRY_LIMIT 4U
-struct iwl4965_rx_mem_buffer {
+struct iwl_rx_mem_buffer {
dma_addr_t dma_addr;
struct sk_buff *skb;
struct list_head list;
@@ -124,7 +124,7 @@ struct iwl4965_tx_info {
};
/**
- * struct iwl4965_tx_queue - Tx Queue for DMA
+ * struct iwl_tx_queue - Tx Queue for DMA
* @q: generic Rx/Tx queue descriptor
* @bd: base of circular buffer of TFDs
* @cmd: array of command/Tx buffers
@@ -136,9 +136,9 @@ struct iwl4965_tx_info {
* A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
* descriptors) and required locking structures.
*/
-struct iwl4965_tx_queue {
+struct iwl_tx_queue {
struct iwl4965_queue q;
- struct iwl4965_tfd_frame *bd;
+ struct iwl_tfd_frame *bd;
struct iwl_cmd *cmd;
dma_addr_t dma_addr_cmd;
struct iwl4965_tx_info *txb;
@@ -319,7 +319,7 @@ struct iwl_cmd {
struct iwl_cmd_meta meta; /* driver data */
struct iwl_cmd_header hdr; /* uCode API */
union {
- struct iwl4965_addsta_cmd addsta;
+ struct iwl_addsta_cmd addsta;
struct iwl4965_led_cmd led;
u32 flags;
u8 val8;
@@ -358,7 +358,7 @@ struct iwl_host_cmd {
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
/**
- * struct iwl4965_rx_queue - Rx queue
+ * struct iwl_rx_queue - Rx queue
* @processed: Internal index to last handled Rx packet
* @read: Shared index to newest available Rx buffer
* @write: Shared index to oldest written Rx packet
@@ -367,13 +367,13 @@ struct iwl_host_cmd {
* @rx_used: List of Rx buffers with no SKB
* @need_update: flag to indicate we need to update read/write index
*
- * NOTE: rx_free and rx_used are used as a FIFO for iwl4965_rx_mem_buffers
+ * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
*/
-struct iwl4965_rx_queue {
+struct iwl_rx_queue {
__le32 *bd;
dma_addr_t dma_addr;
- struct iwl4965_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
- struct iwl4965_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+ struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+ struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
u32 processed;
u32 read;
u32 write;
@@ -401,7 +401,7 @@ struct iwl4965_rx_queue {
#ifdef CONFIG_IWL4965_HT
/**
- * struct iwl4965_ht_agg -- aggregation status while waiting for block-ack
+ * struct iwl_ht_agg -- aggregation status while waiting for block-ack
* @txq_id: Tx queue used for Tx attempt
* @frame_count: # frames attempted by Tx command
* @wait_for_ba: Expect block-ack before next Tx reply
@@ -414,7 +414,7 @@ struct iwl4965_rx_queue {
* for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info
* until block ack arrives.
*/
-struct iwl4965_ht_agg {
+struct iwl_ht_agg {
u16 txq_id;
u16 frame_count;
u16 wait_for_ba;
@@ -430,15 +430,15 @@ struct iwl4965_ht_agg {
#endif /* CONFIG_IWL4965_HT */
-struct iwl4965_tid_data {
+struct iwl_tid_data {
u16 seq_number;
u16 tfds_in_queue;
#ifdef CONFIG_IWL4965_HT
- struct iwl4965_ht_agg agg;
+ struct iwl_ht_agg agg;
#endif /* CONFIG_IWL4965_HT */
};
-struct iwl4965_hw_key {
+struct iwl_hw_key {
enum ieee80211_key_alg alg;
int keylen;
u8 keyidx;
@@ -454,7 +454,6 @@ union iwl4965_ht_rate_supp {
};
};
-#ifdef CONFIG_IWL4965_HT
#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3)
#define CFG_HT_MPDU_DENSITY_2USEC (0x5)
#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_2USEC
@@ -477,7 +476,6 @@ struct iwl_ht_info {
u8 ht_protection;
u8 non_GF_STA_present;
};
-#endif /*CONFIG_IWL4965_HT */
union iwl4965_qos_capabity {
struct {
@@ -510,12 +508,12 @@ struct iwl4965_qos_info {
#define STA_PS_STATUS_WAKE 0
#define STA_PS_STATUS_SLEEP 1
-struct iwl4965_station_entry {
- struct iwl4965_addsta_cmd sta;
- struct iwl4965_tid_data tid[MAX_TID_COUNT];
+struct iwl_station_entry {
+ struct iwl_addsta_cmd sta;
+ struct iwl_tid_data tid[MAX_TID_COUNT];
u8 used;
u8 ps_status;
- struct iwl4965_hw_key keyinfo;
+ struct iwl_hw_key keyinfo;
};
/* one for each uCode image (inst/data, boot/init/runtime) */
@@ -634,35 +632,26 @@ struct iwl_hw_params {
* for use by iwl-*.c
*
*****************************************************************************/
-struct iwl4965_addsta_cmd;
-extern int iwl4965_send_add_station(struct iwl_priv *priv,
- struct iwl4965_addsta_cmd *sta, u8 flags);
+struct iwl_addsta_cmd;
+extern int iwl_send_add_sta(struct iwl_priv *priv,
+ struct iwl_addsta_cmd *sta, u8 flags);
extern u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
int is_ap, u8 flags, void *ht_data);
extern int iwl4965_is_network_packet(struct iwl_priv *priv,
struct ieee80211_hdr *header);
extern int iwl4965_power_init_handle(struct iwl_priv *priv);
extern void iwl4965_handle_data_packet_monitor(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb,
+ struct iwl_rx_mem_buffer *rxb,
void *data, short len,
struct ieee80211_rx_status *stats,
u16 phy_flags);
extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv,
struct ieee80211_hdr *header);
-extern int iwl4965_rx_queue_alloc(struct iwl_priv *priv);
-extern void iwl4965_rx_queue_reset(struct iwl_priv *priv,
- struct iwl4965_rx_queue *rxq);
extern int iwl4965_calc_db_from_ratio(int sig_ratio);
extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm);
-extern int iwl4965_tx_queue_init(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq, int count, u32 id);
-extern void iwl4965_rx_replenish(void *data);
-extern void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
const u8 *dest, int left);
-extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl4965_rx_queue *q);
extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
@@ -700,20 +689,14 @@ extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
-extern int iwl4965_hw_nic_init(struct iwl_priv *priv);
extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
-extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv);
extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl4965_hw_nic_reset(struct iwl_priv *priv);
extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
dma_addr_t addr, u16 len);
-extern int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
-extern int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq);
extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl4965_frame *frame, u8 rate);
-extern int iwl4965_hw_get_rx_read(struct iwl_priv *priv);
extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
struct iwl_cmd *cmd,
struct ieee80211_tx_control *ctrl,
@@ -722,7 +705,7 @@ extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
extern int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv);
extern int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb);
+ struct iwl_rx_mem_buffer *rxb);
extern void iwl4965_disable_events(struct iwl_priv *priv);
extern int iwl4965_get_temperature(const struct iwl_priv *priv);
@@ -746,7 +729,7 @@ extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio);
* Forward declare iwl-4965.c functions for iwl-base.c
*/
extern int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq,
+ struct iwl_tx_queue *txq,
u16 byte_cnt);
extern void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr,
int is_ap);
@@ -778,9 +761,9 @@ static inline void iwl4965_init_ht_hw_capab(const struct iwl_priv *priv,
#endif /*CONFIG_IWL4965_HT */
/* Structures, enum, and defines specific to the 4965 */
-#define IWL4965_KW_SIZE 0x1000 /*4k */
+#define IWL_KW_SIZE 0x1000 /*4k */
-struct iwl4965_kw {
+struct iwl_kw {
dma_addr_t dma_addr;
void *v_addr;
size_t size;
@@ -960,7 +943,7 @@ struct iwl_priv {
bool add_radiotap;
void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb);
+ struct iwl_rx_mem_buffer *rxb);
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
@@ -1077,10 +1060,10 @@ struct iwl_priv {
int activity_timer_active;
/* Rx and Tx DMA processing queues */
- struct iwl4965_rx_queue rxq;
- struct iwl4965_tx_queue txq[IWL_MAX_NUM_QUEUES];
+ struct iwl_rx_queue rxq;
+ struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES];
unsigned long txq_ctx_active_msk;
- struct iwl4965_kw kw; /* keep warm address */
+ struct iwl_kw kw; /* keep warm address */
u32 scd_base_addr; /* scheduler sram base address */
unsigned long status;
@@ -1113,7 +1096,7 @@ struct iwl_priv {
/*station table variables */
spinlock_t sta_lock;
int num_stations;
- struct iwl4965_station_entry stations[IWL_STATION_COUNT];
+ struct iwl_station_entry stations[IWL_STATION_COUNT];
struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
u8 default_wep_key;
u8 key_mapping_key;
@@ -1154,6 +1137,7 @@ struct iwl_priv {
struct iwl_hw_params hw_params;
/* driver/uCode shared Tx Byte Counts and Rx status */
void *shared_virt;
+ int rb_closed_offset;
/* Physical Pointer to Tx Byte Counts and Rx status */
dma_addr_t shared_phys;
@@ -1179,6 +1163,7 @@ struct iwl_priv {
struct work_struct report_work;
struct work_struct request_scan;
struct work_struct beacon_update;
+ struct work_struct set_monitor;
struct tasklet_struct irq_tasklet;
@@ -1200,6 +1185,7 @@ struct iwl_priv {
#ifdef CONFIG_IWLWIFI_DEBUG
/* debugging info */
+ u32 debug_level;
u32 framecnt_to_us;
atomic_t restrict_refcnt;
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -1252,6 +1238,23 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch)
return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
+static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
+ void *p, u32 len)
+{
+ if (!(priv->debug_level & level))
+ return;
+
+ print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
+ p, len, 1);
+}
+#else
+static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
+ void *p, u32 len)
+{
+}
+#endif
+
extern const struct iwl_channel_info *iwl_get_channel_info(
const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index acb5a8abd78..0412adf6ef8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -101,7 +101,7 @@ EXPORT_SYMBOL(get_cmd_string);
static int iwl_generic_cmd_callback(struct iwl_priv *priv,
struct iwl_cmd *cmd, struct sk_buff *skb)
{
- struct iwl4965_rx_packet *pkt = NULL;
+ struct iwl_rx_packet *pkt = NULL;
if (!skb) {
IWL_ERROR("Error: Response NULL in %s.\n",
@@ -109,7 +109,7 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv,
return 1;
}
- pkt = (struct iwl4965_rx_packet *)skb->data;
+ pkt = (struct iwl_rx_packet *)skb->data;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from %s (0x%08X)\n",
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
new file mode 100644
index 00000000000..a2eb90d40b7
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -0,0 +1,422 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <net/mac80211.h>
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+/************************** RX-FUNCTIONS ****************************/
+/*
+ * Rx theory of operation
+ *
+ * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
+ * each of which point to Receive Buffers to be filled by the NIC. These get
+ * used not only for Rx frames, but for any command response or notification
+ * from the NIC. The driver and NIC manage the Rx buffers by means
+ * of indexes into the circular buffer.
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization, the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ index
+ * and fire the RX interrupt. The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
+ * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ * to replenish the iwl->rxq->rx_free.
+ * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ * iwl->rxq is replenished and the READ INDEX is updated (updating the
+ * 'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ * detached from the iwl->rxq. The driver 'processed' index is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there
+ * were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * iwl_rx_queue_alloc() Allocates rx_free
+ * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls
+ * iwl_rx_queue_restock
+ * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ * queue, updates firmware pointers, and updates
+ * the WRITE index. If insufficient rx_free buffers
+ * are available, schedules iwl_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the
+ * READ INDEX, detaching the SKB from the pool.
+ * Moves the packet buffer from queue to rx_used.
+ * Calls iwl_rx_queue_restock to refill any empty
+ * slots.
+ * ...
+ *
+ */
+
+/**
+ * iwl_rx_queue_space - Return number of free slots available in queue.
+ */
+int iwl_rx_queue_space(const struct iwl_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;
+}
+EXPORT_SYMBOL(iwl_rx_queue_space);
+
+/**
+ * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+ */
+int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
+{
+ u32 reg = 0;
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&q->lock, flags);
+
+ if (q->need_update == 0)
+ goto exit_unlock;
+
+ /* If power-saving is in use, make sure device is awake */
+ if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+ reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+ if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+ iwl_set_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ goto exit_unlock;
+ }
+
+ ret = iwl_grab_nic_access(priv);
+ if (ret)
+ goto exit_unlock;
+
+ /* Device expects a multiple of 8 */
+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
+ q->write & ~0x7);
+ iwl_release_nic_access(priv);
+
+ /* Else device is assumed to be awake */
+ } else
+ /* Device expects a multiple of 8 */
+ iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
+
+
+ q->need_update = 0;
+
+ exit_unlock:
+ spin_unlock_irqrestore(&q->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
+/**
+ * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
+ dma_addr_t dma_addr)
+{
+ return cpu_to_le32((u32)(dma_addr >> 8));
+}
+
+/**
+ * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
+ *
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can, pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+int iwl_rx_queue_restock(struct iwl_priv *priv)
+{
+ struct iwl_rx_queue *rxq = &priv->rxq;
+ struct list_head *element;
+ struct iwl_rx_mem_buffer *rxb;
+ unsigned long flags;
+ int write;
+ int ret = 0;
+
+ spin_lock_irqsave(&rxq->lock, flags);
+ write = rxq->write & ~0x7;
+ while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+ /* Get next free Rx buffer, remove from free list */
+ element = rxq->rx_free.next;
+ rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ list_del(element);
+
+ /* Point to Rx buffer via next RBD in circular buffer */
+ rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr);
+ rxq->queue[rxq->write] = rxb;
+ rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
+ rxq->free_count--;
+ }
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ /* If the pre-allocated buffer pool is dropping low, schedule to
+ * refill it */
+ if (rxq->free_count <= RX_LOW_WATERMARK)
+ queue_work(priv->workqueue, &priv->rx_replenish);
+
+
+ /* If we've added more space for the firmware to place data, tell it.
+ * Increment device's write pointer in multiples of 8. */
+ if ((write != (rxq->write & ~0x7))
+ || (abs(rxq->write - rxq->read) > 7)) {
+ spin_lock_irqsave(&rxq->lock, flags);
+ rxq->need_update = 1;
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ ret = iwl_rx_queue_update_write_ptr(priv, rxq);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(iwl_rx_queue_restock);
+
+
+/**
+ * iwl_rx_replenish - Move all used packet from rx_used to rx_free
+ *
+ * When moving to rx_free an SKB is allocated for the slot.
+ *
+ * Also restock the Rx queue via iwl_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+void iwl_rx_allocate(struct iwl_priv *priv)
+{
+ struct iwl_rx_queue *rxq = &priv->rxq;
+ struct list_head *element;
+ struct iwl_rx_mem_buffer *rxb;
+ unsigned long flags;
+ spin_lock_irqsave(&rxq->lock, flags);
+ while (!list_empty(&rxq->rx_used)) {
+ element = rxq->rx_used.next;
+ rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+
+ /* Alloc a new receive buffer */
+ rxb->skb = alloc_skb(priv->hw_params.rx_buf_size,
+ __GFP_NOWARN | GFP_ATOMIC);
+ if (!rxb->skb) {
+ if (net_ratelimit())
+ printk(KERN_CRIT DRV_NAME
+ ": Can not allocate SKB buffers\n");
+ /* We don't reschedule replenish work here -- we will
+ * call the restock method and if it still needs
+ * more buffers it will schedule replenish */
+ break;
+ }
+ priv->alloc_rxb_skb++;
+ list_del(element);
+
+ /* Get physical address of RB/SKB */
+ rxb->dma_addr =
+ pci_map_single(priv->pci_dev, rxb->skb->data,
+ priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE);
+ list_add_tail(&rxb->list, &rxq->rx_free);
+ rxq->free_count++;
+ }
+ spin_unlock_irqrestore(&rxq->lock, flags);
+}
+EXPORT_SYMBOL(iwl_rx_allocate);
+
+void iwl_rx_replenish(struct iwl_priv *priv)
+{
+ unsigned long flags;
+
+ iwl_rx_allocate(priv);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ iwl_rx_queue_restock(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+EXPORT_SYMBOL(iwl_rx_replenish);
+
+
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
+ * This free routine walks the list of POOL entries and if SKB is set to
+ * non NULL it is unmapped and freed
+ */
+void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+ int i;
+ for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+ if (rxq->pool[i].skb != NULL) {
+ pci_unmap_single(priv->pci_dev,
+ rxq->pool[i].dma_addr,
+ priv->hw_params.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(rxq->pool[i].skb);
+ }
+ }
+
+ pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ rxq->dma_addr);
+ rxq->bd = NULL;
+}
+EXPORT_SYMBOL(iwl_rx_queue_free);
+
+int iwl_rx_queue_alloc(struct iwl_priv *priv)
+{
+ struct iwl_rx_queue *rxq = &priv->rxq;
+ struct pci_dev *dev = priv->pci_dev;
+ int i;
+
+ spin_lock_init(&rxq->lock);
+ INIT_LIST_HEAD(&rxq->rx_free);
+ INIT_LIST_HEAD(&rxq->rx_used);
+
+ /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
+ rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
+ if (!rxq->bd)
+ return -ENOMEM;
+
+ /* Fill the rx_used queue with _all_ of the Rx buffers */
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
+ list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+
+ /* 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->free_count = 0;
+ rxq->need_update = 0;
+ return 0;
+}
+EXPORT_SYMBOL(iwl_rx_queue_alloc);
+
+void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+ unsigned long flags;
+ int i;
+ spin_lock_irqsave(&rxq->lock, flags);
+ INIT_LIST_HEAD(&rxq->rx_free);
+ INIT_LIST_HEAD(&rxq->rx_used);
+ /* Fill the rx_used queue with _all_ of the Rx buffers */
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+ /* In the reset function, these buffers may have been allocated
+ * to an SKB, so we need to unmap and free potential storage */
+ if (rxq->pool[i].skb != NULL) {
+ pci_unmap_single(priv->pci_dev,
+ rxq->pool[i].dma_addr,
+ priv->hw_params.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ priv->alloc_rxb_skb--;
+ dev_kfree_skb(rxq->pool[i].skb);
+ rxq->pool[i].skb = NULL;
+ }
+ list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+ }
+
+ /* 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->free_count = 0;
+ spin_unlock_irqrestore(&rxq->lock, flags);
+}
+EXPORT_SYMBOL(iwl_rx_queue_reset);
+
+int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+ int ret;
+ unsigned long flags;
+ unsigned int rb_size;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ret = iwl_grab_nic_access(priv);
+ if (ret) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return ret;
+ }
+
+ if (priv->cfg->mod_params->amsdu_size_8K)
+ rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+ else
+ rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+ /* Stop Rx DMA */
+ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+ /* Reset driver's Rx queue write index */
+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+ /* Tell device where to find RBD circular buffer in DRAM */
+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+ rxq->dma_addr >> 8);
+
+ /* Tell device where in DRAM to update its Rx status */
+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+ (priv->shared_phys + priv->rb_closed_offset) >> 4);
+
+ /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
+ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+ FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+ FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+ rb_size |
+ /* 0x10 << 4 | */
+ (RX_QUEUE_SIZE_LOG <<
+ FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
+
+ /*
+ * iwl_write32(priv,CSR_INT_COAL_REG,0);
+ */
+
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 31b37a1a643..f2267047d10 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -70,6 +70,52 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
}
EXPORT_SYMBOL(iwl_find_station);
+int iwl_send_add_sta(struct iwl_priv *priv,
+ struct iwl_addsta_cmd *sta, u8 flags)
+{
+ struct iwl_rx_packet *res = NULL;
+ int ret = 0;
+ u8 data[sizeof(*sta)];
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_ADD_STA,
+ .meta.flags = flags,
+ .data = data,
+ };
+
+ if (!(flags & CMD_ASYNC))
+ cmd.meta.flags |= CMD_WANT_SKB;
+
+ cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
+ ret = iwl_send_cmd(priv, &cmd);
+
+ if (ret || (flags & CMD_ASYNC))
+ return ret;
+
+ res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
+ res->hdr.flags);
+ ret = -EIO;
+ }
+
+ if (ret == 0) {
+ switch (res->u.add_sta.status) {
+ case ADD_STA_SUCCESS_MSK:
+ IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
+ break;
+ default:
+ ret = -EIO;
+ IWL_WARNING("REPLY_ADD_STA failed\n");
+ break;
+ }
+ }
+
+ priv->alloc_rxb_skb--;
+ dev_kfree_skb_any(cmd.meta.u.skb);
+
+ return ret;
+}
+EXPORT_SYMBOL(iwl_send_add_sta);
int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{
@@ -124,6 +170,7 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
else
return 0;
}
+EXPORT_SYMBOL(iwl_send_static_wepkey_cmd);
int iwl_remove_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf)
@@ -144,6 +191,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
return ret;
}
+EXPORT_SYMBOL(iwl_remove_default_wep_key);
int iwl_set_default_wep_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf)
@@ -171,6 +219,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
return ret;
}
+EXPORT_SYMBOL(iwl_set_default_wep_key);
static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf,
@@ -216,8 +265,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- ret = iwl4965_send_add_station(priv,
- &priv->stations[sta_id].sta, CMD_ASYNC);
+ ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
spin_unlock_irqrestore(&priv->sta_lock, flags);
@@ -265,8 +313,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
spin_unlock_irqrestore(&priv->sta_lock, flags);
IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
- return iwl4965_send_add_station(priv,
- &priv->stations[sta_id].sta, CMD_ASYNC);
+ return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
}
static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
@@ -333,7 +380,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
IWL_ERROR("index %d not used in uCode key table.\n",
priv->stations[sta_id].sta.key.key_offset);
memset(&priv->stations[sta_id].keyinfo, 0,
- sizeof(struct iwl4965_hw_key));
+ sizeof(struct iwl_hw_key));
memset(&priv->stations[sta_id].sta.key, 0,
sizeof(struct iwl4965_keyinfo));
priv->stations[sta_id].sta.key.key_flags =
@@ -343,10 +390,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
- ret = iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+ ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
}
+EXPORT_SYMBOL(iwl_remove_dynamic_key);
int iwl_set_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key, u8 sta_id)
@@ -372,6 +420,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
return ret;
}
+EXPORT_SYMBOL(iwl_set_dynamic_key);
#ifdef CONFIG_IWLWIFI_DEBUG
static void iwl_dump_lq_cmd(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
new file mode 100644
index 00000000000..a1e03ccd514
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -0,0 +1,373 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <net/mac80211.h>
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+
+/**
+ * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ *
+ * Does NOT advance any TFD circular buffer read/write indexes
+ * Does NOT free the TFD itself (which is within circular buffer)
+ */
+int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+ struct iwl_tfd_frame *bd_tmp = (struct iwl_tfd_frame *)&txq->bd[0];
+ struct iwl_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
+ struct pci_dev *dev = priv->pci_dev;
+ int i;
+ int counter = 0;
+ int index, is_odd;
+
+ /* Host command buffers stay mapped in memory, nothing to clean */
+ if (txq->q.id == IWL_CMD_QUEUE_NUM)
+ return 0;
+
+ /* Sanity check on number of chunks */
+ counter = IWL_GET_BITS(*bd, num_tbs);
+ if (counter > MAX_NUM_OF_TBS) {
+ IWL_ERROR("Too many chunks: %i\n", counter);
+ /* @todo issue fatal error, it is quite serious situation */
+ return 0;
+ }
+
+ /* Unmap chunks, if any.
+ * TFD info for odd chunks is different format than for even chunks. */
+ for (i = 0; i < counter; i++) {
+ index = i / 2;
+ is_odd = i & 0x1;
+
+ if (is_odd)
+ pci_unmap_single(
+ dev,
+ IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
+ (IWL_GET_BITS(bd->pa[index],
+ tb2_addr_hi20) << 16),
+ IWL_GET_BITS(bd->pa[index], tb2_len),
+ PCI_DMA_TODEVICE);
+
+ else if (i > 0)
+ pci_unmap_single(dev,
+ le32_to_cpu(bd->pa[index].tb1_addr),
+ IWL_GET_BITS(bd->pa[index], tb1_len),
+ PCI_DMA_TODEVICE);
+
+ /* Free SKB, if any, for this chunk */
+ if (txq->txb[txq->q.read_ptr].skb[i]) {
+ struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i];
+
+ dev_kfree_skb(skb);
+ txq->txb[txq->q.read_ptr].skb[i] = NULL;
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL(iwl_hw_txq_free_tfd);
+
+/**
+ * iwl_tx_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+ struct iwl4965_queue *q = &txq->q;
+ struct pci_dev *dev = priv->pci_dev;
+ int len;
+
+ if (q->n_bd == 0)
+ return;
+
+ /* first, empty all BD's */
+ for (; q->write_ptr != q->read_ptr;
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
+ iwl_hw_txq_free_tfd(priv, txq);
+
+ len = sizeof(struct iwl_cmd) * q->n_window;
+ if (q->id == IWL_CMD_QUEUE_NUM)
+ len += IWL_MAX_SCAN_SIZE;
+
+ /* De-alloc array of command/tx buffers */
+ pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
+
+ /* De-alloc circular buffer of TFDs */
+ if (txq->q.n_bd)
+ pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
+ txq->q.n_bd, txq->bd, txq->q.dma_addr);
+
+ /* De-alloc array of per-TFD driver data */
+ kfree(txq->txb);
+ txq->txb = NULL;
+
+ /* 0-fill queue descriptor structure */
+ memset(txq, 0, sizeof(*txq));
+}
+
+/**
+ * iwl_hw_txq_ctx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
+{
+ int txq_id;
+
+ /* Tx queues */
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+ iwl_tx_queue_free(priv, &priv->txq[txq_id]);
+
+ /* Keep-warm buffer */
+ iwl_kw_free(priv);
+}
+EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
+
+/**
+ * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+static int iwl_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
+ int count, int slots_num, u32 id)
+{
+ q->n_bd = count;
+ q->n_window = slots_num;
+ q->id = id;
+
+ /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
+ * and iwl_queue_dec_wrap are broken. */
+ BUG_ON(!is_power_of_2(count));
+
+ /* slots_num must be power-of-two size, otherwise
+ * get_cmd_index is broken. */
+ BUG_ON(!is_power_of_2(slots_num));
+
+ q->low_mark = q->n_window / 4;
+ if (q->low_mark < 4)
+ q->low_mark = 4;
+
+ q->high_mark = q->n_window / 8;
+ if (q->high_mark < 2)
+ q->high_mark = 2;
+
+ q->write_ptr = q->read_ptr = 0;
+
+ return 0;
+}
+
+/**
+ * iwl_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+ */
+static int iwl_tx_queue_alloc(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq, u32 id)
+{
+ struct pci_dev *dev = priv->pci_dev;
+
+ /* Driver private data, only for Tx (not command) queues,
+ * not shared with device. */
+ if (id != IWL_CMD_QUEUE_NUM) {
+ txq->txb = kmalloc(sizeof(txq->txb[0]) *
+ TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
+ if (!txq->txb) {
+ IWL_ERROR("kmalloc for auxiliary BD "
+ "structures failed\n");
+ goto error;
+ }
+ } else
+ txq->txb = NULL;
+
+ /* Circular buffer of transmit frame descriptors (TFDs),
+ * shared with device */
+ txq->bd = pci_alloc_consistent(dev,
+ sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
+ &txq->q.dma_addr);
+
+ if (!txq->bd) {
+ IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
+ sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
+ goto error;
+ }
+ txq->q.id = id;
+
+ return 0;
+
+ error:
+ kfree(txq->txb);
+ txq->txb = NULL;
+
+ return -ENOMEM;
+}
+
+/*
+ * Tell nic where to find circular buffer of Tx Frame Descriptors for
+ * given Tx queue, and enable the DMA channel used for that queue.
+ *
+ * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * channels supported in hardware.
+ */
+static int iwl_hw_tx_queue_init(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq)
+{
+ int rc;
+ unsigned long flags;
+ int txq_id = txq->q.id;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ rc = iwl_grab_nic_access(priv);
+ if (rc) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return rc;
+ }
+
+ /* Circular buffer (TFD queue in DRAM) physical base address */
+ iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
+ txq->q.dma_addr >> 8);
+
+ /* Enable DMA channel, using same id as for TFD queue */
+ iwl_write_direct32(
+ priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
+ iwl_release_nic_access(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+/**
+ * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue
+ */
+static int iwl_tx_queue_init(struct iwl_priv *priv,
+ struct iwl_tx_queue *txq,
+ int slots_num, u32 txq_id)
+{
+ struct pci_dev *dev = priv->pci_dev;
+ int len;
+ int rc = 0;
+
+ /*
+ * Alloc buffer array for commands (Tx or other types of commands).
+ * For the command queue (#4), allocate command space + one big
+ * command for scan, since scan command is very huge; the system will
+ * not have two scans at the same time, so only one is needed.
+ * For normal Tx queues (all other queues), no super-size command
+ * space is needed.
+ */
+ len = sizeof(struct iwl_cmd) * slots_num;
+ if (txq_id == IWL_CMD_QUEUE_NUM)
+ len += IWL_MAX_SCAN_SIZE;
+ txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
+ if (!txq->cmd)
+ return -ENOMEM;
+
+ /* Alloc driver data array and TFD circular buffer */
+ rc = iwl_tx_queue_alloc(priv, txq, txq_id);
+ if (rc) {
+ pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
+
+ return -ENOMEM;
+ }
+ txq->need_update = 0;
+
+ /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+ * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+ /* Initialize queue's high/low-water marks, and head/tail indexes */
+ iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+ /* Tell device where to find queue */
+ iwl_hw_tx_queue_init(priv, txq);
+
+ return 0;
+}
+
+/**
+ * iwl_txq_ctx_reset - Reset TX queue context
+ * Destroys all DMA structures and initialise them again
+ *
+ * @param priv
+ * @return error code
+ */
+int iwl_txq_ctx_reset(struct iwl_priv *priv)
+{
+ int ret = 0;
+ int txq_id, slots_num;
+
+ iwl_kw_free(priv);
+
+ /* Free all tx/cmd queues and keep-warm buffer */
+ iwl_hw_txq_ctx_free(priv);
+
+ /* Alloc keep-warm buffer */
+ ret = iwl_kw_alloc(priv);
+ if (ret) {
+ IWL_ERROR("Keep Warm allocation failed");
+ goto error_kw;
+ }
+
+ /* Turn off all Tx DMA fifos */
+ ret = priv->cfg->ops->lib->disable_tx_fifo(priv);
+ if (unlikely(ret))
+ goto error_reset;
+
+ /* Tell nic where to find the keep-warm buffer */
+ ret = iwl_kw_init(priv);
+ if (ret) {
+ IWL_ERROR("kw_init failed\n");
+ goto error_reset;
+ }
+
+ /* Alloc and init all (default 16) Tx queues,
+ * including the command queue (#4) */
+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+ slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
+ TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+ ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
+ txq_id);
+ if (ret) {
+ IWL_ERROR("Tx %d queue init failed\n", txq_id);
+ goto error;
+ }
+ }
+
+ return ret;
+
+ error:
+ iwl_hw_txq_ctx_free(priv);
+ error_reset:
+ iwl_kw_free(priv);
+ error_kw:
+ return ret;
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 7040cde8bc2..c1234ff4fc9 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -6144,6 +6144,24 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
mutex_unlock(&priv->mutex);
}
+static void iwl3945_bg_set_monitor(struct work_struct *work)
+{
+ struct iwl3945_priv *priv = container_of(work,
+ struct iwl3945_priv, set_monitor);
+
+ IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
+
+ mutex_lock(&priv->mutex);
+
+ if (!iwl3945_is_ready(priv))
+ IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
+ else
+ if (iwl3945_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0)
+ IWL_ERROR("iwl3945_set_mode() failed\n");
+
+ mutex_unlock(&priv->mutex);
+}
+
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
static void iwl3945_bg_scan_check(struct work_struct *data)
@@ -6996,7 +7014,22 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
* XXX: dummy
* see also iwl3945_connection_init_rx_config
*/
- *total_flags = 0;
+ struct iwl3945_priv *priv = hw->priv;
+ int new_flags = 0;
+ if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
+ if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
+ IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
+ IEEE80211_IF_TYPE_MNTR,
+ changed_flags, *total_flags);
+ /* queue work 'cuz mac80211 is holding a lock which
+ * prevents us from issuing (synchronous) f/w cmds */
+ queue_work(priv->workqueue, &priv->set_monitor);
+ new_flags &= FIF_PROMISC_IN_BSS |
+ FIF_OTHER_BSS |
+ FIF_ALLMULTI;
+ }
+ }
+ *total_flags = new_flags;
}
static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
@@ -7054,9 +7087,10 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
rc = -EAGAIN;
goto out_unlock;
}
- /* if we just finished scan ask for delay */
- if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
- IWL_DELAY_NEXT_SCAN, jiffies)) {
+ /* if we just finished scan ask for delay for a broadcast scan */
+ if ((len == 0) && priv->last_scan_jiffies &&
+ time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
+ jiffies)) {
rc = -EAGAIN;
goto out_unlock;
}
@@ -7872,6 +7906,7 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
+ INIT_WORK(&priv->set_monitor, iwl3945_bg_set_monitor);
INIT_DELAYED_WORK(&priv->post_associate, iwl3945_bg_post_associate);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
@@ -7994,17 +8029,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->ibss_beacon = NULL;
- /* Tell mac80211 and its clients (e.g. Wireless Extensions)
- * the range of signal quality values that we'll provide.
- * Negative values for level/noise indicate that we'll provide dBm.
- * For WE, at least, non-0 values here *enable* display of values
- * in app (iwconfig). */
- hw->max_rssi = -20; /* signal level, negative indicates dBm */
- hw->max_noise = -20; /* noise level, negative indicates dBm */
- hw->max_signal = 100; /* link quality indication (%) */
-
- /* Tell mac80211 our Tx characteristics */
- hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+ /* Tell mac80211 our characteristics */
+ hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_NOISE_DBM;
/* 4 EDCA QOS priorities */
hw->queues = 4;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 4406fc72d88..55ca752ae9e 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -54,7 +54,7 @@
#include "iwl-calib.h"
static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq);
+ struct iwl_tx_queue *txq);
/******************************************************************************
*
@@ -145,6 +145,7 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
return escaped;
}
+
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
* DMA services
*
@@ -206,173 +207,6 @@ static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge)
return index & (q->n_window - 1);
}
-/**
- * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes
- */
-static int iwl4965_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
- int count, int slots_num, u32 id)
-{
- q->n_bd = count;
- q->n_window = slots_num;
- q->id = id;
-
- /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
- * and iwl_queue_dec_wrap are broken. */
- BUG_ON(!is_power_of_2(count));
-
- /* slots_num must be power-of-two size, otherwise
- * get_cmd_index is broken. */
- BUG_ON(!is_power_of_2(slots_num));
-
- q->low_mark = q->n_window / 4;
- if (q->low_mark < 4)
- q->low_mark = 4;
-
- q->high_mark = q->n_window / 8;
- if (q->high_mark < 2)
- q->high_mark = 2;
-
- q->write_ptr = q->read_ptr = 0;
-
- return 0;
-}
-
-/**
- * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
- */
-static int iwl4965_tx_queue_alloc(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq, u32 id)
-{
- struct pci_dev *dev = priv->pci_dev;
-
- /* Driver private data, only for Tx (not command) queues,
- * not shared with device. */
- if (id != IWL_CMD_QUEUE_NUM) {
- txq->txb = kmalloc(sizeof(txq->txb[0]) *
- TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
- if (!txq->txb) {
- IWL_ERROR("kmalloc for auxiliary BD "
- "structures failed\n");
- goto error;
- }
- } else
- txq->txb = NULL;
-
- /* Circular buffer of transmit frame descriptors (TFDs),
- * shared with device */
- txq->bd = pci_alloc_consistent(dev,
- sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
- &txq->q.dma_addr);
-
- if (!txq->bd) {
- IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
- sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
- goto error;
- }
- txq->q.id = id;
-
- return 0;
-
- error:
- if (txq->txb) {
- kfree(txq->txb);
- txq->txb = NULL;
- }
-
- return -ENOMEM;
-}
-
-/**
- * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue
- */
-int iwl4965_tx_queue_init(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id)
-{
- struct pci_dev *dev = priv->pci_dev;
- int len;
- int rc = 0;
-
- /*
- * Alloc buffer array for commands (Tx or other types of commands).
- * For the command queue (#4), allocate command space + one big
- * command for scan, since scan command is very huge; the system will
- * not have two scans at the same time, so only one is needed.
- * For normal Tx queues (all other queues), no super-size command
- * space is needed.
- */
- len = sizeof(struct iwl_cmd) * slots_num;
- if (txq_id == IWL_CMD_QUEUE_NUM)
- len += IWL_MAX_SCAN_SIZE;
- txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
- if (!txq->cmd)
- return -ENOMEM;
-
- /* Alloc driver data array and TFD circular buffer */
- rc = iwl4965_tx_queue_alloc(priv, txq, txq_id);
- if (rc) {
- pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
-
- return -ENOMEM;
- }
- txq->need_update = 0;
-
- /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
- * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
- BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
- /* Initialize queue's high/low-water marks, and head/tail indexes */
- iwl4965_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
-
- /* Tell device where to find queue */
- iwl4965_hw_tx_queue_init(priv, txq);
-
- return 0;
-}
-
-/**
- * iwl4965_tx_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
-void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
-{
- struct iwl4965_queue *q = &txq->q;
- struct pci_dev *dev = priv->pci_dev;
- int len;
-
- if (q->n_bd == 0)
- return;
-
- /* first, empty all BD's */
- for (; q->write_ptr != q->read_ptr;
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
- iwl4965_hw_txq_free_tfd(priv, txq);
-
- len = sizeof(struct iwl_cmd) * q->n_window;
- if (q->id == IWL_CMD_QUEUE_NUM)
- len += IWL_MAX_SCAN_SIZE;
-
- /* De-alloc array of command/tx buffers */
- pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
-
- /* De-alloc circular buffer of TFDs */
- if (txq->q.n_bd)
- pci_free_consistent(dev, sizeof(struct iwl4965_tfd_frame) *
- txq->q.n_bd, txq->bd, txq->q.dma_addr);
-
- /* De-alloc array of per-TFD driver data */
- if (txq->txb) {
- kfree(txq->txb);
- txq->txb = NULL;
- }
-
- /* 0-fill queue descriptor structure */
- memset(txq, 0, sizeof(*txq));
-}
-
const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/*************** STATION TABLE MANAGEMENT ****
@@ -433,7 +267,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
{
int i;
int index = IWL_INVALID_STATION;
- struct iwl4965_station_entry *station;
+ struct iwl_station_entry *station;
unsigned long flags_spin;
DECLARE_MAC_BUF(mac);
@@ -476,7 +310,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
priv->num_stations++;
/* Set up the REPLY_ADD_STA command to send to device */
- memset(&station->sta, 0, sizeof(struct iwl4965_addsta_cmd));
+ memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
station->sta.mode = 0;
station->sta.sta.sta_id = index;
@@ -493,7 +327,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
/* Add station to device's station table */
- iwl4965_send_add_station(priv, &station->sta, flags);
+ iwl_send_add_sta(priv, &station->sta, flags);
return index;
}
@@ -513,9 +347,9 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
*/
int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
- struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
struct iwl4965_queue *q = &txq->q;
- struct iwl4965_tfd_frame *tfd;
+ struct iwl_tfd_frame *tfd;
u32 *control_flags;
struct iwl_cmd *out_cmd;
u32 idx;
@@ -902,8 +736,8 @@ static int iwl4965_send_bt_config(struct iwl_priv *priv)
static int iwl4965_send_scan_abort(struct iwl_priv *priv)
{
- int rc = 0;
- struct iwl4965_rx_packet *res;
+ int ret = 0;
+ struct iwl_rx_packet *res;
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
.meta.flags = CMD_WANT_SKB,
@@ -917,13 +751,13 @@ static int iwl4965_send_scan_abort(struct iwl_priv *priv)
return 0;
}
- rc = iwl_send_cmd_sync(priv, &cmd);
- if (rc) {
+ ret = iwl_send_cmd_sync(priv, &cmd);
+ if (ret) {
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
- return rc;
+ return ret;
}
- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
if (res->u.status != CAN_ABORT_STATUS) {
/* The scan abort will return 1 for success or
* 2 for "failure". A failure condition can be
@@ -938,7 +772,7 @@ static int iwl4965_send_scan_abort(struct iwl_priv *priv)
dev_kfree_skb_any(cmd.meta.u.skb);
- return rc;
+ return ret;
}
/*
@@ -963,51 +797,6 @@ static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_fla
return iwl_send_cmd(priv, &cmd);
}
-int iwl4965_send_add_station(struct iwl_priv *priv,
- struct iwl4965_addsta_cmd *sta, u8 flags)
-{
- struct iwl4965_rx_packet *res = NULL;
- int rc = 0;
- struct iwl_host_cmd cmd = {
- .id = REPLY_ADD_STA,
- .len = sizeof(struct iwl4965_addsta_cmd),
- .meta.flags = flags,
- .data = sta,
- };
-
- if (!(flags & CMD_ASYNC))
- cmd.meta.flags |= CMD_WANT_SKB;
-
- rc = iwl_send_cmd(priv, &cmd);
-
- if (rc || (flags & CMD_ASYNC))
- return rc;
-
- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
- if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
- IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
- res->hdr.flags);
- rc = -EIO;
- }
-
- if (rc == 0) {
- switch (res->u.add_sta.status) {
- case ADD_STA_SUCCESS_MSK:
- IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n");
- break;
- default:
- rc = -EIO;
- IWL_WARNING("REPLY_ADD_STA failed\n");
- break;
- }
- }
-
- priv->alloc_rxb_skb--;
- dev_kfree_skb_any(cmd.meta.u.skb);
-
- return rc;
-}
-
static void iwl4965_clear_free_frames(struct iwl_priv *priv)
{
struct list_head *element;
@@ -1783,7 +1572,7 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
struct sk_buff *skb_frag,
int sta_id)
{
- struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
+ struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
struct iwl_wep_key *wepkey;
int keyidx = 0;
@@ -1959,7 +1748,7 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv,
IWL_DEBUG_DROP("Station %s not in station map. "
"Defaulting to broadcast...\n",
print_mac(mac, hdr->addr1));
- iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
+ iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_params.bcast_sta_id;
default:
@@ -1975,10 +1764,10 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl4965_tfd_frame *tfd;
+ struct iwl_tfd_frame *tfd;
u32 *control_flags;
int txq_id = ctl->queue;
- struct iwl4965_tx_queue *txq = NULL;
+ struct iwl_tx_queue *txq = NULL;
struct iwl4965_queue *q = NULL;
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
@@ -2175,10 +1964,10 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
txq->need_update = 0;
}
- iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
+ iwl_print_hex_dump(priv, IWL_DL_TX, out_cmd->cmd.payload,
sizeof(out_cmd->cmd.tx));
- iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
+ iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
ieee80211_get_hdrlen(fc));
/* Set up entry for this TFD in Tx byte-count array */
@@ -2441,7 +2230,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv,
u8 type)
{
struct iwl4965_spectrum_cmd spectrum;
- struct iwl4965_rx_packet *res;
+ struct iwl_rx_packet *res;
struct iwl_host_cmd cmd = {
.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
.data = (void *)&spectrum,
@@ -2486,7 +2275,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv,
if (rc)
return rc;
- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
rc = -EIO;
@@ -2542,7 +2331,7 @@ static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
*/
int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
{
- struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
+ struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct iwl4965_queue *q = &txq->q;
int nfreed = 0;
@@ -2559,7 +2348,7 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
if (txq_id != IWL_CMD_QUEUE_NUM) {
iwl4965_txstatus_to_ieee(priv,
&(txq->txb[txq->q.read_ptr]));
- iwl4965_hw_txq_free_tfd(priv, txq);
+ iwl_hw_txq_free_tfd(priv, txq);
} else if (nfreed > 1) {
IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
q->write_ptr, q->read_ptr);
@@ -2568,12 +2357,6 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
nfreed++;
}
-/* if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
- (txq_id != IWL_CMD_QUEUE_NUM) &&
- priv->mac80211_registered)
- ieee80211_wake_queue(priv->hw, txq_id); */
-
-
return nfreed;
}
@@ -2623,7 +2406,7 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
* iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
*/
static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
- struct iwl4965_ht_agg *agg,
+ struct iwl_ht_agg *agg,
struct iwl4965_tx_resp_agg *tx_resp,
u16 start_idx)
{
@@ -2742,13 +2525,13 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
* iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
*/
static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
- struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
+ struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct ieee80211_tx_status *tx_status;
struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le32_to_cpu(tx_resp->status);
@@ -2781,7 +2564,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
if (txq->sched_retry) {
const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
- struct iwl4965_ht_agg *agg = NULL;
+ struct iwl_ht_agg *agg = NULL;
if (!qc)
return;
@@ -2797,7 +2580,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
}
if (txq->q.read_ptr != (scd_ssn & 0xff)) {
- int freed;
+ int freed, ampdu_q;
index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
"%d index %d\n", scd_ssn , index);
@@ -2806,9 +2589,15 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
txq_id >= 0 && priv->mac80211_registered &&
- agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
- ieee80211_wake_queue(priv->hw, txq_id);
-
+ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
+ /* calculate mac80211 ampdu sw queue to wake */
+ ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID +
+ priv->hw->queues;
+ if (agg->state == IWL_AGG_OFF)
+ ieee80211_wake_queue(priv->hw, txq_id);
+ else
+ ieee80211_wake_queue(priv->hw, ampdu_q);
+ }
iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
}
} else {
@@ -2827,20 +2616,17 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
tx_resp->failure_frame);
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
+#ifdef CONFIG_IWL4965_HT
if (index != -1) {
int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
-#ifdef CONFIG_IWL4965_HT
if (tid != MAX_TID_COUNT)
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
- (txq_id >= 0) &&
- priv->mac80211_registered)
+ (txq_id >= 0) && priv->mac80211_registered)
ieee80211_wake_queue(priv->hw, txq_id);
if (tid != MAX_TID_COUNT)
iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
-#endif
}
-#ifdef CONFIG_IWL4965_HT
}
#endif /* CONFIG_IWL4965_HT */
@@ -2850,9 +2636,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_alive_resp *palive;
struct delayed_work *pwork;
@@ -2886,18 +2672,18 @@ static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
}
static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
return;
}
static void iwl4965_rx_reply_error(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
"seq 0x%04X ser 0x%08X\n",
@@ -2910,9 +2696,9 @@ static void iwl4965_rx_reply_error(struct iwl_priv *priv,
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
+static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_rxon_cmd *rxon = (void *)&priv->active_rxon;
struct iwl4965_csa_notification *csa = &(pkt->u.csa_notif);
IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
@@ -2922,15 +2708,15 @@ static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *
}
static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif);
if (!report->state) {
- IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO,
- "Spectrum Measure Notification: Start\n");
+ IWL_DEBUG(IWL_DL_11H,
+ "Spectrum Measure Notification: Start\n");
return;
}
@@ -2940,10 +2726,10 @@ static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
}
static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
@@ -2951,13 +2737,13 @@ static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
}
static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
"notification for %s:\n",
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
- iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+ iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
}
static void iwl4965_bg_beacon_update(struct work_struct *work)
@@ -2986,10 +2772,10 @@ static void iwl4965_bg_beacon_update(struct work_struct *work)
}
static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
@@ -3009,10 +2795,10 @@ static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
/* Service response to REPLY_SCAN_CMD (0x80) */
static void iwl4965_rx_reply_scan(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_scanreq_notification *notif =
(struct iwl4965_scanreq_notification *)pkt->u.raw;
@@ -3022,9 +2808,9 @@ static void iwl4965_rx_reply_scan(struct iwl_priv *priv,
/* Service SCAN_START_NOTIFICATION (0x82) */
static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_scanstart_notification *notif =
(struct iwl4965_scanstart_notification *)pkt->u.raw;
priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
@@ -3039,9 +2825,9 @@ static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv,
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_scanresults_notification *notif =
(struct iwl4965_scanresults_notification *)pkt->u.raw;
@@ -3064,9 +2850,9 @@ static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv,
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
@@ -3122,9 +2908,9 @@ reschedule:
/* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */
static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status;
@@ -3242,9 +3028,9 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
* if the callback returns 1
*/
static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
+ struct iwl_rx_mem_buffer *rxb)
{
- struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
@@ -3279,438 +3065,28 @@ static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
}
}
-/************************** RX-FUNCTIONS ****************************/
-/*
- * Rx theory of operation
- *
- * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
- * each of which point to Receive Buffers to be filled by 4965. These get
- * used not only for Rx frames, but for any command response or notification
- * from the 4965. The driver and 4965 manage the Rx buffers by means
- * of indexes into the circular buffer.
- *
- * Rx Queue Indexes
- * The host/firmware share two index registers for managing the Rx buffers.
- *
- * The READ index maps to the first position that the firmware may be writing
- * to -- the driver can read up to (but not including) this position and get
- * good data.
- * The READ index is managed by the firmware once the card is enabled.
- *
- * The WRITE index maps to the last position the driver has read from -- the
- * position preceding WRITE is the last slot the firmware can place a packet.
- *
- * The queue is empty (no good data) if WRITE = READ - 1, and is full if
- * WRITE = READ.
- *
- * During initialization, the host sets up the READ queue position to the first
- * INDEX position, and WRITE to the last (READ - 1 wrapped)
- *
- * When the firmware places a packet in a buffer, it will advance the READ index
- * and fire the RX interrupt. The driver can then query the READ index and
- * process as many packets as possible, moving the WRITE index forward as it
- * resets the Rx queue buffers with new memory.
- *
- * The management in the driver is as follows:
- * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
- * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- * to replenish the iwl->rxq->rx_free.
- * + In iwl4965_rx_replenish (scheduled) if 'processed' != 'read' then the
- * iwl->rxq is replenished and the READ INDEX is updated (updating the
- * 'processed' and 'read' driver indexes as well)
- * + A received packet is processed and handed to the kernel network stack,
- * detached from the iwl->rxq. The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
- * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
- * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there
- * were enough free buffers and RX_STALLED is set it is cleared.
- *
- *
- * Driver sequence:
- *
- * iwl4965_rx_queue_alloc() Allocates rx_free
- * iwl4965_rx_replenish() Replenishes rx_free list from rx_used, and calls
- * iwl4965_rx_queue_restock
- * iwl4965_rx_queue_restock() Moves available buffers from rx_free into Rx
- * queue, updates firmware pointers, and updates
- * the WRITE index. If insufficient rx_free buffers
- * are available, schedules iwl4965_rx_replenish
- *
- * -- enable interrupts --
- * ISR - iwl4965_rx() Detach iwl4965_rx_mem_buffers from pool up to the
- * READ INDEX, detaching the SKB from the pool.
- * Moves the packet buffer from queue to rx_used.
- * Calls iwl4965_rx_queue_restock to refill any empty
- * slots.
- * ...
- *
- */
-
-/**
- * iwl4965_rx_queue_space - Return number of free slots available in queue.
- */
-static int iwl4965_rx_queue_space(const struct iwl4965_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;
-}
-
-/**
- * iwl4965_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- */
-int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q)
-{
- u32 reg = 0;
- int rc = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&q->lock, flags);
-
- if (q->need_update == 0)
- goto exit_unlock;
-
- /* If power-saving is in use, make sure device is awake */
- if (test_bit(STATUS_POWER_PMI, &priv->status)) {
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
- if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- iwl_set_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- goto exit_unlock;
- }
-
- rc = iwl_grab_nic_access(priv);
- if (rc)
- goto exit_unlock;
-
- /* Device expects a multiple of 8 */
- iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
- q->write & ~0x7);
- iwl_release_nic_access(priv);
-
- /* Else device is assumed to be awake */
- } else
- /* Device expects a multiple of 8 */
- iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
-
-
- q->need_update = 0;
-
- exit_unlock:
- spin_unlock_irqrestore(&q->lock, flags);
- return rc;
-}
-
-/**
- * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv,
- dma_addr_t dma_addr)
-{
- return cpu_to_le32((u32)(dma_addr >> 8));
-}
-
-
-/**
- * iwl4965_rx_queue_restock - refill RX queue from pre-allocated pool
- *
- * If there are slots in the RX queue that need to be restocked,
- * and we have free pre-allocated buffers, fill the ranks as much
- * as we can, pulling from rx_free.
- *
- * This moves the 'write' index forward to catch up with 'processed', and
- * also updates the memory address in the firmware to reference the new
- * target buffer.
- */
-static int iwl4965_rx_queue_restock(struct iwl_priv *priv)
-{
- struct iwl4965_rx_queue *rxq = &priv->rxq;
- struct list_head *element;
- struct iwl4965_rx_mem_buffer *rxb;
- unsigned long flags;
- int write, rc;
-
- spin_lock_irqsave(&rxq->lock, flags);
- write = rxq->write & ~0x7;
- while ((iwl4965_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
- /* Get next free Rx buffer, remove from free list */
- element = rxq->rx_free.next;
- rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list);
- list_del(element);
-
- /* Point to Rx buffer via next RBD in circular buffer */
- rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv, rxb->dma_addr);
- rxq->queue[rxq->write] = rxb;
- rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
- rxq->free_count--;
- }
- spin_unlock_irqrestore(&rxq->lock, flags);
- /* If the pre-allocated buffer pool is dropping low, schedule to
- * refill it */
- if (rxq->free_count <= RX_LOW_WATERMARK)
- queue_work(priv->workqueue, &priv->rx_replenish);
-
-
- /* If we've added more space for the firmware to place data, tell it.
- * Increment device's write pointer in multiples of 8. */
- if ((write != (rxq->write & ~0x7))
- || (abs(rxq->write - rxq->read) > 7)) {
- spin_lock_irqsave(&rxq->lock, flags);
- rxq->need_update = 1;
- spin_unlock_irqrestore(&rxq->lock, flags);
- rc = iwl4965_rx_queue_update_write_ptr(priv, rxq);
- if (rc)
- return rc;
- }
-
- return 0;
-}
-
-/**
- * iwl4965_rx_replenish - Move all used packet from rx_used to rx_free
- *
- * When moving to rx_free an SKB is allocated for the slot.
- *
- * Also restock the Rx queue via iwl4965_rx_queue_restock.
- * This is called as a scheduled work item (except for during initialization)
- */
-static void iwl4965_rx_allocate(struct iwl_priv *priv)
-{
- struct iwl4965_rx_queue *rxq = &priv->rxq;
- struct list_head *element;
- struct iwl4965_rx_mem_buffer *rxb;
- unsigned long flags;
- spin_lock_irqsave(&rxq->lock, flags);
- while (!list_empty(&rxq->rx_used)) {
- element = rxq->rx_used.next;
- rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list);
-
- /* Alloc a new receive buffer */
- rxb->skb =
- alloc_skb(priv->hw_params.rx_buf_size,
- __GFP_NOWARN | GFP_ATOMIC);
- if (!rxb->skb) {
- if (net_ratelimit())
- printk(KERN_CRIT DRV_NAME
- ": Can not allocate SKB buffers\n");
- /* We don't reschedule replenish work here -- we will
- * call the restock method and if it still needs
- * more buffers it will schedule replenish */
- break;
- }
- priv->alloc_rxb_skb++;
- list_del(element);
-
- /* Get physical address of RB/SKB */
- rxb->dma_addr =
- pci_map_single(priv->pci_dev, rxb->skb->data,
- priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE);
- list_add_tail(&rxb->list, &rxq->rx_free);
- rxq->free_count++;
- }
- spin_unlock_irqrestore(&rxq->lock, flags);
-}
-
/*
* this should be called while priv->lock is locked
*/
-static void __iwl4965_rx_replenish(void *data)
-{
- struct iwl_priv *priv = data;
-
- iwl4965_rx_allocate(priv);
- iwl4965_rx_queue_restock(priv);
-}
-
-
-void iwl4965_rx_replenish(void *data)
-{
- struct iwl_priv *priv = data;
- unsigned long flags;
-
- iwl4965_rx_allocate(priv);
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl4965_rx_queue_restock(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have its SKB set to NULL
- * This free routine walks the list of POOL entries and if SKB is set to
- * non NULL it is unmapped and freed
- */
-static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
-{
- int i;
- for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
- if (rxq->pool[i].skb != NULL) {
- pci_unmap_single(priv->pci_dev,
- rxq->pool[i].dma_addr,
- priv->hw_params.rx_buf_size,
- PCI_DMA_FROMDEVICE);
- dev_kfree_skb(rxq->pool[i].skb);
- }
- }
-
- pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
- rxq->dma_addr);
- rxq->bd = NULL;
-}
-
-int iwl4965_rx_queue_alloc(struct iwl_priv *priv)
+static void __iwl_rx_replenish(struct iwl_priv *priv)
{
- struct iwl4965_rx_queue *rxq = &priv->rxq;
- struct pci_dev *dev = priv->pci_dev;
- int i;
-
- spin_lock_init(&rxq->lock);
- INIT_LIST_HEAD(&rxq->rx_free);
- INIT_LIST_HEAD(&rxq->rx_used);
-
- /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
- rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
- if (!rxq->bd)
- return -ENOMEM;
-
- /* Fill the rx_used queue with _all_ of the Rx buffers */
- for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-
- /* 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->free_count = 0;
- rxq->need_update = 0;
- return 0;
+ iwl_rx_allocate(priv);
+ iwl_rx_queue_restock(priv);
}
-void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
-{
- unsigned long flags;
- int i;
- spin_lock_irqsave(&rxq->lock, flags);
- INIT_LIST_HEAD(&rxq->rx_free);
- INIT_LIST_HEAD(&rxq->rx_used);
- /* Fill the rx_used queue with _all_ of the Rx buffers */
- for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
- /* In the reset function, these buffers may have been allocated
- * to an SKB, so we need to unmap and free potential storage */
- if (rxq->pool[i].skb != NULL) {
- pci_unmap_single(priv->pci_dev,
- rxq->pool[i].dma_addr,
- priv->hw_params.rx_buf_size,
- PCI_DMA_FROMDEVICE);
- priv->alloc_rxb_skb--;
- dev_kfree_skb(rxq->pool[i].skb);
- rxq->pool[i].skb = NULL;
- }
- list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
- }
-
- /* 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->free_count = 0;
- spin_unlock_irqrestore(&rxq->lock, flags);
-}
-
-/* Convert linear signal-to-noise ratio into dB */
-static u8 ratio2dB[100] = {
-/* 0 1 2 3 4 5 6 7 8 9 */
- 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
- 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
- 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
- 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
- 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
- 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
- 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
- 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
- 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
- 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */
-};
-
-/* Calculates a relative dB value from a ratio of linear
- * (i.e. not dB) signal levels.
- * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
-int iwl4965_calc_db_from_ratio(int sig_ratio)
-{
- /* 1000:1 or higher just report as 60 dB */
- if (sig_ratio >= 1000)
- return 60;
-
- /* 100:1 or higher, divide by 10 and use table,
- * add 20 dB to make up for divide by 10 */
- if (sig_ratio >= 100)
- return (20 + (int)ratio2dB[sig_ratio/10]);
-
- /* We shouldn't see this */
- if (sig_ratio < 1)
- return 0;
-
- /* Use table for ratios 1:1 - 99:1 */
- return (int)ratio2dB[sig_ratio];
-}
-
-#define PERFECT_RSSI (-20) /* dBm */
-#define WORST_RSSI (-95) /* dBm */
-#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
-
-/* Calculate an indication of rx signal quality (a percentage, not dBm!).
- * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
- * about formulas used below. */
-int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
-{
- int sig_qual;
- int degradation = PERFECT_RSSI - rssi_dbm;
-
- /* If we get a noise measurement, use signal-to-noise ratio (SNR)
- * as indicator; formula is (signal dbm - noise dbm).
- * SNR at or above 40 is a great signal (100%).
- * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
- * Weakest usable signal is usually 10 - 15 dB SNR. */
- if (noise_dbm) {
- if (rssi_dbm - noise_dbm >= 40)
- return 100;
- else if (rssi_dbm < noise_dbm)
- return 0;
- sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
-
- /* Else use just the signal level.
- * This formula is a least squares fit of data points collected and
- * compared with a reference system that had a percentage (%) display
- * for signal quality. */
- } else
- sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
- (15 * RSSI_RANGE + 62 * degradation)) /
- (RSSI_RANGE * RSSI_RANGE);
-
- if (sig_qual > 100)
- sig_qual = 100;
- else if (sig_qual < 1)
- sig_qual = 0;
-
- return sig_qual;
-}
/**
- * iwl4965_rx_handle - Main entry function for receiving responses from uCode
+ * iwl_rx_handle - Main entry function for receiving responses from uCode
*
* Uses the priv->rx_handlers callback function array to invoke
* the appropriate handlers, including command responses,
* frame-received notifications, and other notifications.
*/
-static void iwl4965_rx_handle(struct iwl_priv *priv)
+void iwl_rx_handle(struct iwl_priv *priv)
{
- struct iwl4965_rx_mem_buffer *rxb;
- struct iwl4965_rx_packet *pkt;
- struct iwl4965_rx_queue *rxq = &priv->rxq;
+ struct iwl_rx_mem_buffer *rxb;
+ struct iwl_rx_packet *pkt;
+ struct iwl_rx_queue *rxq = &priv->rxq;
u32 r, i;
int reclaim;
unsigned long flags;
@@ -3719,14 +3095,14 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
/* uCode's read index (stored in shared DRAM) indicates the last Rx
* buffer that the driver may process (last buffer filled by ucode). */
- r = iwl4965_hw_get_rx_read(priv);
+ r = priv->cfg->ops->lib->shared_mem_rx_idx(priv);
i = rxq->read;
/* Rx interrupt, but nothing sent from uCode */
if (i == r)
- IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
+ IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d\n", r, i);
- if (iwl4965_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
+ if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
fill_rx = 1;
while (i != r) {
@@ -3742,7 +3118,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
priv->hw_params.rx_buf_size,
PCI_DMA_FROMDEVICE);
- pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
+ pkt = (struct iwl_rx_packet *)rxb->skb->data;
/* Reclaim a command buffer only if this packet is a response
* to a (driver-originated) command.
@@ -3761,13 +3137,12 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
* handle those that need handling via function in
* rx_handlers table. See iwl4965_setup_rx_handlers() */
if (priv->rx_handlers[pkt->hdr.cmd]) {
- IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
- "r = %d, i = %d, %s, 0x%02x\n", r, i,
- get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+ IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d, %s, 0x%02x\n", r,
+ i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
} else {
/* No handling needed */
- IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
+ IWL_DEBUG(IWL_DL_RX,
"r %d i %d No handler needed for %s, 0x%02x\n",
r, i, get_cmd_string(pkt->hdr.cmd),
pkt->hdr.cmd);
@@ -3805,7 +3180,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
count++;
if (count >= 8) {
priv->rxq.read = i;
- __iwl4965_rx_replenish(priv);
+ __iwl_rx_replenish(priv);
count = 0;
}
}
@@ -3813,14 +3188,91 @@ static void iwl4965_rx_handle(struct iwl_priv *priv)
/* Backtrack one entry */
priv->rxq.read = i;
- iwl4965_rx_queue_restock(priv);
+ iwl_rx_queue_restock(priv);
+}
+/* Convert linear signal-to-noise ratio into dB */
+static u8 ratio2dB[100] = {
+/* 0 1 2 3 4 5 6 7 8 9 */
+ 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
+ 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
+ 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
+ 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
+ 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
+ 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
+ 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
+ 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
+ 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
+ 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */
+};
+
+/* Calculates a relative dB value from a ratio of linear
+ * (i.e. not dB) signal levels.
+ * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
+int iwl4965_calc_db_from_ratio(int sig_ratio)
+{
+ /* 1000:1 or higher just report as 60 dB */
+ if (sig_ratio >= 1000)
+ return 60;
+
+ /* 100:1 or higher, divide by 10 and use table,
+ * add 20 dB to make up for divide by 10 */
+ if (sig_ratio >= 100)
+ return (20 + (int)ratio2dB[sig_ratio/10]);
+
+ /* We shouldn't see this */
+ if (sig_ratio < 1)
+ return 0;
+
+ /* Use table for ratios 1:1 - 99:1 */
+ return (int)ratio2dB[sig_ratio];
+}
+
+#define PERFECT_RSSI (-20) /* dBm */
+#define WORST_RSSI (-95) /* dBm */
+#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI)
+
+/* Calculate an indication of rx signal quality (a percentage, not dBm!).
+ * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
+ * about formulas used below. */
+int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
+{
+ int sig_qual;
+ int degradation = PERFECT_RSSI - rssi_dbm;
+
+ /* If we get a noise measurement, use signal-to-noise ratio (SNR)
+ * as indicator; formula is (signal dbm - noise dbm).
+ * SNR at or above 40 is a great signal (100%).
+ * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator.
+ * Weakest usable signal is usually 10 - 15 dB SNR. */
+ if (noise_dbm) {
+ if (rssi_dbm - noise_dbm >= 40)
+ return 100;
+ else if (rssi_dbm < noise_dbm)
+ return 0;
+ sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2;
+
+ /* Else use just the signal level.
+ * This formula is a least squares fit of data points collected and
+ * compared with a reference system that had a percentage (%) display
+ * for signal quality. */
+ } else
+ sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation *
+ (15 * RSSI_RANGE + 62 * degradation)) /
+ (RSSI_RANGE * RSSI_RANGE);
+
+ if (sig_qual > 100)
+ sig_qual = 100;
+ else if (sig_qual < 1)
+ sig_qual = 0;
+
+ return sig_qual;
}
/**
* iwl4965_tx_queue_update_write_ptr - Send new write index to hardware
*/
static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq)
+ struct iwl_tx_queue *txq)
{
u32 reg = 0;
int rc = 0;
@@ -3863,12 +3315,13 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
}
#ifdef CONFIG_IWLWIFI_DEBUG
-static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon)
+static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
{
+ struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
DECLARE_MAC_BUF(mac);
IWL_DEBUG_RADIO("RX CONFIG:\n");
- iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+ iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
@@ -4094,10 +3547,10 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_FW_ERRORS) {
+ if (priv->debug_level & IWL_DL_FW_ERRORS) {
iwl4965_dump_nic_error_log(priv);
iwl4965_dump_nic_event_log(priv);
- iwl4965_print_rx_config_cmd(&priv->staging_rxon);
+ iwl4965_print_rx_config_cmd(priv);
}
#endif
@@ -4108,7 +3561,7 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
clear_bit(STATUS_READY, &priv->status);
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
+ IWL_DEBUG(IWL_DL_FW_ERRORS,
"Restarting adapter due to uCode error.\n");
if (iwl_is_associated(priv)) {
@@ -4116,7 +3569,8 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
sizeof(priv->recovery_rxon));
priv->error_recovering = 1;
}
- queue_work(priv->workqueue, &priv->restart);
+ if (priv->cfg->mod_params->restart_fw)
+ queue_work(priv->workqueue, &priv->restart);
}
}
@@ -4161,7 +3615,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_ISR) {
+ if (priv->debug_level & IWL_DL_ISR) {
/* just for debug */
inta_mask = iwl_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -4195,7 +3649,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
+ if (priv->debug_level & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD)
IWL_DEBUG_ISR("Scheduler finished to transmit "
@@ -4216,8 +3670,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
hw_rf_kill = 1;
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
- "RF_KILL bit toggled to %s.\n",
+ IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
hw_rf_kill ? "disable radio":"enable radio");
/* Queue restart only if RF_KILL switch was set to "kill"
@@ -4249,7 +3702,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
/* uCode wakes up after power-down sleep */
if (inta & CSR_INT_BIT_WAKEUP) {
IWL_DEBUG_ISR("Wakeup interrupt\n");
- iwl4965_rx_queue_update_write_ptr(priv, &priv->rxq);
+ iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[0]);
iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[1]);
iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[2]);
@@ -4264,7 +3717,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
* Rx "responses" (frame-received notification), and other
* notifications from uCode come through here*/
if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
- iwl4965_rx_handle(priv);
+ iwl_rx_handle(priv);
handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
}
@@ -4288,7 +3741,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
iwl4965_enable_interrupts(priv);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
+ if (priv->debug_level & (IWL_DL_ISR)) {
inta = iwl_read32(priv, CSR_INT);
inta_mask = iwl_read32(priv, CSR_INT_MASK);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
@@ -4708,105 +4161,6 @@ static int iwl4965_read_ucode(struct iwl_priv *priv)
return ret;
}
-
-/**
- * iwl4965_set_ucode_ptrs - Set uCode address location
- *
- * Tell initialization uCode where to find runtime uCode.
- *
- * BSM registers initially contain pointers to initialization uCode.
- * We need to replace them to load runtime uCode inst and data,
- * and to save runtime data when powering down.
- */
-static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
-{
- dma_addr_t pinst;
- dma_addr_t pdata;
- int rc = 0;
- unsigned long flags;
-
- /* bits 35:4 for 4965 */
- pinst = priv->ucode_code.p_addr >> 4;
- pdata = priv->ucode_data_backup.p_addr >> 4;
-
- spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_nic_access(priv);
- if (rc) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
-
- /* Tell bootstrap uCode where to find image to load */
- iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
- iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
- iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
- priv->ucode_data.len);
-
- /* Inst bytecount must be last to set up, bit 31 signals uCode
- * that all new ptr/size info is in place */
- iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
- priv->ucode_code.len | BSM_DRAM_INST_LOAD);
-
- iwl_release_nic_access(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- IWL_DEBUG_INFO("Runtime uCode pointers are set.\n");
-
- return rc;
-}
-
-/**
- * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
- *
- * Called after REPLY_ALIVE notification received from "initialize" uCode.
- *
- * The 4965 "initialize" ALIVE reply contains calibration data for:
- * Voltage, temperature, and MIMO tx gain correction, now stored in priv
- * (3945 does not contain this data).
- *
- * Tell "initialize" uCode to go ahead and load the runtime uCode.
-*/
-static void iwl4965_init_alive_start(struct iwl_priv *priv)
-{
- /* Check alive response for "valid" sign from uCode */
- if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
- /* We had an error bringing up the hardware, so take it
- * all the way back down so we can try again */
- IWL_DEBUG_INFO("Initialize Alive failed.\n");
- goto restart;
- }
-
- /* Bootstrap uCode has loaded initialize uCode ... verify inst image.
- * This is a paranoid check, because we would not have gotten the
- * "initialize" alive if code weren't properly loaded. */
- if (iwl_verify_ucode(priv)) {
- /* Runtime instruction load was bad;
- * take it all the way back down so we can try again */
- IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
- goto restart;
- }
-
- /* Calculate temperature */
- priv->temperature = iwl4965_get_temperature(priv);
-
- /* Send pointers to protocol/runtime uCode image ... init code will
- * load and launch runtime uCode, which will send us another "Alive"
- * notification. */
- IWL_DEBUG_INFO("Initialization Alive received.\n");
- if (iwl4965_set_ucode_ptrs(priv)) {
- /* Runtime instruction load won't happen;
- * take it all the way back down so we can try again */
- IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n");
- goto restart;
- }
- return;
-
- restart:
- queue_work(priv->workqueue, &priv->restart);
-}
-
-
/**
* iwl4965_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
@@ -5056,7 +4410,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
return ret;
}
- ret = priv->cfg->ops->lib->hw_nic_init(priv);
+ ret = iwl_hw_nic_init(priv);
if (ret) {
IWL_ERROR("Unable to init nic\n");
return ret;
@@ -5132,7 +4486,7 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data)
return;
mutex_lock(&priv->mutex);
- iwl4965_init_alive_start(priv);
+ priv->cfg->ops->lib->init_alive_start(priv);
mutex_unlock(&priv->mutex);
}
@@ -5161,7 +4515,7 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
mutex_lock(&priv->mutex);
if (!iwl_is_rfkill(priv)) {
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
+ IWL_DEBUG(IWL_DL_RF_KILL,
"HW and/or SW RF Kill no longer active, restarting "
"device\n");
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -5184,6 +4538,24 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
mutex_unlock(&priv->mutex);
}
+static void iwl4965_bg_set_monitor(struct work_struct *work)
+{
+ struct iwl_priv *priv = container_of(work,
+ struct iwl_priv, set_monitor);
+
+ IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
+
+ mutex_lock(&priv->mutex);
+
+ if (!iwl_is_ready(priv))
+ IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
+ else
+ if (iwl4965_set_mode(priv, IEEE80211_IF_TYPE_MNTR) != 0)
+ IWL_ERROR("iwl4965_set_mode() failed\n");
+
+ mutex_unlock(&priv->mutex);
+}
+
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
static void iwl4965_bg_scan_check(struct work_struct *data)
@@ -5197,9 +4569,9 @@ static void iwl4965_bg_scan_check(struct work_struct *data)
mutex_lock(&priv->mutex);
if (test_bit(STATUS_SCANNING, &priv->status) ||
test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN,
- "Scan completion watchdog resetting adapter (%dms)\n",
- jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
+ IWL_DEBUG(IWL_DL_SCAN, "Scan completion watchdog resetting "
+ "adapter (%dms)\n",
+ jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
iwl4965_send_scan_abort(priv);
@@ -5453,7 +4825,7 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data)
return;
mutex_lock(&priv->mutex);
- iwl4965_rx_replenish(priv);
+ iwl_rx_replenish(priv);
mutex_unlock(&priv->mutex);
}
@@ -5501,7 +4873,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
#ifdef CONFIG_IWL4965_HT
if (priv->current_ht_config.is_ht)
- iwl4965_set_rxon_ht(priv, &priv->current_ht_config);
+ iwl_set_rxon_ht(priv, &priv->current_ht_config);
#endif /* CONFIG_IWL4965_HT*/
iwl_set_rxon_chain(priv);
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
@@ -5600,7 +4972,7 @@ static void iwl4965_bg_scan_completed(struct work_struct *work)
struct iwl_priv *priv =
container_of(work, struct iwl_priv, scan_completed);
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
+ IWL_DEBUG(IWL_DL_SCAN, "SCAN complete scan\n");
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -6073,7 +5445,22 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw,
* XXX: dummy
* see also iwl4965_connection_init_rx_config
*/
- *total_flags = 0;
+ struct iwl_priv *priv = hw->priv;
+ int new_flags = 0;
+ if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
+ if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
+ IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
+ IEEE80211_IF_TYPE_MNTR,
+ changed_flags, *total_flags);
+ /* queue work 'cuz mac80211 is holding a lock which
+ * prevents us from issuing (synchronous) f/w cmds */
+ queue_work(priv->workqueue, &priv->set_monitor);
+ new_flags &= FIF_PROMISC_IN_BSS |
+ FIF_OTHER_BSS |
+ FIF_ALLMULTI;
+ }
+ }
+ *total_flags = new_flags;
}
static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
@@ -6261,7 +5648,7 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
spin_unlock_irqrestore(&priv->sta_lock, flags);
@@ -6395,7 +5782,7 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
{
struct iwl_priv *priv = hw->priv;
int i, avail;
- struct iwl4965_tx_queue *txq;
+ struct iwl_tx_queue *txq;
struct iwl4965_queue *q;
unsigned long flags;
@@ -6428,6 +5815,9 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
+ struct iwl_priv *priv = hw->priv;
+
+ priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
IWL_DEBUG_MAC80211("leave\n");
@@ -6436,6 +5826,9 @@ static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw)
{
+ struct iwl_priv *priv;
+
+ priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
IWL_DEBUG_MAC80211("leave\n");
@@ -6569,13 +5962,18 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
* See the level definitions in iwl for details.
*/
-static ssize_t show_debug_level(struct device_driver *d, char *buf)
+static ssize_t show_debug_level(struct device *d,
+ struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "0x%08X\n", iwl_debug_level);
+ struct iwl_priv *priv = d->driver_data;
+
+ return sprintf(buf, "0x%08X\n", priv->debug_level);
}
-static ssize_t store_debug_level(struct device_driver *d,
+static ssize_t store_debug_level(struct device *d,
+ struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct iwl_priv *priv = d->driver_data;
char *p = (char *)buf;
u32 val;
@@ -6584,17 +5982,37 @@ static ssize_t store_debug_level(struct device_driver *d,
printk(KERN_INFO DRV_NAME
": %s is not in hex or decimal form.\n", buf);
else
- iwl_debug_level = val;
+ priv->debug_level = val;
return strnlen(buf, count);
}
-static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
- show_debug_level, store_debug_level);
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+ show_debug_level, store_debug_level);
+
#endif /* CONFIG_IWLWIFI_DEBUG */
+static ssize_t show_version(struct device *d,
+ struct device_attribute *attr, char *buf)
+{
+ struct iwl_priv *priv = d->driver_data;
+ struct iwl4965_alive_resp *palive = &priv->card_alive;
+
+ if (palive->is_valid)
+ return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
+ "fw type: 0x%01X 0x%01X\n",
+ palive->ucode_major, palive->ucode_minor,
+ palive->sw_rev[0], palive->sw_rev[1],
+ palive->ver_type, palive->ver_subtype);
+
+ else
+ return sprintf(buf, "fw not loaded\n");
+}
+
+static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);
+
static ssize_t show_temperature(struct device *d,
struct device_attribute *attr, char *buf)
{
@@ -6998,6 +6416,7 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->abort_scan, iwl4965_bg_abort_scan);
INIT_WORK(&priv->rf_kill, iwl4965_bg_rf_kill);
INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
+ INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
@@ -7036,6 +6455,10 @@ static struct attribute *iwl4965_sysfs_entries[] = {
&dev_attr_status.attr,
&dev_attr_temperature.attr,
&dev_attr_tx_power.attr,
+#ifdef CONFIG_IWLWIFI_DEBUG
+ &dev_attr_debug_level.attr,
+#endif
+ &dev_attr_version.attr,
NULL
};
@@ -7085,7 +6508,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
/* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan. */
if (cfg->mod_params->disable_hw_scan) {
- IWL_DEBUG_INFO("Disabling hw_scan\n");
+ if (cfg->mod_params->debug & IWL_DL_INFO)
+ dev_printk(KERN_DEBUG, &(pdev->dev),
+ "Disabling hw_scan\n");
iwl4965_hw_ops.hw_scan = NULL;
}
@@ -7104,7 +6529,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
priv->pci_dev = pdev;
#ifdef CONFIG_IWLWIFI_DEBUG
- iwl_debug_level = priv->cfg->mod_params->debug;
+ priv->debug_level = priv->cfg->mod_params->debug;
atomic_set(&priv->restrict_refcnt, 0);
#endif
@@ -7310,8 +6735,8 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
iwl4965_dealloc_ucode_pci(priv);
if (priv->rxq.bd)
- iwl4965_rx_queue_free(priv, &priv->rxq);
- iwl4965_hw_txq_ctx_free(priv);
+ iwl_rx_queue_free(priv, &priv->rxq);
+ iwl_hw_txq_ctx_free(priv);
iwlcore_clear_stations_table(priv);
iwl_eeprom_free(priv);
@@ -7420,18 +6845,11 @@ static int __init iwl4965_init(void)
IWL_ERROR("Unable to initialize PCI module\n");
goto error_register;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
- ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
- if (ret) {
- IWL_ERROR("Unable to create driver sysfs file\n");
- goto error_debug;
- }
-#endif
return ret;
+
#ifdef CONFIG_IWLWIFI_DEBUG
-error_debug:
pci_unregister_driver(&iwl_driver);
#endif
error_register:
@@ -7441,9 +6859,6 @@ error_register:
static void __exit iwl4965_exit(void)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
-#endif
pci_unregister_driver(&iwl_driver);
iwl4965_rate_control_unregister();
}
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 6328b959387..c2dd43ece06 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -697,38 +697,6 @@ static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
}
/**
- * @brief Get the current data rate
- *
- * @param priv A pointer to struct lbs_private structure
- *
- * @return The data rate on success, error on failure
- */
-int lbs_get_data_rate(struct lbs_private *priv)
-{
- struct cmd_ds_802_11_data_rate cmd;
- int ret = -1;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_ACT_GET_TX_RATE);
-
- ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
- if (ret)
- goto out;
-
- lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd));
-
- ret = (int) lbs_fw_index_to_data_rate(cmd.rates[0]);
- lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", ret);
-
-out:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-/**
* @brief Set the data rate
*
* @param priv A pointer to struct lbs_private structure
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 4295bc61366..f4019c22adf 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -34,7 +34,6 @@ int lbs_update_hw_spec(struct lbs_private *priv);
int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
struct cmd_ds_mesh_access *cmd);
-int lbs_get_data_rate(struct lbs_private *priv);
int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
int lbs_get_channel(struct lbs_private *priv);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 0be89573716..e333f14dce2 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -927,20 +927,10 @@ static int lbs_setup_firmware(struct lbs_private *priv)
*/
memset(priv->current_addr, 0xff, ETH_ALEN);
ret = lbs_update_hw_spec(priv);
- if (ret) {
- ret = -1;
+ if (ret)
goto done;
- }
lbs_set_mac_control(priv);
-
- ret = lbs_get_data_rate(priv);
- if (ret < 0) {
- ret = -1;
- goto done;
- }
-
- ret = 0;
done:
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
return ret;
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 33d608a60d7..9cbef5bce0f 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -355,7 +355,7 @@ static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
struct ieee80211_rx_status rx_status = {0};
u16 freq = le16_to_cpu(hdr->freq);
- rx_status.ssi = hdr->rssi;
+ rx_status.signal = hdr->rssi;
/* XX correct? */
rx_status.rate_idx = hdr->rate & 0xf;
rx_status.freq = freq;
@@ -1000,9 +1000,10 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
skb_queue_head_init(&priv->tx_queue);
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
- IEEE80211_HW_RX_INCLUDES_FCS;
+ IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_UNSPEC;
dev->channel_change_time = 1000; /* TODO: find actual value */
- dev->max_rssi = 127;
+ dev->max_signal = 127;
priv->tx_stats[0].limit = 5;
dev->queues = 1;
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 247fbbfb0f2..afa565c6362 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1361,10 +1361,9 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all hw fields.
*/
- rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+ rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM;
rt2x00dev->hw->extra_tx_headroom = 0;
- rt2x00dev->hw->max_signal = MAX_SIGNAL;
- rt2x00dev->hw->max_rssi = MAX_RX_SSI;
rt2x00dev->hw->queues = 2;
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 0d53c75d55d..c06f1b5e588 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1680,10 +1680,10 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all hw fields.
*/
- rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+ rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM;
+
rt2x00dev->hw->extra_tx_headroom = 0;
- rt2x00dev->hw->max_signal = MAX_SIGNAL;
- rt2x00dev->hw->max_rssi = MAX_RX_SSI;
rt2x00dev->hw->queues = 2;
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 80b34d47114..88bafdf8f0f 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1587,10 +1587,10 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->flags =
IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM;
+
rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
- rt2x00dev->hw->max_signal = MAX_SIGNAL;
- rt2x00dev->hw->max_rssi = MAX_RX_SSI;
rt2x00dev->hw->queues = 2;
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 61510c51935..3a49c256789 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -600,9 +600,9 @@ void rt2x00lib_rxdone(struct queue_entry *entry,
rt2x00dev->link.qual.rx_success++;
rx_status->rate_idx = idx;
- rx_status->signal =
+ rx_status->qual =
rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
- rx_status->ssi = rxdesc->rssi;
+ rx_status->signal = rxdesc->rssi;
rx_status->flag = rxdesc->flags;
rx_status->antenna = rt2x00dev->link.ant.active.rx;
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index b64f2f5d0d5..edddbf35bba 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2245,10 +2245,9 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
*/
rt2x00dev->hw->flags =
IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM;
rt2x00dev->hw->extra_tx_headroom = 0;
- rt2x00dev->hw->max_signal = MAX_SIGNAL;
- rt2x00dev->hw->max_rssi = MAX_RX_SSI;
rt2x00dev->hw->queues = 4;
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 351d95c4f50..51c5575ed02 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1830,10 +1830,9 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
*/
rt2x00dev->hw->flags =
IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM;
rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
- rt2x00dev->hw->max_signal = MAX_SIGNAL;
- rt2x00dev->hw->max_rssi = MAX_RX_SSI;
rt2x00dev->hw->queues = 4;
SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index c181f23e930..c220998cee6 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -132,8 +132,8 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
rx_status.antenna = (flags2 >> 15) & 1;
/* TODO: improve signal/rssi reporting */
- rx_status.signal = flags2 & 0xFF;
- rx_status.ssi = (flags2 >> 8) & 0x7F;
+ rx_status.qual = flags2 & 0xFF;
+ rx_status.signal = (flags2 >> 8) & 0x7F;
/* XXX: is this correct? */
rx_status.rate_idx = (flags >> 20) & 0xF;
rx_status.freq = dev->conf.channel->center_freq;
@@ -894,9 +894,10 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_RX_INCLUDES_FCS;
+ IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_UNSPEC;
dev->queues = 1;
- dev->max_rssi = 65;
+ dev->max_signal = 65;
reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
reg &= RTL818X_TX_CONF_HWVER_MASK;
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index d5787b37e1f..e14c8424868 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -261,8 +261,8 @@ static void rtl8187_rx_cb(struct urb *urb)
}
rx_status.antenna = (hdr->signal >> 7) & 1;
- rx_status.signal = 64 - min(hdr->noise, (u8)64);
- rx_status.ssi = signal;
+ rx_status.qual = 64 - min(hdr->noise, (u8)64);
+ rx_status.signal = signal;
rx_status.rate_idx = rate;
rx_status.freq = dev->conf.channel->center_freq;
rx_status.band = dev->conf.channel->band;
@@ -740,11 +740,11 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
priv->mode = IEEE80211_IF_TYPE_MNTR;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_RX_INCLUDES_FCS;
+ IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_UNSPEC;
dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
dev->queues = 1;
- dev->max_rssi = 65;
- dev->max_signal = 64;
+ dev->max_signal = 65;
eeprom.data = dev;
eeprom.register_read = rtl8187_eeprom_register_read;
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 69c45ca9905..0c736735e21 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -638,7 +638,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
memset(&status, 0, sizeof(status));
status.flags = IEEE80211_TX_STATUS_ACK;
- status.ack_signal = stats->ssi;
+ status.ack_signal = stats->signal;
__skb_unlink(skb, q);
tx_status(hw, skb, &status, 1);
goto out;
@@ -691,8 +691,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
stats.band = IEEE80211_BAND_2GHZ;
- stats.ssi = status->signal_strength;
- stats.signal = zd_rx_qual_percent(buffer,
+ stats.signal = status->signal_strength;
+ stats.qual = zd_rx_qual_percent(buffer,
length - sizeof(struct rx_status),
status);
@@ -751,6 +751,7 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
case IEEE80211_IF_TYPE_MNTR:
case IEEE80211_IF_TYPE_MESH_POINT:
case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
mac->type = conf->type;
break;
default:
@@ -781,7 +782,8 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
struct zd_mac *mac = zd_hw_mac(hw);
int associated;
- if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) {
+ if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
+ mac->type == IEEE80211_IF_TYPE_IBSS) {
associated = true;
if (conf->beacon) {
zd_mac_config_beacon(hw, conf->beacon);
@@ -941,6 +943,18 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
}
}
+static int zd_op_beacon_update(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl)
+{
+ struct zd_mac *mac = zd_hw_mac(hw);
+ zd_mac_config_beacon(hw, skb);
+ kfree_skb(skb);
+ zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
+ hw->conf.beacon_int);
+ return 0;
+}
+
static const struct ieee80211_ops zd_ops = {
.tx = zd_op_tx,
.start = zd_op_start,
@@ -951,6 +965,7 @@ static const struct ieee80211_ops zd_ops = {
.config_interface = zd_op_config_interface,
.configure_filter = zd_op_configure_filter,
.bss_info_changed = zd_op_bss_info_changed,
+ .beacon_update = zd_op_beacon_update,
};
struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
@@ -982,10 +997,10 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
- hw->max_rssi = 100;
- hw->max_signal = 100;
+ IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
+ IEEE80211_HW_SIGNAL_DB;
+ hw->max_signal = 100;
hw->queues = 1;
hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 0b5e03eae6d..a9102bc78b6 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -552,16 +552,17 @@ enum ieee80211_back_parties {
*/
static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr)
{
- u8 *raw = (u8 *) hdr;
- u8 tofrom = (*(raw+1)) & 3; /* get the TODS and FROMDS bits */
-
- switch (tofrom) {
- case 2:
- return hdr->addr3;
- case 3:
- return hdr->addr4;
+ __le16 fc = hdr->frame_control;
+ fc &= cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
+
+ switch (fc) {
+ case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS):
+ return hdr->addr3;
+ case __constant_cpu_to_le16(IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS):
+ return hdr->addr4;
+ default:
+ return hdr->addr2;
}
- return hdr->addr2;
}
/**
@@ -577,12 +578,13 @@ static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr)
*/
static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
{
- u8 *raw = (u8 *) hdr;
- u8 to_ds = (*(raw+1)) & 1; /* get the TODS bit */
+ __le16 fc = hdr->frame_control;
+ fc &= cpu_to_le16(IEEE80211_FCTL_TODS);
- if (to_ds)
+ if (fc)
return hdr->addr3;
- return hdr->addr1;
+ else
+ return hdr->addr1;
}
/**
@@ -595,8 +597,8 @@ static inline u8 *ieee80211_get_DA(struct ieee80211_hdr *hdr)
*/
static inline int ieee80211_get_morefrag(struct ieee80211_hdr *hdr)
{
- return (le16_to_cpu(hdr->frame_control) &
- IEEE80211_FCTL_MOREFRAGS) != 0;
+ __le16 fc = hdr->frame_control;
+ return !!(fc & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS));
}
#endif /* IEEE80211_H */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 75a34609eed..909956c97c4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -336,13 +336,16 @@ enum mac80211_rx_flags {
* The low-level driver should provide this information (the subset
* supported by hardware) to the 802.11 code with each received
* frame.
+ *
* @mactime: value in microseconds of the 64-bit Time Synchronization Function
* (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
* @band: the active band when this frame was received
* @freq: frequency the radio was tuned to when receiving this frame, in MHz
- * @ssi: signal strength when receiving this frame
- * @signal: used as 'qual' in statistics reporting
- * @noise: PHY noise when receiving this frame
+ * @signal: signal strength when receiving this frame, either in dBm, in dB or
+ * unspecified depending on the hardware capabilities flags
+ * @IEEE80211_HW_SIGNAL_*
+ * @noise: noise when receiving this frame, in dBm.
+ * @qual: overall signal quality indication, in percent (0-100).
* @antenna: antenna used
* @rate_idx: index of data rate into band's supported rates
* @flag: %RX_FLAG_*
@@ -351,9 +354,9 @@ struct ieee80211_rx_status {
u64 mactime;
enum ieee80211_band band;
int freq;
- int ssi;
int signal;
int noise;
+ int qual;
int antenna;
int rate_idx;
int flag;
@@ -392,7 +395,8 @@ enum ieee80211_tx_status_flags {
* relevant only if IEEE80211_TX_STATUS_AMPDU was set.
* @ampdu_ack_map: block ack bit map for the aggregation.
* relevant only if IEEE80211_TX_STATUS_AMPDU was set.
- * @ack_signal: signal strength of the ACK frame
+ * @ack_signal: signal strength of the ACK frame either in dBm, dB or unspec
+ * depending on hardware capabilites flags @IEEE80211_HW_SIGNAL_*
*/
struct ieee80211_tx_status {
struct ieee80211_tx_control control;
@@ -703,6 +707,25 @@ enum ieee80211_tkip_key_type {
* @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE:
* Hardware is not capable of receiving frames with short preamble on
* the 2.4 GHz band.
+ *
+ * @IEEE80211_HW_SIGNAL_UNSPEC:
+ * Hardware can provide signal values but we don't know its units. We
+ * expect values between 0 and @max_signal.
+ * If possible please provide dB or dBm instead.
+ *
+ * @IEEE80211_HW_SIGNAL_DB:
+ * Hardware gives signal values in dB, decibel difference from an
+ * arbitrary, fixed reference. We expect values between 0 and @max_signal.
+ * If possible please provide dBm instead.
+ *
+ * @IEEE80211_HW_SIGNAL_DBM:
+ * Hardware gives signal values in dBm, decibel difference from
+ * one milliwatt. This is the preferred method since it is standardized
+ * between different devices. @max_signal does not need to be set.
+ *
+ * @IEEE80211_HW_NOISE_DBM:
+ * Hardware can provide noise (radio interference) values in units dBm,
+ * decibel difference from one milliwatt.
*/
enum ieee80211_hw_flags {
IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE = 1<<0,
@@ -710,6 +733,10 @@ enum ieee80211_hw_flags {
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2,
IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3,
IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4,
+ IEEE80211_HW_SIGNAL_UNSPEC = 1<<5,
+ IEEE80211_HW_SIGNAL_DB = 1<<6,
+ IEEE80211_HW_SIGNAL_DBM = 1<<7,
+ IEEE80211_HW_NOISE_DBM = 1<<8,
};
/**
@@ -740,12 +767,8 @@ enum ieee80211_hw_flags {
*
* @channel_change_time: time (in microseconds) it takes to change channels.
*
- * @max_rssi: Maximum value for ssi in RX information, use
- * negative numbers for dBm and 0 to indicate no support.
- *
- * @max_signal: like @max_rssi, but for the signal value.
- *
- * @max_noise: like @max_rssi, but for the noise value.
+ * @max_signal: Maximum value for signal (rssi) in RX information, used
+ * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
*
* @queues: number of available hardware transmit queues for
* data packets. WMM/QoS requires at least four, these
@@ -775,9 +798,7 @@ struct ieee80211_hw {
int channel_change_time;
int vif_data_size;
u16 queues, ampdu_queues;
- s8 max_rssi;
s8 max_signal;
- s8 max_noise;
};
/**
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 200ee1e6372..69dbc342a46 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -391,7 +391,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
wstats.updated = 0;
if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
- wstats.level = rx_stats->rssi;
+ wstats.level = rx_stats->signal;
wstats.updated |= IW_QUAL_LEVEL_UPDATED;
} else
wstats.updated |= IW_QUAL_LEVEL_INVALID;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 699d97b8de5..3cef80dcd0e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -602,6 +602,7 @@ static void sta_apply_parameters(struct ieee80211_local *local,
*/
if (params->station_flags & STATION_FLAG_CHANGED) {
+ spin_lock_bh(&sta->lock);
sta->flags &= ~WLAN_STA_AUTHORIZED;
if (params->station_flags & STATION_FLAG_AUTHORIZED)
sta->flags |= WLAN_STA_AUTHORIZED;
@@ -613,6 +614,7 @@ static void sta_apply_parameters(struct ieee80211_local *local,
sta->flags &= ~WLAN_STA_WME;
if (params->station_flags & STATION_FLAG_WME)
sta->flags |= WLAN_STA_WME;
+ spin_unlock_bh(&sta->lock);
}
/*
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 676a93202ff..a2cc0284c9d 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -63,8 +63,8 @@ STA_FILE(tx_fragments, tx_fragments, LU);
STA_FILE(tx_filtered, tx_filtered_count, LU);
STA_FILE(tx_retry_failed, tx_retry_failed, LU);
STA_FILE(tx_retry_count, tx_retry_count, LU);
-STA_FILE(last_rssi, last_rssi, D);
STA_FILE(last_signal, last_signal, D);
+STA_FILE(last_qual, last_qual, D);
STA_FILE(last_noise, last_noise, D);
STA_FILE(channel_use, channel_use, D);
STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
@@ -74,14 +74,15 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
{
char buf[100];
struct sta_info *sta = file->private_data;
+ u32 staflags = get_sta_flags(sta);
int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
- sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
- sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
- sta->flags & WLAN_STA_PS ? "PS\n" : "",
- sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
- sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
- sta->flags & WLAN_STA_WME ? "WME\n" : "",
- sta->flags & WLAN_STA_WDS ? "WDS\n" : "");
+ staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
+ staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+ staflags & WLAN_STA_PS ? "PS\n" : "",
+ staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+ staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
+ staflags & WLAN_STA_WME ? "WME\n" : "",
+ staflags & WLAN_STA_WDS ? "WDS\n" : "");
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
STA_OPS(flags);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d82ed20a344..ed0d9b35ae6 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -82,7 +82,7 @@ struct ieee80211_sta_bss {
u16 capability; /* host byte order */
enum ieee80211_band band;
int freq;
- int rssi, signal, noise;
+ int signal, noise, qual;
u8 *wpa_ie;
size_t wpa_ie_len;
u8 *rsn_ie;
@@ -610,8 +610,8 @@ struct ieee80211_local {
struct sta_info *sta_hash[STA_HASH_SIZE];
struct timer_list sta_cleanup;
- unsigned long state[IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_AMPDU_QUEUES];
- struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_AMPDU_QUEUES];
+ unsigned long state[IEEE80211_MAX_QUEUES + IEEE80211_MAX_AMPDU_QUEUES];
+ struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES + IEEE80211_MAX_AMPDU_QUEUES];
struct tasklet_struct tx_pending_tasklet;
/* number of interfaces with corresponding IFF_ flags */
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 4a8062f8b1c..3c64e42eb12 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -166,9 +166,10 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
IEEE80211_AUTH_ALG_SHARED_KEY;
ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
- IEEE80211_STA_WMM_ENABLED |
IEEE80211_STA_AUTO_BSSID_SEL |
IEEE80211_STA_AUTO_CHANNEL_SEL;
+ if (sdata->local->hw.queues >= 4)
+ ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
sdata->bss = &msdata->u.ap;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 88b211af7c1..d4893bd1775 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -321,7 +321,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
* some hardware cannot handle TKIP with QoS, so
* we indicate whether QoS could be in use.
*/
- if (sta->flags & WLAN_STA_WME)
+ if (test_sta_flags(sta, WLAN_STA_WME))
key->conf.flags |= IEEE80211_KEY_FLAG_WMM_STA;
/*
@@ -342,7 +342,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
/* same here, the AP could be using QoS */
ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
if (ap) {
- if (ap->flags & WLAN_STA_WME)
+ if (test_sta_flags(ap, WLAN_STA_WME))
key->conf.flags |=
IEEE80211_KEY_FLAG_WMM_STA;
}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index eb347eca30b..36016363d22 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -346,6 +346,7 @@ static int ieee80211_open(struct net_device *dev)
goto err_del_interface;
}
+ /* no locking required since STA is not live yet */
sta->flags |= WLAN_STA_AUTHORIZED;
res = sta_info_insert(sta);
@@ -588,7 +589,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
return -ENOENT;
}
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_lock_bh(&sta->lock);
/* we have tried too many times, receiver does not want A-MPDU */
if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
@@ -691,7 +692,7 @@ start_ba_err:
spin_unlock_bh(&local->mdev->queue_lock);
ret = -EBUSY;
start_ba_exit:
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return ret;
}
@@ -719,7 +720,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
/* check if the TID is in aggregation */
state = &sta->ampdu_mlme.tid_state_tx[tid];
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_lock_bh(&sta->lock);
if (*state != HT_AGG_STATE_OPERATIONAL) {
ret = -ENOENT;
@@ -749,7 +750,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
}
stop_BA_exit:
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return ret;
}
@@ -778,12 +779,12 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
}
state = &sta->ampdu_mlme.tid_state_tx[tid];
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_lock_bh(&sta->lock);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
*state);
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
}
@@ -796,7 +797,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
}
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
}
EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
@@ -830,10 +831,10 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
}
state = &sta->ampdu_mlme.tid_state_tx[tid];
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_lock_bh(&sta->lock);
if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
}
@@ -860,7 +861,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
sta->ampdu_mlme.addba_req_num[tid] = 0;
kfree(sta->ampdu_mlme.tid_tx[tid]);
sta->ampdu_mlme.tid_tx[tid] = NULL;
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
}
@@ -1315,7 +1316,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
* packet. If the STA went to power save mode, this will happen
* happen when it wakes up for the next time.
*/
- sta->flags |= WLAN_STA_CLEAR_PS_FILT;
+ set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT);
/*
* This code races in the following way:
@@ -1347,7 +1348,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
* can be unknown, for example with different interrupt status
* bits.
*/
- if (sta->flags & WLAN_STA_PS &&
+ if (test_sta_flags(sta, WLAN_STA_PS) &&
skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
ieee80211_remove_tx_extra(local, sta->key, skb,
&status->control);
@@ -1355,7 +1356,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
return;
}
- if (!(sta->flags & WLAN_STA_PS) &&
+ if (!test_sta_flags(sta, WLAN_STA_PS) &&
!(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
/* Software retry the packet once */
status->control.flags |= IEEE80211_TXCTL_REQUEUE;
@@ -1370,7 +1371,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
"queue_len=%d PS=%d @%lu\n",
wiphy_name(local->hw.wiphy),
skb_queue_len(&sta->tx_filtered),
- !!(sta->flags & WLAN_STA_PS), jiffies);
+ !!test_sta_flags(sta, WLAN_STA_PS), jiffies);
dev_kfree_skb(skb);
}
@@ -1399,7 +1400,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
struct sta_info *sta;
sta = sta_info_get(local, hdr->addr1);
if (sta) {
- if (sta->flags & WLAN_STA_PS) {
+ if (test_sta_flags(sta, WLAN_STA_PS)) {
/*
* The STA is in power save mode, so assume
* that this TX packet failed because of that.
@@ -1701,13 +1702,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
local->hw.conf.beacon_int = 1000;
- local->wstats_flags |= local->hw.max_rssi ?
- IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
- local->wstats_flags |= local->hw.max_signal ?
+ local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
+ IEEE80211_HW_SIGNAL_DB |
+ IEEE80211_HW_SIGNAL_DBM) ?
IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
- local->wstats_flags |= local->hw.max_noise ?
+ local->wstats_flags |= local->hw.flags & IEEE80211_HW_NOISE_DBM ?
IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
- if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
local->wstats_flags |= IW_QUAL_DBM;
result = sta_info_start(local);
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index af0cd1e3e21..7fa149e230e 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -26,7 +26,7 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
{
if (ae)
offset += 6;
- return le32_to_cpu(get_unaligned((__le32 *) (preq_elem + offset)));
+ return get_unaligned_le32(preq_elem + offset);
}
/* HWMP IE processing macros */
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 37f0c2b94ae..9efeb1f0702 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -79,7 +79,7 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
*
* @sta: mes peer link to restart
*
- * Locking: this function must be called holding sta->plink_lock
+ * Locking: this function must be called holding sta->lock
*/
static inline void mesh_plink_fsm_restart(struct sta_info *sta)
{
@@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
if (!sta)
return NULL;
- sta->flags |= WLAN_STA_AUTHORIZED;
+ sta->flags = WLAN_STA_AUTHORIZED;
sta->supp_rates[local->hw.conf.channel->band] = rates;
return sta;
@@ -118,7 +118,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
*
* All mesh paths with this peer as next hop will be flushed
*
- * Locking: the caller must hold sta->plink_lock
+ * Locking: the caller must hold sta->lock
*/
static void __mesh_plink_deactivate(struct sta_info *sta)
{
@@ -139,9 +139,9 @@ static void __mesh_plink_deactivate(struct sta_info *sta)
*/
void mesh_plink_deactivate(struct sta_info *sta)
{
- spin_lock_bh(&sta->plink_lock);
+ spin_lock_bh(&sta->lock);
__mesh_plink_deactivate(sta);
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
}
static int mesh_plink_frame_tx(struct net_device *dev,
@@ -270,10 +270,10 @@ static void mesh_plink_timer(unsigned long data)
*/
sta = (struct sta_info *) data;
- spin_lock_bh(&sta->plink_lock);
+ spin_lock_bh(&sta->lock);
if (sta->ignore_plink_timer) {
sta->ignore_plink_timer = false;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
return;
}
mpl_dbg("Mesh plink timer for %s fired on state %d\n",
@@ -298,7 +298,7 @@ static void mesh_plink_timer(unsigned long data)
rand % sta->plink_timeout;
++sta->plink_retries;
mod_plink_timer(sta, sta->plink_timeout);
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
0, 0);
break;
@@ -311,7 +311,7 @@ static void mesh_plink_timer(unsigned long data)
reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT);
sta->plink_state = PLINK_HOLDING;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid,
reason);
break;
@@ -319,10 +319,10 @@ static void mesh_plink_timer(unsigned long data)
/* holding timer */
del_timer(&sta->plink_timer);
mesh_plink_fsm_restart(sta);
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
default:
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
}
}
@@ -344,16 +344,16 @@ int mesh_plink_open(struct sta_info *sta)
DECLARE_MAC_BUF(mac);
#endif
- spin_lock_bh(&sta->plink_lock);
+ spin_lock_bh(&sta->lock);
get_random_bytes(&llid, 2);
sta->llid = llid;
if (sta->plink_state != PLINK_LISTEN) {
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
return -EBUSY;
}
sta->plink_state = PLINK_OPN_SNT;
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink: starting establishment with %s\n",
print_mac(mac, sta->addr));
@@ -367,10 +367,10 @@ void mesh_plink_block(struct sta_info *sta)
DECLARE_MAC_BUF(mac);
#endif
- spin_lock_bh(&sta->plink_lock);
+ spin_lock_bh(&sta->lock);
__mesh_plink_deactivate(sta);
sta->plink_state = PLINK_BLOCKED;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
}
int mesh_plink_close(struct sta_info *sta)
@@ -383,14 +383,14 @@ int mesh_plink_close(struct sta_info *sta)
mpl_dbg("Mesh plink: closing link with %s\n",
print_mac(mac, sta->addr));
- spin_lock_bh(&sta->plink_lock);
+ spin_lock_bh(&sta->lock);
sta->reason = cpu_to_le16(MESH_LINK_CANCELLED);
reason = sta->reason;
if (sta->plink_state == PLINK_LISTEN ||
sta->plink_state == PLINK_BLOCKED) {
mesh_plink_fsm_restart(sta);
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
return 0;
} else if (sta->plink_state == PLINK_ESTAB) {
__mesh_plink_deactivate(sta);
@@ -402,7 +402,7 @@ int mesh_plink_close(struct sta_info *sta)
sta->plink_state = PLINK_HOLDING;
llid = sta->llid;
plid = sta->plid;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
return 0;
@@ -490,7 +490,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
/* avoid warning */
break;
}
- spin_lock_bh(&sta->plink_lock);
+ spin_lock_bh(&sta->lock);
} else if (!sta) {
/* ftype == PLINK_OPEN */
u64 rates;
@@ -512,9 +512,9 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
return;
}
event = OPN_ACPT;
- spin_lock_bh(&sta->plink_lock);
+ spin_lock_bh(&sta->lock);
} else {
- spin_lock_bh(&sta->plink_lock);
+ spin_lock_bh(&sta->lock);
switch (ftype) {
case PLINK_OPEN:
if (!mesh_plink_free_count(sdata) ||
@@ -551,7 +551,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
break;
default:
mpl_dbg("Mesh plink: unknown frame subtype\n");
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
}
@@ -568,7 +568,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
switch (event) {
case CLS_ACPT:
mesh_plink_fsm_restart(sta);
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
case OPN_ACPT:
sta->plink_state = PLINK_OPN_RCVD;
@@ -576,14 +576,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
get_random_bytes(&llid, 2);
sta->llid = llid;
mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
0, 0);
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr,
llid, plid, 0);
break;
default:
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
}
break;
@@ -603,7 +603,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->ignore_plink_timer = true;
llid = sta->llid;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
@@ -612,7 +612,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->plink_state = PLINK_OPN_RCVD;
sta->plid = plid;
llid = sta->llid;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
plid, 0);
break;
@@ -622,10 +622,10 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
dot11MeshConfirmTimeout(sdata)))
sta->ignore_plink_timer = true;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
default:
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
}
break;
@@ -645,13 +645,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->ignore_plink_timer = true;
llid = sta->llid;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
case OPN_ACPT:
llid = sta->llid;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
plid, 0);
break;
@@ -659,12 +659,12 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
del_timer(&sta->plink_timer);
sta->plink_state = PLINK_ESTAB;
mesh_plink_inc_estab_count(sdata);
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink with %s ESTABLISHED\n",
print_mac(mac, sta->addr));
break;
default:
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
}
break;
@@ -684,7 +684,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->ignore_plink_timer = true;
llid = sta->llid;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
@@ -692,14 +692,14 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
del_timer(&sta->plink_timer);
sta->plink_state = PLINK_ESTAB;
mesh_plink_inc_estab_count(sdata);
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mpl_dbg("Mesh plink with %s ESTABLISHED\n",
print_mac(mac, sta->addr));
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
plid, 0);
break;
default:
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
}
break;
@@ -713,18 +713,18 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
sta->plink_state = PLINK_HOLDING;
llid = sta->llid;
mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
case OPN_ACPT:
llid = sta->llid;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
plid, 0);
break;
default:
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
}
break;
@@ -734,7 +734,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
if (del_timer(&sta->plink_timer))
sta->ignore_plink_timer = 1;
mesh_plink_fsm_restart(sta);
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
case OPN_ACPT:
case CNF_ACPT:
@@ -742,19 +742,19 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
case CNF_RJCT:
llid = sta->llid;
reason = sta->reason;
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
plid, reason);
break;
default:
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
}
break;
default:
/* should not get here, PLINK_BLOCKED is dealt with at the
* beggining of the function
*/
- spin_unlock_bh(&sta->plink_lock);
+ spin_unlock_bh(&sta->lock);
break;
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 5d7719f44be..7877d3b3f4c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -272,6 +272,12 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
int count;
u8 *pos;
+ if (!(ifsta->flags & IEEE80211_STA_WMM_ENABLED))
+ return;
+
+ if (!wmm_param)
+ return;
+
if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
return;
count = wmm_param[6] & 0x0f;
@@ -799,8 +805,10 @@ static void ieee80211_send_assoc(struct net_device *dev,
*pos++ = 1; /* WME ver */
*pos++ = 0;
}
+
/* wmm support is a must to HT */
- if (wmm && sband->ht_info.ht_supported) {
+ if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
+ sband->ht_info.ht_supported) {
__le16 tmp = cpu_to_le16(sband->ht_info.cap);
pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
*pos++ = WLAN_EID_HT_CAPABILITY;
@@ -1269,7 +1277,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
/* examine state machine */
- spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
+ spin_lock_bh(&sta->lock);
if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -1336,7 +1344,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev,
tid_agg_rx->stored_mpdu_num = 0;
status = WLAN_STATUS_SUCCESS;
end:
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+ spin_unlock_bh(&sta->lock);
end_no_lock:
ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid,
@@ -1368,10 +1376,10 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
state = &sta->ampdu_mlme.tid_state_tx[tid];
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_lock_bh(&sta->lock);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
"%d\n", *state);
goto addba_resp_exit;
@@ -1379,7 +1387,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
if (mgmt->u.action.u.addba_resp.dialog_token !=
sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */
@@ -1403,7 +1411,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
}
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid);
} else {
printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid);
@@ -1411,7 +1419,7 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev,
sta->ampdu_mlme.addba_req_num[tid]++;
/* this will allow the state check in stop_BA_session */
*state = HT_AGG_STATE_OPERATIONAL;
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
WLAN_BACK_INITIATOR);
}
@@ -1481,17 +1489,17 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
}
/* check if TID is in operational state */
- spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
+ spin_lock_bh(&sta->lock);
if (sta->ampdu_mlme.tid_state_rx[tid]
!= HT_AGG_STATE_OPERATIONAL) {
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+ spin_unlock_bh(&sta->lock);
rcu_read_unlock();
return;
}
sta->ampdu_mlme.tid_state_rx[tid] =
HT_AGG_STATE_REQ_STOP_BA_MSK |
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
+ spin_unlock_bh(&sta->lock);
/* stop HW Rx aggregation. ampdu_action existence
* already verified in session init so we add the BUG_ON */
@@ -1568,10 +1576,10 @@ static void ieee80211_sta_process_delba(struct net_device *dev,
ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
WLAN_BACK_INITIATOR, 0);
else { /* WLAN_BACK_RECIPIENT */
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_lock_bh(&sta->lock);
sta->ampdu_mlme.tid_state_tx[tid] =
HT_AGG_STATE_OPERATIONAL;
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
WLAN_BACK_RECIPIENT);
}
@@ -1608,9 +1616,9 @@ void sta_addba_resp_timer_expired(unsigned long data)
state = &sta->ampdu_mlme.tid_state_tx[tid];
/* check if the TID waits for addBA response */
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_lock_bh(&sta->lock);
if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
*state = HT_AGG_STATE_IDLE;
printk(KERN_DEBUG "timer expired on tid %d but we are not "
"expecting addBA response there", tid);
@@ -1621,7 +1629,7 @@ void sta_addba_resp_timer_expired(unsigned long data)
/* go through the state check in stop_BA_session */
*state = HT_AGG_STATE_OPERATIONAL;
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid,
WLAN_BACK_INITIATOR);
@@ -1987,8 +1995,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
local->hw.conf.channel->center_freq,
ifsta->ssid, ifsta->ssid_len);
if (bss) {
- sta->last_rssi = bss->rssi;
sta->last_signal = bss->signal;
+ sta->last_qual = bss->qual;
sta->last_noise = bss->noise;
ieee80211_rx_bss_put(dev, bss);
}
@@ -2012,8 +2020,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
* to between the sta_info_alloc() and sta_info_insert() above.
*/
- sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
- WLAN_STA_AUTHORIZED;
+ set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
+ WLAN_STA_AUTHORIZED);
rates = 0;
basic_rates = 0;
@@ -2057,7 +2065,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
else
sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
- if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
+ if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
+ (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
struct ieee80211_ht_bss_info bss_info;
ieee80211_ht_cap_ie_to_ht_info(
(struct ieee80211_ht_cap *)
@@ -2070,8 +2079,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
rate_control_rate_init(sta, local);
- if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
- sta->flags |= WLAN_STA_WME;
+ if (elems.wmm_param) {
+ set_sta_flags(sta, WLAN_STA_WME);
rcu_read_unlock();
ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
elems.wmm_param_len);
@@ -2656,9 +2665,9 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
bss->timestamp = beacon_timestamp;
bss->last_update = jiffies;
- bss->rssi = rx_status->ssi;
bss->signal = rx_status->signal;
bss->noise = rx_status->noise;
+ bss->qual = rx_status->qual;
if (!beacon && !bss->probe_resp)
bss->probe_resp = true;
@@ -2853,10 +2862,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
- if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
- ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
- elems.wmm_param_len);
- }
+ ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
+ elems.wmm_param_len);
/* Do not send changes to driver if we are scanning. This removes
* requirement that driver's bss_info_changed function needs to be
@@ -3456,9 +3463,9 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
!ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
continue;
- if (!selected || top_rssi < bss->rssi) {
+ if (!selected || top_rssi < bss->signal) {
selected = bss;
- top_rssi = bss->rssi;
+ top_rssi = bss->signal;
}
}
if (selected)
@@ -4089,8 +4096,8 @@ ieee80211_sta_scan_result(struct net_device *dev,
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = IWEVQUAL;
- iwe.u.qual.qual = bss->signal;
- iwe.u.qual.level = bss->rssi;
+ iwe.u.qual.qual = bss->qual;
+ iwe.u.qual.level = bss->signal;
iwe.u.qual.noise = bss->noise;
iwe.u.qual.updated = local->wstats_flags;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
@@ -4266,7 +4273,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev,
if (!sta)
return NULL;
- sta->flags |= WLAN_STA_AUTHORIZED;
+ set_sta_flags(sta, WLAN_STA_AUTHORIZED);
sta->supp_rates[local->hw.conf.channel->band] =
sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band];
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9b5a3cbec26..fa68305fd59 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -77,6 +77,134 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status,
return 0;
}
+static int
+ieee80211_rx_radiotap_len(struct ieee80211_local *local,
+ struct ieee80211_rx_status *status)
+{
+ int len;
+
+ /* always present fields */
+ len = sizeof(struct ieee80211_radiotap_header) + 9;
+
+ if (status->flag & RX_FLAG_TSFT)
+ len += 8;
+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DB ||
+ local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+ len += 1;
+ if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
+ len += 1;
+
+ if (len & 1) /* padding for RX_FLAGS if necessary */
+ len++;
+
+ /* make sure radiotap starts at a naturally aligned address */
+ if (len % 8)
+ len = roundup(len, 8);
+
+ return len;
+}
+
+/**
+ * ieee80211_add_rx_radiotap_header - add radiotap header
+ *
+ * add a radiotap header containing all the fields which the hardware provided.
+ */
+static void
+ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
+ struct sk_buff *skb,
+ struct ieee80211_rx_status *status,
+ struct ieee80211_rate *rate,
+ int rtap_len)
+{
+ struct ieee80211_radiotap_header *rthdr;
+ unsigned char *pos;
+
+ rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
+ memset(rthdr, 0, rtap_len);
+
+ /* radiotap header, set always present flags */
+ rthdr->it_present =
+ cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
+ (1 << IEEE80211_RADIOTAP_RATE) |
+ (1 << IEEE80211_RADIOTAP_CHANNEL) |
+ (1 << IEEE80211_RADIOTAP_ANTENNA) |
+ (1 << IEEE80211_RADIOTAP_RX_FLAGS));
+ rthdr->it_len = cpu_to_le16(rtap_len);
+
+ pos = (unsigned char *)(rthdr+1);
+
+ /* the order of the following fields is important */
+
+ /* IEEE80211_RADIOTAP_TSFT */
+ if (status->flag & RX_FLAG_TSFT) {
+ *(__le64 *)pos = cpu_to_le64(status->mactime);
+ rthdr->it_present |=
+ cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
+ pos += 8;
+ }
+
+ /* IEEE80211_RADIOTAP_FLAGS */
+ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
+ *pos |= IEEE80211_RADIOTAP_F_FCS;
+ pos++;
+
+ /* IEEE80211_RADIOTAP_RATE */
+ *pos = rate->bitrate / 5;
+ pos++;
+
+ /* IEEE80211_RADIOTAP_CHANNEL */
+ *(__le16 *)pos = cpu_to_le16(status->freq);
+ pos += 2;
+ if (status->band == IEEE80211_BAND_5GHZ)
+ *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_5GHZ);
+ else
+ *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_DYN |
+ IEEE80211_CHAN_2GHZ);
+ pos += 2;
+
+ /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+ *pos = status->signal;
+ rthdr->it_present |=
+ cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
+ pos++;
+ }
+
+ /* IEEE80211_RADIOTAP_DBM_ANTNOISE */
+ if (local->hw.flags & IEEE80211_HW_NOISE_DBM) {
+ *pos = status->noise;
+ rthdr->it_present |=
+ cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);
+ pos++;
+ }
+
+ /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */
+
+ /* IEEE80211_RADIOTAP_ANTENNA */
+ *pos = status->antenna;
+ pos++;
+
+ /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */
+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) {
+ *pos = status->signal;
+ rthdr->it_present |=
+ cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL);
+ pos++;
+ }
+
+ /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */
+
+ /* IEEE80211_RADIOTAP_RX_FLAGS */
+ /* ensure 2 byte alignment for the 2 byte field as required */
+ if ((pos - (unsigned char *)rthdr) & 1)
+ pos++;
+ /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */
+ if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
+ *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
+ pos += 2;
+}
+
/*
* This function copies a received frame to all monitor interfaces and
* returns a cleaned-up SKB that no longer includes the FCS nor the
@@ -89,17 +217,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
{
struct ieee80211_sub_if_data *sdata;
int needed_headroom = 0;
- struct ieee80211_radiotap_header *rthdr;
- __le64 *rttsft = NULL;
- struct ieee80211_rtap_fixed_data {
- u8 flags;
- u8 rate;
- __le16 chan_freq;
- __le16 chan_flags;
- u8 antsignal;
- u8 padding_for_rxflags;
- __le16 rx_flags;
- } __attribute__ ((packed)) *rtfixed;
struct sk_buff *skb, *skb2;
struct net_device *prev_dev = NULL;
int present_fcs_len = 0;
@@ -116,8 +233,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
if (status->flag & RX_FLAG_RADIOTAP)
rtap_len = ieee80211_get_radiotap_len(origskb->data);
else
- /* room for radiotap header, always present fields and TSFT */
- needed_headroom = sizeof(*rthdr) + sizeof(*rtfixed) + 8;
+ /* room for the radiotap header based on driver features */
+ needed_headroom = ieee80211_rx_radiotap_len(local, status);
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
present_fcs_len = FCS_LEN;
@@ -163,55 +280,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
}
/* if necessary, prepend radiotap information */
- if (!(status->flag & RX_FLAG_RADIOTAP)) {
- rtfixed = (void *) skb_push(skb, sizeof(*rtfixed));
- rtap_len = sizeof(*rthdr) + sizeof(*rtfixed);
- if (status->flag & RX_FLAG_TSFT) {
- rttsft = (void *) skb_push(skb, sizeof(*rttsft));
- rtap_len += 8;
- }
- rthdr = (void *) skb_push(skb, sizeof(*rthdr));
- memset(rthdr, 0, sizeof(*rthdr));
- memset(rtfixed, 0, sizeof(*rtfixed));
- rthdr->it_present =
- cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
- (1 << IEEE80211_RADIOTAP_RATE) |
- (1 << IEEE80211_RADIOTAP_CHANNEL) |
- (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |
- (1 << IEEE80211_RADIOTAP_RX_FLAGS));
- rtfixed->flags = 0;
- if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
- rtfixed->flags |= IEEE80211_RADIOTAP_F_FCS;
-
- if (rttsft) {
- *rttsft = cpu_to_le64(status->mactime);
- rthdr->it_present |=
- cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
- }
-
- /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */
- rtfixed->rx_flags = 0;
- if (status->flag &
- (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
- rtfixed->rx_flags |=
- cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
-
- rtfixed->rate = rate->bitrate / 5;
-
- rtfixed->chan_freq = cpu_to_le16(status->freq);
-
- if (status->band == IEEE80211_BAND_5GHZ)
- rtfixed->chan_flags =
- cpu_to_le16(IEEE80211_CHAN_OFDM |
- IEEE80211_CHAN_5GHZ);
- else
- rtfixed->chan_flags =
- cpu_to_le16(IEEE80211_CHAN_DYN |
- IEEE80211_CHAN_2GHZ);
-
- rtfixed->antsignal = status->ssi;
- rthdr->it_len = cpu_to_le16(rtap_len);
- }
+ if (!(status->flag & RX_FLAG_RADIOTAP))
+ ieee80211_add_rx_radiotap_header(local, skb, status, rate,
+ needed_headroom);
skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -479,7 +550,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
(rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
- (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
+ (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
!(rx->fc & IEEE80211_FCTL_TODS) &&
(rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
@@ -630,8 +701,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
if (sdata->bss)
atomic_inc(&sdata->bss->num_sta_ps);
- sta->flags |= WLAN_STA_PS;
- sta->flags &= ~WLAN_STA_PSPOLL;
+ set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
dev->name, print_mac(mac, sta->addr), sta->aid);
@@ -652,7 +722,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
if (sdata->bss)
atomic_dec(&sdata->bss->num_sta_ps);
- sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL);
+ clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
if (!skb_queue_empty(&sta->ps_tx_buf))
sta_info_clear_tim_bit(sta);
@@ -720,16 +790,17 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
sta->rx_fragments++;
sta->rx_bytes += rx->skb->len;
- sta->last_rssi = rx->status->ssi;
sta->last_signal = rx->status->signal;
+ sta->last_qual = rx->status->qual;
sta->last_noise = rx->status->noise;
if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
/* Change STA power saving mode only in the end of a frame
* exchange sequence */
- if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM))
+ if (test_sta_flags(sta, WLAN_STA_PS) &&
+ !(rx->fc & IEEE80211_FCTL_PM))
rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
- else if (!(sta->flags & WLAN_STA_PS) &&
+ else if (!test_sta_flags(sta, WLAN_STA_PS) &&
(rx->fc & IEEE80211_FCTL_PM))
ap_sta_ps_start(dev, sta);
}
@@ -983,7 +1054,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
* Tell TX path to send one frame even though the STA may
* still remain is PS mode after this frame exchange.
*/
- rx->sta->flags |= WLAN_STA_PSPOLL;
+ set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",
@@ -1046,7 +1117,8 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
static int
ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
{
- if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) {
+ if (unlikely(!rx->sta ||
+ !test_sta_flags(rx->sta, WLAN_STA_AUTHORIZED))) {
#ifdef CONFIG_MAC80211_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: dropped frame "
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 631943e8af8..baf5e474688 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -202,14 +202,12 @@ void sta_info_destroy(struct sta_info *sta)
dev_kfree_skb_any(skb);
for (i = 0; i < STA_TID_NUM; i++) {
- spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
+ spin_lock_bh(&sta->lock);
if (sta->ampdu_mlme.tid_rx[i])
del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer);
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
- spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
if (sta->ampdu_mlme.tid_tx[i])
del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer);
- spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
+ spin_unlock_bh(&sta->lock);
}
__sta_info_free(local, sta);
@@ -236,6 +234,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
if (!sta)
return NULL;
+ spin_lock_init(&sta->lock);
+
memcpy(sta->addr, addr, ETH_ALEN);
sta->local = local;
sta->sdata = sdata;
@@ -249,8 +249,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
return NULL;
}
- spin_lock_init(&sta->ampdu_mlme.ampdu_rx);
- spin_lock_init(&sta->ampdu_mlme.ampdu_tx);
for (i = 0; i < STA_TID_NUM; i++) {
/* timer_to_tid must be initialized with identity mapping to
* enable session_timer's data differentiation. refer to
@@ -276,7 +274,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
#ifdef CONFIG_MAC80211_MESH
sta->plink_state = PLINK_LISTEN;
- spin_lock_init(&sta->plink_lock);
init_timer(&sta->plink_timer);
#endif
@@ -437,8 +434,7 @@ void __sta_info_unlink(struct sta_info **sta)
list_del(&(*sta)->list);
- if ((*sta)->flags & WLAN_STA_PS) {
- (*sta)->flags &= ~WLAN_STA_PS;
+ if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) {
if (sdata->bss)
atomic_dec(&sdata->bss->num_sta_ps);
__sta_info_clear_tim_bit(sdata->bss, *sta);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index f8c95bc9659..e89cc165554 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -129,23 +129,19 @@ enum plink_state {
*
* @tid_state_rx: TID's state in Rx session state machine.
* @tid_rx: aggregation info for Rx per TID
- * @ampdu_rx: for locking sections in aggregation Rx flow
* @tid_state_tx: TID's state in Tx session state machine.
* @tid_tx: aggregation info for Tx per TID
* @addba_req_num: number of times addBA request has been sent.
- * @ampdu_tx: for locking sectionsi in aggregation Tx flow
* @dialog_token_allocator: dialog token enumerator for each new session;
*/
struct sta_ampdu_mlme {
/* rx */
u8 tid_state_rx[STA_TID_NUM];
struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
- spinlock_t ampdu_rx;
/* tx */
u8 tid_state_tx[STA_TID_NUM];
struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
u8 addba_req_num[STA_TID_NUM];
- spinlock_t ampdu_tx;
u8 dialog_token_allocator;
};
@@ -177,6 +173,8 @@ struct sta_ampdu_mlme {
* @rx_bytes: Number of bytes received from this STA
* @supp_rates: Bitmap of supported rates (per band)
* @ht_info: HT capabilities of this STA
+ * @lock: used for locking all fields that require locking, see comments
+ * in the header file.
*/
struct sta_info {
/* General information, mostly static */
@@ -187,6 +185,7 @@ struct sta_info {
struct ieee80211_key *key;
struct rate_control_ref *rate_ctrl;
void *rate_ctrl_priv;
+ spinlock_t lock;
struct ieee80211_ht_info ht_info;
u64 supp_rates[IEEE80211_NUM_BANDS];
u8 addr[ETH_ALEN];
@@ -199,7 +198,7 @@ struct sta_info {
*/
u8 pin_status;
- /* frequently updated information, needs locking? */
+ /* frequently updated information, locked with lock spinlock */
u32 flags;
/*
@@ -217,8 +216,8 @@ struct sta_info {
* from this STA */
unsigned long rx_fragments; /* number of received MPDUs */
unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
- int last_rssi; /* RSSI of last received frame from this STA */
int last_signal; /* signal of last received frame from this STA */
+ int last_qual; /* qual of last received frame from this STA */
int last_noise; /* noise of last received frame from this STA */
/* last received seq/frag number from this STA (per RX queue) */
__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
@@ -251,7 +250,7 @@ struct sta_info {
int channel_use_raw;
/*
- * Aggregation information, comes with own locking.
+ * Aggregation information, locked with lock.
*/
struct sta_ampdu_mlme ampdu_mlme;
u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */
@@ -270,9 +269,6 @@ struct sta_info {
enum plink_state plink_state;
u32 plink_timeout;
struct timer_list plink_timer;
- spinlock_t plink_lock; /* For peer_state reads / updates and other
- updates in the structure. Ensures robust
- transitions for the peerlink FSM */
#endif
#ifdef CONFIG_MAC80211_DEBUGFS
@@ -299,6 +295,64 @@ static inline enum plink_state sta_plink_state(struct sta_info *sta)
return PLINK_LISTEN;
}
+static inline void set_sta_flags(struct sta_info *sta, const u32 flags)
+{
+ spin_lock_bh(&sta->lock);
+ sta->flags |= flags;
+ spin_unlock_bh(&sta->lock);
+}
+
+static inline void clear_sta_flags(struct sta_info *sta, const u32 flags)
+{
+ spin_lock_bh(&sta->lock);
+ sta->flags &= ~flags;
+ spin_unlock_bh(&sta->lock);
+}
+
+static inline void set_and_clear_sta_flags(struct sta_info *sta,
+ const u32 set, const u32 clear)
+{
+ spin_lock_bh(&sta->lock);
+ sta->flags |= set;
+ sta->flags &= ~clear;
+ spin_unlock_bh(&sta->lock);
+}
+
+static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags)
+{
+ u32 ret;
+
+ spin_lock_bh(&sta->lock);
+ ret = sta->flags & flags;
+ spin_unlock_bh(&sta->lock);
+
+ return ret;
+}
+
+static inline u32 test_and_clear_sta_flags(struct sta_info *sta,
+ const u32 flags)
+{
+ u32 ret;
+
+ spin_lock_bh(&sta->lock);
+ ret = sta->flags & flags;
+ sta->flags &= ~flags;
+ spin_unlock_bh(&sta->lock);
+
+ return ret;
+}
+
+static inline u32 get_sta_flags(struct sta_info *sta)
+{
+ u32 ret;
+
+ spin_lock_bh(&sta->lock);
+ ret = sta->flags;
+ spin_unlock_bh(&sta->lock);
+
+ return ret;
+}
+
/* Maximum number of concurrently registered stations */
#define MAX_STA_COUNT 2007
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c
index 09093da24af..a7c3febc5a4 100644
--- a/net/mac80211/tkip.c
+++ b/net/mac80211/tkip.c
@@ -8,23 +8,22 @@
*/
#include <linux/kernel.h>
+#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/netdevice.h>
+#include <asm/unaligned.h>
#include <net/mac80211.h>
#include "key.h"
#include "tkip.h"
#include "wep.h"
-
-/* TKIP key mixing functions */
-
-
#define PHASE1_LOOP_COUNT 8
-
-/* 2-byte by 2-byte subset of the full AES S-box table; second part of this
- * table is identical to first part but byte-swapped */
+/*
+ * 2-byte by 2-byte subset of the full AES S-box table; second part of this
+ * table is identical to first part but byte-swapped
+ */
static const u16 tkip_sbox[256] =
{
0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
@@ -61,53 +60,13 @@ static const u16 tkip_sbox[256] =
0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
};
-
-static inline u16 Mk16(u8 x, u8 y)
-{
- return ((u16) x << 8) | (u16) y;
-}
-
-
-static inline u8 Hi8(u16 v)
-{
- return v >> 8;
-}
-
-
-static inline u8 Lo8(u16 v)
-{
- return v & 0xff;
-}
-
-
-static inline u16 Hi16(u32 v)
-{
- return v >> 16;
-}
-
-
-static inline u16 Lo16(u32 v)
-{
- return v & 0xffff;
-}
-
-
-static inline u16 RotR1(u16 v)
+static u16 tkipS(u16 val)
{
- return (v >> 1) | ((v & 0x0001) << 15);
-}
-
-
-static inline u16 tkip_S(u16 val)
-{
- u16 a = tkip_sbox[Hi8(val)];
-
- return tkip_sbox[Lo8(val)] ^ Hi8(a) ^ (Lo8(a) << 8);
+ return tkip_sbox[val & 0xff] ^ swab16(tkip_sbox[val >> 8]);
}
-
-
-/* P1K := Phase1(TA, TK, TSC)
+/*
+ * P1K := Phase1(TA, TK, TSC)
* TA = transmitter address (48 bits)
* TK = dot11DefaultKeyValue or dot11KeyMappingValue (128 bits)
* TSC = TKIP sequence counter (48 bits, only 32 msb bits used)
@@ -118,23 +77,22 @@ static void tkip_mixing_phase1(const u8 *ta, const u8 *tk, u32 tsc_IV32,
{
int i, j;
- p1k[0] = Lo16(tsc_IV32);
- p1k[1] = Hi16(tsc_IV32);
- p1k[2] = Mk16(ta[1], ta[0]);
- p1k[3] = Mk16(ta[3], ta[2]);
- p1k[4] = Mk16(ta[5], ta[4]);
+ p1k[0] = tsc_IV32 & 0xFFFF;
+ p1k[1] = tsc_IV32 >> 16;
+ p1k[2] = get_unaligned_le16(ta + 0);
+ p1k[3] = get_unaligned_le16(ta + 2);
+ p1k[4] = get_unaligned_le16(ta + 4);
for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
j = 2 * (i & 1);
- p1k[0] += tkip_S(p1k[4] ^ Mk16(tk[ 1 + j], tk[ 0 + j]));
- p1k[1] += tkip_S(p1k[0] ^ Mk16(tk[ 5 + j], tk[ 4 + j]));
- p1k[2] += tkip_S(p1k[1] ^ Mk16(tk[ 9 + j], tk[ 8 + j]));
- p1k[3] += tkip_S(p1k[2] ^ Mk16(tk[13 + j], tk[12 + j]));
- p1k[4] += tkip_S(p1k[3] ^ Mk16(tk[ 1 + j], tk[ 0 + j])) + i;
+ p1k[0] += tkipS(p1k[4] ^ get_unaligned_le16(tk + 0 + j));
+ p1k[1] += tkipS(p1k[0] ^ get_unaligned_le16(tk + 4 + j));
+ p1k[2] += tkipS(p1k[1] ^ get_unaligned_le16(tk + 8 + j));
+ p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j));
+ p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i;
}
}
-
static void tkip_mixing_phase2(const u16 *p1k, const u8 *tk, u16 tsc_IV16,
u8 *rc4key)
{
@@ -148,31 +106,29 @@ static void tkip_mixing_phase2(const u16 *p1k, const u8 *tk, u16 tsc_IV16,
ppk[4] = p1k[4];
ppk[5] = p1k[4] + tsc_IV16;
- ppk[0] += tkip_S(ppk[5] ^ Mk16(tk[ 1], tk[ 0]));
- ppk[1] += tkip_S(ppk[0] ^ Mk16(tk[ 3], tk[ 2]));
- ppk[2] += tkip_S(ppk[1] ^ Mk16(tk[ 5], tk[ 4]));
- ppk[3] += tkip_S(ppk[2] ^ Mk16(tk[ 7], tk[ 6]));
- ppk[4] += tkip_S(ppk[3] ^ Mk16(tk[ 9], tk[ 8]));
- ppk[5] += tkip_S(ppk[4] ^ Mk16(tk[11], tk[10]));
- ppk[0] += RotR1(ppk[5] ^ Mk16(tk[13], tk[12]));
- ppk[1] += RotR1(ppk[0] ^ Mk16(tk[15], tk[14]));
- ppk[2] += RotR1(ppk[1]);
- ppk[3] += RotR1(ppk[2]);
- ppk[4] += RotR1(ppk[3]);
- ppk[5] += RotR1(ppk[4]);
-
- rc4key[0] = Hi8(tsc_IV16);
- rc4key[1] = (Hi8(tsc_IV16) | 0x20) & 0x7f;
- rc4key[2] = Lo8(tsc_IV16);
- rc4key[3] = Lo8((ppk[5] ^ Mk16(tk[1], tk[0])) >> 1);
-
- for (i = 0; i < 6; i++) {
- rc4key[4 + 2 * i] = Lo8(ppk[i]);
- rc4key[5 + 2 * i] = Hi8(ppk[i]);
- }
+ ppk[0] += tkipS(ppk[5] ^ get_unaligned_le16(tk + 0));
+ ppk[1] += tkipS(ppk[0] ^ get_unaligned_le16(tk + 2));
+ ppk[2] += tkipS(ppk[1] ^ get_unaligned_le16(tk + 4));
+ ppk[3] += tkipS(ppk[2] ^ get_unaligned_le16(tk + 6));
+ ppk[4] += tkipS(ppk[3] ^ get_unaligned_le16(tk + 8));
+ ppk[5] += tkipS(ppk[4] ^ get_unaligned_le16(tk + 10));
+ ppk[0] += ror16(ppk[5] ^ get_unaligned_le16(tk + 12), 1);
+ ppk[1] += ror16(ppk[0] ^ get_unaligned_le16(tk + 14), 1);
+ ppk[2] += ror16(ppk[1], 1);
+ ppk[3] += ror16(ppk[2], 1);
+ ppk[4] += ror16(ppk[3], 1);
+ ppk[5] += ror16(ppk[4], 1);
+
+ rc4key[0] = tsc_IV16 >> 8;
+ rc4key[1] = ((tsc_IV16 >> 8) | 0x20) & 0x7f;
+ rc4key[2] = tsc_IV16 & 0xFF;
+ rc4key[3] = ((ppk[5] ^ get_unaligned_le16(tk)) >> 1) & 0xFF;
+
+ rc4key += 4;
+ for (i = 0; i < 6; i++)
+ put_unaligned_le16(ppk[i], rc4key + 2 * i);
}
-
/* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
* of the IV. Returns pointer to the octet following IVs (i.e., beginning of
* the packet payload). */
@@ -183,14 +139,10 @@ u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
*pos++ = iv1;
*pos++ = iv2;
*pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */;
- *pos++ = key->u.tkip.iv32 & 0xff;
- *pos++ = (key->u.tkip.iv32 >> 8) & 0xff;
- *pos++ = (key->u.tkip.iv32 >> 16) & 0xff;
- *pos++ = (key->u.tkip.iv32 >> 24) & 0xff;
- return pos;
+ put_unaligned_le32(key->u.tkip.iv32, pos);
+ return pos + 4;
}
-
void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta,
u16 *phase1key)
{
@@ -228,10 +180,8 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
u16 iv16;
u32 iv32;
- iv16 = data[hdr_len] << 8;
- iv16 += data[hdr_len + 2];
- iv32 = data[hdr_len + 4] | (data[hdr_len + 5] << 8) |
- (data[hdr_len + 6] << 16) | (data[hdr_len + 7] << 24);
+ iv16 = data[hdr_len + 2] | (data[hdr_len] << 8);
+ iv32 = get_unaligned_le32(data + hdr_len + 4);
#ifdef CONFIG_TKIP_DEBUG
printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n",
@@ -281,7 +231,6 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
}
-
/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
* beginning of the buffer containing IEEE 802.11 header payload, i.e.,
* including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
@@ -302,7 +251,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
iv16 = (pos[0] << 8) | pos[2];
keyid = pos[3];
- iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
+ iv32 = get_unaligned_le32(pos + 4);
pos += 8;
#ifdef CONFIG_TKIP_DEBUG
{
@@ -409,5 +358,3 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
return res;
}
-
-
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 1d7dd54aace..aecec2a72b0 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -256,7 +256,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
if (tx->flags & IEEE80211_TX_PS_BUFFERED)
return TX_CONTINUE;
- sta_flags = tx->sta ? tx->sta->flags : 0;
+ sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0;
if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
@@ -391,6 +391,7 @@ static ieee80211_tx_result
ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
{
struct sta_info *sta = tx->sta;
+ u32 staflags;
DECLARE_MAC_BUF(mac);
if (unlikely(!sta ||
@@ -398,8 +399,10 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
(tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)))
return TX_CONTINUE;
- if (unlikely((sta->flags & WLAN_STA_PS) &&
- !(sta->flags & WLAN_STA_PSPOLL))) {
+ staflags = get_sta_flags(sta);
+
+ if (unlikely((staflags & WLAN_STA_PS) &&
+ !(staflags & WLAN_STA_PSPOLL))) {
struct ieee80211_tx_packet_data *pkt_data;
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries "
@@ -430,13 +433,13 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
return TX_QUEUED;
}
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- else if (unlikely(sta->flags & WLAN_STA_PS)) {
+ else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) {
printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll "
"set -> send frame\n", tx->dev->name,
print_mac(mac, sta->addr));
}
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
- sta->flags &= ~WLAN_STA_PSPOLL;
+ clear_sta_flags(sta, WLAN_STA_PSPOLL);
return TX_CONTINUE;
}
@@ -697,7 +700,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
(tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
tx->sdata->bss_conf.use_short_preamble &&
- (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
+ (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) {
tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
}
@@ -1025,10 +1028,8 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
if (!tx->sta)
control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
- else if (tx->sta->flags & WLAN_STA_CLEAR_PS_FILT) {
+ else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT))
control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
- tx->sta->flags &= ~WLAN_STA_CLEAR_PS_FILT;
- }
hdrlen = ieee80211_get_hdrlen(tx->fc);
if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
@@ -1336,6 +1337,8 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
pkt_data->ifindex = dev->ifindex;
pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
+ /* Interfaces should always request a status report */
+ pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
/*
* fix up the pointers accounting for the radiotap
@@ -1486,12 +1489,12 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
rcu_read_lock();
sta = sta_info_get(local, hdr.addr1);
if (sta)
- sta_flags = sta->flags;
+ sta_flags = get_sta_flags(sta);
rcu_read_unlock();
}
- /* receiver is QoS enabled, use a QoS type frame */
- if (sta_flags & WLAN_STA_WME) {
+ /* receiver and we are QoS enabled, use a QoS type frame */
+ if (sta_flags & WLAN_STA_WME && local->hw.queues >= 4) {
fc |= IEEE80211_STYPE_QOS_DATA;
hdrlen += 2;
}
@@ -1617,6 +1620,9 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
if (ethertype == ETH_P_PAE)
pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
+ /* Interfaces should always request a status report */
+ pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
+
skb->dev = local->mdev;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 76e1de1dc73..6a342a9a40c 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -169,14 +169,26 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
range->num_encoding_sizes = 2;
range->max_encoding_tokens = NUM_DEFAULT_KEYS;
- range->max_qual.qual = local->hw.max_signal;
- range->max_qual.level = local->hw.max_rssi;
- range->max_qual.noise = local->hw.max_noise;
+ if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC ||
+ local->hw.flags & IEEE80211_HW_SIGNAL_DB)
+ range->max_qual.level = local->hw.max_signal;
+ else if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+ range->max_qual.level = -110;
+ else
+ range->max_qual.level = 0;
+
+ if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
+ range->max_qual.noise = -110;
+ else
+ range->max_qual.noise = 0;
+
+ range->max_qual.qual = 100;
range->max_qual.updated = local->wstats_flags;
- range->avg_qual.qual = local->hw.max_signal/2;
- range->avg_qual.level = 0;
- range->avg_qual.noise = 0;
+ range->avg_qual.qual = 50;
+ /* not always true but better than nothing */
+ range->avg_qual.level = range->max_qual.level / 2;
+ range->avg_qual.noise = range->max_qual.noise / 2;
range->avg_qual.updated = local->wstats_flags;
range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
@@ -996,8 +1008,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev
wstats->qual.noise = 0;
wstats->qual.updated = IW_QUAL_ALL_INVALID;
} else {
- wstats->qual.level = sta->last_rssi;
- wstats->qual.qual = sta->last_signal;
+ wstats->qual.level = sta->last_signal;
+ wstats->qual.qual = sta->last_qual;
wstats->qual.noise = sta->last_noise;
wstats->qual.updated = local->wstats_flags;
}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 80afacdae46..f1da0b93bc5 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -143,8 +143,11 @@ void cfg80211_put_dev(struct cfg80211_registered_device *drv)
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
{
+ struct cfg80211_registered_device *drv;
int idx, taken = -1, result, digits;
+ mutex_lock(&cfg80211_drv_mutex);
+
/* prohibit calling the thing phy%d when %d is not its number */
sscanf(newname, PHY_NAME "%d%n", &idx, &taken);
if (taken == strlen(newname) && idx != rdev->idx) {
@@ -156,14 +159,30 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
* deny the name if it is phy<idx> where <idx> is printed
* without leading zeroes. taken == strlen(newname) here
*/
+ result = -EINVAL;
if (taken == strlen(PHY_NAME) + digits)
- return -EINVAL;
+ goto out_unlock;
+ }
+
+
+ /* Ignore nop renames */
+ result = 0;
+ if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
+ goto out_unlock;
+
+ /* Ensure another device does not already have this name. */
+ list_for_each_entry(drv, &cfg80211_drv_list, list) {
+ result = -EINVAL;
+ if (strcmp(newname, dev_name(&drv->wiphy.dev)) == 0)
+ goto out_unlock;
}
- /* this will check for collisions */
+ /* this will only check for collisions in sysfs
+ * which is not even always compiled in.
+ */
result = device_rename(&rdev->wiphy.dev, newname);
if (result)
- return result;
+ goto out_unlock;
if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
rdev->wiphy.debugfsdir,
@@ -172,9 +191,13 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n",
newname);
- nl80211_notify_dev_rename(rdev);
+ result = 0;
+out_unlock:
+ mutex_unlock(&cfg80211_drv_mutex);
+ if (result == 0)
+ nl80211_notify_dev_rename(rdev);
- return 0;
+ return result;
}
/* exported functions */
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
index 28fbd0b0b56..f591871a7b4 100644
--- a/net/wireless/radiotap.c
+++ b/net/wireless/radiotap.c
@@ -59,23 +59,21 @@ int ieee80211_radiotap_iterator_init(
return -EINVAL;
/* sanity check for allowed length and radiotap length field */
- if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
+ if (max_length < get_unaligned_le16(&radiotap_header->it_len))
return -EINVAL;
iterator->rtheader = radiotap_header;
- iterator->max_length = le16_to_cpu(get_unaligned(
- &radiotap_header->it_len));
+ iterator->max_length = get_unaligned_le16(&radiotap_header->it_len);
iterator->arg_index = 0;
- iterator->bitmap_shifter = le32_to_cpu(get_unaligned(
- &radiotap_header->it_present));
+ iterator->bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
iterator->this_arg = NULL;
/* find payload start allowing for extended bitmap(s) */
if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
- while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) &
- (1<<IEEE80211_RADIOTAP_EXT)) {
+ while (get_unaligned_le32(iterator->arg) &
+ (1 << IEEE80211_RADIOTAP_EXT)) {
iterator->arg += sizeof(u32);
/*
@@ -241,8 +239,8 @@ int ieee80211_radiotap_iterator_next(
if (iterator->bitmap_shifter & 1) {
/* b31 was set, there is more */
/* move to next u32 bitmap */
- iterator->bitmap_shifter = le32_to_cpu(
- get_unaligned(iterator->next_bitmap));
+ iterator->bitmap_shifter =
+ get_unaligned_le32(iterator->next_bitmap);
iterator->next_bitmap++;
} else
/* no more bitmaps: end */