Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
f42a44494b
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!) */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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_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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -696,38 +696,6 @@ static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
__le16 fc = hdr->frame_control;
|
||||
fc &= cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
|
||||
|
||||
switch (tofrom) {
|
||||
case 2:
|
||||
return hdr->addr3;
|
||||
case 3:
|
||||
return hdr->addr4;
|
||||
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 */
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
static u16 tkipS(u16 val)
|
||||
{
|
||||
return ((u16) x << 8) | (u16) y;
|
||||
return tkip_sbox[val & 0xff] ^ swab16(tkip_sbox[val >> 8]);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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]);
|
||||
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] = 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);
|
||||
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;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
rc4key[4 + 2 * i] = Lo8(ppk[i]);
|
||||
rc4key[5 + 2 * i] = Hi8(ppk[i]);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/* this will check for collisions */
|
||||
|
||||
/* 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 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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue