Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: drivers/net/wireless/wl12xx/wl1271.h drivers/net/wireless/wl12xx/wl1271_cmd.h
This commit is contained in:
commit
14599f1e34
|
@ -2978,7 +2978,6 @@ F: drivers/net/ixgb/
|
|||
F: drivers/net/ixgbe/
|
||||
|
||||
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
@ -2988,7 +2987,6 @@ F: Documentation/networking/README.ipw2100
|
|||
F: drivers/net/wireless/ipw2x00/ipw2100.*
|
||||
|
||||
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
@ -3019,8 +3017,8 @@ F: drivers/net/wimax/i2400m/
|
|||
F: include/linux/wimax/i2400m.h
|
||||
|
||||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://intellinuxwireless.org
|
||||
|
@ -3030,7 +3028,6 @@ F: drivers/net/wireless/iwlwifi/
|
|||
|
||||
INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
|
||||
M: Samuel Ortiz <samuel.ortiz@intel.com>
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Supported
|
||||
|
|
|
@ -150,9 +150,8 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev,
|
|||
unsigned long offset,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
ssb_dma_sync_single_range_for_device(sdev, dma_base,
|
||||
offset & dma_desc_align_mask,
|
||||
dma_desc_sync_size, dir);
|
||||
dma_sync_single_for_device(sdev->dma_dev, dma_base + offset,
|
||||
dma_desc_sync_size, dir);
|
||||
}
|
||||
|
||||
static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
|
||||
|
@ -160,9 +159,8 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
|
|||
unsigned long offset,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
|
||||
offset & dma_desc_align_mask,
|
||||
dma_desc_sync_size, dir);
|
||||
dma_sync_single_for_cpu(sdev->dma_dev, dma_base + offset,
|
||||
dma_desc_sync_size, dir);
|
||||
}
|
||||
|
||||
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
|
||||
|
@ -608,10 +606,10 @@ static void b44_tx(struct b44 *bp)
|
|||
|
||||
BUG_ON(skb == NULL);
|
||||
|
||||
ssb_dma_unmap_single(bp->sdev,
|
||||
rp->mapping,
|
||||
skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev,
|
||||
rp->mapping,
|
||||
skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
rp->skb = NULL;
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
|
@ -648,29 +646,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
|||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mapping = ssb_dma_map_single(bp->sdev, skb->data,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
/* Hardware bug work-around, the chip is unable to do PCI DMA
|
||||
to/from anything above 1GB :-( */
|
||||
if (ssb_dma_mapping_error(bp->sdev, mapping) ||
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
|
||||
mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
|
||||
/* Sigh... */
|
||||
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||
ssb_dma_unmap_single(bp->sdev, mapping,
|
||||
if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
|
||||
dma_unmap_single(bp->sdev->dma_dev, mapping,
|
||||
RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
|
||||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
mapping = ssb_dma_map_single(bp->sdev, skb->data,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ssb_dma_mapping_error(bp->sdev, mapping) ||
|
||||
mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
|
||||
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||
ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
|
||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, mapping) ||
|
||||
mapping + RX_PKT_BUF_SZ > DMA_BIT_MASK(30)) {
|
||||
if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
|
||||
dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -745,9 +743,9 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
|||
dest_idx * sizeof(*dest_desc),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_device(bp->sdev->dma_dev, dest_map->mapping,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
static int b44_rx(struct b44 *bp, int budget)
|
||||
|
@ -767,9 +765,9 @@ static int b44_rx(struct b44 *bp, int budget)
|
|||
struct rx_header *rh;
|
||||
u16 len;
|
||||
|
||||
ssb_dma_sync_single_for_cpu(bp->sdev, map,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
|
||||
RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
rh = (struct rx_header *) skb->data;
|
||||
len = le16_to_cpu(rh->len);
|
||||
if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
|
||||
|
@ -801,8 +799,8 @@ static int b44_rx(struct b44 *bp, int budget)
|
|||
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
|
||||
if (skb_size < 0)
|
||||
goto drop_it;
|
||||
ssb_dma_unmap_single(bp->sdev, map,
|
||||
skb_size, DMA_FROM_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev, map,
|
||||
skb_size, DMA_FROM_DEVICE);
|
||||
/* Leave out rx_header */
|
||||
skb_put(skb, len + RX_PKT_OFFSET);
|
||||
skb_pull(skb, RX_PKT_OFFSET);
|
||||
|
@ -954,24 +952,24 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
|
||||
if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
|
||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
|
||||
struct sk_buff *bounce_skb;
|
||||
|
||||
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
|
||||
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||
ssb_dma_unmap_single(bp->sdev, mapping, len,
|
||||
if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
|
||||
dma_unmap_single(bp->sdev->dma_dev, mapping, len,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
bounce_skb = __netdev_alloc_skb(dev, len, GFP_ATOMIC | GFP_DMA);
|
||||
if (!bounce_skb)
|
||||
goto err_out;
|
||||
|
||||
mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data,
|
||||
len, DMA_TO_DEVICE);
|
||||
if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
|
||||
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||
ssb_dma_unmap_single(bp->sdev, mapping,
|
||||
mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
|
||||
len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, mapping) || mapping + len > DMA_BIT_MASK(30)) {
|
||||
if (!dma_mapping_error(bp->sdev->dma_dev, mapping))
|
||||
dma_unmap_single(bp->sdev->dma_dev, mapping,
|
||||
len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(bounce_skb);
|
||||
goto err_out;
|
||||
|
@ -1068,8 +1066,8 @@ static void b44_free_rings(struct b44 *bp)
|
|||
|
||||
if (rp->skb == NULL)
|
||||
continue;
|
||||
ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(rp->skb);
|
||||
rp->skb = NULL;
|
||||
}
|
||||
|
@ -1080,8 +1078,8 @@ static void b44_free_rings(struct b44 *bp)
|
|||
|
||||
if (rp->skb == NULL)
|
||||
continue;
|
||||
ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(rp->skb);
|
||||
rp->skb = NULL;
|
||||
}
|
||||
|
@ -1103,14 +1101,12 @@ static void b44_init_rings(struct b44 *bp)
|
|||
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
|
||||
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
||||
ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
|
||||
|
||||
if (bp->flags & B44_FLAG_TX_RING_HACK)
|
||||
ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES, DMA_TO_DEVICE);
|
||||
|
||||
for (i = 0; i < bp->rx_pending; i++) {
|
||||
if (b44_alloc_rx_skb(bp, -1, i) < 0)
|
||||
|
@ -1130,27 +1126,23 @@ static void b44_free_consistent(struct b44 *bp)
|
|||
bp->tx_buffers = NULL;
|
||||
if (bp->rx_ring) {
|
||||
if (bp->flags & B44_FLAG_RX_RING_HACK) {
|
||||
ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
|
||||
DMA_TABLE_BYTES, DMA_BIDIRECTIONAL);
|
||||
kfree(bp->rx_ring);
|
||||
} else
|
||||
ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
|
||||
bp->rx_ring, bp->rx_ring_dma,
|
||||
GFP_KERNEL);
|
||||
dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
|
||||
bp->rx_ring, bp->rx_ring_dma);
|
||||
bp->rx_ring = NULL;
|
||||
bp->flags &= ~B44_FLAG_RX_RING_HACK;
|
||||
}
|
||||
if (bp->tx_ring) {
|
||||
if (bp->flags & B44_FLAG_TX_RING_HACK) {
|
||||
ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
|
||||
DMA_TABLE_BYTES, DMA_TO_DEVICE);
|
||||
kfree(bp->tx_ring);
|
||||
} else
|
||||
ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
|
||||
bp->tx_ring, bp->tx_ring_dma,
|
||||
GFP_KERNEL);
|
||||
dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
|
||||
bp->tx_ring, bp->tx_ring_dma);
|
||||
bp->tx_ring = NULL;
|
||||
bp->flags &= ~B44_FLAG_TX_RING_HACK;
|
||||
}
|
||||
|
@ -1175,7 +1167,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||
goto out_err;
|
||||
|
||||
size = DMA_TABLE_BYTES;
|
||||
bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp);
|
||||
bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
|
||||
&bp->rx_ring_dma, gfp);
|
||||
if (!bp->rx_ring) {
|
||||
/* Allocation may have failed due to pci_alloc_consistent
|
||||
insisting on use of GFP_DMA, which is more restrictive
|
||||
|
@ -1187,11 +1180,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||
if (!rx_ring)
|
||||
goto out_err;
|
||||
|
||||
rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) ||
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, rx_ring_dma) ||
|
||||
rx_ring_dma + size > DMA_BIT_MASK(30)) {
|
||||
kfree(rx_ring);
|
||||
goto out_err;
|
||||
|
@ -1202,7 +1195,8 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||
bp->flags |= B44_FLAG_RX_RING_HACK;
|
||||
}
|
||||
|
||||
bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp);
|
||||
bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size,
|
||||
&bp->tx_ring_dma, gfp);
|
||||
if (!bp->tx_ring) {
|
||||
/* Allocation may have failed due to ssb_dma_alloc_consistent
|
||||
insisting on use of GFP_DMA, which is more restrictive
|
||||
|
@ -1214,11 +1208,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||
if (!tx_ring)
|
||||
goto out_err;
|
||||
|
||||
tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
|
||||
DMA_TABLE_BYTES,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) ||
|
||||
if (dma_mapping_error(bp->sdev->dma_dev, tx_ring_dma) ||
|
||||
tx_ring_dma + size > DMA_BIT_MASK(30)) {
|
||||
kfree(tx_ring);
|
||||
goto out_err;
|
||||
|
@ -2176,12 +2170,14 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
|
|||
"Failed to powerup the bus\n");
|
||||
goto err_out_free_dev;
|
||||
}
|
||||
err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30));
|
||||
if (err) {
|
||||
|
||||
if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
|
||||
dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
|
||||
dev_err(sdev->dev,
|
||||
"Required 30BIT DMA mask unsupported by the system\n");
|
||||
goto err_out_powerdown;
|
||||
}
|
||||
|
||||
err = b44_get_invariants(bp);
|
||||
if (err) {
|
||||
dev_err(sdev->dev,
|
||||
|
|
|
@ -13,5 +13,6 @@ ath5k-y += base.o
|
|||
ath5k-y += led.o
|
||||
ath5k-y += rfkill.o
|
||||
ath5k-y += ani.o
|
||||
ath5k-y += sysfs.o
|
||||
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
|
||||
obj-$(CONFIG_ATH5K) += ath5k.o
|
||||
|
|
|
@ -74,8 +74,8 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
|
|||
const s8 fr[] = { -78, -80 };
|
||||
#endif
|
||||
if (level < 0 || level >= ARRAY_SIZE(sz)) {
|
||||
ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
|
||||
"level out of range %d", level);
|
||||
ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range",
|
||||
level);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -106,8 +106,8 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
|
|||
|
||||
if (level < 0 || level >= ARRAY_SIZE(val) ||
|
||||
level > ah->ah_sc->ani_state.max_spur_level) {
|
||||
ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
|
||||
"level out of range %d", level);
|
||||
ATH5K_ERR(ah->ah_sc, "spur immunity level %d out of range",
|
||||
level);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -130,8 +130,7 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
|
|||
const int val[] = { 0, 4, 8 };
|
||||
|
||||
if (level < 0 || level >= ARRAY_SIZE(val)) {
|
||||
ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,
|
||||
"level out of range %d", level);
|
||||
ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -481,14 +480,15 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
|
|||
struct ath5k_ani_state *as = &ah->ah_sc->ani_state;
|
||||
int listen, ofdm_high, ofdm_low, cck_high, cck_low;
|
||||
|
||||
if (as->ani_mode != ATH5K_ANI_MODE_AUTO)
|
||||
return;
|
||||
|
||||
/* get listen time since last call and add it to the counter because we
|
||||
* might not have restarted the "ani period" last time */
|
||||
* might not have restarted the "ani period" last time.
|
||||
* always do this to calculate the busy time also in manual mode */
|
||||
listen = ath5k_hw_ani_get_listen_time(ah, as);
|
||||
as->listen_time += listen;
|
||||
|
||||
if (as->ani_mode != ATH5K_ANI_MODE_AUTO)
|
||||
return;
|
||||
|
||||
ath5k_ani_save_and_clear_phy_errors(ah, as);
|
||||
|
||||
ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000;
|
||||
|
|
|
@ -204,6 +204,7 @@
|
|||
#define AR5K_TUNE_TPC_TXPOWER false
|
||||
#define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */
|
||||
#define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */
|
||||
#define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */
|
||||
|
||||
#define AR5K_INIT_CARR_SENSE_EN 1
|
||||
|
||||
|
@ -1118,6 +1119,7 @@ struct ath5k_hw {
|
|||
/* Calibration timestamp */
|
||||
unsigned long ah_cal_next_full;
|
||||
unsigned long ah_cal_next_ani;
|
||||
unsigned long ah_cal_next_nf;
|
||||
|
||||
/* Calibration mask */
|
||||
u8 ah_cal_mask;
|
||||
|
@ -1148,6 +1150,9 @@ struct ath5k_hw {
|
|||
int ath5k_hw_attach(struct ath5k_softc *sc);
|
||||
void ath5k_hw_detach(struct ath5k_hw *ah);
|
||||
|
||||
int ath5k_sysfs_register(struct ath5k_softc *sc);
|
||||
void ath5k_sysfs_unregister(struct ath5k_softc *sc);
|
||||
|
||||
/* LED functions */
|
||||
int ath5k_init_leds(struct ath5k_softc *sc);
|
||||
void ath5k_led_enable(struct ath5k_softc *sc);
|
||||
|
@ -1270,6 +1275,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
|
|||
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
|
||||
int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel);
|
||||
void ath5k_hw_update_noise_floor(struct ath5k_hw *ah);
|
||||
/* Spur mitigation */
|
||||
bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel);
|
||||
|
@ -1280,6 +1286,7 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
|
|||
int ath5k_hw_phy_disable(struct ath5k_hw *ah);
|
||||
/* Antenna control */
|
||||
void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode);
|
||||
void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode);
|
||||
/* TX power setup */
|
||||
int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
||||
u8 ee_mode, u8 txpower);
|
||||
|
|
|
@ -351,8 +351,6 @@ err_free:
|
|||
*/
|
||||
void ath5k_hw_detach(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
__set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
|
||||
|
||||
if (ah->ah_rf_banks != NULL)
|
||||
|
|
|
@ -195,7 +195,7 @@ static const struct ieee80211_rate ath5k_rates[] = {
|
|||
static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id);
|
||||
static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ath5k_pci_suspend(struct device *dev);
|
||||
static int ath5k_pci_resume(struct device *dev);
|
||||
|
||||
|
@ -203,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
|
|||
#define ATH5K_PM_OPS (&ath5k_pm_ops)
|
||||
#else
|
||||
#define ATH5K_PM_OPS NULL
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static struct pci_driver ath5k_pci_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
|
@ -578,7 +578,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
|
|||
spin_lock_init(&sc->block);
|
||||
|
||||
/* Set private data */
|
||||
pci_set_drvdata(pdev, hw);
|
||||
pci_set_drvdata(pdev, sc);
|
||||
|
||||
/* Setup interrupt handler */
|
||||
ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
|
||||
|
@ -694,25 +694,23 @@ err:
|
|||
static void __devexit
|
||||
ath5k_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_softc *sc = pci_get_drvdata(pdev);
|
||||
|
||||
ath5k_debug_finish_device(sc);
|
||||
ath5k_detach(pdev, hw);
|
||||
ath5k_detach(pdev, sc->hw);
|
||||
ath5k_hw_detach(sc->ah);
|
||||
kfree(sc->ah);
|
||||
free_irq(pdev->irq, sc);
|
||||
pci_iounmap(pdev, sc->iobase);
|
||||
pci_release_region(pdev, 0);
|
||||
pci_disable_device(pdev);
|
||||
ieee80211_free_hw(hw);
|
||||
ieee80211_free_hw(sc->hw);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ath5k_pci_suspend(struct device *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
|
||||
|
||||
ath5k_led_off(sc);
|
||||
return 0;
|
||||
|
@ -721,8 +719,7 @@ static int ath5k_pci_suspend(struct device *dev)
|
|||
static int ath5k_pci_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_softc *sc = pci_get_drvdata(pdev);
|
||||
|
||||
/*
|
||||
* Suspend/Resume resets the PCI configuration space, so we have to
|
||||
|
@ -734,7 +731,7 @@ static int ath5k_pci_resume(struct device *dev)
|
|||
ath5k_led_enable(sc);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
|
||||
/***********************\
|
||||
|
@ -864,6 +861,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
|||
|
||||
ath5k_init_leds(sc);
|
||||
|
||||
ath5k_sysfs_register(sc);
|
||||
|
||||
return 0;
|
||||
err_queues:
|
||||
ath5k_txq_release(sc);
|
||||
|
@ -899,6 +898,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
|
|||
ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
|
||||
ath5k_unregister_leds(sc);
|
||||
|
||||
ath5k_sysfs_unregister(sc);
|
||||
/*
|
||||
* NB: can't reclaim these until after ieee80211_ifdetach
|
||||
* returns because we'll get called back to reclaim node
|
||||
|
@ -2785,10 +2785,6 @@ ath5k_tasklet_calibrate(unsigned long data)
|
|||
/* Only full calibration for now */
|
||||
ah->ah_cal_mask |= AR5K_CALIBRATION_FULL;
|
||||
|
||||
/* Stop queues so that calibration
|
||||
* doesn't interfere with tx */
|
||||
ieee80211_stop_queues(sc->hw);
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
|
||||
ieee80211_frequency_to_channel(sc->curchan->center_freq),
|
||||
sc->curchan->hw_value);
|
||||
|
@ -2806,8 +2802,16 @@ ath5k_tasklet_calibrate(unsigned long data)
|
|||
ieee80211_frequency_to_channel(
|
||||
sc->curchan->center_freq));
|
||||
|
||||
/* Wake queues */
|
||||
ieee80211_wake_queues(sc->hw);
|
||||
/* Noise floor calibration interrupts rx/tx path while I/Q calibration
|
||||
* doesn't. We stop the queues so that calibration doesn't interfere
|
||||
* with TX and don't run it as often */
|
||||
if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) {
|
||||
ah->ah_cal_next_nf = jiffies +
|
||||
msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF);
|
||||
ieee80211_stop_queues(sc->hw);
|
||||
ath5k_hw_update_noise_floor(ah);
|
||||
ieee80211_wake_queues(sc->hw);
|
||||
}
|
||||
|
||||
ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
|
||||
}
|
||||
|
@ -2926,6 +2930,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
|
|||
|
||||
ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode);
|
||||
|
||||
ah->ah_cal_next_full = jiffies;
|
||||
ah->ah_cal_next_ani = jiffies;
|
||||
ah->ah_cal_next_nf = jiffies;
|
||||
|
||||
/*
|
||||
* Change channels and update the h/w rate map if we're switching;
|
||||
* e.g. 11a to 11b/g.
|
||||
|
@ -3140,13 +3148,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
|||
|
||||
if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
|
||||
if (*new_flags & FIF_PROMISC_IN_BSS) {
|
||||
rfilt |= AR5K_RX_FILTER_PROM;
|
||||
__set_bit(ATH_STAT_PROMISC, sc->status);
|
||||
} else {
|
||||
__clear_bit(ATH_STAT_PROMISC, sc->status);
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(ATH_STAT_PROMISC, sc->status))
|
||||
rfilt |= AR5K_RX_FILTER_PROM;
|
||||
|
||||
/* Note, AR5K_RX_FILTER_MCAST is already enabled */
|
||||
if (*new_flags & FIF_ALLMULTI) {
|
||||
mfilt[0] = ~0;
|
||||
|
|
|
@ -34,7 +34,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
|
|||
{
|
||||
u16 ee_header;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/* Capabilities stored in the EEPROM */
|
||||
ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
|
||||
|
||||
|
@ -123,8 +122,6 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah,
|
|||
enum ath5k_capability_type cap_type,
|
||||
u32 capability, u32 *result)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
switch (cap_type) {
|
||||
case AR5K_CAP_NUM_TXQUEUES:
|
||||
if (result) {
|
||||
|
@ -173,8 +170,6 @@ yes:
|
|||
int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
|
||||
u16 assoc_id)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (ah->ah_version == AR5K_AR5210) {
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
|
||||
AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
|
||||
|
@ -186,8 +181,6 @@ int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
|
|||
|
||||
int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (ah->ah_version == AR5K_AR5210) {
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
|
||||
AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
|
||||
|
|
|
@ -307,7 +307,6 @@ static const struct {
|
|||
{ ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" },
|
||||
{ ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" },
|
||||
{ ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
|
||||
{ ATH5K_DEBUG_TRACE, "trace", "trace function calls" },
|
||||
{ ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" },
|
||||
{ ATH5K_DEBUG_ANY, "all", "show all debug levels" },
|
||||
};
|
||||
|
@ -426,6 +425,13 @@ static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
|
|||
"AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
|
||||
(v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
|
||||
|
||||
v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
|
||||
v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -729,6 +735,66 @@ static const struct file_operations fops_ani = {
|
|||
};
|
||||
|
||||
|
||||
/* debugfs: queues etc */
|
||||
|
||||
static ssize_t read_file_queue(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
char buf[700];
|
||||
unsigned int len = 0;
|
||||
|
||||
struct ath5k_txq *txq;
|
||||
struct ath5k_buf *bf, *bf0;
|
||||
int i, n = 0;
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"available txbuffers: %d\n", sc->txbuf_len);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
|
||||
txq = &sc->txqs[i];
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"%02d: %ssetup\n", i, txq->setup ? "" : "not ");
|
||||
|
||||
if (!txq->setup)
|
||||
continue;
|
||||
|
||||
list_for_each_entry_safe(bf, bf0, &txq->q, list)
|
||||
n++;
|
||||
len += snprintf(buf+len, sizeof(buf)-len, " len: %d\n", n);
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_queue(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
char buf[20];
|
||||
|
||||
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
|
||||
return -EFAULT;
|
||||
|
||||
if (strncmp(buf, "start", 5) == 0)
|
||||
ieee80211_wake_queues(sc->hw);
|
||||
else if (strncmp(buf, "stop", 4) == 0)
|
||||
ieee80211_stop_queues(sc->hw);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations fops_queue = {
|
||||
.read = read_file_queue,
|
||||
.write = write_file_queue,
|
||||
.open = ath5k_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
/* init */
|
||||
|
||||
void
|
||||
|
@ -772,6 +838,11 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
|
|||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc,
|
||||
&fops_ani);
|
||||
|
||||
sc->debug.debugfs_queue = debugfs_create_file("queue",
|
||||
S_IWUSR | S_IRUSR,
|
||||
sc->debug.debugfs_phydir, sc,
|
||||
&fops_queue);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -790,6 +861,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
|
|||
debugfs_remove(sc->debug.debugfs_antenna);
|
||||
debugfs_remove(sc->debug.debugfs_frameerrors);
|
||||
debugfs_remove(sc->debug.debugfs_ani);
|
||||
debugfs_remove(sc->debug.debugfs_queue);
|
||||
debugfs_remove(sc->debug.debugfs_phydir);
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ struct ath5k_dbg_info {
|
|||
struct dentry *debugfs_antenna;
|
||||
struct dentry *debugfs_frameerrors;
|
||||
struct dentry *debugfs_ani;
|
||||
struct dentry *debugfs_queue;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -115,18 +116,12 @@ enum ath5k_debug_level {
|
|||
ATH5K_DEBUG_DUMP_RX = 0x00000100,
|
||||
ATH5K_DEBUG_DUMP_TX = 0x00000200,
|
||||
ATH5K_DEBUG_DUMPBANDS = 0x00000400,
|
||||
ATH5K_DEBUG_TRACE = 0x00001000,
|
||||
ATH5K_DEBUG_ANI = 0x00002000,
|
||||
ATH5K_DEBUG_ANY = 0xffffffff
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ATH5K_DEBUG
|
||||
|
||||
#define ATH5K_TRACE(_sc) do { \
|
||||
if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
|
||||
printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \
|
||||
if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \
|
||||
ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
|
||||
|
@ -168,8 +163,6 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
|
|||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
|
||||
|
||||
static inline void __attribute__ ((format (printf, 3, 4)))
|
||||
ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
|
||||
|
||||
|
|
|
@ -176,7 +176,6 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
|
|||
struct ath5k_hw_4w_tx_ctl *tx_ctl;
|
||||
unsigned int frame_len;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
|
||||
|
||||
/*
|
||||
|
@ -342,8 +341,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
|
|||
struct ath5k_hw_2w_tx_ctl *tx_ctl;
|
||||
struct ath5k_hw_tx_status *tx_status;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
|
||||
tx_status = &desc->ud.ds_tx5210.tx_stat;
|
||||
|
||||
|
@ -396,8 +393,6 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
|
|||
struct ath5k_hw_4w_tx_ctl *tx_ctl;
|
||||
struct ath5k_hw_tx_status *tx_status;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
|
||||
tx_status = &desc->ud.ds_tx5212.tx_stat;
|
||||
|
||||
|
@ -490,7 +485,6 @@ static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
|
|||
{
|
||||
struct ath5k_hw_rx_ctl *rx_ctl;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
rx_ctl = &desc->ud.ds_rx.rx_ctl;
|
||||
|
||||
/*
|
||||
|
@ -593,7 +587,6 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
|
|||
struct ath5k_hw_rx_status *rx_status;
|
||||
struct ath5k_hw_rx_error *rx_err;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
rx_status = &desc->ud.ds_rx.u.rx_stat;
|
||||
|
||||
/* Overlay on error */
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
*/
|
||||
void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
|
||||
ath5k_hw_reg_read(ah, AR5K_CR);
|
||||
}
|
||||
|
@ -62,7 +61,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
|
||||
|
||||
/*
|
||||
|
@ -96,8 +94,6 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
|
|||
*/
|
||||
void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
|
||||
}
|
||||
|
||||
|
@ -125,7 +121,6 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
|
|||
{
|
||||
u32 tx_queue;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||
|
||||
/* Return if queue is declared inactive */
|
||||
|
@ -186,7 +181,6 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
|
|||
unsigned int i = 40;
|
||||
u32 tx_queue, pending;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||
|
||||
/* Return if queue is declared inactive */
|
||||
|
@ -297,7 +291,6 @@ u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
|
|||
{
|
||||
u16 tx_reg;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||
|
||||
/*
|
||||
|
@ -340,7 +333,6 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
|
|||
{
|
||||
u16 tx_reg;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||
|
||||
/*
|
||||
|
@ -400,8 +392,6 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
|
|||
u32 trigger_level, imr;
|
||||
int ret = -EIO;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/*
|
||||
* Disable interrupts by setting the mask
|
||||
*/
|
||||
|
@ -451,7 +441,6 @@ done:
|
|||
*/
|
||||
bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -475,8 +464,6 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
|
|||
{
|
||||
u32 data;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/*
|
||||
* Read interrupt status from the Interrupt Status register
|
||||
* on 5210
|
||||
|
|
|
@ -35,7 +35,6 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
|
|||
{
|
||||
u32 status, timeout;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/*
|
||||
* Initialize EEPROM access
|
||||
*/
|
||||
|
@ -715,7 +714,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
|
|||
|
||||
/* Only one curve for RF5111
|
||||
* find out which one and place
|
||||
* in in pd_curves.
|
||||
* in pd_curves.
|
||||
* Note: ee_x_gain is reversed here */
|
||||
for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) {
|
||||
|
||||
|
|
|
@ -34,8 +34,6 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
|
|||
/*5210 has different led mode handling*/
|
||||
u32 led_5210;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/*Reset led status*/
|
||||
if (ah->ah_version != AR5K_AR5210)
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
|
||||
|
@ -82,7 +80,6 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
|
|||
*/
|
||||
int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -98,7 +95,6 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
|
|||
*/
|
||||
int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -114,7 +110,6 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
|
|||
*/
|
||||
u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return 0xffffffff;
|
||||
|
||||
|
@ -129,7 +124,6 @@ u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
|
|||
int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
|
||||
{
|
||||
u32 data;
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return -EINVAL;
|
||||
|
@ -153,7 +147,6 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
|
|||
{
|
||||
u32 data;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return;
|
||||
|
||||
|
|
|
@ -59,8 +59,6 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
|
|||
|
||||
beacon_reg = 0;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
switch (op_mode) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
|
||||
|
@ -173,7 +171,6 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
|
|||
*/
|
||||
static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK))
|
||||
<= timeout)
|
||||
return -EINVAL;
|
||||
|
@ -192,7 +189,6 @@ static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
|||
*/
|
||||
static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS))
|
||||
<= timeout)
|
||||
return -EINVAL;
|
||||
|
@ -297,7 +293,6 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
|
|||
u32 low_id, high_id;
|
||||
u32 pcu_reg;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/* Set new station ID */
|
||||
memcpy(common->macaddr, mac, ETH_ALEN);
|
||||
|
||||
|
@ -357,7 +352,6 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah)
|
|||
void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/* Cache bssid mask so that we can restore it
|
||||
* on reset */
|
||||
|
@ -382,7 +376,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
|
|||
*/
|
||||
void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
|
||||
}
|
||||
|
||||
|
@ -397,7 +390,6 @@ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
|
|||
*/
|
||||
void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
|
||||
}
|
||||
|
||||
|
@ -406,8 +398,6 @@ void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
|
|||
*/
|
||||
void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/* Set the multicat filter */
|
||||
ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
|
||||
ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
|
||||
}
|
||||
|
@ -427,7 +417,6 @@ u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
|
|||
{
|
||||
u32 data, filter = 0;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
|
||||
|
||||
/*Radar detection for 5212*/
|
||||
|
@ -457,8 +446,6 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
|
|||
{
|
||||
u32 data = 0;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/* Set PHY error filter register on 5212*/
|
||||
if (ah->ah_version == AR5K_AR5212) {
|
||||
if (filter & AR5K_RX_FILTER_RADARERR)
|
||||
|
@ -533,8 +520,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
|
|||
|
||||
WARN_ON( i == ATH5K_MAX_TSF_READ );
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
return (((u64)tsf_upper1 << 32) | tsf_lower);
|
||||
}
|
||||
|
||||
|
@ -548,8 +533,6 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
|
|||
*/
|
||||
void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32);
|
||||
ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32);
|
||||
}
|
||||
|
@ -565,8 +548,6 @@ void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
|
|||
{
|
||||
u32 val;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF;
|
||||
|
||||
/*
|
||||
|
@ -586,7 +567,6 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
|
|||
{
|
||||
u32 timer1, timer2, timer3;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/*
|
||||
* Set the additional timers by mode
|
||||
*/
|
||||
|
@ -674,7 +654,6 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
|
|||
unsigned int i, type;
|
||||
u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
|
||||
|
||||
type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
|
||||
|
@ -749,8 +728,6 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
|
|||
bool is_tkip;
|
||||
const u8 *key_ptr;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
is_tkip = (key->alg == ALG_TKIP);
|
||||
|
||||
/*
|
||||
|
@ -836,7 +813,6 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
|
|||
{
|
||||
u32 low_id, high_id;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/* Invalid entry (key table overflow) */
|
||||
AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
|
||||
|
||||
|
|
|
@ -378,8 +378,6 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)
|
|||
u32 data, type;
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (ah->ah_rf_banks == NULL ||
|
||||
ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
|
||||
return AR5K_RFGAIN_INACTIVE;
|
||||
|
@ -1167,7 +1165,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
|
|||
* The median of the values in the history is then loaded into the
|
||||
* hardware for its own use for RSSI and CCA measurements.
|
||||
*/
|
||||
static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
|
||||
void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
u32 val;
|
||||
|
@ -1248,7 +1246,6 @@ static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
|
|||
/*
|
||||
* Perform a PHY calibration on RF5110
|
||||
* -Fix BPSK/QAM Constellation (I/Q correction)
|
||||
* -Calculate Noise Floor
|
||||
*/
|
||||
static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel)
|
||||
|
@ -1335,8 +1332,6 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ath5k_hw_update_noise_floor(ah);
|
||||
|
||||
/*
|
||||
* Re-enable RX/TX and beacons
|
||||
*/
|
||||
|
@ -1348,22 +1343,20 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
|
|||
}
|
||||
|
||||
/*
|
||||
* Perform a PHY calibration on RF5111/5112 and newer chips
|
||||
* Perform I/Q calibration on RF5111/5112 and newer chips
|
||||
*/
|
||||
static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel)
|
||||
static int
|
||||
ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah)
|
||||
{
|
||||
u32 i_pwr, q_pwr;
|
||||
s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
|
||||
int i;
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (!ah->ah_calibration ||
|
||||
ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
|
||||
goto done;
|
||||
return 0;
|
||||
|
||||
/* Calibration has finished, get the results and re-run */
|
||||
|
||||
/* work around empty results which can apparently happen on 5212 */
|
||||
for (i = 0; i <= 10; i++) {
|
||||
iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
|
||||
|
@ -1384,7 +1377,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
|
|||
|
||||
/* protect against divide by 0 and loss of sign bits */
|
||||
if (i_coffd == 0 || q_coffd < 2)
|
||||
goto done;
|
||||
return -1;
|
||||
|
||||
i_coff = (-iq_corr) / i_coffd;
|
||||
i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */
|
||||
|
@ -1410,17 +1403,6 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
|
|||
AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
|
||||
|
||||
done:
|
||||
|
||||
/* TODO: Separate noise floor calibration from I/Q calibration
|
||||
* since noise floor calibration interrupts rx path while I/Q
|
||||
* calibration doesn't. We don't need to run noise floor calibration
|
||||
* as often as I/Q calibration.*/
|
||||
ath5k_hw_update_noise_floor(ah);
|
||||
|
||||
/* Initiate a gain_F calibration */
|
||||
ath5k_hw_request_rfgain_probe(ah);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1434,8 +1416,10 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
|
|||
|
||||
if (ah->ah_radio == AR5K_RF5110)
|
||||
ret = ath5k_hw_rf5110_calibrate(ah, channel);
|
||||
else
|
||||
ret = ath5k_hw_rf511x_calibrate(ah, channel);
|
||||
else {
|
||||
ret = ath5k_hw_rf511x_iq_calibrate(ah);
|
||||
ath5k_hw_request_rfgain_probe(ah);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1693,7 +1677,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
|
|||
|
||||
int ath5k_hw_phy_disable(struct ath5k_hw *ah)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
/*Just a try M.F.*/
|
||||
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
|
||||
|
||||
|
@ -1709,8 +1692,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
|
|||
u32 srev;
|
||||
u16 ret;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/*
|
||||
* Set the radio chip access register
|
||||
*/
|
||||
|
@ -1755,8 +1736,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
|
|||
static void /*TODO:Boundary check*/
|
||||
ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (ah->ah_version != AR5K_AR5210)
|
||||
ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA);
|
||||
}
|
||||
|
@ -1789,19 +1768,50 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
|
|||
|
||||
if (enable) {
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
|
||||
AR5K_PHY_RESTART_DIV_GC, 0xc);
|
||||
AR5K_PHY_RESTART_DIV_GC, 1);
|
||||
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
|
||||
AR5K_PHY_FAST_ANT_DIV_EN);
|
||||
} else {
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
|
||||
AR5K_PHY_RESTART_DIV_GC, 0x8);
|
||||
AR5K_PHY_RESTART_DIV_GC, 0);
|
||||
|
||||
AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
|
||||
AR5K_PHY_FAST_ANT_DIV_EN);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode)
|
||||
{
|
||||
u8 ant0, ant1;
|
||||
|
||||
/*
|
||||
* In case a fixed antenna was set as default
|
||||
* use the same switch table twice.
|
||||
*/
|
||||
if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A)
|
||||
ant0 = ant1 = AR5K_ANT_SWTABLE_A;
|
||||
else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B)
|
||||
ant0 = ant1 = AR5K_ANT_SWTABLE_B;
|
||||
else {
|
||||
ant0 = AR5K_ANT_SWTABLE_A;
|
||||
ant1 = AR5K_ANT_SWTABLE_B;
|
||||
}
|
||||
|
||||
/* Set antenna idle switch table */
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
|
||||
AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
|
||||
(ah->ah_ant_ctl[ee_mode][AR5K_ANT_CTL] |
|
||||
AR5K_PHY_ANT_CTL_TXRX_EN));
|
||||
|
||||
/* Set antenna switch tables */
|
||||
ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant0],
|
||||
AR5K_PHY_ANT_SWITCH_TABLE_0);
|
||||
ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant1],
|
||||
AR5K_PHY_ANT_SWITCH_TABLE_1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set antenna operating mode
|
||||
*/
|
||||
|
@ -1814,9 +1824,14 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
|
|||
u8 def_ant, tx_ant, ee_mode;
|
||||
u32 sta_id1 = 0;
|
||||
|
||||
def_ant = ah->ah_def_ant;
|
||||
/* if channel is not initialized yet we can't set the antennas
|
||||
* so just store the mode. it will be set on the next reset */
|
||||
if (channel == NULL) {
|
||||
ah->ah_ant_mode = ant_mode;
|
||||
return;
|
||||
}
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
def_ant = ah->ah_def_ant;
|
||||
|
||||
switch (channel->hw_value & CHANNEL_MODES) {
|
||||
case CHANNEL_A:
|
||||
|
@ -1916,6 +1931,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
|
|||
if (sta_id1)
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1);
|
||||
|
||||
ath5k_hw_set_antenna_switch(ah, ee_mode);
|
||||
/* Note: set diversity before default antenna
|
||||
* because it won't work correctly */
|
||||
ath5k_hw_set_fast_div(ah, ee_mode, fast_div);
|
||||
|
@ -2981,7 +2997,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
|
|||
u8 type;
|
||||
int ret;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (txpower > AR5K_TUNE_MAX_TXPOWER) {
|
||||
ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
|
||||
return -EINVAL;
|
||||
|
@ -3077,8 +3092,6 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
|
|||
struct ieee80211_channel *channel = ah->ah_current_channel;
|
||||
u8 ee_mode;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
switch (channel->hw_value & CHANNEL_MODES) {
|
||||
case CHANNEL_A:
|
||||
case CHANNEL_T:
|
||||
|
|
|
@ -31,7 +31,6 @@ Queue Control Unit, DFS Control Unit Functions
|
|||
int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
|
||||
struct ath5k_txq_info *queue_info)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
|
||||
return 0;
|
||||
}
|
||||
|
@ -42,7 +41,6 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
|
|||
int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
|
||||
const struct ath5k_txq_info *queue_info)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||
|
||||
if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
|
||||
|
@ -69,8 +67,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
|
|||
unsigned int queue;
|
||||
int ret;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/*
|
||||
* Get queue by type
|
||||
*/
|
||||
|
@ -149,7 +145,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
|
|||
u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
|
||||
{
|
||||
u32 pending;
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||
|
||||
/* Return if queue is declared inactive */
|
||||
|
@ -177,7 +172,6 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
|
|||
*/
|
||||
void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
|
||||
return;
|
||||
|
||||
|
@ -195,7 +189,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||
u32 cw_min, cw_max, retry_lg, retry_sh;
|
||||
struct ath5k_txq_info *tq = &ah->ah_txq[queue];
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||
|
||||
tq = &ah->ah_txq[queue];
|
||||
|
@ -523,8 +516,6 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
|
|||
{
|
||||
u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -201,8 +201,6 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
|
|||
int ret;
|
||||
u32 mask = val ? val : ~0U;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/* Read-and-clear RX Descriptor Pointer*/
|
||||
ath5k_hw_reg_read(ah, AR5K_RXDP);
|
||||
|
||||
|
@ -246,7 +244,6 @@ static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
|||
unsigned int i;
|
||||
u32 staid, data;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
|
||||
|
||||
switch (mode) {
|
||||
|
@ -393,8 +390,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
|
|||
mode = 0;
|
||||
clock = 0;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
/* Wakeup the device */
|
||||
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
|
||||
if (ret) {
|
||||
|
@ -734,7 +729,7 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
|
|||
}
|
||||
|
||||
static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel, u8 *ant, u8 ee_mode)
|
||||
struct ieee80211_channel *channel, u8 ee_mode)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
s16 cck_ofdm_pwr_delta;
|
||||
|
@ -768,17 +763,9 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
|
|||
ee->ee_cck_ofdm_gain_delta;
|
||||
}
|
||||
|
||||
/* Set antenna idle switch table */
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL,
|
||||
AR5K_PHY_ANT_CTL_SWTABLE_IDLE,
|
||||
(ah->ah_ant_ctl[ee_mode][0] |
|
||||
AR5K_PHY_ANT_CTL_TXRX_EN));
|
||||
|
||||
/* Set antenna switch tables */
|
||||
ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]],
|
||||
AR5K_PHY_ANT_SWITCH_TABLE_0);
|
||||
ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]],
|
||||
AR5K_PHY_ANT_SWITCH_TABLE_1);
|
||||
/* XXX: necessary here? is called from ath5k_hw_set_antenna_mode()
|
||||
* too */
|
||||
ath5k_hw_set_antenna_switch(ah, ee_mode);
|
||||
|
||||
/* Noise floor threshold */
|
||||
ath5k_hw_reg_write(ah,
|
||||
|
@ -855,7 +842,6 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
|
|||
AR5K_PHY_NF_THRESH62,
|
||||
ee->ee_thr_62[ee_mode]);
|
||||
|
||||
|
||||
/* False detect backoff for channels
|
||||
* that have spur noise. Write the new
|
||||
* cyclic power RSSI threshold. */
|
||||
|
@ -891,14 +877,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
struct ieee80211_channel *channel, bool change_channel)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo;
|
||||
u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo;
|
||||
u32 phy_tst1;
|
||||
u8 mode, freq, ee_mode, ant[2];
|
||||
u8 mode, freq, ee_mode;
|
||||
int i, ret;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
s_ant = 0;
|
||||
ee_mode = 0;
|
||||
staid1_flags = 0;
|
||||
tsf_up = 0;
|
||||
|
@ -995,9 +978,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
}
|
||||
}
|
||||
|
||||
/* Save default antenna */
|
||||
s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
|
||||
|
||||
if (ah->ah_version == AR5K_AR5212) {
|
||||
/* Restore normal 32/40MHz clock operation
|
||||
* to avoid register access delay on certain
|
||||
|
@ -1094,22 +1074,17 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
/* Write OFDM timings on 5212*/
|
||||
if (ah->ah_version == AR5K_AR5212 &&
|
||||
channel->hw_value & CHANNEL_OFDM) {
|
||||
struct ath5k_eeprom_info *ee =
|
||||
&ah->ah_capabilities.cap_eeprom;
|
||||
|
||||
ret = ath5k_hw_write_ofdm_timings(ah, channel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Note: According to docs we can have a newer
|
||||
* EEPROM on old hardware, so we need to verify
|
||||
* that our hardware is new enough to have spur
|
||||
* mitigation registers (delta phase etc) */
|
||||
if (ah->ah_mac_srev >= AR5K_SREV_AR5424 ||
|
||||
(ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
|
||||
ee->ee_version >= AR5K_EEPROM_VERSION_5_3))
|
||||
/* Spur info is available only from EEPROM versions
|
||||
* bigger than 5.3 but but the EEPOM routines will use
|
||||
* static values for older versions */
|
||||
if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
|
||||
ath5k_hw_set_spur_mitigation_filter(ah,
|
||||
channel);
|
||||
channel);
|
||||
}
|
||||
|
||||
/*Enable/disable 802.11b mode on 5111
|
||||
|
@ -1123,21 +1098,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
AR5K_TXCFG_B_MODE);
|
||||
}
|
||||
|
||||
/*
|
||||
* In case a fixed antenna was set as default
|
||||
* use the same switch table twice.
|
||||
*/
|
||||
if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A)
|
||||
ant[0] = ant[1] = AR5K_ANT_SWTABLE_A;
|
||||
else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B)
|
||||
ant[0] = ant[1] = AR5K_ANT_SWTABLE_B;
|
||||
else {
|
||||
ant[0] = AR5K_ANT_SWTABLE_A;
|
||||
ant[1] = AR5K_ANT_SWTABLE_B;
|
||||
}
|
||||
|
||||
/* Commit values from EEPROM */
|
||||
ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode);
|
||||
ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode);
|
||||
|
||||
} else {
|
||||
/*
|
||||
|
@ -1175,8 +1137,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
|
||||
}
|
||||
}
|
||||
|
||||
ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
|
||||
}
|
||||
|
||||
/* Ledstate */
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "ath5k.h"
|
||||
#include "reg.h"
|
||||
|
||||
#define SIMPLE_SHOW_STORE(name, get, set) \
|
||||
static ssize_t ath5k_attr_show_##name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct ath5k_softc *sc = dev_get_drvdata(dev); \
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", get); \
|
||||
} \
|
||||
\
|
||||
static ssize_t ath5k_attr_store_##name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count) \
|
||||
{ \
|
||||
struct ath5k_softc *sc = dev_get_drvdata(dev); \
|
||||
int val; \
|
||||
\
|
||||
val = (int)simple_strtoul(buf, NULL, 10); \
|
||||
set(sc->ah, val); \
|
||||
return count; \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, \
|
||||
ath5k_attr_show_##name, ath5k_attr_store_##name)
|
||||
|
||||
#define SIMPLE_SHOW(name, get) \
|
||||
static ssize_t ath5k_attr_show_##name(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct ath5k_softc *sc = dev_get_drvdata(dev); \
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", get); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL)
|
||||
|
||||
/*** ANI ***/
|
||||
|
||||
SIMPLE_SHOW_STORE(ani_mode, sc->ani_state.ani_mode, ath5k_ani_init);
|
||||
SIMPLE_SHOW_STORE(noise_immunity_level, sc->ani_state.noise_imm_level,
|
||||
ath5k_ani_set_noise_immunity_level);
|
||||
SIMPLE_SHOW_STORE(spur_level, sc->ani_state.spur_level,
|
||||
ath5k_ani_set_spur_immunity_level);
|
||||
SIMPLE_SHOW_STORE(firstep_level, sc->ani_state.firstep_level,
|
||||
ath5k_ani_set_firstep_level);
|
||||
SIMPLE_SHOW_STORE(ofdm_weak_signal_detection, sc->ani_state.ofdm_weak_sig,
|
||||
ath5k_ani_set_ofdm_weak_signal_detection);
|
||||
SIMPLE_SHOW_STORE(cck_weak_signal_detection, sc->ani_state.cck_weak_sig,
|
||||
ath5k_ani_set_cck_weak_signal_detection);
|
||||
SIMPLE_SHOW(spur_level_max, sc->ani_state.max_spur_level);
|
||||
|
||||
static ssize_t ath5k_attr_show_noise_immunity_level_max(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_NOISE_IMM_LVL);
|
||||
}
|
||||
static DEVICE_ATTR(noise_immunity_level_max, S_IRUGO,
|
||||
ath5k_attr_show_noise_immunity_level_max, NULL);
|
||||
|
||||
static ssize_t ath5k_attr_show_firstep_level_max(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ATH5K_ANI_MAX_FIRSTEP_LVL);
|
||||
}
|
||||
static DEVICE_ATTR(firstep_level_max, S_IRUGO,
|
||||
ath5k_attr_show_firstep_level_max, NULL);
|
||||
|
||||
static struct attribute *ath5k_sysfs_entries_ani[] = {
|
||||
&dev_attr_ani_mode.attr,
|
||||
&dev_attr_noise_immunity_level.attr,
|
||||
&dev_attr_spur_level.attr,
|
||||
&dev_attr_firstep_level.attr,
|
||||
&dev_attr_ofdm_weak_signal_detection.attr,
|
||||
&dev_attr_cck_weak_signal_detection.attr,
|
||||
&dev_attr_noise_immunity_level_max.attr,
|
||||
&dev_attr_spur_level_max.attr,
|
||||
&dev_attr_firstep_level_max.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group ath5k_attribute_group_ani = {
|
||||
.name = "ani",
|
||||
.attrs = ath5k_sysfs_entries_ani,
|
||||
};
|
||||
|
||||
|
||||
/*** register / unregister ***/
|
||||
|
||||
int
|
||||
ath5k_sysfs_register(struct ath5k_softc *sc)
|
||||
{
|
||||
struct device *dev = &sc->pdev->dev;
|
||||
int err;
|
||||
|
||||
err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani);
|
||||
if (err) {
|
||||
ATH5K_ERR(sc, "failed to create sysfs group\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ath5k_sysfs_unregister(struct ath5k_softc *sc)
|
||||
{
|
||||
struct device *dev = &sc->pdev->dev;
|
||||
|
||||
sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani);
|
||||
}
|
|
@ -495,6 +495,7 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
|
|||
REG_WRITE(ah, AR_FILT_OFDM, 0);
|
||||
REG_WRITE(ah, AR_FILT_CCK, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
|
||||
|
||||
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
|
||||
u32 *rxc_pcnt,
|
||||
|
|
|
@ -742,17 +742,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (AR_SREV_9287_12_OR_LATER(ah)) {
|
||||
/* Enable ASYNC FIFO */
|
||||
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
|
||||
REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
|
||||
REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
|
||||
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set correct baseband to analog shift setting to
|
||||
* access analog chips.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "ar5008_initvals.h"
|
||||
#include "ar9001_initvals.h"
|
||||
#include "ar9002_initvals.h"
|
||||
#include "ar9002_phy.h"
|
||||
|
||||
/* General hardware code for the A5008/AR9001/AR9002 hadware families */
|
||||
|
||||
|
@ -436,55 +437,84 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
|
|||
}
|
||||
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
/* set bit 19 to allow forcing of pcie core into L1 state */
|
||||
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||
if (power_off) {
|
||||
/* clear bit 19 to disable L1 */
|
||||
REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||
|
||||
/* Several PCIe massages to ensure proper behaviour */
|
||||
val = REG_READ(ah, AR_WA);
|
||||
|
||||
/*
|
||||
* Set PCIe workaround bits
|
||||
* In AR9280 and AR9285, bit 14 in WA register (disable L1)
|
||||
* should only be set when device enters D3 and be
|
||||
* cleared when device comes back to D0.
|
||||
*/
|
||||
if (ah->config.pcie_waen) {
|
||||
if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
|
||||
val |= AR_WA_D3_L1_DISABLE;
|
||||
} else {
|
||||
if (((AR_SREV_9285(ah) ||
|
||||
AR_SREV_9271(ah) ||
|
||||
AR_SREV_9287(ah)) &&
|
||||
(AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
|
||||
(AR_SREV_9280(ah) &&
|
||||
(AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
|
||||
val |= AR_WA_D3_L1_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
|
||||
/*
|
||||
* Disable bit 6 and 7 before entering D3 to
|
||||
* prevent system hang.
|
||||
*/
|
||||
val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
|
||||
}
|
||||
|
||||
if (AR_SREV_9285E_20(ah))
|
||||
val |= AR_WA_BIT23;
|
||||
|
||||
REG_WRITE(ah, AR_WA, val);
|
||||
} else {
|
||||
if (ah->config.pcie_waen) {
|
||||
val = ah->config.pcie_waen;
|
||||
if (!power_off)
|
||||
val &= (~AR_WA_D3_L1_DISABLE);
|
||||
} else {
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
|
||||
if (AR_SREV_9285(ah) ||
|
||||
AR_SREV_9271(ah) ||
|
||||
AR_SREV_9287(ah)) {
|
||||
val = AR9285_WA_DEFAULT;
|
||||
if (!power_off)
|
||||
val &= (~AR_WA_D3_L1_DISABLE);
|
||||
} else if (AR_SREV_9280(ah)) {
|
||||
}
|
||||
else if (AR_SREV_9280(ah)) {
|
||||
/*
|
||||
* On AR9280 chips bit 22 of 0x4004 needs to be
|
||||
* set otherwise card may disappear.
|
||||
* For AR9280 chips, bit 22 of 0x4004
|
||||
* needs to be set.
|
||||
*/
|
||||
val = AR9280_WA_DEFAULT;
|
||||
if (!power_off)
|
||||
val &= (~AR_WA_D3_L1_DISABLE);
|
||||
} else
|
||||
} else {
|
||||
val = AR_WA_DEFAULT;
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_WA, val);
|
||||
}
|
||||
|
||||
if (power_off) {
|
||||
/*
|
||||
* Set PCIe workaround bits
|
||||
* bit 14 in WA register (disable L1) should only
|
||||
* be set when device enters D3 and be cleared
|
||||
* when device comes back to D0.
|
||||
*/
|
||||
if (ah->config.pcie_waen) {
|
||||
if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
|
||||
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
|
||||
} else {
|
||||
if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
|
||||
AR_SREV_9287(ah)) &&
|
||||
(AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
|
||||
(AR_SREV_9280(ah) &&
|
||||
(AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
|
||||
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* WAR for ASPM system hang */
|
||||
if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
|
||||
val |= (AR_WA_BIT6 | AR_WA_BIT7);
|
||||
}
|
||||
|
||||
if (AR_SREV_9285E_20(ah))
|
||||
val |= AR_WA_BIT23;
|
||||
|
||||
REG_WRITE(ah, AR_WA, val);
|
||||
|
||||
/* set bit 19 to allow forcing of pcie core into L1 state */
|
||||
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -536,18 +566,29 @@ int ar9002_hw_rf_claim(struct ath_hw *ah)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_13_OR_LATER(ah)) {
|
||||
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
|
||||
REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
|
||||
REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
|
||||
REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
|
||||
AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable ASYNC FIFO
|
||||
*
|
||||
* If Async FIFO is enabled, the following counters change as MAC now runs
|
||||
* at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
|
||||
*
|
||||
* The values below tested for ht40 2 chain.
|
||||
* Overwrite the delay/timeouts initialized in process ini.
|
||||
*/
|
||||
void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
|
||||
void ar9002_hw_update_async_fifo(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_12_OR_LATER(ah)) {
|
||||
if (AR_SREV_9287_13_OR_LATER(ah)) {
|
||||
REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
|
||||
AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
|
||||
REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
|
||||
|
@ -571,9 +612,9 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
|
|||
*/
|
||||
void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9287_12_OR_LATER(ah)) {
|
||||
if (AR_SREV_9287_13_OR_LATER(ah)) {
|
||||
REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
|
||||
AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
|
||||
AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4492,7 +4492,7 @@ static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {
|
|||
};
|
||||
|
||||
|
||||
/* AR9271 initialization values automaticaly created: 06/04/09 */
|
||||
/* AR9271 initialization values automaticaly created: 03/31/10 */
|
||||
static const u32 ar9271Modes_9271[][6] = {
|
||||
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
|
||||
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
|
||||
|
@ -5011,7 +5011,7 @@ static const u32 ar9271Common_9271[][2] = {
|
|||
{ 0x0000783c, 0x72ee0a72 },
|
||||
{ 0x00007840, 0xbbfffffc },
|
||||
{ 0x00007844, 0x000c0db6 },
|
||||
{ 0x00007848, 0x6db61b6f },
|
||||
{ 0x00007848, 0x6db6246f },
|
||||
{ 0x0000784c, 0x6d9b66db },
|
||||
{ 0x00007850, 0x6d8c6dba },
|
||||
{ 0x00007854, 0x00040000 },
|
||||
|
@ -5218,7 +5218,7 @@ static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = {
|
|||
{ 0x00007824, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff, 0x00d8a7ff },
|
||||
{ 0x0000786c, 0x08609eb6, 0x08609eb6, 0x08609eba, 0x08609eba, 0x08609eb6 },
|
||||
{ 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 },
|
||||
{ 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a212652, 0x0a212652, 0x0a22a652 },
|
||||
{ 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a214652, 0x0a214652, 0x0a22a652 },
|
||||
{ 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 },
|
||||
{ 0x0000a27c, 0x05018063, 0x05038063, 0x05018063, 0x05018063, 0x05018063 },
|
||||
{ 0x0000a394, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 },
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef INITVALS_9003_H
|
||||
#define INITVALS_9003_H
|
||||
#ifndef INITVALS_9003_2P0_H
|
||||
#define INITVALS_9003_2P0_H
|
||||
|
||||
/* AR9003 2.0 */
|
||||
|
||||
|
@ -1781,4 +1781,4 @@ static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = {
|
|||
{0x00004044, 0x00000000},
|
||||
};
|
||||
|
||||
#endif /* INITVALS_9003_H */
|
||||
#endif /* INITVALS_9003_2P0_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -739,6 +739,12 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
|||
*/
|
||||
ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
|
||||
|
||||
/* Do Tx IQ Calibration */
|
||||
ar9003_hw_tx_iq_cal(ah);
|
||||
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
|
||||
udelay(5);
|
||||
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
|
||||
|
||||
/* Calibrate the AGC */
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
|
@ -753,10 +759,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Do Tx IQ Calibration */
|
||||
if (ah->config.tx_iq_calibration)
|
||||
ar9003_hw_tx_iq_cal(ah);
|
||||
|
||||
/* Revert chainmasks to their original values before NF cal */
|
||||
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
#include "hw.h"
|
||||
#include "ar9003_mac.h"
|
||||
#include "ar9003_initvals.h"
|
||||
#include "ar9003_2p0_initvals.h"
|
||||
#include "ar9003_2p2_initvals.h"
|
||||
|
||||
/* General hardware code for the AR9003 hadware family */
|
||||
|
||||
|
@ -31,12 +32,8 @@ static bool ar9003_hw_macversion_supported(u32 macversion)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */
|
||||
/*
|
||||
* XXX: move TX/RX gain INI to its own init_mode_gain_regs after
|
||||
* ensuring it does not affect hardware bring up
|
||||
*/
|
||||
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
||||
/* AR9003 2.0 */
|
||||
static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
/* mac */
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
|
||||
|
@ -106,27 +103,128 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
|||
3);
|
||||
}
|
||||
|
||||
/* AR9003 2.2 */
|
||||
static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
/* mac */
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
|
||||
ar9300_2p2_mac_core,
|
||||
ARRAY_SIZE(ar9300_2p2_mac_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
|
||||
ar9300_2p2_mac_postamble,
|
||||
ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
|
||||
|
||||
/* bb */
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
|
||||
ar9300_2p2_baseband_core,
|
||||
ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
|
||||
ar9300_2p2_baseband_postamble,
|
||||
ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
|
||||
|
||||
/* radio */
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
|
||||
ar9300_2p2_radio_core,
|
||||
ARRAY_SIZE(ar9300_2p2_radio_core), 2);
|
||||
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
|
||||
ar9300_2p2_radio_postamble,
|
||||
ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
|
||||
|
||||
/* soc */
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
|
||||
ar9300_2p2_soc_preamble,
|
||||
ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
|
||||
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
|
||||
ar9300_2p2_soc_postamble,
|
||||
ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
|
||||
|
||||
/* rx/tx gain */
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_rx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
|
||||
5);
|
||||
|
||||
/* Load PCIE SERDES settings from INI */
|
||||
|
||||
/* Awake Setting */
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
|
||||
ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
|
||||
2);
|
||||
|
||||
/* Sleep Setting */
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
||||
ar9300PciePhy_clkreq_enable_L1_2p2,
|
||||
ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2),
|
||||
2);
|
||||
|
||||
/* Fast clock modal settings */
|
||||
INIT_INI_ARRAY(&ah->iniModesAdditional,
|
||||
ar9300Modes_fast_clock_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
|
||||
3);
|
||||
}
|
||||
|
||||
/*
|
||||
* The AR9003 family uses a new INI format (pre, core, post
|
||||
* arrays per subsystem).
|
||||
*/
|
||||
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9300_20(ah))
|
||||
ar9003_2p0_hw_init_mode_regs(ah);
|
||||
else
|
||||
ar9003_2p2_hw_init_mode_regs(ah);
|
||||
}
|
||||
|
||||
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
|
||||
{
|
||||
switch (ar9003_hw_get_tx_gain_idx(ah)) {
|
||||
case 0:
|
||||
default:
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
|
||||
5);
|
||||
if (AR_SREV_9300_20(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
|
||||
5);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
|
||||
5);
|
||||
break;
|
||||
case 1:
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_high_ob_db_tx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0),
|
||||
5);
|
||||
if (AR_SREV_9300_20(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_high_ob_db_tx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0),
|
||||
5);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_high_ob_db_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
|
||||
5);
|
||||
break;
|
||||
case 2:
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_low_ob_db_tx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0),
|
||||
5);
|
||||
if (AR_SREV_9300_20(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_low_ob_db_tx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0),
|
||||
5);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_low_ob_db_tx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
|
||||
5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -136,15 +234,28 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
|
|||
switch (ar9003_hw_get_rx_gain_idx(ah)) {
|
||||
case 0:
|
||||
default:
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Common_rx_gain_table_2p0),
|
||||
2);
|
||||
if (AR_SREV_9300_20(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_rx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Common_rx_gain_table_2p0),
|
||||
2);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_rx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
|
||||
2);
|
||||
break;
|
||||
case 1:
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_wo_xlna_rx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0),
|
||||
2);
|
||||
if (AR_SREV_9300_20(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_wo_xlna_rx_gain_table_2p0,
|
||||
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0),
|
||||
2);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesRxGain,
|
||||
ar9300Common_wo_xlna_rx_gain_table_2p2,
|
||||
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
|
||||
2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
|||
MAP_ISR_S2_CST);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >>
|
||||
MAP_ISR_S2_TSFOOR);
|
||||
mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >>
|
||||
MAP_ISR_S2_BB_WATCHDOG);
|
||||
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
|
||||
REG_WRITE(ah, AR_ISR_S2, isr2);
|
||||
|
@ -167,6 +169,9 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
|||
|
||||
(void) REG_READ(ah, AR_ISR);
|
||||
}
|
||||
|
||||
if (*masked & ATH9K_INT_BB_WATCHDOG)
|
||||
ar9003_hw_bb_watchdog_read(ah);
|
||||
}
|
||||
|
||||
if (sync_cause) {
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#define MAP_ISR_S2_DTIMSYNC 7
|
||||
#define MAP_ISR_S2_DTIM 7
|
||||
#define MAP_ISR_S2_TSFOOR 4
|
||||
#define MAP_ISR_S2_BB_WATCHDOG 6
|
||||
|
||||
#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds)
|
||||
|
||||
|
|
|
@ -1132,3 +1132,122 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
|
|||
priv_ops->do_getnf = ar9003_hw_do_getnf;
|
||||
priv_ops->loadnf = ar9003_hw_loadnf;
|
||||
}
|
||||
|
||||
void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 idle_tmo_ms = ah->bb_watchdog_timeout_ms;
|
||||
u32 val, idle_count;
|
||||
|
||||
if (!idle_tmo_ms) {
|
||||
/* disable IRQ, disable chip-reset for BB panic */
|
||||
REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2,
|
||||
REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) &
|
||||
~(AR_PHY_WATCHDOG_RST_ENABLE |
|
||||
AR_PHY_WATCHDOG_IRQ_ENABLE));
|
||||
|
||||
/* disable watchdog in non-IDLE mode, disable in IDLE mode */
|
||||
REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1,
|
||||
REG_READ(ah, AR_PHY_WATCHDOG_CTL_1) &
|
||||
~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE |
|
||||
AR_PHY_WATCHDOG_IDLE_ENABLE));
|
||||
|
||||
ath_print(common, ATH_DBG_RESET, "Disabled BB Watchdog\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* enable IRQ, disable chip-reset for BB watchdog */
|
||||
val = REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) & AR_PHY_WATCHDOG_CNTL2_MASK;
|
||||
REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2,
|
||||
(val | AR_PHY_WATCHDOG_IRQ_ENABLE) &
|
||||
~AR_PHY_WATCHDOG_RST_ENABLE);
|
||||
|
||||
/* bound limit to 10 secs */
|
||||
if (idle_tmo_ms > 10000)
|
||||
idle_tmo_ms = 10000;
|
||||
|
||||
/*
|
||||
* The time unit for watchdog event is 2^15 44/88MHz cycles.
|
||||
*
|
||||
* For HT20 we have a time unit of 2^15/44 MHz = .74 ms per tick
|
||||
* For HT40 we have a time unit of 2^15/88 MHz = .37 ms per tick
|
||||
*
|
||||
* Given we use fast clock now in 5 GHz, these time units should
|
||||
* be common for both 2 GHz and 5 GHz.
|
||||
*/
|
||||
idle_count = (100 * idle_tmo_ms) / 74;
|
||||
if (ah->curchan && IS_CHAN_HT40(ah->curchan))
|
||||
idle_count = (100 * idle_tmo_ms) / 37;
|
||||
|
||||
/*
|
||||
* enable watchdog in non-IDLE mode, disable in IDLE mode,
|
||||
* set idle time-out.
|
||||
*/
|
||||
REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1,
|
||||
AR_PHY_WATCHDOG_NON_IDLE_ENABLE |
|
||||
AR_PHY_WATCHDOG_IDLE_MASK |
|
||||
(AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2)));
|
||||
|
||||
ath_print(common, ATH_DBG_RESET,
|
||||
"Enabled BB Watchdog timeout (%u ms)\n",
|
||||
idle_tmo_ms);
|
||||
}
|
||||
|
||||
void ar9003_hw_bb_watchdog_read(struct ath_hw *ah)
|
||||
{
|
||||
/*
|
||||
* we want to avoid printing in ISR context so we save the
|
||||
* watchdog status to be printed later in bottom half context.
|
||||
*/
|
||||
ah->bb_watchdog_last_status = REG_READ(ah, AR_PHY_WATCHDOG_STATUS);
|
||||
|
||||
/*
|
||||
* the watchdog timer should reset on status read but to be sure
|
||||
* sure we write 0 to the watchdog status bit.
|
||||
*/
|
||||
REG_WRITE(ah, AR_PHY_WATCHDOG_STATUS,
|
||||
ah->bb_watchdog_last_status & ~AR_PHY_WATCHDOG_STATUS_CLR);
|
||||
}
|
||||
|
||||
void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status;
|
||||
|
||||
if (likely(!(common->debug_mask & ATH_DBG_RESET)))
|
||||
return;
|
||||
|
||||
status = ah->bb_watchdog_last_status;
|
||||
ath_print(common, ATH_DBG_RESET,
|
||||
"\n==== BB update: BB status=0x%08x ====\n", status);
|
||||
ath_print(common, ATH_DBG_RESET,
|
||||
"** BB state: wd=%u det=%u rdar=%u rOFDM=%d "
|
||||
"rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n",
|
||||
MS(status, AR_PHY_WATCHDOG_INFO),
|
||||
MS(status, AR_PHY_WATCHDOG_DET_HANG),
|
||||
MS(status, AR_PHY_WATCHDOG_RADAR_SM),
|
||||
MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM),
|
||||
MS(status, AR_PHY_WATCHDOG_RX_CCK_SM),
|
||||
MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM),
|
||||
MS(status, AR_PHY_WATCHDOG_TX_CCK_SM),
|
||||
MS(status, AR_PHY_WATCHDOG_AGC_SM),
|
||||
MS(status,AR_PHY_WATCHDOG_SRCH_SM));
|
||||
|
||||
ath_print(common, ATH_DBG_RESET,
|
||||
"** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n",
|
||||
REG_READ(ah, AR_PHY_WATCHDOG_CTL_1),
|
||||
REG_READ(ah, AR_PHY_WATCHDOG_CTL_2));
|
||||
ath_print(common, ATH_DBG_RESET,
|
||||
"** BB mode: BB_gen_controls=0x%08x **\n",
|
||||
REG_READ(ah, AR_PHY_GEN_CTRL));
|
||||
|
||||
if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt))
|
||||
ath_print(common, ATH_DBG_RESET,
|
||||
"** BB busy times: rx_clear=%d%%, "
|
||||
"rx_frame=%d%%, tx_frame=%d%% **\n",
|
||||
rxc_pcnt, rxf_pcnt, txf_pcnt);
|
||||
|
||||
ath_print(common, ATH_DBG_RESET,
|
||||
"==== BB update: done ====\n\n");
|
||||
}
|
||||
EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info);
|
||||
|
|
|
@ -483,10 +483,10 @@
|
|||
#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c)
|
||||
#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450)
|
||||
|
||||
#define AR_PHY_PANIC_WD_STATUS (AR_SM_BASE + 0x5c0)
|
||||
#define AR_PHY_PANIC_WD_CTL_1 (AR_SM_BASE + 0x5c4)
|
||||
#define AR_PHY_PANIC_WD_CTL_2 (AR_SM_BASE + 0x5c8)
|
||||
#define AR_PHY_BT_CTL (AR_SM_BASE + 0x5cc)
|
||||
#define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0)
|
||||
#define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4)
|
||||
#define AR_PHY_WATCHDOG_CTL_2 (AR_SM_BASE + 0x5c8)
|
||||
#define AR_PHY_WATCHDOG_CTL (AR_SM_BASE + 0x5cc)
|
||||
#define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0)
|
||||
#define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4)
|
||||
#define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc)
|
||||
|
@ -812,35 +812,35 @@
|
|||
#define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
|
||||
#define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
|
||||
|
||||
#define AR_PHY_BB_PANIC_NON_IDLE_ENABLE 0x00000001
|
||||
#define AR_PHY_BB_PANIC_IDLE_ENABLE 0x00000002
|
||||
#define AR_PHY_BB_PANIC_IDLE_MASK 0xFFFF0000
|
||||
#define AR_PHY_BB_PANIC_NON_IDLE_MASK 0x0000FFFC
|
||||
#define AR_PHY_WATCHDOG_NON_IDLE_ENABLE 0x00000001
|
||||
#define AR_PHY_WATCHDOG_IDLE_ENABLE 0x00000002
|
||||
#define AR_PHY_WATCHDOG_IDLE_MASK 0xFFFF0000
|
||||
#define AR_PHY_WATCHDOG_NON_IDLE_MASK 0x0000FFFC
|
||||
|
||||
#define AR_PHY_BB_PANIC_RST_ENABLE 0x00000002
|
||||
#define AR_PHY_BB_PANIC_IRQ_ENABLE 0x00000004
|
||||
#define AR_PHY_BB_PANIC_CNTL2_MASK 0xFFFFFFF9
|
||||
#define AR_PHY_WATCHDOG_RST_ENABLE 0x00000002
|
||||
#define AR_PHY_WATCHDOG_IRQ_ENABLE 0x00000004
|
||||
#define AR_PHY_WATCHDOG_CNTL2_MASK 0xFFFFFFF9
|
||||
|
||||
#define AR_PHY_BB_WD_STATUS 0x00000007
|
||||
#define AR_PHY_BB_WD_STATUS_S 0
|
||||
#define AR_PHY_BB_WD_DET_HANG 0x00000008
|
||||
#define AR_PHY_BB_WD_DET_HANG_S 3
|
||||
#define AR_PHY_BB_WD_RADAR_SM 0x000000F0
|
||||
#define AR_PHY_BB_WD_RADAR_SM_S 4
|
||||
#define AR_PHY_BB_WD_RX_OFDM_SM 0x00000F00
|
||||
#define AR_PHY_BB_WD_RX_OFDM_SM_S 8
|
||||
#define AR_PHY_BB_WD_RX_CCK_SM 0x0000F000
|
||||
#define AR_PHY_BB_WD_RX_CCK_SM_S 12
|
||||
#define AR_PHY_BB_WD_TX_OFDM_SM 0x000F0000
|
||||
#define AR_PHY_BB_WD_TX_OFDM_SM_S 16
|
||||
#define AR_PHY_BB_WD_TX_CCK_SM 0x00F00000
|
||||
#define AR_PHY_BB_WD_TX_CCK_SM_S 20
|
||||
#define AR_PHY_BB_WD_AGC_SM 0x0F000000
|
||||
#define AR_PHY_BB_WD_AGC_SM_S 24
|
||||
#define AR_PHY_BB_WD_SRCH_SM 0xF0000000
|
||||
#define AR_PHY_BB_WD_SRCH_SM_S 28
|
||||
#define AR_PHY_WATCHDOG_INFO 0x00000007
|
||||
#define AR_PHY_WATCHDOG_INFO_S 0
|
||||
#define AR_PHY_WATCHDOG_DET_HANG 0x00000008
|
||||
#define AR_PHY_WATCHDOG_DET_HANG_S 3
|
||||
#define AR_PHY_WATCHDOG_RADAR_SM 0x000000F0
|
||||
#define AR_PHY_WATCHDOG_RADAR_SM_S 4
|
||||
#define AR_PHY_WATCHDOG_RX_OFDM_SM 0x00000F00
|
||||
#define AR_PHY_WATCHDOG_RX_OFDM_SM_S 8
|
||||
#define AR_PHY_WATCHDOG_RX_CCK_SM 0x0000F000
|
||||
#define AR_PHY_WATCHDOG_RX_CCK_SM_S 12
|
||||
#define AR_PHY_WATCHDOG_TX_OFDM_SM 0x000F0000
|
||||
#define AR_PHY_WATCHDOG_TX_OFDM_SM_S 16
|
||||
#define AR_PHY_WATCHDOG_TX_CCK_SM 0x00F00000
|
||||
#define AR_PHY_WATCHDOG_TX_CCK_SM_S 20
|
||||
#define AR_PHY_WATCHDOG_AGC_SM 0x0F000000
|
||||
#define AR_PHY_WATCHDOG_AGC_SM_S 24
|
||||
#define AR_PHY_WATCHDOG_SRCH_SM 0xF0000000
|
||||
#define AR_PHY_WATCHDOG_SRCH_SM_S 28
|
||||
|
||||
#define AR_PHY_BB_WD_STATUS_CLR 0x00000008
|
||||
#define AR_PHY_WATCHDOG_STATUS_CLR 0x00000008
|
||||
|
||||
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
|
||||
|
||||
|
|
|
@ -136,6 +136,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
|
|||
#define ATH_MAX_ANTENNA 3
|
||||
#define ATH_RXBUF 512
|
||||
#define ATH_TXBUF 512
|
||||
#define ATH_TXBUF_RESERVE 5
|
||||
#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
|
||||
#define ATH_TXMAXTRY 13
|
||||
#define ATH_MGT_TXMAXTRY 4
|
||||
|
||||
|
@ -204,6 +206,71 @@ struct ath_txq {
|
|||
struct list_head txq_fifo_pending;
|
||||
u8 txq_headidx;
|
||||
u8 txq_tailidx;
|
||||
int pending_frames;
|
||||
};
|
||||
|
||||
struct ath_atx_ac {
|
||||
int sched;
|
||||
int qnum;
|
||||
struct list_head list;
|
||||
struct list_head tid_q;
|
||||
};
|
||||
|
||||
struct ath_buf_state {
|
||||
int bfs_nframes;
|
||||
u16 bfs_al;
|
||||
u16 bfs_frmlen;
|
||||
int bfs_seqno;
|
||||
int bfs_tidno;
|
||||
int bfs_retries;
|
||||
u8 bf_type;
|
||||
u32 bfs_keyix;
|
||||
enum ath9k_key_type bfs_keytype;
|
||||
};
|
||||
|
||||
struct ath_buf {
|
||||
struct list_head list;
|
||||
struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or
|
||||
an aggregate) */
|
||||
struct ath_buf *bf_next; /* next subframe in the aggregate */
|
||||
struct sk_buff *bf_mpdu; /* enclosing frame structure */
|
||||
void *bf_desc; /* virtual addr of desc */
|
||||
dma_addr_t bf_daddr; /* physical addr of desc */
|
||||
dma_addr_t bf_buf_addr; /* physical addr of data buffer */
|
||||
bool bf_stale;
|
||||
bool bf_isnullfunc;
|
||||
bool bf_tx_aborted;
|
||||
u16 bf_flags;
|
||||
struct ath_buf_state bf_state;
|
||||
dma_addr_t bf_dmacontext;
|
||||
struct ath_wiphy *aphy;
|
||||
struct ath_txq *txq;
|
||||
};
|
||||
|
||||
struct ath_atx_tid {
|
||||
struct list_head list;
|
||||
struct list_head buf_q;
|
||||
struct ath_node *an;
|
||||
struct ath_atx_ac *ac;
|
||||
struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
|
||||
u16 seq_start;
|
||||
u16 seq_next;
|
||||
u16 baw_size;
|
||||
int tidno;
|
||||
int baw_head; /* first un-acked tx buffer */
|
||||
int baw_tail; /* next unused tx buffer slot */
|
||||
int sched;
|
||||
int paused;
|
||||
u8 state;
|
||||
};
|
||||
|
||||
struct ath_node {
|
||||
struct ath_common *common;
|
||||
struct ath_atx_tid tid[WME_NUM_TID];
|
||||
struct ath_atx_ac ac[WME_NUM_AC];
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
int last_rssi;
|
||||
};
|
||||
|
||||
#define AGGR_CLEANUP BIT(1)
|
||||
|
@ -267,7 +334,6 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
|
|||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
|
||||
int ath_tx_init(struct ath_softc *sc, int nbufs);
|
||||
void ath_tx_cleanup(struct ath_softc *sc);
|
||||
struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
|
||||
int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
struct ath9k_tx_queue_info *q);
|
||||
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
|
|
|
@ -27,270 +27,6 @@ MODULE_AUTHOR("Atheros Communications");
|
|||
MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
/* Common RX processing */
|
||||
|
||||
/* Assumes you've already done the endian to CPU conversion */
|
||||
static bool ath9k_rx_accept(struct ath_common *common,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
struct ath_rx_status *rx_stats,
|
||||
bool *decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_hdr *hdr;
|
||||
__le16 fc;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
fc = hdr->frame_control;
|
||||
|
||||
if (!rx_stats->rs_datalen)
|
||||
return false;
|
||||
/*
|
||||
* rs_status follows rs_datalen so if rs_datalen is too large
|
||||
* we can take a hint that hardware corrupted it, so ignore
|
||||
* those frames.
|
||||
*/
|
||||
if (rx_stats->rs_datalen > common->rx_bufsize)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* rs_more indicates chained descriptors which can be used
|
||||
* to link buffers together for a sort of scatter-gather
|
||||
* operation.
|
||||
* reject the frame, we don't support scatter-gather yet and
|
||||
* the frame is probably corrupt anyway
|
||||
*/
|
||||
if (rx_stats->rs_more)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* The rx_stats->rs_status will not be set until the end of the
|
||||
* chained descriptors so it can be ignored if rs_more is set. The
|
||||
* rs_more will be false at the last element of the chained
|
||||
* descriptors.
|
||||
*/
|
||||
if (rx_stats->rs_status != 0) {
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_CRC)
|
||||
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_PHY)
|
||||
return false;
|
||||
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
|
||||
*decrypt_error = true;
|
||||
} else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
|
||||
if (ieee80211_is_ctl(fc))
|
||||
/*
|
||||
* Sometimes, we get invalid
|
||||
* MIC failures on valid control frames.
|
||||
* Remove these mic errors.
|
||||
*/
|
||||
rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
|
||||
else
|
||||
rxs->flag |= RX_FLAG_MMIC_ERROR;
|
||||
}
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (ah->opmode == NL80211_IFTYPE_MONITOR) {
|
||||
if (rx_stats->rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
return false;
|
||||
} else {
|
||||
if (rx_stats->rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ath9k_process_rate(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum ieee80211_band band;
|
||||
unsigned int i = 0;
|
||||
|
||||
band = hw->conf.channel->band;
|
||||
sband = hw->wiphy->bands[band];
|
||||
|
||||
if (rx_stats->rs_rate & 0x80) {
|
||||
/* HT rate */
|
||||
rxs->flag |= RX_FLAG_HT;
|
||||
if (rx_stats->rs_flags & ATH9K_RX_2040)
|
||||
rxs->flag |= RX_FLAG_40MHZ;
|
||||
if (rx_stats->rs_flags & ATH9K_RX_GI)
|
||||
rxs->flag |= RX_FLAG_SHORT_GI;
|
||||
rxs->rate_idx = rx_stats->rs_rate & 0x7f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
|
||||
rxs->rate_idx = i;
|
||||
return 0;
|
||||
}
|
||||
if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
|
||||
rxs->flag |= RX_FLAG_SHORTPRE;
|
||||
rxs->rate_idx = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No valid hardware bitrate found -- we should not get here
|
||||
* because hardware has already validated this frame as OK.
|
||||
*/
|
||||
ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected "
|
||||
"0x%02x using 1 Mbit\n", rx_stats->rs_rate);
|
||||
if ((common->debug_mask & ATH_DBG_XMIT))
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void ath9k_process_rssi(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ath_node *an;
|
||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
__le16 fc;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
|
||||
rcu_read_lock();
|
||||
/*
|
||||
* XXX: use ieee80211_find_sta! This requires quite a bit of work
|
||||
* under the current ath9k virtual wiphy implementation as we have
|
||||
* no way of tying a vif to wiphy. Typically vifs are attached to
|
||||
* at least one sdata of a wiphy on mac80211 but with ath9k virtual
|
||||
* wiphy you'd have to iterate over every wiphy and each sdata.
|
||||
*/
|
||||
sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
|
||||
if (sta) {
|
||||
an = (struct ath_node *) sta->drv_priv;
|
||||
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
|
||||
!rx_stats->rs_moreaggr)
|
||||
ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
|
||||
last_rssi = an->last_rssi;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
|
||||
rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
|
||||
ATH_RSSI_EP_MULTIPLIER);
|
||||
if (rx_stats->rs_rssi < 0)
|
||||
rx_stats->rs_rssi = 0;
|
||||
|
||||
/* Update Beacon RSSI, this is used by ANI. */
|
||||
if (ieee80211_is_beacon(fc))
|
||||
ah->stats.avgbrssi = rx_stats->rs_rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
* For Decrypt or Demic errors, we only mark packet status here and always push
|
||||
* up the frame up to let mac80211 handle the actual error case, be it no
|
||||
* decryption key or real decryption error. This let us keep statistics there.
|
||||
*/
|
||||
int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
bool *decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
|
||||
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
|
||||
|
||||
/*
|
||||
* everything but the rate is checked here, the rate check is done
|
||||
* separately to avoid doing two lookups for a rate for each frame.
|
||||
*/
|
||||
if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error))
|
||||
return -EINVAL;
|
||||
|
||||
ath9k_process_rssi(common, hw, skb, rx_stats);
|
||||
|
||||
if (ath9k_process_rate(common, hw, rx_stats, rx_status, skb))
|
||||
return -EINVAL;
|
||||
|
||||
rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
|
||||
rx_status->antenna = rx_stats->rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_TSFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_rx_skb_preprocess);
|
||||
|
||||
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
bool decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int hdrlen, padpos, padsize;
|
||||
u8 keyix;
|
||||
__le16 fc;
|
||||
|
||||
/* see if any padding is done by the hw and remove it */
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
fc = hdr->frame_control;
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
|
||||
/* The MAC header is padded to have 32-bit boundary if the
|
||||
* packet payload is non-zero. The general calculation for
|
||||
* padsize would take into account odd header lengths:
|
||||
* padsize = (4 - padpos % 4) % 4; However, since only
|
||||
* even-length headers are used, padding can only be 0 or 2
|
||||
* bytes and we can optimize this a bit. In addition, we must
|
||||
* not try to remove padding from short control frames that do
|
||||
* not have payload. */
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
|
||||
memmove(skb->data + padsize, skb->data, padpos);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
keyix = rx_stats->rs_keyix;
|
||||
|
||||
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
|
||||
ieee80211_has_protected(fc)) {
|
||||
rxs->flag |= RX_FLAG_DECRYPTED;
|
||||
} else if (ieee80211_has_protected(fc)
|
||||
&& !decrypt_error && skb->len >= hdrlen + 4) {
|
||||
keyix = skb->data[hdrlen + 3] >> 6;
|
||||
|
||||
if (test_bit(keyix, common->keymap))
|
||||
rxs->flag |= RX_FLAG_DECRYPTED;
|
||||
}
|
||||
if (ah->sw_mgmt_crypto &&
|
||||
(rxs->flag & RX_FLAG_DECRYPTED) &&
|
||||
ieee80211_is_mgmt(fc))
|
||||
/* Use software decrypt for management frames. */
|
||||
rxs->flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
|
||||
|
||||
int ath9k_cmn_padpos(__le16 frame_control)
|
||||
{
|
||||
int padpos = 24;
|
||||
|
@ -475,10 +211,14 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int ath_reserve_key_cache_slot(struct ath_common *common)
|
||||
static int ath_reserve_key_cache_slot(struct ath_common *common,
|
||||
enum ieee80211_key_alg alg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (alg == ALG_TKIP)
|
||||
return ath_reserve_key_cache_slot_tkip(common);
|
||||
|
||||
/* First, try to find slots that would not be available for TKIP. */
|
||||
if (common->splitmic) {
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
|
||||
|
@ -547,6 +287,7 @@ int ath9k_cmn_key_config(struct ath_common *common,
|
|||
struct ath_hw *ah = common->ah;
|
||||
struct ath9k_keyval hk;
|
||||
const u8 *mac = NULL;
|
||||
u8 gmac[ETH_ALEN];
|
||||
int ret = 0;
|
||||
int idx;
|
||||
|
||||
|
@ -570,9 +311,23 @@ int ath9k_cmn_key_config(struct ath_common *common,
|
|||
memcpy(hk.kv_val, key->key, key->keylen);
|
||||
|
||||
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
/* For now, use the default keys for broadcast keys. This may
|
||||
* need to change with virtual interfaces. */
|
||||
idx = key->keyidx;
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
memcpy(gmac, vif->addr, ETH_ALEN);
|
||||
gmac[0] |= 0x01;
|
||||
mac = gmac;
|
||||
idx = ath_reserve_key_cache_slot(common, key->alg);
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
memcpy(gmac, sta->addr, ETH_ALEN);
|
||||
gmac[0] |= 0x01;
|
||||
mac = gmac;
|
||||
idx = ath_reserve_key_cache_slot(common, key->alg);
|
||||
break;
|
||||
default:
|
||||
idx = key->keyidx;
|
||||
break;
|
||||
}
|
||||
} else if (key->keyidx) {
|
||||
if (WARN_ON(!sta))
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -589,14 +344,12 @@ int ath9k_cmn_key_config(struct ath_common *common,
|
|||
return -EOPNOTSUPP;
|
||||
mac = sta->addr;
|
||||
|
||||
if (key->alg == ALG_TKIP)
|
||||
idx = ath_reserve_key_cache_slot_tkip(common);
|
||||
else
|
||||
idx = ath_reserve_key_cache_slot(common);
|
||||
if (idx < 0)
|
||||
return -ENOSPC; /* no free key cache entries */
|
||||
idx = ath_reserve_key_cache_slot(common, key->alg);
|
||||
}
|
||||
|
||||
if (idx < 0)
|
||||
return -ENOSPC; /* no free key cache entries */
|
||||
|
||||
if (key->alg == ALG_TKIP)
|
||||
ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
|
||||
vif->type == NL80211_IFTYPE_AP);
|
||||
|
@ -644,6 +397,19 @@ void ath9k_cmn_key_delete(struct ath_common *common,
|
|||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_key_delete);
|
||||
|
||||
int ath9k_cmn_count_streams(unsigned int chainmask, int max)
|
||||
{
|
||||
int streams = 0;
|
||||
|
||||
do {
|
||||
if (++streams == max)
|
||||
break;
|
||||
} while ((chainmask = chainmask & (chainmask - 1)));
|
||||
|
||||
return streams;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_count_streams);
|
||||
|
||||
static int __init ath9k_cmn_init(void)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -52,82 +52,6 @@
|
|||
#define ATH_EP_RND(x, mul) \
|
||||
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
|
||||
|
||||
struct ath_atx_ac {
|
||||
int sched;
|
||||
int qnum;
|
||||
struct list_head list;
|
||||
struct list_head tid_q;
|
||||
};
|
||||
|
||||
struct ath_buf_state {
|
||||
int bfs_nframes;
|
||||
u16 bfs_al;
|
||||
u16 bfs_frmlen;
|
||||
int bfs_seqno;
|
||||
int bfs_tidno;
|
||||
int bfs_retries;
|
||||
u8 bf_type;
|
||||
u32 bfs_keyix;
|
||||
enum ath9k_key_type bfs_keytype;
|
||||
};
|
||||
|
||||
struct ath_buf {
|
||||
struct list_head list;
|
||||
struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or
|
||||
an aggregate) */
|
||||
struct ath_buf *bf_next; /* next subframe in the aggregate */
|
||||
struct sk_buff *bf_mpdu; /* enclosing frame structure */
|
||||
void *bf_desc; /* virtual addr of desc */
|
||||
dma_addr_t bf_daddr; /* physical addr of desc */
|
||||
dma_addr_t bf_buf_addr; /* physical addr of data buffer */
|
||||
bool bf_stale;
|
||||
bool bf_isnullfunc;
|
||||
bool bf_tx_aborted;
|
||||
u16 bf_flags;
|
||||
struct ath_buf_state bf_state;
|
||||
dma_addr_t bf_dmacontext;
|
||||
struct ath_wiphy *aphy;
|
||||
};
|
||||
|
||||
struct ath_atx_tid {
|
||||
struct list_head list;
|
||||
struct list_head buf_q;
|
||||
struct ath_node *an;
|
||||
struct ath_atx_ac *ac;
|
||||
struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
|
||||
u16 seq_start;
|
||||
u16 seq_next;
|
||||
u16 baw_size;
|
||||
int tidno;
|
||||
int baw_head; /* first un-acked tx buffer */
|
||||
int baw_tail; /* next unused tx buffer slot */
|
||||
int sched;
|
||||
int paused;
|
||||
u8 state;
|
||||
};
|
||||
|
||||
struct ath_node {
|
||||
struct ath_common *common;
|
||||
struct ath_atx_tid tid[WME_NUM_TID];
|
||||
struct ath_atx_ac ac[WME_NUM_AC];
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
int last_rssi;
|
||||
};
|
||||
|
||||
int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
bool *decrypt_error);
|
||||
|
||||
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
bool decrypt_error);
|
||||
|
||||
int ath9k_cmn_padpos(__le16 frame_control);
|
||||
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
|
||||
void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
|
||||
|
@ -140,3 +64,4 @@ int ath9k_cmn_key_config(struct ath_common *common,
|
|||
struct ieee80211_key_conf *key);
|
||||
void ath9k_cmn_key_delete(struct ath_common *common,
|
||||
struct ieee80211_key_conf *key);
|
||||
int ath9k_cmn_count_streams(unsigned int chainmask, int max);
|
||||
|
|
|
@ -42,7 +42,7 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf,
|
|||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", common->debug_mask);
|
||||
len = sprintf(buf, "0x%08x\n", common->debug_mask);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
|
|||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, &mask))
|
||||
|
@ -86,7 +86,7 @@ static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf,
|
|||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", common->tx_chainmask);
|
||||
len = sprintf(buf, "0x%08x\n", common->tx_chainmask);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use
|
|||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, &mask))
|
||||
|
@ -128,7 +128,7 @@ static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
|
|||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", common->rx_chainmask);
|
||||
len = sprintf(buf, "0x%08x\n", common->rx_chainmask);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use
|
|||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, &mask))
|
||||
|
@ -176,7 +176,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
|
|||
|
||||
buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
|
@ -248,6 +248,9 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
|
|||
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
if (len > DMA_BUF_LEN)
|
||||
len = DMA_BUF_LEN;
|
||||
|
||||
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
kfree(buf);
|
||||
return retval;
|
||||
|
@ -269,6 +272,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
|
|||
sc->debug.stats.istats.rxlp++;
|
||||
if (status & ATH9K_INT_RXHP)
|
||||
sc->debug.stats.istats.rxhp++;
|
||||
if (status & ATH9K_INT_BB_WATCHDOG)
|
||||
sc->debug.stats.istats.bb_watchdog++;
|
||||
} else {
|
||||
if (status & ATH9K_INT_RX)
|
||||
sc->debug.stats.istats.rxok++;
|
||||
|
@ -319,6 +324,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
|
|||
"%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%8s: %10u\n", "WATCHDOG",
|
||||
sc->debug.stats.istats.bb_watchdog);
|
||||
} else {
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
|
||||
|
@ -358,6 +366,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
|
|||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total);
|
||||
|
||||
if (len > sizeof(buf))
|
||||
len = sizeof(buf);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -397,11 +408,10 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
|
|||
if (sc->cur_rate_table == NULL)
|
||||
return 0;
|
||||
|
||||
max = 80 + sc->cur_rate_table->rate_cnt * 1024;
|
||||
buf = kmalloc(max + 1, GFP_KERNEL);
|
||||
max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1;
|
||||
buf = kmalloc(max, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
buf[max] = 0;
|
||||
return -ENOMEM;
|
||||
|
||||
len += sprintf(buf, "%6s %6s %6s "
|
||||
"%10s %10s %10s %10s\n",
|
||||
|
@ -443,6 +453,9 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
|
|||
stats->per);
|
||||
}
|
||||
|
||||
if (len > max)
|
||||
len = max;
|
||||
|
||||
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
kfree(buf);
|
||||
return retval;
|
||||
|
@ -505,6 +518,9 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
|
|||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"addrmask: %pM\n", addr);
|
||||
|
||||
if (len > sizeof(buf))
|
||||
len = sizeof(buf);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -630,7 +646,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
|||
|
||||
buf = kzalloc(size, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
|
||||
len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
|
||||
|
||||
|
@ -648,6 +664,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
|||
PR("DATA Underrun: ", data_underrun);
|
||||
PR("DELIM Underrun: ", delim_underrun);
|
||||
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
||||
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
kfree(buf);
|
||||
|
||||
|
@ -700,7 +719,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
|||
|
||||
buf = kzalloc(size, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%18s : %10u\n", "CRC ERR",
|
||||
|
@ -751,6 +770,9 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
|||
PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
|
||||
PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
|
||||
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
||||
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
kfree(buf);
|
||||
|
||||
|
@ -802,7 +824,7 @@ static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
|
|||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.regidx);
|
||||
len = sprintf(buf, "0x%08x\n", sc->debug.regidx);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -816,7 +838,7 @@ static ssize_t write_file_regidx(struct file *file, const char __user *user_buf,
|
|||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, ®idx))
|
||||
|
@ -843,7 +865,7 @@ static ssize_t read_file_regval(struct file *file, char __user *user_buf,
|
|||
u32 regval;
|
||||
|
||||
regval = REG_READ_D(ah, sc->debug.regidx);
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", regval);
|
||||
len = sprintf(buf, "0x%08x\n", regval);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -858,7 +880,7 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf,
|
|||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, ®val))
|
||||
|
|
|
@ -53,6 +53,7 @@ struct ath_buf;
|
|||
* @cabend: RX End of CAB traffic
|
||||
* @dtimsync: DTIM sync lossage
|
||||
* @dtim: RX Beacon with DTIM
|
||||
* @bb_watchdog: Baseband watchdog
|
||||
*/
|
||||
struct ath_interrupt_stats {
|
||||
u32 total;
|
||||
|
@ -76,6 +77,7 @@ struct ath_interrupt_stats {
|
|||
u32 cabend;
|
||||
u32 dtimsync;
|
||||
u32 dtim;
|
||||
u32 bb_watchdog;
|
||||
};
|
||||
|
||||
struct ath_rc_stats {
|
||||
|
|
|
@ -24,6 +24,14 @@ static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
|
|||
return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
|
||||
}
|
||||
|
||||
void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
|
||||
{
|
||||
REG_WRITE(ah, reg, val);
|
||||
|
||||
if (ah->config.analog_shiftreg)
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
|
||||
u32 shift, u32 val)
|
||||
{
|
||||
|
@ -250,6 +258,27 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
|
|||
return twiceMaxEdgePower;
|
||||
}
|
||||
|
||||
void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
|
||||
switch (ar5416_get_ntxchains(ah->txchainmask)) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
|
||||
break;
|
||||
case 3:
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"Invalid chainmask configuration\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ath9k_hw_eeprom_init(struct ath_hw *ah)
|
||||
{
|
||||
int status;
|
||||
|
|
|
@ -679,6 +679,7 @@ struct eeprom_ops {
|
|||
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
|
||||
};
|
||||
|
||||
void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val);
|
||||
void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
|
||||
u32 shift, u32 val);
|
||||
int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
|
||||
|
@ -704,6 +705,7 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah,
|
|||
u16 numRates, bool isHt40Target);
|
||||
u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
|
||||
bool is2GHz, int num_band_edges);
|
||||
void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah);
|
||||
int ath9k_hw_eeprom_init(struct ath_hw *ah);
|
||||
|
||||
#define ar5416_get_ntxchains(_txchainmask) \
|
||||
|
|
|
@ -249,6 +249,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
|
|||
struct chan_centers centers;
|
||||
#define PD_GAIN_BOUNDARY_DEFAULT 58;
|
||||
|
||||
memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS);
|
||||
ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
||||
|
||||
for (numPiers = 0; numPiers < availPiers; numPiers++) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -617,6 +617,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
|
|||
int16_t minDelta = 0;
|
||||
struct chan_centers centers;
|
||||
|
||||
memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS);
|
||||
ath9k_hw_get_channel_centers(ah, chan, ¢ers);
|
||||
|
||||
for (numPiers = 0; numPiers < availPiers; numPiers++) {
|
||||
|
|
|
@ -16,12 +16,10 @@
|
|||
|
||||
#include "htc.h"
|
||||
|
||||
#define ATH9K_FW_USB_DEV(devid, fw) \
|
||||
{ USB_DEVICE(0x0cf3, devid), .driver_info = (unsigned long) fw }
|
||||
|
||||
static struct usb_device_id ath9k_hif_usb_ids[] = {
|
||||
ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"),
|
||||
ATH9K_FW_USB_DEV(0x1006, "ar9271.fw"),
|
||||
{ USB_DEVICE(0x0cf3, 0x9271) },
|
||||
{ USB_DEVICE(0x0cf3, 0x1006) },
|
||||
{ USB_DEVICE(0x0cf3, 0x7010) },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -756,6 +754,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
|
|||
size_t len = hif_dev->firmware->size;
|
||||
u32 addr = AR9271_FIRMWARE;
|
||||
u8 *buf = kzalloc(4096, GFP_KERNEL);
|
||||
u32 firm_offset;
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
@ -779,32 +778,37 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
|
|||
}
|
||||
kfree(buf);
|
||||
|
||||
if (hif_dev->device_id == 0x7010)
|
||||
firm_offset = AR7010_FIRMWARE_TEXT;
|
||||
else
|
||||
firm_offset = AR9271_FIRMWARE_TEXT;
|
||||
|
||||
/*
|
||||
* Issue FW download complete command to firmware.
|
||||
*/
|
||||
err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0),
|
||||
FIRMWARE_DOWNLOAD_COMP,
|
||||
0x40 | USB_DIR_OUT,
|
||||
AR9271_FIRMWARE_TEXT >> 8, 0, NULL, 0, HZ);
|
||||
firm_offset >> 8, 0, NULL, 0, HZ);
|
||||
if (err)
|
||||
return -EIO;
|
||||
|
||||
dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n",
|
||||
"ar9271.fw", (unsigned long) hif_dev->firmware->size);
|
||||
hif_dev->fw_name, (unsigned long) hif_dev->firmware->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev,
|
||||
const char *fw_name)
|
||||
static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Request firmware */
|
||||
ret = request_firmware(&hif_dev->firmware, fw_name, &hif_dev->udev->dev);
|
||||
ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name,
|
||||
&hif_dev->udev->dev);
|
||||
if (ret) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Firmware - %s not found\n", fw_name);
|
||||
"ath9k_htc: Firmware - %s not found\n", hif_dev->fw_name);
|
||||
goto err_fw_req;
|
||||
}
|
||||
|
||||
|
@ -820,7 +824,8 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev,
|
|||
ret = ath9k_hif_usb_download_fw(hif_dev);
|
||||
if (ret) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Firmware - %s download failed\n", fw_name);
|
||||
"ath9k_htc: Firmware - %s download failed\n",
|
||||
hif_dev->fw_name);
|
||||
goto err_fw_download;
|
||||
}
|
||||
|
||||
|
@ -847,7 +852,6 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
|||
{
|
||||
struct usb_device *udev = interface_to_usbdev(interface);
|
||||
struct hif_device_usb *hif_dev;
|
||||
const char *fw_name = (const char *) id->driver_info;
|
||||
int ret = 0;
|
||||
|
||||
hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL);
|
||||
|
@ -872,7 +876,29 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
|||
goto err_htc_hw_alloc;
|
||||
}
|
||||
|
||||
ret = ath9k_hif_usb_dev_init(hif_dev, fw_name);
|
||||
/* Find out which firmware to load */
|
||||
|
||||
switch(hif_dev->device_id) {
|
||||
case 0x9271:
|
||||
case 0x1006:
|
||||
hif_dev->fw_name = "ar9271.fw";
|
||||
break;
|
||||
case 0x7010:
|
||||
if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
|
||||
hif_dev->fw_name = "ar7010_1_1.fw";
|
||||
else
|
||||
hif_dev->fw_name = "ar7010.fw";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hif_dev->fw_name) {
|
||||
dev_err(&udev->dev, "Can't determine firmware !\n");
|
||||
goto err_htc_hw_alloc;
|
||||
}
|
||||
|
||||
ret = ath9k_hif_usb_dev_init(hif_dev);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto err_hif_init_usb;
|
||||
|
@ -907,12 +933,10 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev)
|
|||
void *buf;
|
||||
int ret;
|
||||
|
||||
buf = kmalloc(4, GFP_KERNEL);
|
||||
buf = kmemdup(&reboot_cmd, 4, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
memcpy(buf, &reboot_cmd, 4);
|
||||
|
||||
ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE),
|
||||
buf, 4, NULL, HZ);
|
||||
if (ret)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#define AR9271_FIRMWARE 0x501000
|
||||
#define AR9271_FIRMWARE_TEXT 0x903000
|
||||
#define AR7010_FIRMWARE_TEXT 0x906000
|
||||
|
||||
#define FIRMWARE_DOWNLOAD 0x30
|
||||
#define FIRMWARE_DOWNLOAD_COMP 0x31
|
||||
|
@ -90,6 +91,7 @@ struct hif_device_usb {
|
|||
struct usb_anchor regout_submitted;
|
||||
struct usb_anchor rx_submitted;
|
||||
struct sk_buff *remain_skb;
|
||||
const char *fw_name;
|
||||
int rx_remain_len;
|
||||
int rx_pkt_len;
|
||||
int rx_transfer_len;
|
||||
|
|
|
@ -257,12 +257,15 @@ struct ath9k_htc_tx_ctl {
|
|||
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
|
||||
#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++)
|
||||
|
||||
#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
|
||||
|
||||
struct ath_tx_stats {
|
||||
u32 buf_queued;
|
||||
u32 buf_completed;
|
||||
u32 skb_queued;
|
||||
u32 skb_completed;
|
||||
u32 skb_dropped;
|
||||
u32 queue_stats[WME_NUM_AC];
|
||||
};
|
||||
|
||||
struct ath_rx_stats {
|
||||
|
@ -286,6 +289,8 @@ struct ath9k_debug {
|
|||
#define TX_STAT_INC(c) do { } while (0)
|
||||
#define RX_STAT_INC(c) do { } while (0)
|
||||
|
||||
#define TX_QSTAT_INC(c) do { } while (0)
|
||||
|
||||
#endif /* CONFIG_ATH9K_HTC_DEBUGFS */
|
||||
|
||||
#define ATH_LED_PIN_DEF 1
|
||||
|
@ -390,13 +395,14 @@ struct ath9k_htc_priv {
|
|||
int led_off_duration;
|
||||
int led_on_cnt;
|
||||
int led_off_cnt;
|
||||
|
||||
int beaconq;
|
||||
int cabq;
|
||||
int hwq_map[ATH9K_WME_AC_VO+1];
|
||||
|
||||
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
|
||||
struct ath9k_debug debug;
|
||||
#endif
|
||||
struct ath9k_htc_target_rate tgt_rate;
|
||||
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
|
@ -405,6 +411,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
|
|||
common->bus_ops->read_cachesize(common, csz);
|
||||
}
|
||||
|
||||
void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
|
||||
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending);
|
||||
|
@ -426,6 +433,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb);
|
|||
void ath9k_tx_cleanup(struct ath9k_htc_priv *priv);
|
||||
bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv,
|
||||
enum ath9k_tx_queue_subtype qtype);
|
||||
int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv);
|
||||
int get_hw_qnum(u16 queue, int *hwq_map);
|
||||
int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum,
|
||||
struct ath9k_tx_queue_info *qinfo);
|
||||
|
|
|
@ -222,6 +222,29 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
|
|||
spin_unlock_bh(&priv->beacon_lock);
|
||||
}
|
||||
|
||||
/* Currently, only for IBSS */
|
||||
void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
struct ath_hw *ah = priv->ah;
|
||||
struct ath9k_tx_queue_info qi, qi_be;
|
||||
int qnum = priv->hwq_map[ATH9K_WME_AC_BE];
|
||||
|
||||
memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
|
||||
memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info));
|
||||
|
||||
ath9k_hw_get_txq_props(ah, qnum, &qi_be);
|
||||
|
||||
qi.tqi_aifs = qi_be.tqi_aifs;
|
||||
qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
|
||||
qi.tqi_cwmax = qi_be.tqi_cwmax;
|
||||
|
||||
if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
|
||||
"Unable to update beacon queue %u!\n", qnum);
|
||||
} else {
|
||||
ath9k_hw_resettxqueue(ah, priv->beaconq);
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
|
|
|
@ -34,6 +34,13 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
|
|||
.max_power = 20, \
|
||||
}
|
||||
|
||||
#define CHAN5G(_freq, _idx) { \
|
||||
.band = IEEE80211_BAND_5GHZ, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_idx), \
|
||||
.max_power = 20, \
|
||||
}
|
||||
|
||||
static struct ieee80211_channel ath9k_2ghz_channels[] = {
|
||||
CHAN2G(2412, 0), /* Channel 1 */
|
||||
CHAN2G(2417, 1), /* Channel 2 */
|
||||
|
@ -51,6 +58,37 @@ static struct ieee80211_channel ath9k_2ghz_channels[] = {
|
|||
CHAN2G(2484, 13), /* Channel 14 */
|
||||
};
|
||||
|
||||
static struct ieee80211_channel ath9k_5ghz_channels[] = {
|
||||
/* _We_ call this UNII 1 */
|
||||
CHAN5G(5180, 14), /* Channel 36 */
|
||||
CHAN5G(5200, 15), /* Channel 40 */
|
||||
CHAN5G(5220, 16), /* Channel 44 */
|
||||
CHAN5G(5240, 17), /* Channel 48 */
|
||||
/* _We_ call this UNII 2 */
|
||||
CHAN5G(5260, 18), /* Channel 52 */
|
||||
CHAN5G(5280, 19), /* Channel 56 */
|
||||
CHAN5G(5300, 20), /* Channel 60 */
|
||||
CHAN5G(5320, 21), /* Channel 64 */
|
||||
/* _We_ call this "Middle band" */
|
||||
CHAN5G(5500, 22), /* Channel 100 */
|
||||
CHAN5G(5520, 23), /* Channel 104 */
|
||||
CHAN5G(5540, 24), /* Channel 108 */
|
||||
CHAN5G(5560, 25), /* Channel 112 */
|
||||
CHAN5G(5580, 26), /* Channel 116 */
|
||||
CHAN5G(5600, 27), /* Channel 120 */
|
||||
CHAN5G(5620, 28), /* Channel 124 */
|
||||
CHAN5G(5640, 29), /* Channel 128 */
|
||||
CHAN5G(5660, 30), /* Channel 132 */
|
||||
CHAN5G(5680, 31), /* Channel 136 */
|
||||
CHAN5G(5700, 32), /* Channel 140 */
|
||||
/* _We_ call this UNII 3 */
|
||||
CHAN5G(5745, 33), /* Channel 149 */
|
||||
CHAN5G(5765, 34), /* Channel 153 */
|
||||
CHAN5G(5785, 35), /* Channel 157 */
|
||||
CHAN5G(5805, 36), /* Channel 161 */
|
||||
CHAN5G(5825, 37), /* Channel 165 */
|
||||
};
|
||||
|
||||
/* Atheros hardware rate code addition for short premble */
|
||||
#define SHPCHECK(__hw_rate, __flags) \
|
||||
((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0)
|
||||
|
@ -141,7 +179,7 @@ static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
|
|||
return htc_connect_service(priv->htc, &req, ep_id);
|
||||
}
|
||||
|
||||
static int ath9k_init_htc_services(struct ath9k_htc_priv *priv)
|
||||
static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -199,10 +237,33 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Setup required credits before initializing HTC.
|
||||
* This is a bit hacky, but, since queuing is done in
|
||||
* the HIF layer, shouldn't matter much.
|
||||
*/
|
||||
|
||||
switch(devid) {
|
||||
case 0x9271:
|
||||
case 0x1006:
|
||||
priv->htc->credits = 33;
|
||||
break;
|
||||
case 0x7010:
|
||||
priv->htc->credits = 45;
|
||||
break;
|
||||
default:
|
||||
dev_err(priv->dev, "ath9k_htc: Unsupported device id: 0x%x\n",
|
||||
devid);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = htc_init(priv->htc);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
|
||||
priv->htc->credits);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
@ -398,17 +459,43 @@ static const struct ath_bus_ops ath9k_usb_bus_ops = {
|
|||
static void setup_ht_cap(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *ht_info)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
u8 tx_streams, rx_streams;
|
||||
int i;
|
||||
|
||||
ht_info->ht_supported = true;
|
||||
ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|
||||
IEEE80211_HT_CAP_SM_PS |
|
||||
IEEE80211_HT_CAP_SGI_40 |
|
||||
IEEE80211_HT_CAP_DSSSCCK40;
|
||||
|
||||
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
|
||||
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
|
||||
|
||||
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
|
||||
|
||||
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
|
||||
ht_info->mcs.rx_mask[0] = 0xff;
|
||||
|
||||
/* ath9k_htc supports only 1 or 2 stream devices */
|
||||
tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
|
||||
rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"TX streams %d, RX streams: %d\n",
|
||||
tx_streams, rx_streams);
|
||||
|
||||
if (tx_streams != rx_streams) {
|
||||
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
|
||||
ht_info->mcs.tx_params |= ((tx_streams - 1) <<
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
|
||||
}
|
||||
|
||||
for (i = 0; i < rx_streams; i++)
|
||||
ht_info->mcs.rx_mask[i] = 0xff;
|
||||
|
||||
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
|
||||
}
|
||||
|
||||
|
@ -420,6 +507,20 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv)
|
|||
for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
|
||||
priv->hwq_map[i] = -1;
|
||||
|
||||
priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
|
||||
if (priv->beaconq == -1) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup BEACON xmit queue\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
priv->cabq = ath9k_htc_cabq_setup(priv);
|
||||
if (priv->cabq == -1) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup CAB xmit queue\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BE)) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for BE traffic\n");
|
||||
|
@ -512,6 +613,17 @@ static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
|
|||
priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
|
||||
ARRAY_SIZE(ath9k_legacy_rates);
|
||||
}
|
||||
|
||||
if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) {
|
||||
priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
|
||||
priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
|
||||
priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
|
||||
ARRAY_SIZE(ath9k_5ghz_channels);
|
||||
priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
|
||||
ath9k_legacy_rates + 4;
|
||||
priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
|
||||
ARRAY_SIZE(ath9k_legacy_rates) - 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_init_misc(struct ath9k_htc_priv *priv)
|
||||
|
@ -643,11 +755,17 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
|||
if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
|
||||
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
|
||||
&priv->sbands[IEEE80211_BAND_2GHZ];
|
||||
if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
|
||||
hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
|
||||
&priv->sbands[IEEE80211_BAND_5GHZ];
|
||||
|
||||
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
|
||||
setup_ht_cap(priv,
|
||||
&priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
|
||||
if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
|
||||
setup_ht_cap(priv,
|
||||
&priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
|
||||
}
|
||||
|
||||
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
|
||||
|
@ -747,7 +865,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
ret = ath9k_init_htc_services(priv);
|
||||
ret = ath9k_init_htc_services(priv, devid);
|
||||
if (ret)
|
||||
goto err_init;
|
||||
|
||||
|
@ -790,7 +908,8 @@ int ath9k_htc_resume(struct htc_target *htc_handle)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath9k_init_htc_services(htc_handle->drv_priv);
|
||||
ret = ath9k_init_htc_services(htc_handle->drv_priv,
|
||||
htc_handle->drv_priv->ah->hw_version.devid);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -325,133 +325,122 @@ static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv)
|
|||
tcap.flags_ext = 0x80601000;
|
||||
tcap.ampdu_limit = 0xffff0000;
|
||||
tcap.ampdu_subframes = 20;
|
||||
tcap.tx_chainmask_legacy = 1;
|
||||
tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask;
|
||||
tcap.protmode = 1;
|
||||
tcap.tx_chainmask = 1;
|
||||
tcap.tx_chainmask = priv->ah->caps.tx_chainmask;
|
||||
|
||||
WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ath9k_htc_target_rate *trate)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ath9k_htc_target_rate trate;
|
||||
u32 caps = 0;
|
||||
u8 cmd_rsp;
|
||||
int i, j, ret;
|
||||
int i, j;
|
||||
|
||||
memset(&trate, 0, sizeof(trate));
|
||||
|
||||
/* Only 2GHz is supported */
|
||||
sband = priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ];
|
||||
sband = priv->hw->wiphy->bands[priv->hw->conf.channel->band];
|
||||
|
||||
for (i = 0, j = 0; i < sband->n_bitrates; i++) {
|
||||
if (sta->supp_rates[sband->band] & BIT(i)) {
|
||||
priv->tgt_rate.rates.legacy_rates.rs_rates[j]
|
||||
trate->rates.legacy_rates.rs_rates[j]
|
||||
= (sband->bitrates[i].bitrate * 2) / 10;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
priv->tgt_rate.rates.legacy_rates.rs_nrates = j;
|
||||
trate->rates.legacy_rates.rs_nrates = j;
|
||||
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
for (i = 0, j = 0; i < 77; i++) {
|
||||
if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
|
||||
priv->tgt_rate.rates.ht_rates.rs_rates[j++] = i;
|
||||
trate->rates.ht_rates.rs_rates[j++] = i;
|
||||
if (j == ATH_HTC_RATE_MAX)
|
||||
break;
|
||||
}
|
||||
priv->tgt_rate.rates.ht_rates.rs_nrates = j;
|
||||
trate->rates.ht_rates.rs_nrates = j;
|
||||
|
||||
caps = WLAN_RC_HT_FLAG;
|
||||
if (priv->ah->caps.tx_chainmask != 1 &&
|
||||
ath9k_hw_getcapability(priv->ah, ATH9K_CAP_DS, 0, NULL)) {
|
||||
if (sta->ht_cap.mcs.rx_mask[1])
|
||||
caps |= WLAN_RC_DS_FLAG;
|
||||
}
|
||||
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
|
||||
caps |= WLAN_RC_40_FLAG;
|
||||
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
|
||||
if (conf_is_ht40(&priv->hw->conf) &&
|
||||
(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40))
|
||||
caps |= WLAN_RC_SGI_FLAG;
|
||||
else if (conf_is_ht20(&priv->hw->conf) &&
|
||||
(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20))
|
||||
caps |= WLAN_RC_SGI_FLAG;
|
||||
|
||||
}
|
||||
|
||||
priv->tgt_rate.sta_index = ista->index;
|
||||
priv->tgt_rate.isnew = 1;
|
||||
trate = priv->tgt_rate;
|
||||
priv->tgt_rate.capflags = cpu_to_be32(caps);
|
||||
trate.capflags = cpu_to_be32(caps);
|
||||
trate->sta_index = ista->index;
|
||||
trate->isnew = 1;
|
||||
trate->capflags = cpu_to_be32(caps);
|
||||
}
|
||||
|
||||
WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);
|
||||
static int ath9k_htc_send_rate_cmd(struct ath9k_htc_priv *priv,
|
||||
struct ath9k_htc_target_rate *trate)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
int ret;
|
||||
u8 cmd_rsp;
|
||||
|
||||
WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate);
|
||||
if (ret) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to initialize Rate information on target\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"Updated target STA: %pM (caps: 0x%x)\n", sta->addr, caps);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool check_rc_update(struct ieee80211_hw *hw, bool *cw40)
|
||||
static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
|
||||
if (!conf_is_ht(conf))
|
||||
return false;
|
||||
|
||||
if (!(priv->op_flags & OP_ASSOCIATED) ||
|
||||
(priv->op_flags & OP_SCANNING))
|
||||
return false;
|
||||
|
||||
if (conf_is_ht40(conf)) {
|
||||
if (priv->ah->curchan->chanmode &
|
||||
(CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)) {
|
||||
return false;
|
||||
} else {
|
||||
*cw40 = true;
|
||||
return true;
|
||||
}
|
||||
} else { /* ht20 */
|
||||
if (priv->ah->curchan->chanmode & CHANNEL_HT20)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40)
|
||||
{
|
||||
struct ath9k_htc_target_rate trate;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_target_rate trate;
|
||||
int ret;
|
||||
u32 caps = be32_to_cpu(priv->tgt_rate.capflags);
|
||||
u8 cmd_rsp;
|
||||
|
||||
memset(&trate, 0, sizeof(trate));
|
||||
memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
|
||||
ath9k_htc_setup_rate(priv, sta, &trate);
|
||||
ret = ath9k_htc_send_rate_cmd(priv, &trate);
|
||||
if (!ret)
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"Updated target sta: %pM, rate caps: 0x%X\n",
|
||||
sta->addr, be32_to_cpu(trate.capflags));
|
||||
}
|
||||
|
||||
trate = priv->tgt_rate;
|
||||
static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_target_rate trate;
|
||||
struct ieee80211_sta *sta;
|
||||
int ret;
|
||||
|
||||
if (is_cw40)
|
||||
caps |= WLAN_RC_40_FLAG;
|
||||
else
|
||||
caps &= ~WLAN_RC_40_FLAG;
|
||||
memset(&trate, 0, sizeof(struct ath9k_htc_target_rate));
|
||||
|
||||
priv->tgt_rate.capflags = cpu_to_be32(caps);
|
||||
trate.capflags = cpu_to_be32(caps);
|
||||
|
||||
WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);
|
||||
if (ret) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to update Rate information on target\n");
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (!sta) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
ath9k_htc_setup_rate(priv, sta, &trate);
|
||||
rcu_read_unlock();
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG, "Rate control updated with "
|
||||
"caps:0x%x on target\n", priv->tgt_rate.capflags);
|
||||
ret = ath9k_htc_send_rate_cmd(priv, &trate);
|
||||
if (!ret)
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"Updated target sta: %pM, rate caps: 0x%X\n",
|
||||
bss_conf->bssid, be32_to_cpu(trate.capflags));
|
||||
}
|
||||
|
||||
static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv,
|
||||
|
@ -617,6 +606,19 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
|||
"%20s : %10u\n", "SKBs dropped",
|
||||
priv->debug.tx_stats.skb_dropped);
|
||||
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%20s : %10u\n", "BE queued",
|
||||
priv->debug.tx_stats.queue_stats[WME_AC_BE]);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%20s : %10u\n", "BK queued",
|
||||
priv->debug.tx_stats.queue_stats[WME_AC_BK]);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%20s : %10u\n", "VI queued",
|
||||
priv->debug.tx_stats.queue_stats[WME_AC_VI]);
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"%20s : %10u\n", "VO queued",
|
||||
priv->debug.tx_stats.queue_stats[WME_AC_VO]);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
|
@ -1054,6 +1056,95 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
|
|||
wiphy_rfkill_start_polling(priv->hw->wiphy);
|
||||
}
|
||||
|
||||
static void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int ret;
|
||||
u8 cmd_rsp;
|
||||
|
||||
if (!ah->curchan)
|
||||
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
|
||||
|
||||
/* Reset the HW */
|
||||
ret = ath9k_hw_reset(ah, ah->curchan, false);
|
||||
if (ret) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d "
|
||||
"(freq %u MHz)\n", ret, ah->curchan->channel);
|
||||
}
|
||||
|
||||
ath_update_txpow(priv);
|
||||
|
||||
/* Start RX */
|
||||
WMI_CMD(WMI_START_RECV_CMDID);
|
||||
ath9k_host_rx_init(priv);
|
||||
|
||||
/* Start TX */
|
||||
htc_start(priv->htc);
|
||||
spin_lock_bh(&priv->tx_lock);
|
||||
priv->tx_queues_stop = false;
|
||||
spin_unlock_bh(&priv->tx_lock);
|
||||
ieee80211_wake_queues(hw);
|
||||
|
||||
WMI_CMD(WMI_ENABLE_INTR_CMDID);
|
||||
|
||||
/* Enable LED */
|
||||
ath9k_hw_cfg_output(ah, ah->led_pin,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
||||
}
|
||||
|
||||
static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int ret;
|
||||
u8 cmd_rsp;
|
||||
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
|
||||
/* Disable LED */
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||
|
||||
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||
|
||||
/* Stop TX */
|
||||
ieee80211_stop_queues(hw);
|
||||
htc_stop(priv->htc);
|
||||
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
||||
skb_queue_purge(&priv->tx_queue);
|
||||
|
||||
/* Stop RX */
|
||||
WMI_CMD(WMI_STOP_RECV_CMDID);
|
||||
|
||||
/*
|
||||
* The MIB counters have to be disabled here,
|
||||
* since the target doesn't do it.
|
||||
*/
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
|
||||
if (!ah->curchan)
|
||||
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
|
||||
|
||||
/* Reset the HW */
|
||||
ret = ath9k_hw_reset(ah, ah->curchan, false);
|
||||
if (ret) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d "
|
||||
"(freq %u MHz)\n", ret, ah->curchan->channel);
|
||||
}
|
||||
|
||||
/* Disable the PHY */
|
||||
ath9k_hw_phy_disable(ah);
|
||||
|
||||
ath9k_htc_ps_restore(priv);
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* mac80211 Callbacks */
|
||||
/**********************/
|
||||
|
@ -1099,7 +1190,7 @@ fail_tx:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led)
|
||||
static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
|
@ -1111,10 +1202,16 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led)
|
|||
__be16 htc_mode;
|
||||
u8 cmd_rsp;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"Starting driver with initial channel: %d MHz\n",
|
||||
curchan->center_freq);
|
||||
|
||||
/* Ensure that HW is awake before flushing RX */
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
|
||||
WMI_CMD(WMI_FLUSH_RECV_CMDID);
|
||||
|
||||
/* setup initial channel */
|
||||
init_channel = ath9k_cmn_get_curchannel(hw, ah);
|
||||
|
||||
|
@ -1127,6 +1224,7 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led)
|
|||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d "
|
||||
"(freq %u MHz)\n", ret, curchan->center_freq);
|
||||
mutex_unlock(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1147,31 +1245,14 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led)
|
|||
priv->tx_queues_stop = false;
|
||||
spin_unlock_bh(&priv->tx_lock);
|
||||
|
||||
if (led) {
|
||||
/* Enable LED */
|
||||
ath9k_hw_cfg_output(ah, ah->led_pin,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
||||
}
|
||||
|
||||
ieee80211_wake_queues(hw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ret = ath9k_htc_radio_enable(hw, false);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led)
|
||||
static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
|
@ -1179,17 +1260,14 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led)
|
|||
int ret = 0;
|
||||
u8 cmd_rsp;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (priv->op_flags & OP_INVALID) {
|
||||
ath_print(common, ATH_DBG_ANY, "Device not present\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (led) {
|
||||
/* Disable LED */
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||
}
|
||||
|
||||
/* Cancel all the running timers/work .. */
|
||||
cancel_work_sync(&priv->ps_work);
|
||||
cancel_delayed_work_sync(&priv->ath9k_ani_work);
|
||||
|
@ -1202,12 +1280,6 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led)
|
|||
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
||||
WMI_CMD(WMI_STOP_RECV_CMDID);
|
||||
ath9k_hw_phy_disable(ah);
|
||||
ath9k_hw_disable(ah);
|
||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
|
||||
|
||||
skb_queue_purge(&priv->tx_queue);
|
||||
|
||||
/* Remove monitor interface here */
|
||||
|
@ -1220,21 +1292,18 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led)
|
|||
"Monitor interface removed\n");
|
||||
}
|
||||
|
||||
ath9k_hw_phy_disable(ah);
|
||||
ath9k_hw_disable(ah);
|
||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
|
||||
|
||||
priv->op_flags |= OP_INVALID;
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
|
||||
}
|
||||
|
||||
static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_radio_disable(hw, false);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
|
||||
static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
@ -1302,6 +1371,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
|||
out:
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1318,6 +1388,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
|
|||
ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
|
||||
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
|
||||
memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
|
||||
|
@ -1328,6 +1399,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
|
|||
ath9k_htc_remove_station(priv, vif, NULL);
|
||||
priv->vif = NULL;
|
||||
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
|
@ -1343,30 +1415,27 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
|||
bool enable_radio = false;
|
||||
bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
|
||||
|
||||
mutex_lock(&priv->htc_pm_lock);
|
||||
if (!idle && priv->ps_idle)
|
||||
enable_radio = true;
|
||||
|
||||
priv->ps_idle = idle;
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
|
||||
if (enable_radio) {
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
|
||||
ath9k_htc_radio_enable(hw, true);
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"not-idle: enabling radio\n");
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
|
||||
ath9k_htc_radio_enable(hw);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
int pos = curchan->hw_value;
|
||||
bool is_cw40 = false;
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
|
||||
curchan->center_freq);
|
||||
|
||||
if (check_rc_update(hw, &is_cw40))
|
||||
ath9k_htc_rc_update(priv, is_cw40);
|
||||
|
||||
ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]);
|
||||
|
||||
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
|
||||
|
@ -1399,14 +1468,21 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
|||
}
|
||||
}
|
||||
|
||||
if (priv->ps_idle) {
|
||||
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||
mutex_lock(&priv->htc_pm_lock);
|
||||
if (!priv->ps_idle) {
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"idle: disabling radio\n");
|
||||
ath9k_htc_radio_disable(hw, true);
|
||||
ath9k_htc_radio_disable(hw);
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1428,8 +1504,8 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
|
|||
u32 rfilt;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
|
||||
changed_flags &= SUPPORTED_FILTERS;
|
||||
*total_flags &= SUPPORTED_FILTERS;
|
||||
|
||||
|
@ -1444,30 +1520,38 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
|
|||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void ath9k_htc_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
static int ath9k_htc_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_ADD:
|
||||
ret = ath9k_htc_add_station(priv, vif, sta);
|
||||
if (!ret)
|
||||
ath9k_htc_init_rate(priv, vif, sta);
|
||||
break;
|
||||
case STA_NOTIFY_REMOVE:
|
||||
ath9k_htc_remove_station(priv, vif, sta);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
ret = ath9k_htc_add_station(priv, vif, sta);
|
||||
if (!ret)
|
||||
ath9k_htc_init_rate(priv, sta);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
ret = ath9k_htc_remove_station(priv, vif, sta);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
|
@ -1482,6 +1566,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
|||
return 0;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
|
||||
memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
|
||||
|
||||
|
@ -1499,9 +1584,16 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
|||
params->cw_max, params->txop);
|
||||
|
||||
ret = ath_htc_txq_update(priv, qnum, &qi);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
|
||||
(qnum == priv->hwq_map[ATH9K_WME_AC_BE]))
|
||||
ath9k_htc_beaconq_config(priv);
|
||||
out:
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
|
@ -1574,7 +1666,6 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
|
|||
ath_start_ani(priv);
|
||||
} else {
|
||||
priv->op_flags &= ~OP_ASSOCIATED;
|
||||
cancel_work_sync(&priv->ps_work);
|
||||
cancel_delayed_work_sync(&priv->ath9k_ani_work);
|
||||
}
|
||||
}
|
||||
|
@ -1631,6 +1722,9 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
|
|||
ath9k_hw_init_global_settings(ah);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_HT)
|
||||
ath9k_htc_update_rate(priv, vif, bss_conf);
|
||||
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
@ -1641,7 +1735,9 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
|
|||
u64 tsf;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
tsf = ath9k_hw_gettsf64(priv->ah);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return tsf;
|
||||
|
@ -1652,7 +1748,9 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
|||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
ath9k_hw_settsf64(priv->ah, tsf);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
|
@ -1660,11 +1758,11 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw)
|
|||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
ath9k_hw_reset_tsf(priv->ah);
|
||||
mutex_unlock(&priv->mutex);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
|
||||
|
@ -1722,8 +1820,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
|
|||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
spin_lock_bh(&priv->beacon_lock);
|
||||
priv->op_flags &= ~OP_SCANNING;
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
|
@ -1731,8 +1829,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
|
|||
if (priv->op_flags & OP_ASSOCIATED)
|
||||
ath9k_htc_beacon_config(priv, priv->vif);
|
||||
ath_start_ani(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
|
@ -1746,8 +1844,10 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw,
|
|||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
priv->ah->coverage_class = coverage_class;
|
||||
ath9k_hw_init_global_settings(priv->ah);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
|
@ -1759,7 +1859,8 @@ struct ieee80211_ops ath9k_htc_ops = {
|
|||
.remove_interface = ath9k_htc_remove_interface,
|
||||
.config = ath9k_htc_config,
|
||||
.configure_filter = ath9k_htc_configure_filter,
|
||||
.sta_notify = ath9k_htc_sta_notify,
|
||||
.sta_add = ath9k_htc_sta_add,
|
||||
.sta_remove = ath9k_htc_sta_remove,
|
||||
.conf_tx = ath9k_htc_conf_tx,
|
||||
.bss_info_changed = ath9k_htc_bss_info_changed,
|
||||
.set_key = ath9k_htc_set_key,
|
||||
|
|
|
@ -20,6 +20,16 @@
|
|||
/* TX */
|
||||
/******/
|
||||
|
||||
#define ATH9K_HTC_INIT_TXQ(subtype) do { \
|
||||
qi.tqi_subtype = subtype; \
|
||||
qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \
|
||||
qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \
|
||||
qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \
|
||||
qi.tqi_physCompBuf = 0; \
|
||||
qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | \
|
||||
TXQ_FLAG_TXDESCINT_ENABLE; \
|
||||
} while (0)
|
||||
|
||||
int get_hw_qnum(u16 queue, int *hwq_map)
|
||||
{
|
||||
switch (queue) {
|
||||
|
@ -71,7 +81,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
|
|||
struct ath9k_htc_vif *avp;
|
||||
struct ath9k_htc_tx_ctl tx_ctl;
|
||||
enum htc_endpoint_id epid;
|
||||
u16 qnum, hw_qnum;
|
||||
u16 qnum;
|
||||
__le16 fc;
|
||||
u8 *tx_fhdr;
|
||||
u8 sta_idx;
|
||||
|
@ -131,20 +141,23 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
|
|||
memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));
|
||||
|
||||
qnum = skb_get_queue_mapping(skb);
|
||||
hw_qnum = get_hw_qnum(qnum, priv->hwq_map);
|
||||
|
||||
switch (hw_qnum) {
|
||||
switch (qnum) {
|
||||
case 0:
|
||||
epid = priv->data_be_ep;
|
||||
break;
|
||||
case 2:
|
||||
epid = priv->data_vi_ep;
|
||||
break;
|
||||
case 3:
|
||||
TX_QSTAT_INC(WME_AC_VO);
|
||||
epid = priv->data_vo_ep;
|
||||
break;
|
||||
case 1:
|
||||
TX_QSTAT_INC(WME_AC_VI);
|
||||
epid = priv->data_vi_ep;
|
||||
break;
|
||||
case 2:
|
||||
TX_QSTAT_INC(WME_AC_BE);
|
||||
epid = priv->data_be_ep;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
TX_QSTAT_INC(WME_AC_BK);
|
||||
epid = priv->data_bk_ep;
|
||||
break;
|
||||
}
|
||||
|
@ -293,13 +306,7 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv,
|
|||
int qnum;
|
||||
|
||||
memset(&qi, 0, sizeof(qi));
|
||||
|
||||
qi.tqi_subtype = subtype;
|
||||
qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
|
||||
qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
|
||||
qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
|
||||
qi.tqi_physCompBuf = 0;
|
||||
qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | TXQ_FLAG_TXDESCINT_ENABLE;
|
||||
ATH9K_HTC_INIT_TXQ(subtype);
|
||||
|
||||
qnum = ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_DATA, &qi);
|
||||
if (qnum == -1)
|
||||
|
@ -317,6 +324,16 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv,
|
|||
return true;
|
||||
}
|
||||
|
||||
int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
struct ath9k_tx_queue_info qi;
|
||||
|
||||
memset(&qi, 0, sizeof(qi));
|
||||
ATH9K_HTC_INIT_TXQ(0);
|
||||
|
||||
return ath9k_hw_setuptxqueue(priv->ah, ATH9K_TX_QUEUE_CAB, &qi);
|
||||
}
|
||||
|
||||
/******/
|
||||
/* RX */
|
||||
/******/
|
||||
|
|
|
@ -89,7 +89,6 @@ static void htc_process_target_rdy(struct htc_target *target,
|
|||
struct htc_endpoint *endpoint;
|
||||
struct htc_ready_msg *htc_ready_msg = (struct htc_ready_msg *) buf;
|
||||
|
||||
target->credits = be16_to_cpu(htc_ready_msg->credits);
|
||||
target->credit_size = be16_to_cpu(htc_ready_msg->credit_size);
|
||||
|
||||
endpoint = &target->endpoint[ENDPOINT0];
|
||||
|
@ -159,7 +158,7 @@ static int htc_config_pipe_credits(struct htc_target *target)
|
|||
|
||||
cp_msg->message_id = cpu_to_be16(HTC_MSG_CONFIG_PIPE_ID);
|
||||
cp_msg->pipe_id = USB_WLAN_TX_PIPE;
|
||||
cp_msg->credits = 28;
|
||||
cp_msg->credits = target->credits;
|
||||
|
||||
target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS;
|
||||
|
||||
|
|
|
@ -391,12 +391,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
|
|||
|
||||
ah->config.rx_intr_mitigation = true;
|
||||
|
||||
/*
|
||||
* Tx IQ Calibration (ah->config.tx_iq_calibration) is only
|
||||
* used by AR9003, but it is showing reliability issues.
|
||||
* It will take a while to fix so this is currently disabled.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We need this for PCI devices only (Cardbus, PCI, miniPCI)
|
||||
* _and_ if on non-uniprocessor systems (Multiprocessor/HT).
|
||||
|
@ -627,6 +621,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
|
|||
ar9003_hw_set_nf_limits(ah);
|
||||
|
||||
ath9k_init_nfcal_hist_buffer(ah);
|
||||
ah->bb_watchdog_timeout_ms = 25;
|
||||
|
||||
common->state = ATH_HW_INITIALIZED;
|
||||
|
||||
|
@ -1303,6 +1298,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
|
||||
|
||||
if (!AR_SREV_9300_20_OR_LATER(ah))
|
||||
ar9002_hw_enable_async_fifo(ah);
|
||||
|
||||
r = ath9k_hw_process_ini(ah, chan);
|
||||
if (r)
|
||||
return r;
|
||||
|
@ -1375,7 +1373,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
ath9k_hw_init_global_settings(ah);
|
||||
|
||||
if (!AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
ar9002_hw_enable_async_fifo(ah);
|
||||
ar9002_hw_update_async_fifo(ah);
|
||||
ar9002_hw_enable_wep_aggregation(ah);
|
||||
}
|
||||
|
||||
|
@ -1426,9 +1424,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
"Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
|
||||
}
|
||||
} else {
|
||||
/* Configure AR9271 target WLAN */
|
||||
if (AR_SREV_9271(ah))
|
||||
REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
|
||||
if (common->bus_ops->ath_bus_type == ATH_USB) {
|
||||
/* Configure AR9271 target WLAN */
|
||||
if (AR_SREV_9271(ah))
|
||||
REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
|
||||
else
|
||||
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
|
||||
}
|
||||
#ifdef __BIG_ENDIAN
|
||||
else
|
||||
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
|
||||
|
@ -1441,6 +1443,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
ath9k_hw_loadnf(ah, curchan);
|
||||
ath9k_hw_start_nfcal(ah);
|
||||
ar9003_hw_bb_watchdog_config(ah);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1489,6 +1492,7 @@ EXPORT_SYMBOL(ath9k_hw_keyreset);
|
|||
bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
|
||||
{
|
||||
u32 macHi, macLo;
|
||||
u32 unicast_flag = AR_KEYTABLE_VALID;
|
||||
|
||||
if (entry >= ah->caps.keycache_size) {
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
|
||||
|
@ -1497,6 +1501,16 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
|
|||
}
|
||||
|
||||
if (mac != NULL) {
|
||||
/*
|
||||
* AR_KEYTABLE_VALID indicates that the address is a unicast
|
||||
* address, which must match the transmitter address for
|
||||
* decrypting frames.
|
||||
* Not setting this bit allows the hardware to use the key
|
||||
* for multicast frame decryption.
|
||||
*/
|
||||
if (mac[0] & 0x01)
|
||||
unicast_flag = 0;
|
||||
|
||||
macHi = (mac[5] << 8) | mac[4];
|
||||
macLo = (mac[3] << 24) |
|
||||
(mac[2] << 16) |
|
||||
|
@ -1509,7 +1523,7 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
|
|||
macLo = macHi = 0;
|
||||
}
|
||||
REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
|
||||
REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
|
||||
REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2165,7 +2179,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
|
||||
}
|
||||
#endif
|
||||
if (AR_SREV_9271(ah))
|
||||
if (AR_SREV_9271(ah) || AR_SREV_9300_20_OR_LATER(ah))
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
|
||||
else
|
||||
pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
|
||||
|
@ -2232,6 +2246,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
|||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
|
||||
|
||||
if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah))
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,6 +199,7 @@ enum ath9k_hw_caps {
|
|||
ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18),
|
||||
ATH9K_HW_CAP_LDPC = BIT(19),
|
||||
ATH9K_HW_CAP_FASTCLOCK = BIT(20),
|
||||
ATH9K_HW_CAP_SGI_20 = BIT(21),
|
||||
};
|
||||
|
||||
enum ath9k_capability_type {
|
||||
|
@ -262,7 +263,6 @@ struct ath9k_ops_config {
|
|||
#define AR_BASE_FREQ_5GHZ 4900
|
||||
#define AR_SPUR_FEEQ_BOUND_HT40 19
|
||||
#define AR_SPUR_FEEQ_BOUND_HT20 10
|
||||
bool tx_iq_calibration; /* Only available for >= AR9003 */
|
||||
int spurmode;
|
||||
u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
|
||||
u8 max_txtrig_level;
|
||||
|
@ -279,6 +279,7 @@ enum ath9k_int {
|
|||
ATH9K_INT_TX = 0x00000040,
|
||||
ATH9K_INT_TXDESC = 0x00000080,
|
||||
ATH9K_INT_TIM_TIMER = 0x00000100,
|
||||
ATH9K_INT_BB_WATCHDOG = 0x00000400,
|
||||
ATH9K_INT_TXURN = 0x00000800,
|
||||
ATH9K_INT_MIB = 0x00001000,
|
||||
ATH9K_INT_RXPHY = 0x00004000,
|
||||
|
@ -459,7 +460,7 @@ struct ath9k_hw_version {
|
|||
#define AR_GENTMR_BIT(_index) (1 << (_index))
|
||||
|
||||
/*
|
||||
* Using de Bruijin sequence to to look up 1's index in a 32 bit number
|
||||
* Using de Bruijin sequence to look up 1's index in a 32 bit number
|
||||
* debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
|
||||
*/
|
||||
#define debruijn32 0x077CB531U
|
||||
|
@ -789,6 +790,9 @@ struct ath_hw {
|
|||
u32 ts_paddr_end;
|
||||
u16 ts_tail;
|
||||
u8 ts_size;
|
||||
|
||||
u32 bb_watchdog_last_status;
|
||||
u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */
|
||||
};
|
||||
|
||||
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
|
||||
|
@ -907,13 +911,17 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
|
|||
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
|
||||
int ar9002_hw_rf_claim(struct ath_hw *ah);
|
||||
void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
|
||||
void ar9002_hw_update_async_fifo(struct ath_hw *ah);
|
||||
void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
|
||||
|
||||
/*
|
||||
* Code specifric to AR9003, we stuff these here to avoid callbacks
|
||||
* Code specific to AR9003, we stuff these here to avoid callbacks
|
||||
* for older families
|
||||
*/
|
||||
void ar9003_hw_set_nf_limits(struct ath_hw *ah);
|
||||
void ar9003_hw_bb_watchdog_config(struct ath_hw *ah);
|
||||
void ar9003_hw_bb_watchdog_read(struct ath_hw *ah);
|
||||
void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah);
|
||||
|
||||
/* Hardware family op attach helpers */
|
||||
void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
|
||||
|
|
|
@ -175,18 +175,6 @@ static const struct ath_ops ath9k_common_ops = {
|
|||
.write = ath9k_iowrite32,
|
||||
};
|
||||
|
||||
static int count_streams(unsigned int chainmask, int max)
|
||||
{
|
||||
int streams = 0;
|
||||
|
||||
do {
|
||||
if (++streams == max)
|
||||
break;
|
||||
} while ((chainmask = chainmask & (chainmask - 1)));
|
||||
|
||||
return streams;
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/* Initialization */
|
||||
/**************************/
|
||||
|
@ -208,6 +196,9 @@ static void setup_ht_cap(struct ath_softc *sc,
|
|||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
|
||||
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
|
||||
|
||||
|
@ -224,8 +215,8 @@ static void setup_ht_cap(struct ath_softc *sc,
|
|||
|
||||
/* set up supported mcs set */
|
||||
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
|
||||
tx_streams = count_streams(common->tx_chainmask, max_streams);
|
||||
rx_streams = count_streams(common->rx_chainmask, max_streams);
|
||||
tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
|
||||
rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"TX streams %d, RX streams: %d\n",
|
||||
|
|
|
@ -520,6 +520,12 @@ irqreturn_t ath_isr(int irq, void *dev)
|
|||
!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
|
||||
goto chip_reset;
|
||||
|
||||
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
|
||||
(status & ATH9K_INT_BB_WATCHDOG)) {
|
||||
ar9003_hw_bb_watchdog_dbg_info(ah);
|
||||
goto chip_reset;
|
||||
}
|
||||
|
||||
if (status & ATH9K_INT_SWBA)
|
||||
tasklet_schedule(&sc->bcon_tasklet);
|
||||
|
||||
|
@ -615,234 +621,6 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
|
|||
return chanmode;
|
||||
}
|
||||
|
||||
static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
|
||||
struct ath9k_keyval *hk, const u8 *addr,
|
||||
bool authenticator)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
const u8 *key_rxmic;
|
||||
const u8 *key_txmic;
|
||||
|
||||
key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
|
||||
key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
|
||||
|
||||
if (addr == NULL) {
|
||||
/*
|
||||
* Group key installation - only two key cache entries are used
|
||||
* regardless of splitmic capability since group key is only
|
||||
* used either for TX or RX.
|
||||
*/
|
||||
if (authenticator) {
|
||||
memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
|
||||
memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
|
||||
} else {
|
||||
memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
|
||||
memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
|
||||
}
|
||||
return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
|
||||
}
|
||||
if (!common->splitmic) {
|
||||
/* TX and RX keys share the same key cache entry. */
|
||||
memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
|
||||
memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
|
||||
return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
|
||||
}
|
||||
|
||||
/* Separate key cache entries for TX and RX */
|
||||
|
||||
/* TX key goes at first index, RX key at +32. */
|
||||
memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
|
||||
if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) {
|
||||
/* TX MIC entry failed. No need to proceed further */
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Setting TX MIC Key Failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
|
||||
/* XXX delete tx key on failure? */
|
||||
return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr);
|
||||
}
|
||||
|
||||
static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
|
||||
if (test_bit(i, common->keymap) ||
|
||||
test_bit(i + 64, common->keymap))
|
||||
continue; /* At least one part of TKIP key allocated */
|
||||
if (common->splitmic &&
|
||||
(test_bit(i + 32, common->keymap) ||
|
||||
test_bit(i + 64 + 32, common->keymap)))
|
||||
continue; /* At least one part of TKIP key allocated */
|
||||
|
||||
/* Found a free slot for a TKIP key */
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ath_reserve_key_cache_slot(struct ath_common *common)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* First, try to find slots that would not be available for TKIP. */
|
||||
if (common->splitmic) {
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
|
||||
if (!test_bit(i, common->keymap) &&
|
||||
(test_bit(i + 32, common->keymap) ||
|
||||
test_bit(i + 64, common->keymap) ||
|
||||
test_bit(i + 64 + 32, common->keymap)))
|
||||
return i;
|
||||
if (!test_bit(i + 32, common->keymap) &&
|
||||
(test_bit(i, common->keymap) ||
|
||||
test_bit(i + 64, common->keymap) ||
|
||||
test_bit(i + 64 + 32, common->keymap)))
|
||||
return i + 32;
|
||||
if (!test_bit(i + 64, common->keymap) &&
|
||||
(test_bit(i , common->keymap) ||
|
||||
test_bit(i + 32, common->keymap) ||
|
||||
test_bit(i + 64 + 32, common->keymap)))
|
||||
return i + 64;
|
||||
if (!test_bit(i + 64 + 32, common->keymap) &&
|
||||
(test_bit(i, common->keymap) ||
|
||||
test_bit(i + 32, common->keymap) ||
|
||||
test_bit(i + 64, common->keymap)))
|
||||
return i + 64 + 32;
|
||||
}
|
||||
} else {
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
|
||||
if (!test_bit(i, common->keymap) &&
|
||||
test_bit(i + 64, common->keymap))
|
||||
return i;
|
||||
if (test_bit(i, common->keymap) &&
|
||||
!test_bit(i + 64, common->keymap))
|
||||
return i + 64;
|
||||
}
|
||||
}
|
||||
|
||||
/* No partially used TKIP slots, pick any available slot */
|
||||
for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
|
||||
/* Do not allow slots that could be needed for TKIP group keys
|
||||
* to be used. This limitation could be removed if we know that
|
||||
* TKIP will not be used. */
|
||||
if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
|
||||
continue;
|
||||
if (common->splitmic) {
|
||||
if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
|
||||
continue;
|
||||
if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!test_bit(i, common->keymap))
|
||||
return i; /* Found a free slot for a key */
|
||||
}
|
||||
|
||||
/* No free slot found */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ath_key_config(struct ath_common *common,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ath9k_keyval hk;
|
||||
const u8 *mac = NULL;
|
||||
int ret = 0;
|
||||
int idx;
|
||||
|
||||
memset(&hk, 0, sizeof(hk));
|
||||
|
||||
switch (key->alg) {
|
||||
case ALG_WEP:
|
||||
hk.kv_type = ATH9K_CIPHER_WEP;
|
||||
break;
|
||||
case ALG_TKIP:
|
||||
hk.kv_type = ATH9K_CIPHER_TKIP;
|
||||
break;
|
||||
case ALG_CCMP:
|
||||
hk.kv_type = ATH9K_CIPHER_AES_CCM;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
hk.kv_len = key->keylen;
|
||||
memcpy(hk.kv_val, key->key, key->keylen);
|
||||
|
||||
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
|
||||
/* For now, use the default keys for broadcast keys. This may
|
||||
* need to change with virtual interfaces. */
|
||||
idx = key->keyidx;
|
||||
} else if (key->keyidx) {
|
||||
if (WARN_ON(!sta))
|
||||
return -EOPNOTSUPP;
|
||||
mac = sta->addr;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_AP) {
|
||||
/* Only keyidx 0 should be used with unicast key, but
|
||||
* allow this for client mode for now. */
|
||||
idx = key->keyidx;
|
||||
} else
|
||||
return -EIO;
|
||||
} else {
|
||||
if (WARN_ON(!sta))
|
||||
return -EOPNOTSUPP;
|
||||
mac = sta->addr;
|
||||
|
||||
if (key->alg == ALG_TKIP)
|
||||
idx = ath_reserve_key_cache_slot_tkip(common);
|
||||
else
|
||||
idx = ath_reserve_key_cache_slot(common);
|
||||
if (idx < 0)
|
||||
return -ENOSPC; /* no free key cache entries */
|
||||
}
|
||||
|
||||
if (key->alg == ALG_TKIP)
|
||||
ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
|
||||
vif->type == NL80211_IFTYPE_AP);
|
||||
else
|
||||
ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac);
|
||||
|
||||
if (!ret)
|
||||
return -EIO;
|
||||
|
||||
set_bit(idx, common->keymap);
|
||||
if (key->alg == ALG_TKIP) {
|
||||
set_bit(idx + 64, common->keymap);
|
||||
if (common->splitmic) {
|
||||
set_bit(idx + 32, common->keymap);
|
||||
set_bit(idx + 64 + 32, common->keymap);
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
|
||||
ath9k_hw_keyreset(ah, key->hw_key_idx);
|
||||
if (key->hw_key_idx < IEEE80211_WEP_NKID)
|
||||
return;
|
||||
|
||||
clear_bit(key->hw_key_idx, common->keymap);
|
||||
if (key->alg != ALG_TKIP)
|
||||
return;
|
||||
|
||||
clear_bit(key->hw_key_idx + 64, common->keymap);
|
||||
if (common->splitmic) {
|
||||
ath9k_hw_keyreset(ah, key->hw_key_idx + 32);
|
||||
clear_bit(key->hw_key_idx + 32, common->keymap);
|
||||
clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_bss_assoc_info(struct ath_softc *sc,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
|
@ -1195,7 +973,9 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
|||
ATH9K_INT_GLOBAL;
|
||||
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
ah->imask |= ATH9K_INT_RXHP | ATH9K_INT_RXLP;
|
||||
ah->imask |= ATH9K_INT_RXHP |
|
||||
ATH9K_INT_RXLP |
|
||||
ATH9K_INT_BB_WATCHDOG;
|
||||
else
|
||||
ah->imask |= ATH9K_INT_RX;
|
||||
|
||||
|
@ -1245,6 +1025,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
|
|||
struct ath_tx_control txctl;
|
||||
int padpos, padsize;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
int qnum;
|
||||
|
||||
if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
|
||||
ath_print(common, ATH_DBG_XMIT,
|
||||
|
@ -1274,7 +1055,8 @@ static int ath9k_tx(struct ieee80211_hw *hw,
|
|||
* completed and if needed, also for RX of buffered frames.
|
||||
*/
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_setrxabort(sc->sc_ah, 0);
|
||||
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
ath9k_hw_setrxabort(sc->sc_ah, 0);
|
||||
if (ieee80211_is_pspoll(hdr->frame_control)) {
|
||||
ath_print(common, ATH_DBG_PS,
|
||||
"Sending PS-Poll to pick a buffered frame\n");
|
||||
|
@ -1316,11 +1098,8 @@ static int ath9k_tx(struct ieee80211_hw *hw,
|
|||
memmove(skb->data, skb->data + padsize, padpos);
|
||||
}
|
||||
|
||||
/* Check if a tx queue is available */
|
||||
|
||||
txctl.txq = ath_test_get_txq(sc, skb);
|
||||
if (!txctl.txq)
|
||||
goto exit;
|
||||
qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
|
||||
txctl.txq = &sc->tx.txq[qnum];
|
||||
|
||||
ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
|
||||
|
||||
|
@ -1538,8 +1317,8 @@ void ath9k_enable_ps(struct ath_softc *sc)
|
|||
ah->imask |= ATH9K_INT_TIM_TIMER;
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
}
|
||||
ath9k_hw_setrxabort(ah, 1);
|
||||
}
|
||||
ath9k_hw_setrxabort(ah, 1);
|
||||
}
|
||||
|
||||
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
@ -1804,7 +1583,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
|
|||
|
||||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
ret = ath_key_config(common, vif, sta, key);
|
||||
ret = ath9k_cmn_key_config(common, vif, sta, key);
|
||||
if (ret >= 0) {
|
||||
key->hw_key_idx = ret;
|
||||
/* push IV and Michael MIC generation to stack */
|
||||
|
@ -1817,7 +1596,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
|
|||
}
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
ath_key_delete(common, key);
|
||||
ath9k_cmn_key_delete(common, key);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "ath9k.h"
|
||||
|
||||
static const struct ath_rate_table ar5416_11na_ratetable = {
|
||||
42,
|
||||
43,
|
||||
8, /* MCS start */
|
||||
{
|
||||
{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
|
||||
|
@ -40,73 +40,75 @@ static const struct ath_rate_table ar5416_11na_ratetable = {
|
|||
{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
|
||||
29300, 7, 108, 4, 7, 7, 7, 7 },
|
||||
{ VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
|
||||
6400, 0, 0, 0, 8, 24, 8, 24 },
|
||||
6400, 0, 0, 0, 8, 25, 8, 25 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
|
||||
12700, 1, 1, 2, 9, 25, 9, 25 },
|
||||
12700, 1, 1, 2, 9, 26, 9, 26 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
|
||||
18800, 2, 2, 2, 10, 26, 10, 26 },
|
||||
18800, 2, 2, 2, 10, 27, 10, 27 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
|
||||
25000, 3, 3, 4, 11, 27, 11, 27 },
|
||||
25000, 3, 3, 4, 11, 28, 11, 28 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
|
||||
36700, 4, 4, 4, 12, 28, 12, 28 },
|
||||
36700, 4, 4, 4, 12, 29, 12, 29 },
|
||||
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
|
||||
48100, 5, 5, 4, 13, 29, 13, 29 },
|
||||
48100, 5, 5, 4, 13, 30, 13, 30 },
|
||||
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
|
||||
53500, 6, 6, 4, 14, 30, 14, 30 },
|
||||
53500, 6, 6, 4, 14, 31, 14, 31 },
|
||||
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
|
||||
59000, 7, 7, 4, 15, 31, 15, 32 },
|
||||
59000, 7, 7, 4, 15, 32, 15, 33 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
|
||||
12700, 8, 8, 3, 16, 33, 16, 33 },
|
||||
12700, 8, 8, 3, 16, 34, 16, 34 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
|
||||
24800, 9, 9, 2, 17, 34, 17, 34 },
|
||||
24800, 9, 9, 2, 17, 35, 17, 35 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
|
||||
36600, 10, 10, 2, 18, 35, 18, 35 },
|
||||
36600, 10, 10, 2, 18, 36, 18, 36 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
|
||||
48100, 11, 11, 4, 19, 36, 19, 36 },
|
||||
48100, 11, 11, 4, 19, 37, 19, 37 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
|
||||
69500, 12, 12, 4, 20, 37, 20, 37 },
|
||||
69500, 12, 12, 4, 20, 38, 20, 38 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
|
||||
89500, 13, 13, 4, 21, 38, 21, 38 },
|
||||
89500, 13, 13, 4, 21, 39, 21, 39 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
|
||||
98900, 14, 14, 4, 22, 39, 22, 39 },
|
||||
98900, 14, 14, 4, 22, 40, 22, 40 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
|
||||
108300, 15, 15, 4, 23, 40, 23, 41 },
|
||||
108300, 15, 15, 4, 23, 41, 24, 42 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 144.4 Mb */
|
||||
12000, 15, 15, 4, 23, 41, 24, 42 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
|
||||
13200, 0, 0, 0, 8, 24, 24, 24 },
|
||||
13200, 0, 0, 0, 8, 25, 25, 25 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
|
||||
25900, 1, 1, 2, 9, 25, 25, 25 },
|
||||
25900, 1, 1, 2, 9, 26, 26, 26 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
|
||||
38600, 2, 2, 2, 10, 26, 26, 26 },
|
||||
38600, 2, 2, 2, 10, 27, 27, 27 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
|
||||
49800, 3, 3, 4, 11, 27, 27, 27 },
|
||||
49800, 3, 3, 4, 11, 28, 28, 28 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
|
||||
72200, 4, 4, 4, 12, 28, 28, 28 },
|
||||
72200, 4, 4, 4, 12, 29, 29, 29 },
|
||||
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
|
||||
92900, 5, 5, 4, 13, 29, 29, 29 },
|
||||
92900, 5, 5, 4, 13, 30, 30, 30 },
|
||||
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
|
||||
102700, 6, 6, 4, 14, 30, 30, 30 },
|
||||
102700, 6, 6, 4, 14, 31, 31, 31 },
|
||||
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
|
||||
112000, 7, 7, 4, 15, 31, 32, 32 },
|
||||
112000, 7, 7, 4, 15, 32, 33, 33 },
|
||||
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
|
||||
122000, 7, 7, 4, 15, 31, 32, 32 },
|
||||
122000, 7, 7, 4, 15, 32, 33, 33 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
|
||||
25800, 8, 8, 0, 16, 33, 33, 33 },
|
||||
25800, 8, 8, 0, 16, 34, 34, 34 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
|
||||
49800, 9, 9, 2, 17, 34, 34, 34 },
|
||||
49800, 9, 9, 2, 17, 35, 35, 35 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
|
||||
71900, 10, 10, 2, 18, 35, 35, 35 },
|
||||
71900, 10, 10, 2, 18, 36, 36, 36 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
|
||||
92500, 11, 11, 4, 19, 36, 36, 36 },
|
||||
92500, 11, 11, 4, 19, 37, 37, 37 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
|
||||
130300, 12, 12, 4, 20, 37, 37, 37 },
|
||||
130300, 12, 12, 4, 20, 38, 38, 38 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
|
||||
162800, 13, 13, 4, 21, 38, 38, 38 },
|
||||
162800, 13, 13, 4, 21, 39, 39, 39 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
|
||||
178200, 14, 14, 4, 22, 39, 39, 39 },
|
||||
178200, 14, 14, 4, 22, 40, 40, 40 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
|
||||
192100, 15, 15, 4, 23, 40, 41, 41 },
|
||||
192100, 15, 15, 4, 23, 41, 42, 42 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
|
||||
207000, 15, 15, 4, 23, 40, 41, 41 },
|
||||
207000, 15, 15, 4, 23, 41, 42, 42 },
|
||||
},
|
||||
50, /* probe interval */
|
||||
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
|
||||
|
@ -116,7 +118,7 @@ static const struct ath_rate_table ar5416_11na_ratetable = {
|
|||
* for HT are the 64K max aggregate limit */
|
||||
|
||||
static const struct ath_rate_table ar5416_11ng_ratetable = {
|
||||
46,
|
||||
47,
|
||||
12, /* MCS start */
|
||||
{
|
||||
{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
|
||||
|
@ -144,73 +146,75 @@ static const struct ath_rate_table ar5416_11ng_ratetable = {
|
|||
{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
|
||||
30900, 11, 108, 8, 11, 11, 11, 11 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
|
||||
6400, 0, 0, 4, 12, 28, 12, 28 },
|
||||
6400, 0, 0, 4, 12, 29, 12, 29 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
|
||||
12700, 1, 1, 6, 13, 29, 13, 29 },
|
||||
12700, 1, 1, 6, 13, 30, 13, 30 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
|
||||
18800, 2, 2, 6, 14, 30, 14, 30 },
|
||||
18800, 2, 2, 6, 14, 31, 14, 31 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
|
||||
25000, 3, 3, 8, 15, 31, 15, 31 },
|
||||
25000, 3, 3, 8, 15, 32, 15, 32 },
|
||||
{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
|
||||
36700, 4, 4, 8, 16, 32, 16, 32 },
|
||||
36700, 4, 4, 8, 16, 33, 16, 33 },
|
||||
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
|
||||
48100, 5, 5, 8, 17, 33, 17, 33 },
|
||||
48100, 5, 5, 8, 17, 34, 17, 34 },
|
||||
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
|
||||
53500, 6, 6, 8, 18, 34, 18, 34 },
|
||||
53500, 6, 6, 8, 18, 35, 18, 35 },
|
||||
{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
|
||||
59000, 7, 7, 8, 19, 35, 19, 36 },
|
||||
59000, 7, 7, 8, 19, 36, 19, 37 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
|
||||
12700, 8, 8, 4, 20, 37, 20, 37 },
|
||||
12700, 8, 8, 4, 20, 38, 20, 38 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
|
||||
24800, 9, 9, 6, 21, 38, 21, 38 },
|
||||
24800, 9, 9, 6, 21, 39, 21, 39 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
|
||||
36600, 10, 10, 6, 22, 39, 22, 39 },
|
||||
36600, 10, 10, 6, 22, 40, 22, 40 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
|
||||
48100, 11, 11, 8, 23, 40, 23, 40 },
|
||||
48100, 11, 11, 8, 23, 41, 23, 41 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
|
||||
69500, 12, 12, 8, 24, 41, 24, 41 },
|
||||
69500, 12, 12, 8, 24, 42, 24, 42 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
|
||||
89500, 13, 13, 8, 25, 42, 25, 42 },
|
||||
89500, 13, 13, 8, 25, 43, 25, 43 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
|
||||
98900, 14, 14, 8, 26, 43, 26, 44 },
|
||||
98900, 14, 14, 8, 26, 44, 26, 44 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
|
||||
108300, 15, 15, 8, 27, 44, 27, 45 },
|
||||
108300, 15, 15, 8, 27, 45, 28, 46 },
|
||||
{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 130 Mb */
|
||||
120000, 15, 15, 8, 27, 45, 28, 46 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
|
||||
13200, 0, 0, 8, 12, 28, 28, 28 },
|
||||
13200, 0, 0, 8, 12, 29, 29, 29 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
|
||||
25900, 1, 1, 8, 13, 29, 29, 29 },
|
||||
25900, 1, 1, 8, 13, 30, 30, 30 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
|
||||
38600, 2, 2, 8, 14, 30, 30, 30 },
|
||||
38600, 2, 2, 8, 14, 31, 31, 31 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
|
||||
49800, 3, 3, 8, 15, 31, 31, 31 },
|
||||
49800, 3, 3, 8, 15, 32, 32, 32 },
|
||||
{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
|
||||
72200, 4, 4, 8, 16, 32, 32, 32 },
|
||||
72200, 4, 4, 8, 16, 33, 33, 33 },
|
||||
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
|
||||
92900, 5, 5, 8, 17, 33, 33, 33 },
|
||||
92900, 5, 5, 8, 17, 34, 34, 34 },
|
||||
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
|
||||
102700, 6, 6, 8, 18, 34, 34, 34 },
|
||||
102700, 6, 6, 8, 18, 35, 35, 35 },
|
||||
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
|
||||
112000, 7, 7, 8, 19, 35, 36, 36 },
|
||||
112000, 7, 7, 8, 19, 36, 37, 37 },
|
||||
{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
|
||||
122000, 7, 7, 8, 19, 35, 36, 36 },
|
||||
122000, 7, 7, 8, 19, 36, 37, 37 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
|
||||
25800, 8, 8, 8, 20, 37, 37, 37 },
|
||||
25800, 8, 8, 8, 20, 38, 38, 38 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
|
||||
49800, 9, 9, 8, 21, 38, 38, 38 },
|
||||
49800, 9, 9, 8, 21, 39, 39, 39 },
|
||||
{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
|
||||
71900, 10, 10, 8, 22, 39, 39, 39 },
|
||||
71900, 10, 10, 8, 22, 40, 40, 40 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
|
||||
92500, 11, 11, 8, 23, 40, 40, 40 },
|
||||
92500, 11, 11, 8, 23, 41, 41, 41 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
|
||||
130300, 12, 12, 8, 24, 41, 41, 41 },
|
||||
130300, 12, 12, 8, 24, 42, 42, 42 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
|
||||
162800, 13, 13, 8, 25, 42, 42, 42 },
|
||||
162800, 13, 13, 8, 25, 43, 43, 43 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
|
||||
178200, 14, 14, 8, 26, 43, 43, 43 },
|
||||
178200, 14, 14, 8, 26, 44, 44, 44 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
|
||||
192100, 15, 15, 8, 27, 44, 45, 45 },
|
||||
192100, 15, 15, 8, 27, 45, 46, 46 },
|
||||
{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
|
||||
207000, 15, 15, 8, 27, 44, 45, 45 },
|
||||
207000, 15, 15, 8, 27, 45, 46, 46 },
|
||||
},
|
||||
50, /* probe interval */
|
||||
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
|
||||
|
@ -1193,7 +1197,7 @@ static void ath_rc_init(struct ath_softc *sc,
|
|||
}
|
||||
|
||||
static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
|
||||
bool is_cw40, bool is_sgi40)
|
||||
bool is_cw40, bool is_sgi)
|
||||
{
|
||||
u8 caps = 0;
|
||||
|
||||
|
@ -1206,8 +1210,9 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
}
|
||||
if (is_cw40)
|
||||
caps |= WLAN_RC_40_FLAG;
|
||||
if (is_sgi40)
|
||||
if (is_sgi)
|
||||
caps |= WLAN_RC_SGI_FLAG;
|
||||
|
||||
}
|
||||
|
||||
return caps;
|
||||
|
@ -1300,7 +1305,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
|||
struct ath_softc *sc = priv;
|
||||
struct ath_rate_priv *ath_rc_priv = priv_sta;
|
||||
const struct ath_rate_table *rate_table;
|
||||
bool is_cw40, is_sgi40;
|
||||
bool is_cw40, is_sgi = false;
|
||||
int i, j = 0;
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
|
@ -1323,7 +1328,11 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
|||
}
|
||||
|
||||
is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
|
||||
|
||||
if (is_cw40)
|
||||
is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
|
||||
else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
|
||||
is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20;
|
||||
|
||||
/* Choose rate table first */
|
||||
|
||||
|
@ -1336,7 +1345,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
|||
rate_table = hw_rate_table[sc->cur_rate_mode];
|
||||
}
|
||||
|
||||
ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40);
|
||||
ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi);
|
||||
ath_rc_init(sc, priv_sta, sband, sta, rate_table);
|
||||
}
|
||||
|
||||
|
@ -1347,10 +1356,10 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
|
|||
struct ath_softc *sc = priv;
|
||||
struct ath_rate_priv *ath_rc_priv = priv_sta;
|
||||
const struct ath_rate_table *rate_table = NULL;
|
||||
bool oper_cw40 = false, oper_sgi40;
|
||||
bool oper_cw40 = false, oper_sgi;
|
||||
bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
|
||||
true : false;
|
||||
bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
|
||||
bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
|
||||
true : false;
|
||||
|
||||
/* FIXME: Handle AP mode later when we support CWM */
|
||||
|
@ -1363,15 +1372,21 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
|
|||
oper_chan_type == NL80211_CHAN_HT40PLUS)
|
||||
oper_cw40 = true;
|
||||
|
||||
oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
|
||||
true : false;
|
||||
if (oper_cw40)
|
||||
oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
|
||||
true : false;
|
||||
else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
|
||||
oper_sgi = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ?
|
||||
true : false;
|
||||
else
|
||||
oper_sgi = false;
|
||||
|
||||
if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) {
|
||||
if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) {
|
||||
rate_table = ath_choose_rate_table(sc, sband->band,
|
||||
sta->ht_cap.ht_supported,
|
||||
oper_cw40);
|
||||
ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
|
||||
oper_cw40, oper_sgi40);
|
||||
oper_cw40, oper_sgi);
|
||||
ath_rc_init(sc, priv_sta, sband, sta, rate_table);
|
||||
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
|
||||
|
|
|
@ -700,12 +700,16 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
|
|||
bf = SKB_CB_ATHBUF(skb);
|
||||
BUG_ON(!bf);
|
||||
|
||||
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
||||
dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
|
||||
common->rx_bufsize, DMA_FROM_DEVICE);
|
||||
|
||||
ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data);
|
||||
if (ret == -EINPROGRESS)
|
||||
if (ret == -EINPROGRESS) {
|
||||
/*let device gain the buffer again*/
|
||||
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
||||
common->rx_bufsize, DMA_FROM_DEVICE);
|
||||
return false;
|
||||
}
|
||||
|
||||
__skb_unlink(skb, &rx_edma->rx_fifo);
|
||||
if (ret == -EINVAL) {
|
||||
|
@ -814,13 +818,266 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
|
|||
* 1. accessing the frame
|
||||
* 2. requeueing the same buffer to h/w
|
||||
*/
|
||||
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
||||
dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
|
||||
common->rx_bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
/* Assumes you've already done the endian to CPU conversion */
|
||||
static bool ath9k_rx_accept(struct ath_common *common,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
struct ath_rx_status *rx_stats,
|
||||
bool *decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
__le16 fc;
|
||||
u8 rx_status_len = ah->caps.rx_status_len;
|
||||
|
||||
fc = hdr->frame_control;
|
||||
|
||||
if (!rx_stats->rs_datalen)
|
||||
return false;
|
||||
/*
|
||||
* rs_status follows rs_datalen so if rs_datalen is too large
|
||||
* we can take a hint that hardware corrupted it, so ignore
|
||||
* those frames.
|
||||
*/
|
||||
if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* rs_more indicates chained descriptors which can be used
|
||||
* to link buffers together for a sort of scatter-gather
|
||||
* operation.
|
||||
* reject the frame, we don't support scatter-gather yet and
|
||||
* the frame is probably corrupt anyway
|
||||
*/
|
||||
if (rx_stats->rs_more)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* The rx_stats->rs_status will not be set until the end of the
|
||||
* chained descriptors so it can be ignored if rs_more is set. The
|
||||
* rs_more will be false at the last element of the chained
|
||||
* descriptors.
|
||||
*/
|
||||
if (rx_stats->rs_status != 0) {
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_CRC)
|
||||
rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_PHY)
|
||||
return false;
|
||||
|
||||
if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
|
||||
*decrypt_error = true;
|
||||
} else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
|
||||
if (ieee80211_is_ctl(fc))
|
||||
/*
|
||||
* Sometimes, we get invalid
|
||||
* MIC failures on valid control frames.
|
||||
* Remove these mic errors.
|
||||
*/
|
||||
rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
|
||||
else
|
||||
rxs->flag |= RX_FLAG_MMIC_ERROR;
|
||||
}
|
||||
/*
|
||||
* Reject error frames with the exception of
|
||||
* decryption and MIC failures. For monitor mode,
|
||||
* we also ignore the CRC error.
|
||||
*/
|
||||
if (ah->opmode == NL80211_IFTYPE_MONITOR) {
|
||||
if (rx_stats->rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
|
||||
ATH9K_RXERR_CRC))
|
||||
return false;
|
||||
} else {
|
||||
if (rx_stats->rs_status &
|
||||
~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ath9k_process_rate(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum ieee80211_band band;
|
||||
unsigned int i = 0;
|
||||
|
||||
band = hw->conf.channel->band;
|
||||
sband = hw->wiphy->bands[band];
|
||||
|
||||
if (rx_stats->rs_rate & 0x80) {
|
||||
/* HT rate */
|
||||
rxs->flag |= RX_FLAG_HT;
|
||||
if (rx_stats->rs_flags & ATH9K_RX_2040)
|
||||
rxs->flag |= RX_FLAG_40MHZ;
|
||||
if (rx_stats->rs_flags & ATH9K_RX_GI)
|
||||
rxs->flag |= RX_FLAG_SHORT_GI;
|
||||
rxs->rate_idx = rx_stats->rs_rate & 0x7f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
|
||||
rxs->rate_idx = i;
|
||||
return 0;
|
||||
}
|
||||
if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
|
||||
rxs->flag |= RX_FLAG_SHORTPRE;
|
||||
rxs->rate_idx = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No valid hardware bitrate found -- we should not get here
|
||||
* because hardware has already validated this frame as OK.
|
||||
*/
|
||||
ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected "
|
||||
"0x%02x using 1 Mbit\n", rx_stats->rs_rate);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void ath9k_process_rssi(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rx_stats)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath_node *an;
|
||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
__le16 fc;
|
||||
|
||||
fc = hdr->frame_control;
|
||||
|
||||
rcu_read_lock();
|
||||
/*
|
||||
* XXX: use ieee80211_find_sta! This requires quite a bit of work
|
||||
* under the current ath9k virtual wiphy implementation as we have
|
||||
* no way of tying a vif to wiphy. Typically vifs are attached to
|
||||
* at least one sdata of a wiphy on mac80211 but with ath9k virtual
|
||||
* wiphy you'd have to iterate over every wiphy and each sdata.
|
||||
*/
|
||||
sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
|
||||
if (sta) {
|
||||
an = (struct ath_node *) sta->drv_priv;
|
||||
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
|
||||
!rx_stats->rs_moreaggr)
|
||||
ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
|
||||
last_rssi = an->last_rssi;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
|
||||
rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
|
||||
ATH_RSSI_EP_MULTIPLIER);
|
||||
if (rx_stats->rs_rssi < 0)
|
||||
rx_stats->rs_rssi = 0;
|
||||
|
||||
/* Update Beacon RSSI, this is used by ANI. */
|
||||
if (ieee80211_is_beacon(fc))
|
||||
ah->stats.avgbrssi = rx_stats->rs_rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
* For Decrypt or Demic errors, we only mark packet status here and always push
|
||||
* up the frame up to let mac80211 handle the actual error case, be it no
|
||||
* decryption key or real decryption error. This let us keep statistics there.
|
||||
*/
|
||||
static int ath9k_rx_skb_preprocess(struct ath_common *common,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rx_status,
|
||||
bool *decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
|
||||
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
|
||||
|
||||
/*
|
||||
* everything but the rate is checked here, the rate check is done
|
||||
* separately to avoid doing two lookups for a rate for each frame.
|
||||
*/
|
||||
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
|
||||
return -EINVAL;
|
||||
|
||||
ath9k_process_rssi(common, hw, hdr, rx_stats);
|
||||
|
||||
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
|
||||
return -EINVAL;
|
||||
|
||||
rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
|
||||
rx_status->antenna = rx_stats->rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_TSFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_rx_skb_postprocess(struct ath_common *common,
|
||||
struct sk_buff *skb,
|
||||
struct ath_rx_status *rx_stats,
|
||||
struct ieee80211_rx_status *rxs,
|
||||
bool decrypt_error)
|
||||
{
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int hdrlen, padpos, padsize;
|
||||
u8 keyix;
|
||||
__le16 fc;
|
||||
|
||||
/* see if any padding is done by the hw and remove it */
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
fc = hdr->frame_control;
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
|
||||
/* The MAC header is padded to have 32-bit boundary if the
|
||||
* packet payload is non-zero. The general calculation for
|
||||
* padsize would take into account odd header lengths:
|
||||
* padsize = (4 - padpos % 4) % 4; However, since only
|
||||
* even-length headers are used, padding can only be 0 or 2
|
||||
* bytes and we can optimize this a bit. In addition, we must
|
||||
* not try to remove padding from short control frames that do
|
||||
* not have payload. */
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
|
||||
memmove(skb->data + padsize, skb->data, padpos);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
keyix = rx_stats->rs_keyix;
|
||||
|
||||
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
|
||||
ieee80211_has_protected(fc)) {
|
||||
rxs->flag |= RX_FLAG_DECRYPTED;
|
||||
} else if (ieee80211_has_protected(fc)
|
||||
&& !decrypt_error && skb->len >= hdrlen + 4) {
|
||||
keyix = skb->data[hdrlen + 3] >> 6;
|
||||
|
||||
if (test_bit(keyix, common->keymap))
|
||||
rxs->flag |= RX_FLAG_DECRYPTED;
|
||||
}
|
||||
if (ah->sw_mgmt_crypto &&
|
||||
(rxs->flag & RX_FLAG_DECRYPTED) &&
|
||||
ieee80211_is_mgmt(fc))
|
||||
/* Use software decrypt for management frames. */
|
||||
rxs->flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
{
|
||||
|
@ -842,11 +1099,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|||
enum ath9k_rx_qtype qtype;
|
||||
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
|
||||
int dma_type;
|
||||
u8 rx_status_len = ah->caps.rx_status_len;
|
||||
|
||||
if (edma)
|
||||
dma_type = DMA_FROM_DEVICE;
|
||||
else
|
||||
dma_type = DMA_BIDIRECTIONAL;
|
||||
else
|
||||
dma_type = DMA_FROM_DEVICE;
|
||||
|
||||
qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
|
||||
spin_lock_bh(&sc->rx.rxbuflock);
|
||||
|
@ -869,7 +1127,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|||
if (!skb)
|
||||
continue;
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len);
|
||||
rxs = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
hw = ath_get_virt_hw(sc, hdr);
|
||||
|
@ -883,8 +1141,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|||
if (flush)
|
||||
goto requeue;
|
||||
|
||||
retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, &rs,
|
||||
rxs, &decrypt_error);
|
||||
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
|
||||
rxs, &decrypt_error);
|
||||
if (retval)
|
||||
goto requeue;
|
||||
|
||||
|
@ -908,8 +1166,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|||
if (ah->caps.rx_status_len)
|
||||
skb_pull(skb, ah->caps.rx_status_len);
|
||||
|
||||
ath9k_cmn_rx_skb_postprocess(common, skb, &rs,
|
||||
rxs, decrypt_error);
|
||||
ath9k_rx_skb_postprocess(common, skb, &rs,
|
||||
rxs, decrypt_error);
|
||||
|
||||
/* We will now give hardware our shiny new allocated skb */
|
||||
bf->bf_mpdu = requeue_skb;
|
||||
|
|
|
@ -222,6 +222,7 @@
|
|||
|
||||
#define AR_ISR_S2 0x008c
|
||||
#define AR_ISR_S2_QCU_TXURN 0x000003FF
|
||||
#define AR_ISR_S2_BB_WATCHDOG 0x00010000
|
||||
#define AR_ISR_S2_CST 0x00400000
|
||||
#define AR_ISR_S2_GTT 0x00800000
|
||||
#define AR_ISR_S2_TIM 0x01000000
|
||||
|
@ -699,6 +700,9 @@
|
|||
#define AR_RC_HOSTIF 0x00000100
|
||||
|
||||
#define AR_WA 0x4004
|
||||
#define AR_WA_BIT6 (1 << 6)
|
||||
#define AR_WA_BIT7 (1 << 7)
|
||||
#define AR_WA_BIT23 (1 << 23)
|
||||
#define AR_WA_D3_L1_DISABLE (1 << 14)
|
||||
#define AR9285_WA_DEFAULT 0x004a050b
|
||||
#define AR9280_WA_DEFAULT 0x0040073b
|
||||
|
@ -756,32 +760,33 @@
|
|||
#define AR_SREV_REVISION2 0x00000F00
|
||||
#define AR_SREV_REVISION2_S 8
|
||||
|
||||
#define AR_SREV_VERSION_5416_PCI 0xD
|
||||
#define AR_SREV_VERSION_5416_PCIE 0xC
|
||||
#define AR_SREV_REVISION_5416_10 0
|
||||
#define AR_SREV_REVISION_5416_20 1
|
||||
#define AR_SREV_REVISION_5416_22 2
|
||||
#define AR_SREV_VERSION_9100 0x14
|
||||
#define AR_SREV_VERSION_9160 0x40
|
||||
#define AR_SREV_REVISION_9160_10 0
|
||||
#define AR_SREV_REVISION_9160_11 1
|
||||
#define AR_SREV_VERSION_9280 0x80
|
||||
#define AR_SREV_REVISION_9280_10 0
|
||||
#define AR_SREV_REVISION_9280_20 1
|
||||
#define AR_SREV_REVISION_9280_21 2
|
||||
#define AR_SREV_VERSION_9285 0xC0
|
||||
#define AR_SREV_REVISION_9285_10 0
|
||||
#define AR_SREV_REVISION_9285_11 1
|
||||
#define AR_SREV_REVISION_9285_12 2
|
||||
#define AR_SREV_VERSION_9287 0x180
|
||||
#define AR_SREV_REVISION_9287_10 0
|
||||
#define AR_SREV_REVISION_9287_11 1
|
||||
#define AR_SREV_REVISION_9287_12 2
|
||||
#define AR_SREV_VERSION_9271 0x140
|
||||
#define AR_SREV_REVISION_9271_10 0
|
||||
#define AR_SREV_REVISION_9271_11 1
|
||||
#define AR_SREV_VERSION_9300 0x1c0
|
||||
#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */
|
||||
#define AR_SREV_VERSION_5416_PCI 0xD
|
||||
#define AR_SREV_VERSION_5416_PCIE 0xC
|
||||
#define AR_SREV_REVISION_5416_10 0
|
||||
#define AR_SREV_REVISION_5416_20 1
|
||||
#define AR_SREV_REVISION_5416_22 2
|
||||
#define AR_SREV_VERSION_9100 0x14
|
||||
#define AR_SREV_VERSION_9160 0x40
|
||||
#define AR_SREV_REVISION_9160_10 0
|
||||
#define AR_SREV_REVISION_9160_11 1
|
||||
#define AR_SREV_VERSION_9280 0x80
|
||||
#define AR_SREV_REVISION_9280_10 0
|
||||
#define AR_SREV_REVISION_9280_20 1
|
||||
#define AR_SREV_REVISION_9280_21 2
|
||||
#define AR_SREV_VERSION_9285 0xC0
|
||||
#define AR_SREV_REVISION_9285_10 0
|
||||
#define AR_SREV_REVISION_9285_11 1
|
||||
#define AR_SREV_REVISION_9285_12 2
|
||||
#define AR_SREV_VERSION_9287 0x180
|
||||
#define AR_SREV_REVISION_9287_10 0
|
||||
#define AR_SREV_REVISION_9287_11 1
|
||||
#define AR_SREV_REVISION_9287_12 2
|
||||
#define AR_SREV_REVISION_9287_13 3
|
||||
#define AR_SREV_VERSION_9271 0x140
|
||||
#define AR_SREV_REVISION_9271_10 0
|
||||
#define AR_SREV_REVISION_9271_11 1
|
||||
#define AR_SREV_VERSION_9300 0x1c0
|
||||
#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */
|
||||
|
||||
#define AR_SREV_5416(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
|
||||
|
@ -859,6 +864,11 @@
|
|||
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12)))
|
||||
#define AR_SREV_9287_13_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_13)))
|
||||
|
||||
#define AR_SREV_9271(_ah) \
|
||||
(((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271)
|
||||
#define AR_SREV_9271_10(_ah) \
|
||||
|
|
|
@ -279,9 +279,6 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
|||
if (wmi->drv_priv->op_flags & OP_UNPLUGGED)
|
||||
return 0;
|
||||
|
||||
if (!wmi)
|
||||
return -EINVAL;
|
||||
|
||||
skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -984,32 +984,6 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
|
|||
return qnum;
|
||||
}
|
||||
|
||||
struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
|
||||
{
|
||||
struct ath_txq *txq = NULL;
|
||||
u16 skb_queue = skb_get_queue_mapping(skb);
|
||||
int qnum;
|
||||
|
||||
qnum = ath_get_hal_qnum(skb_queue, sc);
|
||||
txq = &sc->tx.txq[qnum];
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
if (txq->axq_depth >= (ATH_TXBUF - 20)) {
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
|
||||
"TX queue: %d is full, depth: %d\n",
|
||||
qnum, txq->axq_depth);
|
||||
ath_mac80211_stop_queue(sc, skb_queue);
|
||||
txq->stopped = 1;
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
|
||||
return txq;
|
||||
}
|
||||
|
||||
int ath_txq_update(struct ath_softc *sc, int qnum,
|
||||
struct ath9k_tx_queue_info *qinfo)
|
||||
{
|
||||
|
@ -1809,6 +1783,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_txq *txq = txctl->txq;
|
||||
struct ath_buf *bf;
|
||||
int r;
|
||||
|
||||
|
@ -1818,10 +1793,16 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
return -1;
|
||||
}
|
||||
|
||||
bf->txq = txctl->txq;
|
||||
spin_lock_bh(&bf->txq->axq_lock);
|
||||
if (++bf->txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
|
||||
ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
|
||||
txq->stopped = 1;
|
||||
}
|
||||
spin_unlock_bh(&bf->txq->axq_lock);
|
||||
|
||||
r = ath_tx_setup_buffer(hw, bf, skb, txctl);
|
||||
if (unlikely(r)) {
|
||||
struct ath_txq *txq = txctl->txq;
|
||||
|
||||
ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
|
||||
|
||||
/* upon ath_tx_processq() this TX queue will be resumed, we
|
||||
|
@ -1829,7 +1810,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
* we will at least have to run TX completionon one buffer
|
||||
* on the queue */
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
|
||||
if (!txq->stopped && txq->axq_depth > 1) {
|
||||
ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
|
||||
txq->stopped = 1;
|
||||
}
|
||||
|
@ -1970,6 +1951,13 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
|||
tx_flags |= ATH_TX_XRETRY;
|
||||
}
|
||||
|
||||
if (bf->txq) {
|
||||
spin_lock_bh(&bf->txq->axq_lock);
|
||||
bf->txq->pending_frames--;
|
||||
spin_unlock_bh(&bf->txq->axq_lock);
|
||||
bf->txq = NULL;
|
||||
}
|
||||
|
||||
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
|
||||
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
|
||||
ath_debug_stat_tx(sc, txq, bf, ts);
|
||||
|
@ -2058,8 +2046,7 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
|
|||
int qnum;
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (txq->stopped &&
|
||||
sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
|
||||
if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
|
||||
qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
|
||||
if (qnum != -1) {
|
||||
ath_mac80211_start_queue(sc, qnum);
|
||||
|
@ -2279,6 +2266,17 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
|||
|
||||
txok = !(txs.ts_status & ATH9K_TXERR_MASK);
|
||||
|
||||
/*
|
||||
* Make sure null func frame is acked before configuring
|
||||
* hw into ps mode.
|
||||
*/
|
||||
if (bf->bf_isnullfunc && txok) {
|
||||
if ((sc->ps_flags & PS_ENABLED))
|
||||
ath9k_enable_ps(sc);
|
||||
else
|
||||
sc->ps_flags |= PS_NULLFUNC_COMPLETED;
|
||||
}
|
||||
|
||||
if (!bf_isampdu(bf)) {
|
||||
bf->bf_retries = txs.ts_longretry;
|
||||
if (txs.ts_status & ATH9K_TXERR_XRETRY)
|
||||
|
|
|
@ -333,11 +333,11 @@ static inline
|
|||
dma_addr_t dmaaddr;
|
||||
|
||||
if (tx) {
|
||||
dmaaddr = ssb_dma_map_single(ring->dev->dev,
|
||||
buf, len, DMA_TO_DEVICE);
|
||||
dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
|
||||
buf, len, DMA_TO_DEVICE);
|
||||
} else {
|
||||
dmaaddr = ssb_dma_map_single(ring->dev->dev,
|
||||
buf, len, DMA_FROM_DEVICE);
|
||||
dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
|
||||
buf, len, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
return dmaaddr;
|
||||
|
@ -348,11 +348,11 @@ static inline
|
|||
dma_addr_t addr, size_t len, int tx)
|
||||
{
|
||||
if (tx) {
|
||||
ssb_dma_unmap_single(ring->dev->dev,
|
||||
addr, len, DMA_TO_DEVICE);
|
||||
dma_unmap_single(ring->dev->dev->dma_dev,
|
||||
addr, len, DMA_TO_DEVICE);
|
||||
} else {
|
||||
ssb_dma_unmap_single(ring->dev->dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
dma_unmap_single(ring->dev->dev->dma_dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,7 +361,7 @@ static inline
|
|||
dma_addr_t addr, size_t len)
|
||||
{
|
||||
B43_WARN_ON(ring->tx);
|
||||
ssb_dma_sync_single_for_cpu(ring->dev->dev,
|
||||
dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
|
@ -370,8 +370,8 @@ static inline
|
|||
dma_addr_t addr, size_t len)
|
||||
{
|
||||
B43_WARN_ON(ring->tx);
|
||||
ssb_dma_sync_single_for_device(ring->dev->dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_device(ring->dev->dev->dma_dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
static inline
|
||||
|
@ -401,9 +401,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
|
|||
*/
|
||||
if (ring->type == B43_DMA_64BIT)
|
||||
flags |= GFP_DMA;
|
||||
ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
|
||||
B43_DMA_RINGMEMSIZE,
|
||||
&(ring->dmabase), flags);
|
||||
ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
|
||||
B43_DMA_RINGMEMSIZE,
|
||||
&(ring->dmabase), flags);
|
||||
if (!ring->descbase) {
|
||||
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
|
||||
return -ENOMEM;
|
||||
|
@ -420,8 +420,8 @@ static void free_ringmemory(struct b43_dmaring *ring)
|
|||
if (ring->type == B43_DMA_64BIT)
|
||||
flags |= GFP_DMA;
|
||||
|
||||
ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE,
|
||||
ring->descbase, ring->dmabase, flags);
|
||||
dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
|
||||
ring->descbase, ring->dmabase);
|
||||
}
|
||||
|
||||
/* Reset the RX DMA channel */
|
||||
|
@ -528,7 +528,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
|
|||
dma_addr_t addr,
|
||||
size_t buffersize, bool dma_to_device)
|
||||
{
|
||||
if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
|
||||
if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
|
||||
return 1;
|
||||
|
||||
switch (ring->type) {
|
||||
|
@ -874,10 +874,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|||
goto err_kfree_meta;
|
||||
|
||||
/* test for ability to dma to txhdr_cache */
|
||||
dma_test = ssb_dma_map_single(dev->dev,
|
||||
ring->txhdr_cache,
|
||||
b43_txhdr_size(dev),
|
||||
DMA_TO_DEVICE);
|
||||
dma_test = dma_map_single(dev->dev->dma_dev,
|
||||
ring->txhdr_cache,
|
||||
b43_txhdr_size(dev),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (b43_dma_mapping_error(ring, dma_test,
|
||||
b43_txhdr_size(dev), 1)) {
|
||||
|
@ -889,10 +889,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|||
if (!ring->txhdr_cache)
|
||||
goto err_kfree_meta;
|
||||
|
||||
dma_test = ssb_dma_map_single(dev->dev,
|
||||
ring->txhdr_cache,
|
||||
b43_txhdr_size(dev),
|
||||
DMA_TO_DEVICE);
|
||||
dma_test = dma_map_single(dev->dev->dma_dev,
|
||||
ring->txhdr_cache,
|
||||
b43_txhdr_size(dev),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (b43_dma_mapping_error(ring, dma_test,
|
||||
b43_txhdr_size(dev), 1)) {
|
||||
|
@ -903,9 +903,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|||
}
|
||||
}
|
||||
|
||||
ssb_dma_unmap_single(dev->dev,
|
||||
dma_test, b43_txhdr_size(dev),
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(dev->dev->dma_dev,
|
||||
dma_test, b43_txhdr_size(dev),
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
err = alloc_ringmemory(ring);
|
||||
|
@ -1018,9 +1018,12 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
|
|||
/* Try to set the DMA mask. If it fails, try falling back to a
|
||||
* lower mask, as we can always also support a lower one. */
|
||||
while (1) {
|
||||
err = ssb_dma_set_mask(dev->dev, mask);
|
||||
if (!err)
|
||||
break;
|
||||
err = dma_set_mask(dev->dev->dma_dev, mask);
|
||||
if (!err) {
|
||||
err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
if (mask == DMA_BIT_MASK(64)) {
|
||||
mask = DMA_BIT_MASK(32);
|
||||
fallback = 1;
|
||||
|
@ -1221,14 +1224,14 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
|||
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
|
||||
/* create a bounce buffer in zone_dma on mapping failure. */
|
||||
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
|
||||
priv_info->bouncebuffer = kmalloc(skb->len, GFP_ATOMIC | GFP_DMA);
|
||||
priv_info->bouncebuffer = kmemdup(skb->data, skb->len,
|
||||
GFP_ATOMIC | GFP_DMA);
|
||||
if (!priv_info->bouncebuffer) {
|
||||
ring->current_slot = old_top_slot;
|
||||
ring->used_slots = old_used_slots;
|
||||
err = -ENOMEM;
|
||||
goto out_unmap_hdr;
|
||||
}
|
||||
memcpy(priv_info->bouncebuffer, skb->data, skb->len);
|
||||
|
||||
meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1);
|
||||
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
|
||||
|
|
|
@ -394,11 +394,11 @@ dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring,
|
|||
dma_addr_t dmaaddr;
|
||||
|
||||
if (tx)
|
||||
dmaaddr = ssb_dma_map_single(ring->dev->dev,
|
||||
dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
|
||||
buf, len,
|
||||
DMA_TO_DEVICE);
|
||||
else
|
||||
dmaaddr = ssb_dma_map_single(ring->dev->dev,
|
||||
dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
|
||||
buf, len,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
|
@ -412,11 +412,11 @@ void unmap_descbuffer(struct b43legacy_dmaring *ring,
|
|||
int tx)
|
||||
{
|
||||
if (tx)
|
||||
ssb_dma_unmap_single(ring->dev->dev,
|
||||
dma_unmap_single(ring->dev->dev->dma_dev,
|
||||
addr, len,
|
||||
DMA_TO_DEVICE);
|
||||
else
|
||||
ssb_dma_unmap_single(ring->dev->dev,
|
||||
dma_unmap_single(ring->dev->dev->dma_dev,
|
||||
addr, len,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
|
@ -428,8 +428,8 @@ void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring,
|
|||
{
|
||||
B43legacy_WARN_ON(ring->tx);
|
||||
|
||||
ssb_dma_sync_single_for_cpu(ring->dev->dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
static inline
|
||||
|
@ -439,8 +439,8 @@ void sync_descbuffer_for_device(struct b43legacy_dmaring *ring,
|
|||
{
|
||||
B43legacy_WARN_ON(ring->tx);
|
||||
|
||||
ssb_dma_sync_single_for_device(ring->dev->dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_device(ring->dev->dev->dma_dev,
|
||||
addr, len, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
static inline
|
||||
|
@ -460,10 +460,10 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring,
|
|||
static int alloc_ringmemory(struct b43legacy_dmaring *ring)
|
||||
{
|
||||
/* GFP flags must match the flags in free_ringmemory()! */
|
||||
ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
|
||||
B43legacy_DMA_RINGMEMSIZE,
|
||||
&(ring->dmabase),
|
||||
GFP_KERNEL);
|
||||
ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
|
||||
B43legacy_DMA_RINGMEMSIZE,
|
||||
&(ring->dmabase),
|
||||
GFP_KERNEL);
|
||||
if (!ring->descbase) {
|
||||
b43legacyerr(ring->dev->wl, "DMA ringmemory allocation"
|
||||
" failed\n");
|
||||
|
@ -476,8 +476,8 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring)
|
|||
|
||||
static void free_ringmemory(struct b43legacy_dmaring *ring)
|
||||
{
|
||||
ssb_dma_free_consistent(ring->dev->dev, B43legacy_DMA_RINGMEMSIZE,
|
||||
ring->descbase, ring->dmabase, GFP_KERNEL);
|
||||
dma_free_coherent(ring->dev->dev->dma_dev, B43legacy_DMA_RINGMEMSIZE,
|
||||
ring->descbase, ring->dmabase);
|
||||
}
|
||||
|
||||
/* Reset the RX DMA channel */
|
||||
|
@ -589,7 +589,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
|
|||
size_t buffersize,
|
||||
bool dma_to_device)
|
||||
{
|
||||
if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
|
||||
if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
|
||||
return 1;
|
||||
|
||||
switch (ring->type) {
|
||||
|
@ -906,7 +906,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
|
|||
goto err_kfree_meta;
|
||||
|
||||
/* test for ability to dma to txhdr_cache */
|
||||
dma_test = ssb_dma_map_single(dev->dev, ring->txhdr_cache,
|
||||
dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache,
|
||||
sizeof(struct b43legacy_txhdr_fw3),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
|
@ -920,7 +920,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
|
|||
if (!ring->txhdr_cache)
|
||||
goto err_kfree_meta;
|
||||
|
||||
dma_test = ssb_dma_map_single(dev->dev,
|
||||
dma_test = dma_map_single(dev->dev->dma_dev,
|
||||
ring->txhdr_cache,
|
||||
sizeof(struct b43legacy_txhdr_fw3),
|
||||
DMA_TO_DEVICE);
|
||||
|
@ -930,9 +930,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
|
|||
goto err_kfree_txhdr_cache;
|
||||
}
|
||||
|
||||
ssb_dma_unmap_single(dev->dev, dma_test,
|
||||
sizeof(struct b43legacy_txhdr_fw3),
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(dev->dev->dma_dev, dma_test,
|
||||
sizeof(struct b43legacy_txhdr_fw3),
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
ring->nr_slots = nr_slots;
|
||||
|
@ -1040,9 +1040,12 @@ static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask)
|
|||
/* Try to set the DMA mask. If it fails, try falling back to a
|
||||
* lower mask, as we can always also support a lower one. */
|
||||
while (1) {
|
||||
err = ssb_dma_set_mask(dev->dev, mask);
|
||||
if (!err)
|
||||
break;
|
||||
err = dma_set_mask(dev->dev->dma_dev, mask);
|
||||
if (!err) {
|
||||
err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
if (mask == DMA_BIT_MASK(64)) {
|
||||
mask = DMA_BIT_MASK(32);
|
||||
fallback = 1;
|
||||
|
|
|
@ -2618,15 +2618,6 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
|
|||
int events = 0;
|
||||
u16 ev;
|
||||
|
||||
/* Detect early interrupt before driver is fully configued */
|
||||
if (!dev->base_addr) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
|
||||
dev->name);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
|
|
|
@ -3467,10 +3467,8 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv)
|
|||
dma_addr_t p;
|
||||
|
||||
priv->msg_buffers =
|
||||
(struct ipw2100_tx_packet *)kmalloc(IPW_COMMAND_POOL_SIZE *
|
||||
sizeof(struct
|
||||
ipw2100_tx_packet),
|
||||
GFP_KERNEL);
|
||||
kmalloc(IPW_COMMAND_POOL_SIZE * sizeof(struct ipw2100_tx_packet),
|
||||
GFP_KERNEL);
|
||||
if (!priv->msg_buffers) {
|
||||
printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for msg "
|
||||
"buffers.\n", priv->net_dev->name);
|
||||
|
@ -4499,10 +4497,8 @@ static int ipw2100_tx_allocate(struct ipw2100_priv *priv)
|
|||
}
|
||||
|
||||
priv->tx_buffers =
|
||||
(struct ipw2100_tx_packet *)kmalloc(TX_PENDED_QUEUE_LENGTH *
|
||||
sizeof(struct
|
||||
ipw2100_tx_packet),
|
||||
GFP_ATOMIC);
|
||||
kmalloc(TX_PENDED_QUEUE_LENGTH * sizeof(struct ipw2100_tx_packet),
|
||||
GFP_ATOMIC);
|
||||
if (!priv->tx_buffers) {
|
||||
printk(KERN_ERR DRV_NAME
|
||||
": %s: alloc failed form tx buffers.\n",
|
||||
|
@ -4651,9 +4647,9 @@ static int ipw2100_rx_allocate(struct ipw2100_priv *priv)
|
|||
/*
|
||||
* allocate packets
|
||||
*/
|
||||
priv->rx_buffers = (struct ipw2100_rx_packet *)
|
||||
kmalloc(RX_QUEUE_LENGTH * sizeof(struct ipw2100_rx_packet),
|
||||
GFP_KERNEL);
|
||||
priv->rx_buffers = kmalloc(RX_QUEUE_LENGTH *
|
||||
sizeof(struct ipw2100_rx_packet),
|
||||
GFP_KERNEL);
|
||||
if (!priv->rx_buffers) {
|
||||
IPW_DEBUG_INFO("can't allocate rx packet buffer table\n");
|
||||
|
||||
|
|
|
@ -6624,13 +6624,12 @@ static int ipw_wx_set_genie(struct net_device *dev,
|
|||
return -EINVAL;
|
||||
|
||||
if (wrqu->data.length) {
|
||||
buf = kmalloc(wrqu->data.length, GFP_KERNEL);
|
||||
buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL);
|
||||
if (buf == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(buf, extra, wrqu->data.length);
|
||||
kfree(ieee->wpa_ie);
|
||||
ieee->wpa_ie = buf;
|
||||
ieee->wpa_ie_len = wrqu->data.length;
|
||||
|
|
|
@ -30,9 +30,11 @@ config IWLWIFI_DEBUG
|
|||
|
||||
config IWLWIFI_DEBUGFS
|
||||
bool "iwlagn debugfs support"
|
||||
depends on IWLWIFI && IWLWIFI_DEBUG && MAC80211_DEBUGFS
|
||||
depends on IWLWIFI && MAC80211_DEBUGFS
|
||||
---help---
|
||||
Enable creation of debugfs files for the iwlwifi drivers.
|
||||
Enable creation of debugfs files for the iwlwifi drivers. This
|
||||
is a low-impact option that allows getting insight into the
|
||||
driver's state at runtime.
|
||||
|
||||
config IWLWIFI_DEVICE_TRACING
|
||||
bool "iwlwifi device access tracing"
|
||||
|
|
|
@ -158,6 +158,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
BIT(IWL_CALIB_TX_IQ_PERD) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,28 @@
|
|||
|
||||
#include "iwl-3945-debugfs.h"
|
||||
|
||||
|
||||
static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
|
||||
{
|
||||
int p = 0;
|
||||
|
||||
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
|
||||
le32_to_cpu(priv->_3945.statistics.flag));
|
||||
if (le32_to_cpu(priv->_3945.statistics.flag) &
|
||||
UCODE_STATISTICS_CLEAR_MSK)
|
||||
p += scnprintf(buf + p, bufsz - p,
|
||||
"\tStatistics have been cleared\n");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
|
||||
(le32_to_cpu(priv->_3945.statistics.flag) &
|
||||
UCODE_STATISTICS_FREQUENCY_MSK)
|
||||
? "2.4 GHz" : "5.2 GHz");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
|
||||
(le32_to_cpu(priv->_3945.statistics.flag) &
|
||||
UCODE_STATISTICS_NARROW_BAND_MSK)
|
||||
? "enabled" : "disabled");
|
||||
return p;
|
||||
}
|
||||
|
||||
ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
@ -70,7 +92,7 @@ ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
|
|||
max_cck = &priv->_3945.max_delta.rx.cck;
|
||||
max_general = &priv->_3945.max_delta.rx.general;
|
||||
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += iwl3945_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Rx - OFDM:");
|
||||
|
@ -331,7 +353,7 @@ ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
|
|||
accum_tx = &priv->_3945.accum_statistics.tx;
|
||||
delta_tx = &priv->_3945.delta_statistics.tx;
|
||||
max_tx = &priv->_3945.max_delta.tx;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += iwl3945_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Tx:");
|
||||
|
@ -438,7 +460,7 @@ ssize_t iwl3945_ucode_general_stats_read(struct file *file,
|
|||
accum_div = &priv->_3945.accum_statistics.general.div;
|
||||
delta_div = &priv->_3945.delta_statistics.general.div;
|
||||
max_div = &priv->_3945.max_delta.general.div;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += iwl3945_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_General:");
|
||||
|
|
|
@ -279,8 +279,8 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
|
|||
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
|
||||
|
||||
tx_info = &txq->txb[txq->q.read_ptr];
|
||||
ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
|
||||
tx_info->skb[0] = NULL;
|
||||
ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
|
||||
tx_info->skb = NULL;
|
||||
priv->cfg->ops->lib->txq_free_tfd(priv, txq);
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
|
||||
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
|
||||
ieee80211_tx_info_clear_status(info);
|
||||
|
||||
/* Fill the MRR chain with some info about on-chip retransmissions */
|
||||
|
@ -352,7 +352,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
|
|||
* RX handler implementations
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/*
|
||||
* based on the assumption of all statistics counter are in DWORD
|
||||
* FIXME: This function is for debugging, do not deal with
|
||||
|
@ -460,7 +460,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
|||
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
|
||||
(int)sizeof(struct iwl3945_notif_statistics),
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
|
||||
#endif
|
||||
iwl_recover_from_statistics(priv, pkt);
|
||||
|
@ -475,7 +475,7 @@ void iwl3945_reply_statistics(struct iwl_priv *priv,
|
|||
__le32 *flag = (__le32 *)&pkt->u.raw;
|
||||
|
||||
if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
memset(&priv->_3945.accum_statistics, 0,
|
||||
sizeof(struct iwl3945_notif_statistics));
|
||||
memset(&priv->_3945.delta_statistics, 0,
|
||||
|
@ -494,158 +494,6 @@ void iwl3945_reply_statistics(struct iwl_priv *priv,
|
|||
* Misc. internal state and helper functions
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
||||
/**
|
||||
* iwl3945_report_frame - dump frame to syslog during debug sessions
|
||||
*
|
||||
* You may hack this function to show different aspects of received frames,
|
||||
* including selective frame dumps.
|
||||
* group100 parameter selects whether to show 1 out of 100 good frames.
|
||||
*/
|
||||
static void _iwl3945_dbg_report_frame(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt,
|
||||
struct ieee80211_hdr *header, int group100)
|
||||
{
|
||||
u32 to_us;
|
||||
u32 print_summary = 0;
|
||||
u32 print_dump = 0; /* set to 1 to dump all frames' contents */
|
||||
u32 hundred = 0;
|
||||
u32 dataframe = 0;
|
||||
__le16 fc;
|
||||
u16 seq_ctl;
|
||||
u16 channel;
|
||||
u16 phy_flags;
|
||||
u16 length;
|
||||
u16 status;
|
||||
u16 bcn_tmr;
|
||||
u32 tsf_low;
|
||||
u64 tsf;
|
||||
u8 rssi;
|
||||
u8 agc;
|
||||
u16 sig_avg;
|
||||
u16 noise_diff;
|
||||
struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
|
||||
struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
|
||||
struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
|
||||
u8 *data = IWL_RX_DATA(pkt);
|
||||
|
||||
/* MAC header */
|
||||
fc = header->frame_control;
|
||||
seq_ctl = le16_to_cpu(header->seq_ctrl);
|
||||
|
||||
/* metadata */
|
||||
channel = le16_to_cpu(rx_hdr->channel);
|
||||
phy_flags = le16_to_cpu(rx_hdr->phy_flags);
|
||||
length = le16_to_cpu(rx_hdr->len);
|
||||
|
||||
/* end-of-frame status and timestamp */
|
||||
status = le32_to_cpu(rx_end->status);
|
||||
bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
|
||||
tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
|
||||
tsf = le64_to_cpu(rx_end->timestamp);
|
||||
|
||||
/* signal statistics */
|
||||
rssi = rx_stats->rssi;
|
||||
agc = rx_stats->agc;
|
||||
sig_avg = le16_to_cpu(rx_stats->sig_avg);
|
||||
noise_diff = le16_to_cpu(rx_stats->noise_diff);
|
||||
|
||||
to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
|
||||
|
||||
/* if data frame is to us and all is good,
|
||||
* (optionally) print summary for only 1 out of every 100 */
|
||||
if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) ==
|
||||
cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
|
||||
dataframe = 1;
|
||||
if (!group100)
|
||||
print_summary = 1; /* print each frame */
|
||||
else if (priv->framecnt_to_us < 100) {
|
||||
priv->framecnt_to_us++;
|
||||
print_summary = 0;
|
||||
} else {
|
||||
priv->framecnt_to_us = 0;
|
||||
print_summary = 1;
|
||||
hundred = 1;
|
||||
}
|
||||
} else {
|
||||
/* print summary for all other frames */
|
||||
print_summary = 1;
|
||||
}
|
||||
|
||||
if (print_summary) {
|
||||
char *title;
|
||||
int rate;
|
||||
|
||||
if (hundred)
|
||||
title = "100Frames";
|
||||
else if (ieee80211_has_retry(fc))
|
||||
title = "Retry";
|
||||
else if (ieee80211_is_assoc_resp(fc))
|
||||
title = "AscRsp";
|
||||
else if (ieee80211_is_reassoc_resp(fc))
|
||||
title = "RasRsp";
|
||||
else if (ieee80211_is_probe_resp(fc)) {
|
||||
title = "PrbRsp";
|
||||
print_dump = 1; /* dump frame contents */
|
||||
} else if (ieee80211_is_beacon(fc)) {
|
||||
title = "Beacon";
|
||||
print_dump = 1; /* dump frame contents */
|
||||
} else if (ieee80211_is_atim(fc))
|
||||
title = "ATIM";
|
||||
else if (ieee80211_is_auth(fc))
|
||||
title = "Auth";
|
||||
else if (ieee80211_is_deauth(fc))
|
||||
title = "DeAuth";
|
||||
else if (ieee80211_is_disassoc(fc))
|
||||
title = "DisAssoc";
|
||||
else
|
||||
title = "Frame";
|
||||
|
||||
rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
|
||||
if (rate == -1)
|
||||
rate = 0;
|
||||
else
|
||||
rate = iwl3945_rates[rate].ieee / 2;
|
||||
|
||||
/* print frame summary.
|
||||
* MAC addresses show just the last byte (for brevity),
|
||||
* but you can hack it to show more, if you'd like to. */
|
||||
if (dataframe)
|
||||
IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, "
|
||||
"len=%u, rssi=%d, chnl=%d, rate=%d,\n",
|
||||
title, le16_to_cpu(fc), header->addr1[5],
|
||||
length, rssi, channel, rate);
|
||||
else {
|
||||
/* src/dst addresses assume managed mode */
|
||||
IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, "
|
||||
"src=0x%02x, rssi=%u, tim=%lu usec, "
|
||||
"phy=0x%02x, chnl=%d\n",
|
||||
title, le16_to_cpu(fc), header->addr1[5],
|
||||
header->addr3[5], rssi,
|
||||
tsf_low - priv->scan_start_tsf,
|
||||
phy_flags, channel);
|
||||
}
|
||||
}
|
||||
if (print_dump)
|
||||
iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
|
||||
}
|
||||
|
||||
static void iwl3945_dbg_report_frame(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt,
|
||||
struct ieee80211_hdr *header, int group100)
|
||||
{
|
||||
if (iwl_get_debug_level(priv) & IWL_DL_RX)
|
||||
_iwl3945_dbg_report_frame(priv, pkt, header, group100);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void iwl3945_dbg_report_frame(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt,
|
||||
struct ieee80211_hdr *header, int group100)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is necessary only for a number of statistics, see the caller. */
|
||||
static int iwl3945_is_network_packet(struct iwl_priv *priv,
|
||||
|
@ -777,8 +625,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
|
|||
rx_status.signal, rx_status.signal,
|
||||
rx_status.rate_idx);
|
||||
|
||||
/* Set "1" to report good data frames in groups of 100 */
|
||||
iwl3945_dbg_report_frame(priv, pkt, header, 1);
|
||||
iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header);
|
||||
|
||||
if (network_packet) {
|
||||
|
@ -850,25 +696,28 @@ void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
|||
/* Unmap tx_cmd */
|
||||
if (counter)
|
||||
pci_unmap_single(dev,
|
||||
pci_unmap_addr(&txq->meta[index], mapping),
|
||||
pci_unmap_len(&txq->meta[index], len),
|
||||
dma_unmap_addr(&txq->meta[index], mapping),
|
||||
dma_unmap_len(&txq->meta[index], len),
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
/* unmap chunks if any */
|
||||
|
||||
for (i = 1; i < counter; i++) {
|
||||
for (i = 1; i < counter; i++)
|
||||
pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
|
||||
le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE);
|
||||
if (txq->txb[txq->q.read_ptr].skb[0]) {
|
||||
struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[0];
|
||||
if (txq->txb[txq->q.read_ptr].skb[0]) {
|
||||
/* Can be called from interrupt context */
|
||||
dev_kfree_skb_any(skb);
|
||||
txq->txb[txq->q.read_ptr].skb[0] = NULL;
|
||||
}
|
||||
|
||||
/* free SKB */
|
||||
if (txq->txb) {
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = txq->txb[txq->q.read_ptr].skb;
|
||||
|
||||
/* can be called from irqs-disabled context */
|
||||
if (skb) {
|
||||
dev_kfree_skb_any(skb);
|
||||
txq->txb[txq->q.read_ptr].skb = NULL;
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -947,8 +796,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
|
|||
tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
|
||||
}
|
||||
|
||||
static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
|
||||
u16 tx_rate, u8 flags)
|
||||
static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
|
||||
{
|
||||
unsigned long flags_spin;
|
||||
struct iwl_station_entry *station;
|
||||
|
@ -962,10 +810,9 @@ static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
|
|||
station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
|
||||
station->sta.rate_n_flags = cpu_to_le16(tx_rate);
|
||||
station->sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
||||
iwl_send_add_sta(priv, &station->sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||
|
||||
iwl_send_add_sta(priv, &station->sta, flags);
|
||||
IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
|
||||
sta_id, tx_rate);
|
||||
return sta_id;
|
||||
|
@ -2473,8 +2320,7 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
|
|||
|
||||
iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
|
||||
(priv->band == IEEE80211_BAND_5GHZ) ?
|
||||
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
|
||||
CMD_ASYNC);
|
||||
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP);
|
||||
iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
|
||||
|
||||
return 0;
|
||||
|
@ -2590,6 +2436,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
|
|||
|
||||
priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
|
||||
priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
|
||||
priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2852,6 +2699,7 @@ static struct iwl_lib_ops iwl3945_lib = {
|
|||
.isr = iwl_isr_legacy,
|
||||
.config_ap = iwl3945_config_ap,
|
||||
.manage_ibss_station = iwl3945_manage_ibss_station,
|
||||
.recover_from_tx_stall = iwl_bg_monitor_recover,
|
||||
.check_plcp_health = iwl3945_good_plcp_health,
|
||||
|
||||
.debugfs_ops = {
|
||||
|
|
|
@ -346,9 +346,19 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
|
|||
{
|
||||
struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
|
||||
|
||||
if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
|
||||
if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
|
||||
iwl_is_associated(priv)) {
|
||||
struct iwl_calib_diff_gain_cmd cmd;
|
||||
|
||||
/* clear data for chain noise calibration algorithm */
|
||||
data->chain_noise_a = 0;
|
||||
data->chain_noise_b = 0;
|
||||
data->chain_noise_c = 0;
|
||||
data->chain_signal_a = 0;
|
||||
data->chain_signal_b = 0;
|
||||
data->chain_signal_c = 0;
|
||||
data->beacon_count = 0;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
|
||||
cmd.diff_gain_a = 0;
|
||||
|
@ -419,13 +429,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
|
|||
/* Mark so we run this algo only once! */
|
||||
data->state = IWL_CHAIN_NOISE_CALIBRATED;
|
||||
}
|
||||
data->chain_noise_a = 0;
|
||||
data->chain_noise_b = 0;
|
||||
data->chain_noise_c = 0;
|
||||
data->chain_signal_a = 0;
|
||||
data->chain_signal_b = 0;
|
||||
data->chain_signal_c = 0;
|
||||
data->beacon_count = 0;
|
||||
}
|
||||
|
||||
static void iwl4965_bg_txpower_work(struct work_struct *work)
|
||||
|
@ -669,6 +672,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
|
|||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
|
||||
priv->hw_params.sens = &iwl4965_sensitivity;
|
||||
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1441,7 +1445,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
int rc;
|
||||
u8 band = 0;
|
||||
|
@ -1449,11 +1454,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
|||
u8 ctrl_chan_high = 0;
|
||||
struct iwl4965_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
u8 switch_count;
|
||||
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = priv->vif;
|
||||
band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
||||
|
||||
is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
|
||||
|
||||
if (is_ht40 &&
|
||||
|
@ -1462,26 +1470,56 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
|||
|
||||
cmd.band = band;
|
||||
cmd.expect_beacon = 0;
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
switch_count = ch_switch->count;
|
||||
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||
/*
|
||||
* calculate the ucode channel switch time
|
||||
* adding TSF as one of the factor for when to switch
|
||||
*/
|
||||
if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
|
||||
if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
|
||||
beacon_interval)) {
|
||||
switch_count -= (priv->ucode_beacon_time -
|
||||
tsf_low) / beacon_interval;
|
||||
} else
|
||||
switch_count = 0;
|
||||
}
|
||||
if (switch_count <= 1)
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
else {
|
||||
switch_time_in_usec =
|
||||
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
|
||||
ucode_switch_time = iwl_usecs_to_beacons(priv,
|
||||
switch_time_in_usec,
|
||||
beacon_interval);
|
||||
cmd.switch_time = iwl_add_beacon_time(priv,
|
||||
priv->ucode_beacon_time,
|
||||
ucode_switch_time,
|
||||
beacon_interval);
|
||||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd.switch_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, ch);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
priv->active_rxon.channel, ch);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
|
||||
rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
|
||||
ctrl_chan_high, &cmd.tx_power);
|
||||
if (rc) {
|
||||
IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
||||
priv->switch_rxon.channel = cmd.channel;
|
||||
priv->switch_rxon.switch_in_progress = true;
|
||||
|
||||
return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
|
||||
|
@ -1870,7 +1908,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
|||
IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
|
||||
agg->frame_count, agg->start_idx, idx);
|
||||
|
||||
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
|
||||
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
|
||||
info->status.rates[0].count = tx_resp->failure_frame + 1;
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
info->flags |= iwl_tx_status_to_mac80211(status);
|
||||
|
@ -2026,6 +2064,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|||
int sta_id;
|
||||
int freed;
|
||||
u8 *qc = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
|
||||
IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
|
||||
|
@ -2035,7 +2074,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
|
||||
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
|
||||
|
@ -2050,10 +2089,10 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
if (txq->sched_retry) {
|
||||
const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
|
||||
struct iwl_ht_agg *agg = NULL;
|
||||
|
||||
WARN_ON(!qc);
|
||||
|
||||
agg = &priv->stations[sta_id].tid[tid].agg;
|
||||
|
@ -2110,6 +2149,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
|||
iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
|
||||
|
||||
iwl_check_abort_status(priv, tx_resp->frame_count, status);
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
||||
static int iwl4965_calc_rssi(struct iwl_priv *priv,
|
||||
|
@ -2285,7 +2326,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
|
|||
* Force use of chains B and C for scan RX on 5 GHz band
|
||||
* because the device has off-channel reception on chain A.
|
||||
*/
|
||||
.scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
|
||||
.scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
|
||||
};
|
||||
|
||||
/* Module firmware */
|
||||
|
|
|
@ -208,6 +208,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
BIT(IWL_CALIB_TX_IQ_PERD) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -252,6 +254,8 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
|||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -267,33 +271,69 @@ static void iwl5150_temperature(struct iwl_priv *priv)
|
|||
iwl_tt_handler(priv);
|
||||
}
|
||||
|
||||
static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct iwl5000_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
u8 switch_count;
|
||||
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = priv->vif;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_CHANNEL_SWITCH,
|
||||
.len = sizeof(cmd),
|
||||
.flags = CMD_SIZE_HUGE,
|
||||
.flags = CMD_SYNC,
|
||||
.data = &cmd,
|
||||
};
|
||||
|
||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
|
||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
||||
priv->active_rxon.channel, ch);
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
||||
switch_count = ch_switch->count;
|
||||
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||
/*
|
||||
* calculate the ucode channel switch time
|
||||
* adding TSF as one of the factor for when to switch
|
||||
*/
|
||||
if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
|
||||
if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
|
||||
beacon_interval)) {
|
||||
switch_count -= (priv->ucode_beacon_time -
|
||||
tsf_low) / beacon_interval;
|
||||
} else
|
||||
switch_count = 0;
|
||||
}
|
||||
if (switch_count <= 1)
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
else {
|
||||
switch_time_in_usec =
|
||||
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
|
||||
ucode_switch_time = iwl_usecs_to_beacons(priv,
|
||||
switch_time_in_usec,
|
||||
beacon_interval);
|
||||
cmd.switch_time = iwl_add_beacon_time(priv,
|
||||
priv->ucode_beacon_time,
|
||||
ucode_switch_time,
|
||||
beacon_interval);
|
||||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd.switch_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, ch);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
priv->active_rxon.channel, ch);
|
||||
return -EFAULT;
|
||||
}
|
||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
||||
priv->switch_rxon.channel = cmd.channel;
|
||||
priv->switch_rxon.switch_in_progress = true;
|
||||
|
||||
return iwl_send_cmd_sync(priv, &hcmd);
|
||||
|
|
|
@ -71,6 +71,10 @@
|
|||
#define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode"
|
||||
#define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api)
|
||||
|
||||
#define IWL6000G2B_FW_PRE "iwlwifi-6000g2b-"
|
||||
#define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode"
|
||||
#define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
|
||||
|
||||
|
||||
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
||||
{
|
||||
|
@ -183,6 +187,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -228,37 +234,74 @@ static int iwl6050_hw_set_hw_params(struct iwl_priv *priv)
|
|||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct iwl6000_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
u8 switch_count;
|
||||
u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
|
||||
struct ieee80211_vif *vif = priv->vif;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_CHANNEL_SWITCH,
|
||||
.len = sizeof(cmd),
|
||||
.flags = CMD_SIZE_HUGE,
|
||||
.flags = CMD_SYNC,
|
||||
.data = &cmd,
|
||||
};
|
||||
|
||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
|
||||
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, ch);
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = priv->staging_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
||||
switch_count = ch_switch->count;
|
||||
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||
/*
|
||||
* calculate the ucode channel switch time
|
||||
* adding TSF as one of the factor for when to switch
|
||||
*/
|
||||
if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
|
||||
if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
|
||||
beacon_interval)) {
|
||||
switch_count -= (priv->ucode_beacon_time -
|
||||
tsf_low) / beacon_interval;
|
||||
} else
|
||||
switch_count = 0;
|
||||
}
|
||||
if (switch_count <= 1)
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
else {
|
||||
switch_time_in_usec =
|
||||
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
|
||||
ucode_switch_time = iwl_usecs_to_beacons(priv,
|
||||
switch_time_in_usec,
|
||||
beacon_interval);
|
||||
cmd.switch_time = iwl_add_beacon_time(priv,
|
||||
priv->ucode_beacon_time,
|
||||
ucode_switch_time,
|
||||
beacon_interval);
|
||||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd.switch_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, ch);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
priv->active_rxon.channel, ch);
|
||||
return -EFAULT;
|
||||
}
|
||||
priv->switch_rxon.channel = cpu_to_le16(channel);
|
||||
priv->switch_rxon.channel = cmd.channel;
|
||||
priv->switch_rxon.switch_in_progress = true;
|
||||
|
||||
return iwl_send_cmd_sync(priv, &hcmd);
|
||||
|
@ -335,6 +378,25 @@ static const struct iwl_ops iwl6000_ops = {
|
|||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
static void do_not_send_bt_config(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
|
||||
static struct iwl_hcmd_ops iwl6000g2b_hcmd = {
|
||||
.rxon_assoc = iwlagn_send_rxon_assoc,
|
||||
.commit_rxon = iwl_commit_rxon,
|
||||
.set_rxon_chain = iwl_set_rxon_chain,
|
||||
.set_tx_ant = iwlagn_send_tx_ant_config,
|
||||
.send_bt_config = do_not_send_bt_config,
|
||||
};
|
||||
|
||||
static const struct iwl_ops iwl6000g2b_ops = {
|
||||
.lib = &iwl6000_lib,
|
||||
.hcmd = &iwl6000g2b_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl6050_lib = {
|
||||
.set_hw_params = iwl6050_hw_set_hw_params,
|
||||
.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
|
||||
|
@ -445,6 +507,268 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
|
|||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2a_2abg_cfg = {
|
||||
.name = "6000 Series 2x2 ABG Gen2a",
|
||||
.fw_name_pre = IWL6000G2A_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2a_2bg_cfg = {
|
||||
.name = "6000 Series 2x2 BG Gen2a",
|
||||
.fw_name_pre = IWL6000G2A_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2b_2agn_cfg = {
|
||||
.name = "6000 Series 2x2 AGN Gen2b",
|
||||
.fw_name_pre = IWL6000G2B_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2b_2abg_cfg = {
|
||||
.name = "6000 Series 2x2 ABG Gen2b",
|
||||
.fw_name_pre = IWL6000G2B_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2b_2bgn_cfg = {
|
||||
.name = "6000 Series 2x2 BGN Gen2b",
|
||||
.fw_name_pre = IWL6000G2B_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2b_2bg_cfg = {
|
||||
.name = "6000 Series 2x2 BG Gen2b",
|
||||
.fw_name_pre = IWL6000G2B_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2b_bgn_cfg = {
|
||||
.name = "6000 Series 1x2 BGN Gen2b",
|
||||
.fw_name_pre = IWL6000G2B_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000g2b_bg_cfg = {
|
||||
.name = "6000 Series 1x2 BG Gen2b",
|
||||
.fw_name_pre = IWL6000G2B_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G,
|
||||
.ops = &iwl6000g2b_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwlagn_mod_params,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
};
|
||||
|
||||
/*
|
||||
* "i": Internal configuration, use internal Power Amplifier
|
||||
*/
|
||||
|
@ -667,3 +991,4 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
|||
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
|
||||
|
|
|
@ -28,6 +28,27 @@
|
|||
|
||||
#include "iwl-agn-debugfs.h"
|
||||
|
||||
static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
|
||||
{
|
||||
int p = 0;
|
||||
|
||||
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
|
||||
le32_to_cpu(priv->statistics.flag));
|
||||
if (le32_to_cpu(priv->statistics.flag) &
|
||||
UCODE_STATISTICS_CLEAR_MSK)
|
||||
p += scnprintf(buf + p, bufsz - p,
|
||||
"\tStatistics have been cleared\n");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
|
||||
(le32_to_cpu(priv->statistics.flag) &
|
||||
UCODE_STATISTICS_FREQUENCY_MSK)
|
||||
? "2.4 GHz" : "5.2 GHz");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
|
||||
(le32_to_cpu(priv->statistics.flag) &
|
||||
UCODE_STATISTICS_NARROW_BAND_MSK)
|
||||
? "enabled" : "disabled");
|
||||
return p;
|
||||
}
|
||||
|
||||
ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
@ -75,7 +96,7 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
|
|||
max_general = &priv->max_delta.rx.general;
|
||||
max_ht = &priv->max_delta.rx.ofdm_ht;
|
||||
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += iwl_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Rx - OFDM:");
|
||||
|
@ -543,7 +564,7 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
|
|||
accum_tx = &priv->accum_statistics.tx;
|
||||
delta_tx = &priv->delta_statistics.tx;
|
||||
max_tx = &priv->max_delta.tx;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += iwl_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Tx:");
|
||||
|
@ -768,7 +789,7 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
|
|||
accum_div = &priv->accum_statistics.general.div;
|
||||
delta_div = &priv->delta_statistics.general.div;
|
||||
max_div = &priv->max_delta.general.div;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += iwl_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_General:");
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "iwl-io.h"
|
||||
#include "iwl-agn.h"
|
||||
|
||||
static int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
|
||||
int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct iwl5000_rxon_assoc_cmd rxon_assoc;
|
||||
|
@ -84,7 +84,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
|
||||
int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
|
||||
{
|
||||
struct iwl_tx_ant_config_cmd tx_ant_cmd = {
|
||||
.valid = cpu_to_le32(valid_tx_ant),
|
||||
|
@ -176,14 +176,6 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
|
|||
data->radio_write = 1;
|
||||
data->state = IWL_CHAIN_NOISE_CALIBRATED;
|
||||
}
|
||||
|
||||
data->chain_noise_a = 0;
|
||||
data->chain_noise_b = 0;
|
||||
data->chain_noise_c = 0;
|
||||
data->chain_signal_a = 0;
|
||||
data->chain_signal_b = 0;
|
||||
data->chain_signal_c = 0;
|
||||
data->beacon_count = 0;
|
||||
}
|
||||
|
||||
static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
|
||||
|
@ -191,10 +183,20 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
|
|||
struct iwl_chain_noise_data *data = &priv->chain_noise_data;
|
||||
int ret;
|
||||
|
||||
if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
|
||||
if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
|
||||
iwl_is_associated(priv)) {
|
||||
struct iwl_calib_chain_noise_reset_cmd cmd;
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
/* clear data for chain noise calibration algorithm */
|
||||
data->chain_noise_a = 0;
|
||||
data->chain_noise_b = 0;
|
||||
data->chain_noise_c = 0;
|
||||
data->chain_signal_a = 0;
|
||||
data->chain_signal_b = 0;
|
||||
data->chain_signal_c = 0;
|
||||
data->beacon_count = 0;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD;
|
||||
cmd.hdr.first_group = 0;
|
||||
cmd.hdr.groups_num = 1;
|
||||
|
|
|
@ -77,7 +77,7 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
|
|||
IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
|
||||
agg->frame_count, agg->start_idx, idx);
|
||||
|
||||
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
|
||||
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
|
||||
info->status.rates[0].count = tx_resp->failure_frame + 1;
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
info->flags |= iwl_tx_status_to_mac80211(status);
|
||||
|
@ -93,6 +93,12 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
|
|||
} else {
|
||||
/* Two or more frames were attempted; expect block-ack */
|
||||
u64 bitmap = 0;
|
||||
|
||||
/*
|
||||
* Start is the lowest frame sent. It may not be the first
|
||||
* frame in the batch; we figure this out dynamically during
|
||||
* the following loop.
|
||||
*/
|
||||
int start = agg->start_idx;
|
||||
|
||||
/* Construct bit-map of pending frames within Tx window */
|
||||
|
@ -131,25 +137,58 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv,
|
|||
IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
|
||||
i, idx, SEQ_TO_SN(sc));
|
||||
|
||||
/*
|
||||
* sh -> how many frames ahead of the starting frame is
|
||||
* the current one?
|
||||
*
|
||||
* Note that all frames sent in the batch must be in a
|
||||
* 64-frame window, so this number should be in [0,63].
|
||||
* If outside of this window, then we've found a new
|
||||
* "first" frame in the batch and need to change start.
|
||||
*/
|
||||
sh = idx - start;
|
||||
if (sh > 64) {
|
||||
sh = (start - idx) + 0xff;
|
||||
|
||||
/*
|
||||
* If >= 64, out of window. start must be at the front
|
||||
* of the circular buffer, idx must be near the end of
|
||||
* the buffer, and idx is the new "first" frame. Shift
|
||||
* the indices around.
|
||||
*/
|
||||
if (sh >= 64) {
|
||||
/* Shift bitmap by start - idx, wrapped */
|
||||
sh = 0x100 - idx + start;
|
||||
bitmap = bitmap << sh;
|
||||
/* Now idx is the new start so sh = 0 */
|
||||
sh = 0;
|
||||
start = idx;
|
||||
} else if (sh < -64)
|
||||
sh = 0xff - (start - idx);
|
||||
else if (sh < 0) {
|
||||
/*
|
||||
* If <= -64 then wraps the 256-pkt circular buffer
|
||||
* (e.g., start = 255 and idx = 0, sh should be 1)
|
||||
*/
|
||||
} else if (sh <= -64) {
|
||||
sh = 0x100 - start + idx;
|
||||
/*
|
||||
* If < 0 but > -64, out of window. idx is before start
|
||||
* but not wrapped. Shift the indices around.
|
||||
*/
|
||||
} else if (sh < 0) {
|
||||
/* Shift by how far start is ahead of idx */
|
||||
sh = start - idx;
|
||||
start = idx;
|
||||
bitmap = bitmap << sh;
|
||||
/* Now idx is the new start so sh = 0 */
|
||||
start = idx;
|
||||
sh = 0;
|
||||
}
|
||||
/* Sequence number start + sh was sent in this batch */
|
||||
bitmap |= 1ULL << sh;
|
||||
IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
|
||||
start, (unsigned long long)bitmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the bitmap and possibly the new start, if we wrapped
|
||||
* the buffer above
|
||||
*/
|
||||
agg->bitmap = bitmap;
|
||||
agg->start_idx = start;
|
||||
IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
|
||||
|
@ -184,6 +223,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
|
|||
int tid;
|
||||
int sta_id;
|
||||
int freed;
|
||||
unsigned long flags;
|
||||
|
||||
if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
|
||||
IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
|
||||
|
@ -193,15 +233,16 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
|
||||
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
|
||||
sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
if (txq->sched_retry) {
|
||||
const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp);
|
||||
struct iwl_ht_agg *agg = NULL;
|
||||
struct iwl_ht_agg *agg;
|
||||
|
||||
agg = &priv->stations[sta_id].tid[tid].agg;
|
||||
|
||||
|
@ -256,6 +297,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
|
|||
iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
|
||||
|
||||
iwl_check_abort_status(priv, tx_resp->frame_count, status);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
||||
void iwlagn_rx_handler_setup(struct iwl_priv *priv)
|
||||
|
@ -755,132 +797,6 @@ static inline int iwlagn_calc_rssi(struct iwl_priv *priv,
|
|||
return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
/**
|
||||
* iwlagn_dbg_report_frame - dump frame to syslog during debug sessions
|
||||
*
|
||||
* You may hack this function to show different aspects of received frames,
|
||||
* including selective frame dumps.
|
||||
* group100 parameter selects whether to show 1 out of 100 good data frames.
|
||||
* All beacon and probe response frames are printed.
|
||||
*/
|
||||
static void iwlagn_dbg_report_frame(struct iwl_priv *priv,
|
||||
struct iwl_rx_phy_res *phy_res, u16 length,
|
||||
struct ieee80211_hdr *header, int group100)
|
||||
{
|
||||
u32 to_us;
|
||||
u32 print_summary = 0;
|
||||
u32 print_dump = 0; /* set to 1 to dump all frames' contents */
|
||||
u32 hundred = 0;
|
||||
u32 dataframe = 0;
|
||||
__le16 fc;
|
||||
u16 seq_ctl;
|
||||
u16 channel;
|
||||
u16 phy_flags;
|
||||
u32 rate_n_flags;
|
||||
u32 tsf_low;
|
||||
int rssi;
|
||||
|
||||
if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX)))
|
||||
return;
|
||||
|
||||
/* MAC header */
|
||||
fc = header->frame_control;
|
||||
seq_ctl = le16_to_cpu(header->seq_ctrl);
|
||||
|
||||
/* metadata */
|
||||
channel = le16_to_cpu(phy_res->channel);
|
||||
phy_flags = le16_to_cpu(phy_res->phy_flags);
|
||||
rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
|
||||
|
||||
/* signal statistics */
|
||||
rssi = iwlagn_calc_rssi(priv, phy_res);
|
||||
tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff;
|
||||
|
||||
to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
|
||||
|
||||
/* if data frame is to us and all is good,
|
||||
* (optionally) print summary for only 1 out of every 100 */
|
||||
if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) ==
|
||||
cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
|
||||
dataframe = 1;
|
||||
if (!group100)
|
||||
print_summary = 1; /* print each frame */
|
||||
else if (priv->framecnt_to_us < 100) {
|
||||
priv->framecnt_to_us++;
|
||||
print_summary = 0;
|
||||
} else {
|
||||
priv->framecnt_to_us = 0;
|
||||
print_summary = 1;
|
||||
hundred = 1;
|
||||
}
|
||||
} else {
|
||||
/* print summary for all other frames */
|
||||
print_summary = 1;
|
||||
}
|
||||
|
||||
if (print_summary) {
|
||||
char *title;
|
||||
int rate_idx;
|
||||
u32 bitrate;
|
||||
|
||||
if (hundred)
|
||||
title = "100Frames";
|
||||
else if (ieee80211_has_retry(fc))
|
||||
title = "Retry";
|
||||
else if (ieee80211_is_assoc_resp(fc))
|
||||
title = "AscRsp";
|
||||
else if (ieee80211_is_reassoc_resp(fc))
|
||||
title = "RasRsp";
|
||||
else if (ieee80211_is_probe_resp(fc)) {
|
||||
title = "PrbRsp";
|
||||
print_dump = 1; /* dump frame contents */
|
||||
} else if (ieee80211_is_beacon(fc)) {
|
||||
title = "Beacon";
|
||||
print_dump = 1; /* dump frame contents */
|
||||
} else if (ieee80211_is_atim(fc))
|
||||
title = "ATIM";
|
||||
else if (ieee80211_is_auth(fc))
|
||||
title = "Auth";
|
||||
else if (ieee80211_is_deauth(fc))
|
||||
title = "DeAuth";
|
||||
else if (ieee80211_is_disassoc(fc))
|
||||
title = "DisAssoc";
|
||||
else
|
||||
title = "Frame";
|
||||
|
||||
rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
|
||||
if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) {
|
||||
bitrate = 0;
|
||||
WARN_ON_ONCE(1);
|
||||
} else {
|
||||
bitrate = iwl_rates[rate_idx].ieee / 2;
|
||||
}
|
||||
|
||||
/* print frame summary.
|
||||
* MAC addresses show just the last byte (for brevity),
|
||||
* but you can hack it to show more, if you'd like to. */
|
||||
if (dataframe)
|
||||
IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, "
|
||||
"len=%u, rssi=%d, chnl=%d, rate=%u,\n",
|
||||
title, le16_to_cpu(fc), header->addr1[5],
|
||||
length, rssi, channel, bitrate);
|
||||
else {
|
||||
/* src/dst addresses assume managed mode */
|
||||
IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, "
|
||||
"len=%u, rssi=%d, tim=%lu usec, "
|
||||
"phy=0x%02x, chnl=%d\n",
|
||||
title, le16_to_cpu(fc), header->addr1[5],
|
||||
header->addr3[5], length, rssi,
|
||||
tsf_low - priv->scan_start_tsf,
|
||||
phy_flags, channel);
|
||||
}
|
||||
}
|
||||
if (print_dump)
|
||||
iwl_print_hex_dump(priv, IWL_DL_RX, header, length);
|
||||
}
|
||||
#endif
|
||||
|
||||
static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
|
||||
{
|
||||
u32 decrypt_out = 0;
|
||||
|
@ -1060,11 +976,6 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv,
|
|||
/* Find max signal strength (dBm) among 3 antenna/receiver chains */
|
||||
rx_status.signal = iwlagn_calc_rssi(priv, phy_res);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
/* Set "1" to report good data frames in groups of 100 */
|
||||
if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
|
||||
iwlagn_dbg_report_frame(priv, phy_res, len, header, 1);
|
||||
#endif
|
||||
iwl_dbg_log_rx_data_frame(priv, len, header);
|
||||
IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
|
||||
rx_status.signal, (unsigned long long)rx_status.mactime);
|
||||
|
@ -1119,10 +1030,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
|||
struct iwl_scan_channel *scan_ch)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u16 passive_dwell = 0;
|
||||
u16 active_dwell = 0;
|
||||
int i, added = 0;
|
||||
int added = 0;
|
||||
u16 channel = 0;
|
||||
|
||||
sband = iwl_get_hw_mode(priv, band);
|
||||
|
@ -1137,32 +1047,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
|||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
||||
/* only scan single channel, good enough to reset the RF */
|
||||
/* pick the first valid not in-use channel */
|
||||
if (band == IEEE80211_BAND_5GHZ) {
|
||||
for (i = 14; i < priv->channel_count; i++) {
|
||||
if (priv->channel_info[i].channel !=
|
||||
le16_to_cpu(priv->staging_rxon.channel)) {
|
||||
channel = priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 14; i++) {
|
||||
if (priv->channel_info[i].channel !=
|
||||
le16_to_cpu(priv->staging_rxon.channel)) {
|
||||
channel =
|
||||
priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
channel = iwl_get_single_channel_number(priv, band);
|
||||
if (channel) {
|
||||
scan_ch->channel = cpu_to_le16(channel);
|
||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||
|
@ -1278,6 +1163,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
bool is_active = false;
|
||||
int chan_mod;
|
||||
u8 active_chains;
|
||||
u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
|
||||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
||||
|
@ -1429,11 +1315,14 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
|
||||
band = priv->scan_band;
|
||||
|
||||
if (priv->cfg->scan_antennas[band])
|
||||
rx_ant = priv->cfg->scan_antennas[band];
|
||||
if (priv->cfg->scan_rx_antennas[band])
|
||||
rx_ant = priv->cfg->scan_rx_antennas[band];
|
||||
|
||||
priv->scan_tx_ant[band] =
|
||||
iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
|
||||
if (priv->cfg->scan_tx_antennas[band])
|
||||
scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
|
||||
|
||||
priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band],
|
||||
scan_tx_antennas);
|
||||
rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
|
||||
scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
|
||||
|
||||
|
@ -1459,13 +1348,15 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
if (!priv->is_internal_short_scan) {
|
||||
cmd_len = iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
vif->addr,
|
||||
priv->scan_request->ie,
|
||||
priv->scan_request->ie_len,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
} else {
|
||||
/* use bcast addr, will not be transmitted but must be valid */
|
||||
cmd_len = iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
NULL, 0,
|
||||
iwl_bcast_addr, NULL, 0,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
|
||||
}
|
||||
|
@ -1528,3 +1419,18 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
|||
return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
|
||||
vif->bss_conf.bssid);
|
||||
}
|
||||
|
||||
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
|
||||
int sta_id, int tid, int freed)
|
||||
{
|
||||
WARN_ON(!spin_is_locked(&priv->sta_lock));
|
||||
|
||||
if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
|
||||
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
|
||||
else {
|
||||
IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
|
||||
priv->stations[sta_id].tid[tid].tfds_in_queue,
|
||||
freed);
|
||||
priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,8 +313,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
|
|||
*/
|
||||
IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
|
||||
tid);
|
||||
ieee80211_stop_tx_ba_session(sta, tid,
|
||||
WLAN_BACK_INITIATOR);
|
||||
ieee80211_stop_tx_ba_session(sta, tid);
|
||||
}
|
||||
} else
|
||||
IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid);
|
||||
|
|
|
@ -469,7 +469,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
/* Set up antennas */
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
||||
priv->hw_params.valid_tx_ant);
|
||||
rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
|
||||
|
||||
/* Set the rate in the TX cmd */
|
||||
|
@ -567,10 +568,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find index into station table for destination station */
|
||||
if (!info->control.sta)
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
else
|
||||
sta_id = iwl_sta_id(info->control.sta);
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
|
@ -598,11 +596,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
|
||||
|
||||
/* irqs already disabled/saved above when locking priv->lock */
|
||||
spin_lock(&priv->sta_lock);
|
||||
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||
if (unlikely(tid >= MAX_TID_COUNT))
|
||||
if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
|
||||
spin_unlock(&priv->sta_lock);
|
||||
goto drop_unlock;
|
||||
}
|
||||
seq_number = priv->stations[sta_id].tid[tid].seq_number;
|
||||
seq_number &= IEEE80211_SCTL_SEQ;
|
||||
hdr->seq_ctrl = hdr->seq_ctrl &
|
||||
|
@ -620,15 +624,22 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
swq_id = txq->swq_id;
|
||||
q = &txq->q;
|
||||
|
||||
if (unlikely(iwl_queue_space(q) < q->high_mark))
|
||||
if (unlikely(iwl_queue_space(q) < q->high_mark)) {
|
||||
spin_unlock(&priv->sta_lock);
|
||||
goto drop_unlock;
|
||||
}
|
||||
|
||||
if (ieee80211_is_data_qos(fc))
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
priv->stations[sta_id].tid[tid].tfds_in_queue++;
|
||||
if (!ieee80211_has_morefrags(fc))
|
||||
priv->stations[sta_id].tid[tid].seq_number = seq_number;
|
||||
}
|
||||
|
||||
spin_unlock(&priv->sta_lock);
|
||||
|
||||
/* Set up driver data for this TFD */
|
||||
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
|
||||
txq->txb[q->write_ptr].skb[0] = skb;
|
||||
txq->txb[q->write_ptr].skb = skb;
|
||||
|
||||
/* Set up first empty entry in queue's array of Tx/cmd buffers */
|
||||
out_cmd = txq->cmd[q->write_ptr];
|
||||
|
@ -694,8 +705,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
txcmd_phys = pci_map_single(priv->pci_dev,
|
||||
&out_cmd->hdr, len,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
pci_unmap_len_set(out_meta, len, len);
|
||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
dma_unmap_len_set(out_meta, len, len);
|
||||
/* Add buffer containing Tx command and MAC(!) header to TFD's
|
||||
* first entry */
|
||||
priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
|
||||
|
@ -703,8 +714,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
|
||||
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||
txq->need_update = 1;
|
||||
if (qc)
|
||||
priv->stations[sta_id].tid[tid].seq_number = seq_number;
|
||||
} else {
|
||||
wait_write_ptr = 1;
|
||||
txq->need_update = 0;
|
||||
|
@ -1009,6 +1018,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
tid_data = &priv->stations[sta_id].tid[tid];
|
||||
if (tid_data->tfds_in_queue == 0) {
|
||||
IWL_DEBUG_HT(priv, "HW queue is empty\n");
|
||||
tid_data->agg.state = IWL_AGG_ON;
|
||||
|
@ -1018,6 +1029,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||
tid_data->tfds_in_queue);
|
||||
tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1040,11 +1052,14 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
if (priv->stations[sta_id].tid[tid].agg.state ==
|
||||
IWL_EMPTYING_HW_QUEUE_ADDBA) {
|
||||
IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1062,13 +1077,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||
IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
|
||||
priv->stations[sta_id].tid[tid].agg.state =
|
||||
IWL_EMPTYING_HW_QUEUE_DELBA;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWL_DEBUG_HT(priv, "HW queue is empty\n");
|
||||
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
/* do not restore/save irqs */
|
||||
spin_unlock(&priv->sta_lock);
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
/*
|
||||
* the only reason this call can fail is queue number out of range,
|
||||
* which can happen if uCode is reloaded and all the station
|
||||
|
@ -1092,6 +1111,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
|
|||
u8 *addr = priv->stations[sta_id].sta.sta.addr;
|
||||
struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
|
||||
|
||||
WARN_ON(!spin_is_locked(&priv->sta_lock));
|
||||
|
||||
switch (priv->stations[sta_id].tid[tid].agg.state) {
|
||||
case IWL_EMPTYING_HW_QUEUE_DELBA:
|
||||
/* We are reclaiming the last packet of the */
|
||||
|
@ -1116,6 +1137,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1157,12 +1179,12 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
|
|||
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
|
||||
|
||||
tx_info = &txq->txb[txq->q.read_ptr];
|
||||
iwlagn_tx_status(priv, tx_info->skb[0]);
|
||||
iwlagn_tx_status(priv, tx_info->skb);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data;
|
||||
hdr = (struct ieee80211_hdr *)tx_info->skb->data;
|
||||
if (hdr && ieee80211_is_data_qos(hdr->frame_control))
|
||||
nfreed++;
|
||||
tx_info->skb[0] = NULL;
|
||||
tx_info->skb = NULL;
|
||||
|
||||
if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
|
||||
priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq);
|
||||
|
@ -1186,7 +1208,7 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
|
|||
int i, sh, ack;
|
||||
u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
|
||||
u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
|
||||
u64 bitmap;
|
||||
u64 bitmap, sent_bitmap;
|
||||
int successes = 0;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
|
@ -1214,24 +1236,26 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
|
|||
|
||||
/* check for success or failure according to the
|
||||
* transmitted bitmap and block-ack bitmap */
|
||||
bitmap &= agg->bitmap;
|
||||
sent_bitmap = bitmap & agg->bitmap;
|
||||
|
||||
/* For each frame attempted in aggregation,
|
||||
* update driver's record of tx frame's status. */
|
||||
for (i = 0; i < agg->frame_count ; i++) {
|
||||
ack = bitmap & (1ULL << i);
|
||||
successes += !!ack;
|
||||
i = 0;
|
||||
while (sent_bitmap) {
|
||||
ack = sent_bitmap & 1ULL;
|
||||
successes += ack;
|
||||
IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
|
||||
ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff,
|
||||
agg->start_idx + i);
|
||||
sent_bitmap >>= 1;
|
||||
++i;
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]);
|
||||
info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||
info->status.ampdu_ack_len = successes;
|
||||
info->status.ampdu_ack_map = bitmap;
|
||||
info->status.ampdu_len = agg->frame_count;
|
||||
iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
|
||||
|
||||
|
@ -1279,6 +1303,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
int index;
|
||||
int sta_id;
|
||||
int tid;
|
||||
unsigned long flags;
|
||||
|
||||
/* "flow" corresponds to Tx queue */
|
||||
u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
|
||||
|
@ -1301,7 +1326,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
/* Find index just before block-ack window */
|
||||
index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
|
||||
|
||||
/* TODO: Need to get this copy more safely - now good for debug */
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
|
||||
"sta_id = %d\n",
|
||||
|
@ -1337,4 +1362,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
|
||||
iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
|
|
@ -423,3 +423,126 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
|
||||
* using sample data 100 bytes apart. If these sample points are good,
|
||||
* it's a pretty good bet that everything between them is good, too.
|
||||
*/
|
||||
static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
|
||||
{
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
u32 errcnt = 0;
|
||||
u32 i;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
|
||||
|
||||
for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
/* NOTE: Use the debugless read so we don't flood kernel log
|
||||
* if IWL_DL_IO is set */
|
||||
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
|
||||
i + IWLAGN_RTC_INST_LOWER_BOUND);
|
||||
val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
if (val != le32_to_cpu(*image)) {
|
||||
ret = -EIO;
|
||||
errcnt++;
|
||||
if (errcnt >= 3)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwlcore_verify_inst_full - verify runtime uCode image in card vs. host,
|
||||
* looking at all data.
|
||||
*/
|
||||
static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image,
|
||||
u32 len)
|
||||
{
|
||||
u32 val;
|
||||
u32 save_len = len;
|
||||
int ret = 0;
|
||||
u32 errcnt;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
|
||||
|
||||
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
|
||||
IWLAGN_RTC_INST_LOWER_BOUND);
|
||||
|
||||
errcnt = 0;
|
||||
for (; len > 0; len -= sizeof(u32), image++) {
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
/* NOTE: Use the debugless read so we don't flood kernel log
|
||||
* if IWL_DL_IO is set */
|
||||
val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
if (val != le32_to_cpu(*image)) {
|
||||
IWL_ERR(priv, "uCode INST section is invalid at "
|
||||
"offset 0x%x, is 0x%x, s/b 0x%x\n",
|
||||
save_len - len, val, le32_to_cpu(*image));
|
||||
ret = -EIO;
|
||||
errcnt++;
|
||||
if (errcnt >= 20)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!errcnt)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"ucode image in INSTRUCTION memory is good\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_verify_ucode - determine which instruction image is in SRAM,
|
||||
* and verify its contents
|
||||
*/
|
||||
int iwl_verify_ucode(struct iwl_priv *priv)
|
||||
{
|
||||
__le32 *image;
|
||||
u32 len;
|
||||
int ret;
|
||||
|
||||
/* Try bootstrap */
|
||||
image = (__le32 *)priv->ucode_boot.v_addr;
|
||||
len = priv->ucode_boot.len;
|
||||
ret = iwlcore_verify_inst_sparse(priv, image, len);
|
||||
if (!ret) {
|
||||
IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try initialize */
|
||||
image = (__le32 *)priv->ucode_init.v_addr;
|
||||
len = priv->ucode_init.len;
|
||||
ret = iwlcore_verify_inst_sparse(priv, image, len);
|
||||
if (!ret) {
|
||||
IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try runtime/protocol */
|
||||
image = (__le32 *)priv->ucode_code.v_addr;
|
||||
len = priv->ucode_code.len;
|
||||
ret = iwlcore_verify_inst_sparse(priv, image, len);
|
||||
if (!ret) {
|
||||
IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
|
||||
|
||||
/* Since nothing seems to match, show first several data entries in
|
||||
* instruction SRAM, so maybe visual inspection will give a clue.
|
||||
* Selection of bootstrap image (vs. other images) is arbitrary. */
|
||||
image = (__le32 *)priv->ucode_boot.v_addr;
|
||||
len = priv->ucode_boot.len;
|
||||
ret = iwl_verify_inst_full(priv, image, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
(priv->switch_rxon.channel != priv->staging_rxon.channel)) {
|
||||
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
||||
le16_to_cpu(priv->switch_rxon.channel));
|
||||
priv->switch_rxon.switch_in_progress = false;
|
||||
iwl_chswitch_done(priv, false);
|
||||
}
|
||||
|
||||
/* If we don't need to send a full RXON, we can use
|
||||
|
@ -367,7 +367,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
|
|||
|
||||
/* Set up packet rate and flags */
|
||||
rate = iwl_rate_get_lowest_plcp(priv);
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
||||
priv->hw_params.valid_tx_ant);
|
||||
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
|
||||
if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
|
||||
rate_flags |= RATE_MCS_CCK_MSK;
|
||||
|
@ -474,18 +475,25 @@ void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
|||
/* Unmap tx_cmd */
|
||||
if (num_tbs)
|
||||
pci_unmap_single(dev,
|
||||
pci_unmap_addr(&txq->meta[index], mapping),
|
||||
pci_unmap_len(&txq->meta[index], len),
|
||||
dma_unmap_addr(&txq->meta[index], mapping),
|
||||
dma_unmap_len(&txq->meta[index], len),
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
/* Unmap chunks, if any. */
|
||||
for (i = 1; i < num_tbs; i++) {
|
||||
for (i = 1; i < num_tbs; i++)
|
||||
pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
|
||||
iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
|
||||
|
||||
if (txq->txb) {
|
||||
dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]);
|
||||
txq->txb[txq->q.read_ptr].skb[i - 1] = NULL;
|
||||
/* free SKB */
|
||||
if (txq->txb) {
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = txq->txb[txq->q.read_ptr].skb;
|
||||
|
||||
/* can be called from irqs-disabled context */
|
||||
if (skb) {
|
||||
dev_kfree_skb_any(skb);
|
||||
txq->txb[txq->q.read_ptr].skb = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1466,7 +1474,12 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
|
|||
" expected_ack_cnt = %d\n",
|
||||
actual_ack_cnt_delta, expected_ack_cnt_delta);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/*
|
||||
* This is ifdef'ed on DEBUGFS because otherwise the
|
||||
* statistics aren't available. If DEBUGFS is set but
|
||||
* DEBUG is not, these will just compile out.
|
||||
*/
|
||||
IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
|
||||
priv->delta_statistics.tx.rx_detected_cnt);
|
||||
IWL_DEBUG_RADIO(priv,
|
||||
|
@ -1484,6 +1497,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* sysfs attributes
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
||||
/*
|
||||
* The following adds a new attribute to the sysfs representation
|
||||
* of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
|
||||
* used for controlling the debug level.
|
||||
*
|
||||
* See the level definitions in iwl for details.
|
||||
*
|
||||
* The debug_level being managed using sysfs below is a per device debug
|
||||
* level that is used instead of the global debug level if it (the per
|
||||
* device debug level) is set.
|
||||
*/
|
||||
static ssize_t show_debug_level(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
|
||||
}
|
||||
static ssize_t store_debug_level(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
|
||||
else {
|
||||
priv->debug_level = val;
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(priv,
|
||||
"Not enough memory to generate traffic log\n");
|
||||
}
|
||||
return strnlen(buf, count);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
||||
show_debug_level, store_debug_level);
|
||||
|
||||
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
|
||||
static ssize_t show_temperature(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
return sprintf(buf, "%d\n", priv->temperature);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
|
||||
|
||||
static ssize_t show_tx_power(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return sprintf(buf, "off\n");
|
||||
else
|
||||
return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
|
||||
}
|
||||
|
||||
static ssize_t store_tx_power(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "%s is not in decimal form.\n", buf);
|
||||
else {
|
||||
ret = iwl_set_tx_power(priv, val, false);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed setting tx power (0x%d).\n",
|
||||
ret);
|
||||
else
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
|
||||
|
||||
static ssize_t show_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
|
||||
}
|
||||
|
||||
static ssize_t store_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "Input is not in decimal form.\n");
|
||||
else {
|
||||
if (!iwl_is_associated(priv))
|
||||
priv->cfg->use_rts_for_ht = val ? true : false;
|
||||
else
|
||||
IWL_ERR(priv, "Sta associated with AP - "
|
||||
"Change protection mechanism is not allowed\n");
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
|
||||
show_rts_ht_protection, store_rts_ht_protection);
|
||||
|
||||
|
||||
static struct attribute *iwl_sysfs_entries[] = {
|
||||
&dev_attr_temperature.attr,
|
||||
&dev_attr_tx_power.attr,
|
||||
&dev_attr_rts_ht_protection.attr,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
&dev_attr_debug_level.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group iwl_attribute_group = {
|
||||
.name = NULL, /* put in device directory */
|
||||
.attrs = iwl_sysfs_entries,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* uCode download functions
|
||||
|
@ -1544,6 +1707,9 @@ struct iwlagn_firmware_pieces {
|
|||
size_t inst_size, data_size, init_size, init_data_size, boot_size;
|
||||
|
||||
u32 build;
|
||||
|
||||
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
};
|
||||
|
||||
static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
|
||||
|
@ -1721,6 +1887,42 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
|||
capa->max_probe_length =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
|
||||
if (tlv_len != 4)
|
||||
return -EINVAL;
|
||||
pieces->init_evtlog_ptr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
|
||||
if (tlv_len != 4)
|
||||
return -EINVAL;
|
||||
pieces->init_evtlog_size =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
|
||||
if (tlv_len != 4)
|
||||
return -EINVAL;
|
||||
pieces->init_errlog_ptr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
|
||||
if (tlv_len != 4)
|
||||
return -EINVAL;
|
||||
pieces->inst_evtlog_ptr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
|
||||
if (tlv_len != 4)
|
||||
return -EINVAL;
|
||||
pieces->inst_evtlog_size =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
|
||||
if (tlv_len != 4)
|
||||
return -EINVAL;
|
||||
pieces->inst_errlog_ptr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1913,6 +2115,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
goto err_pci_alloc;
|
||||
}
|
||||
|
||||
/* Now that we can no longer fail, copy information */
|
||||
|
||||
/*
|
||||
* The (size - 16) / 12 formula is based on the information recorded
|
||||
* for each event, which is of mode 1 (including timestamp) for all
|
||||
* new microcodes that include this information.
|
||||
*/
|
||||
priv->_agn.init_evtlog_ptr = pieces.init_evtlog_ptr;
|
||||
if (pieces.init_evtlog_size)
|
||||
priv->_agn.init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
|
||||
else
|
||||
priv->_agn.init_evtlog_size = priv->cfg->max_event_log_size;
|
||||
priv->_agn.init_errlog_ptr = pieces.init_errlog_ptr;
|
||||
priv->_agn.inst_evtlog_ptr = pieces.inst_evtlog_ptr;
|
||||
if (pieces.inst_evtlog_size)
|
||||
priv->_agn.inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
|
||||
else
|
||||
priv->_agn.inst_evtlog_size = priv->cfg->max_event_log_size;
|
||||
priv->_agn.inst_errlog_ptr = pieces.inst_errlog_ptr;
|
||||
|
||||
/* Copy images into buffers for card's bus-master reads ... */
|
||||
|
||||
/* Runtime instructions (first block of data in file) */
|
||||
|
@ -1965,6 +2187,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
if (err)
|
||||
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
|
||||
|
||||
err = sysfs_create_group(&priv->pci_dev->dev.kobj,
|
||||
&iwl_attribute_group);
|
||||
if (err) {
|
||||
IWL_ERR(priv, "failed to create sysfs device attributes\n");
|
||||
goto out_unbind;
|
||||
}
|
||||
|
||||
/* We have our copies now, allow OS release its copies */
|
||||
release_firmware(ucode_raw);
|
||||
complete(&priv->_agn.firmware_loading_complete);
|
||||
|
@ -2038,10 +2267,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
|
|||
u32 blink1, blink2, ilink1, ilink2;
|
||||
u32 pc, hcmd;
|
||||
|
||||
if (priv->ucode_type == UCODE_INIT)
|
||||
if (priv->ucode_type == UCODE_INIT) {
|
||||
base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
|
||||
else
|
||||
if (!base)
|
||||
base = priv->_agn.init_errlog_ptr;
|
||||
} else {
|
||||
base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
|
||||
if (!base)
|
||||
base = priv->_agn.inst_errlog_ptr;
|
||||
}
|
||||
|
||||
if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
|
||||
IWL_ERR(priv,
|
||||
|
@ -2101,10 +2335,16 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
|||
|
||||
if (num_events == 0)
|
||||
return pos;
|
||||
if (priv->ucode_type == UCODE_INIT)
|
||||
|
||||
if (priv->ucode_type == UCODE_INIT) {
|
||||
base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
|
||||
else
|
||||
if (!base)
|
||||
base = priv->_agn.init_evtlog_ptr;
|
||||
} else {
|
||||
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
|
||||
if (!base)
|
||||
base = priv->_agn.inst_evtlog_ptr;
|
||||
}
|
||||
|
||||
if (mode == 0)
|
||||
event_size = 2 * sizeof(u32);
|
||||
|
@ -2206,13 +2446,21 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
|
|||
u32 num_wraps; /* # times uCode wrapped to top of log */
|
||||
u32 next_entry; /* index of next entry to be written by uCode */
|
||||
u32 size; /* # entries that we'll print */
|
||||
u32 logsize;
|
||||
int pos = 0;
|
||||
size_t bufsz = 0;
|
||||
|
||||
if (priv->ucode_type == UCODE_INIT)
|
||||
if (priv->ucode_type == UCODE_INIT) {
|
||||
base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
|
||||
else
|
||||
logsize = priv->_agn.init_evtlog_size;
|
||||
if (!base)
|
||||
base = priv->_agn.init_evtlog_ptr;
|
||||
} else {
|
||||
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
|
||||
logsize = priv->_agn.inst_evtlog_size;
|
||||
if (!base)
|
||||
base = priv->_agn.inst_evtlog_ptr;
|
||||
}
|
||||
|
||||
if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
|
||||
IWL_ERR(priv,
|
||||
|
@ -2227,16 +2475,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
|
|||
num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
|
||||
next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
|
||||
|
||||
if (capacity > priv->cfg->max_event_log_size) {
|
||||
if (capacity > logsize) {
|
||||
IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
|
||||
capacity, priv->cfg->max_event_log_size);
|
||||
capacity = priv->cfg->max_event_log_size;
|
||||
capacity, logsize);
|
||||
capacity = logsize;
|
||||
}
|
||||
|
||||
if (next_entry > priv->cfg->max_event_log_size) {
|
||||
if (next_entry > logsize) {
|
||||
IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
|
||||
next_entry, priv->cfg->max_event_log_size);
|
||||
next_entry = priv->cfg->max_event_log_size;
|
||||
next_entry, logsize);
|
||||
next_entry = logsize;
|
||||
}
|
||||
|
||||
size = num_wraps ? capacity : next_entry;
|
||||
|
@ -2361,8 +2609,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
||||
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
/* Configure Bluetooth device coexistence support */
|
||||
|
@ -2777,20 +3023,16 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
|
||||
if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
|
@ -3016,8 +3258,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
|
||||
priv->staging_rxon.assoc_id = 0;
|
||||
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
priv->staging_rxon.flags |=
|
||||
RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
|
@ -3025,17 +3266,12 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |=
|
||||
RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
/* restore RXON assoc */
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
|
@ -3081,17 +3317,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
}
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
|
@ -3262,141 +3490,98 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* sysfs attributes
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
||||
/*
|
||||
* The following adds a new attribute to the sysfs representation
|
||||
* of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
|
||||
* used for controlling the debug level.
|
||||
*
|
||||
* See the level definitions in iwl for details.
|
||||
*
|
||||
* The debug_level being managed using sysfs below is a per device debug
|
||||
* level that is used instead of the global debug level if it (the per
|
||||
* device debug level) is set.
|
||||
*/
|
||||
static ssize_t show_debug_level(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
|
||||
}
|
||||
static ssize_t store_debug_level(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
u16 ch;
|
||||
unsigned long flags = 0;
|
||||
|
||||
ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
|
||||
else {
|
||||
priv->debug_level = val;
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(priv,
|
||||
"Not enough memory to generate traffic log\n");
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
if (iwl_is_rfkill(priv))
|
||||
goto out_exit;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
|
||||
test_bit(STATUS_SCANNING, &priv->status))
|
||||
goto out_exit;
|
||||
|
||||
if (!iwl_is_associated(priv))
|
||||
goto out_exit;
|
||||
|
||||
/* channel switch in progress */
|
||||
if (priv->switch_rxon.switch_in_progress == true)
|
||||
goto out_exit;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if (priv->cfg->ops->lib->set_channel_switch) {
|
||||
|
||||
ch = ieee80211_frequency_to_channel(
|
||||
ch_switch->channel->center_freq);
|
||||
if (le16_to_cpu(priv->active_rxon.channel) != ch) {
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
conf->channel->band,
|
||||
ch);
|
||||
if (!is_channel_valid(ch_info)) {
|
||||
IWL_DEBUG_MAC80211(priv, "invalid channel\n");
|
||||
goto out;
|
||||
}
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
priv->current_ht_config.smps = conf->smps_mode;
|
||||
|
||||
/* Configure HT40 channels */
|
||||
ht_conf->is_ht = conf_is_ht(conf);
|
||||
if (ht_conf->is_ht) {
|
||||
if (conf_is_ht40_minus(conf)) {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
ht_conf->is_40mhz = true;
|
||||
} else if (conf_is_ht40_plus(conf)) {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
ht_conf->is_40mhz = true;
|
||||
} else {
|
||||
ht_conf->extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
ht_conf->is_40mhz = false;
|
||||
}
|
||||
} else
|
||||
ht_conf->is_40mhz = false;
|
||||
|
||||
/* if we are switching from ht to 2.4 clear flags
|
||||
* from any ht related info since 2.4 does not
|
||||
* support ht */
|
||||
if ((le16_to_cpu(priv->staging_rxon.channel) != ch))
|
||||
priv->staging_rxon.flags = 0;
|
||||
|
||||
iwl_set_rxon_channel(priv, conf->channel);
|
||||
iwl_set_rxon_ht(priv, ht_conf);
|
||||
iwl_set_flags_for_band(priv, conf->channel->band,
|
||||
priv->vif);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
iwl_set_rate(priv);
|
||||
/*
|
||||
* at this point, staging_rxon has the
|
||||
* configuration for channel switch
|
||||
*/
|
||||
if (priv->cfg->ops->lib->set_channel_switch(priv,
|
||||
ch_switch))
|
||||
priv->switch_rxon.switch_in_progress = false;
|
||||
}
|
||||
}
|
||||
return strnlen(buf, count);
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
out_exit:
|
||||
if (!priv->switch_rxon.switch_in_progress)
|
||||
ieee80211_chswitch_done(priv->vif, false);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
||||
show_debug_level, store_debug_level);
|
||||
|
||||
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
|
||||
static ssize_t show_temperature(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
return sprintf(buf, "%d\n", priv->temperature);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
|
||||
|
||||
static ssize_t show_tx_power(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return sprintf(buf, "off\n");
|
||||
else
|
||||
return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
|
||||
}
|
||||
|
||||
static ssize_t store_tx_power(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "%s is not in decimal form.\n", buf);
|
||||
else {
|
||||
ret = iwl_set_tx_power(priv, val, false);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed setting tx power (0x%d).\n",
|
||||
ret);
|
||||
else
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
|
||||
|
||||
static ssize_t show_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
|
||||
}
|
||||
|
||||
static ssize_t store_rts_ht_protection(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "Input is not in decimal form.\n");
|
||||
else {
|
||||
if (!iwl_is_associated(priv))
|
||||
priv->cfg->use_rts_for_ht = val ? true : false;
|
||||
else
|
||||
IWL_ERR(priv, "Sta associated with AP - "
|
||||
"Change protection mechanism is not allowed\n");
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
|
||||
show_rts_ht_protection, store_rts_ht_protection);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* driver setup and teardown
|
||||
|
@ -3550,21 +3735,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
|
|||
kfree(priv->scan_cmd);
|
||||
}
|
||||
|
||||
static struct attribute *iwl_sysfs_entries[] = {
|
||||
&dev_attr_temperature.attr,
|
||||
&dev_attr_tx_power.attr,
|
||||
&dev_attr_rts_ht_protection.attr,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
&dev_attr_debug_level.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group iwl_attribute_group = {
|
||||
.name = NULL, /* put in device directory */
|
||||
.attrs = iwl_sysfs_entries,
|
||||
};
|
||||
|
||||
static struct ieee80211_ops iwl_hw_ops = {
|
||||
.tx = iwl_mac_tx,
|
||||
.start = iwl_mac_start,
|
||||
|
@ -3583,6 +3753,7 @@ static struct ieee80211_ops iwl_hw_ops = {
|
|||
.sta_notify = iwl_mac_sta_notify,
|
||||
.sta_add = iwlagn_mac_sta_add,
|
||||
.sta_remove = iwl_mac_sta_remove,
|
||||
.channel_switch = iwl_mac_channel_switch,
|
||||
};
|
||||
|
||||
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
@ -3593,6 +3764,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
|
||||
unsigned long flags;
|
||||
u16 pci_cmd;
|
||||
u8 perm_addr[ETH_ALEN];
|
||||
|
||||
/************************
|
||||
* 1. Allocating HW data
|
||||
|
@ -3622,9 +3794,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
priv->pci_dev = pdev;
|
||||
priv->inta_mask = CSR_INI_SET_MASK;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
atomic_set(&priv->restrict_refcnt, 0);
|
||||
#endif
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(priv, "Not enough memory to generate traffic log\n");
|
||||
|
||||
|
@ -3713,9 +3882,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
goto out_free_eeprom;
|
||||
|
||||
/* extract MAC Address */
|
||||
iwl_eeprom_get_mac(priv, priv->mac_addr);
|
||||
IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr);
|
||||
SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
|
||||
iwl_eeprom_get_mac(priv, perm_addr);
|
||||
IWL_DEBUG_INFO(priv, "MAC address: %pM\n", perm_addr);
|
||||
SET_IEEE80211_PERM_ADDR(priv->hw, perm_addr);
|
||||
|
||||
/************************
|
||||
* 5. Setup HW constants
|
||||
|
@ -3750,11 +3919,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
|
||||
goto out_disable_msi;
|
||||
}
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
|
||||
if (err) {
|
||||
IWL_ERR(priv, "failed to create sysfs device attributes\n");
|
||||
goto out_free_irq;
|
||||
}
|
||||
|
||||
iwl_setup_deferred_work(priv);
|
||||
iwl_setup_rx_handlers(priv);
|
||||
|
@ -3788,15 +3952,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
err = iwl_request_firmware(priv, true);
|
||||
if (err)
|
||||
goto out_remove_sysfs;
|
||||
goto out_destroy_workqueue;
|
||||
|
||||
return 0;
|
||||
|
||||
out_remove_sysfs:
|
||||
out_destroy_workqueue:
|
||||
destroy_workqueue(priv->workqueue);
|
||||
priv->workqueue = NULL;
|
||||
sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
|
||||
out_free_irq:
|
||||
free_irq(priv->pci_dev->irq, priv);
|
||||
iwl_free_isr_ict(priv);
|
||||
out_disable_msi:
|
||||
|
@ -3989,6 +4151,47 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
|||
{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)},
|
||||
|
||||
/* 6x00 Series Gen2b */
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0091, 0x5201, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0091, 0x5205, iwl6000g2b_2bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0091, 0x5206, iwl6000g2b_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0091, 0x5207, iwl6000g2b_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0091, 0x5221, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0091, 0x5225, iwl6000g2b_2bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0091, 0x5226, iwl6000g2b_2abg_cfg)},
|
||||
|
||||
/* 6x50 WiFi/WiMax Series */
|
||||
{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
|
||||
|
|
|
@ -65,6 +65,33 @@
|
|||
|
||||
#include "iwl-dev.h"
|
||||
|
||||
/* configuration for the _agn devices */
|
||||
extern struct iwl_cfg iwl4965_agn_cfg;
|
||||
extern struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern struct iwl_cfg iwl5100_agn_cfg;
|
||||
extern struct iwl_cfg iwl5350_agn_cfg;
|
||||
extern struct iwl_cfg iwl5100_bgn_cfg;
|
||||
extern struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern struct iwl_cfg iwl5150_abg_cfg;
|
||||
extern struct iwl_cfg iwl6000g2a_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000g2a_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6000g2a_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000g2b_bgn_cfg;
|
||||
extern struct iwl_cfg iwl6000g2b_bg_cfg;
|
||||
extern struct iwl_cfg iwl6000g2b_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000g2b_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6000g2b_2bgn_cfg;
|
||||
extern struct iwl_cfg iwl6000g2b_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2abg_cfg;
|
||||
extern struct iwl_cfg iwl1000_bgn_cfg;
|
||||
extern struct iwl_cfg iwl1000_bg_cfg;
|
||||
|
||||
extern struct iwl_mod_params iwlagn_mod_params;
|
||||
extern struct iwl_hcmd_ops iwlagn_hcmd;
|
||||
extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
|
||||
|
@ -93,6 +120,8 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
|
|||
int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
|
||||
u16 ssn_idx, u8 tx_fifo);
|
||||
void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask);
|
||||
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
|
||||
int sta_id, int tid, int freed);
|
||||
|
||||
/* uCode */
|
||||
int iwlagn_load_ucode(struct iwl_priv *priv);
|
||||
|
@ -102,6 +131,7 @@ void iwlagn_rx_calib_complete(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwlagn_init_alive_start(struct iwl_priv *priv);
|
||||
int iwlagn_alive_notify(struct iwl_priv *priv);
|
||||
int iwl_verify_ucode(struct iwl_priv *priv);
|
||||
|
||||
/* lib */
|
||||
void iwl_check_abort_status(struct iwl_priv *priv,
|
||||
|
@ -178,4 +208,8 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
|||
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add);
|
||||
|
||||
/* hcmd */
|
||||
int iwlagn_send_rxon_assoc(struct iwl_priv *priv);
|
||||
int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
|
||||
|
||||
#endif /* __iwl_agn_h__ */
|
||||
|
|
|
@ -95,7 +95,7 @@ enum {
|
|||
|
||||
/* Multi-Station support */
|
||||
REPLY_ADD_STA = 0x18,
|
||||
REPLY_REMOVE_STA = 0x19, /* not used */
|
||||
REPLY_REMOVE_STA = 0x19,
|
||||
REPLY_REMOVE_ALL_STA = 0x1a, /* not used */
|
||||
|
||||
/* Security */
|
||||
|
@ -952,7 +952,6 @@ struct iwl_qosparam_cmd {
|
|||
|
||||
/* Special, dedicated locations within device's station table */
|
||||
#define IWL_AP_ID 0
|
||||
#define IWL_MULTICAST_ID 1
|
||||
#define IWL_STA_ID 2
|
||||
#define IWL3945_BROADCAST_ID 24
|
||||
#define IWL3945_STATION_COUNT 25
|
||||
|
|
|
@ -141,13 +141,14 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
|
||||
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant)
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
|
||||
{
|
||||
int i;
|
||||
u8 ind = ant;
|
||||
|
||||
for (i = 0; i < RATE_ANT_NUM - 1; i++) {
|
||||
ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
|
||||
if (priv->hw_params.valid_tx_ant & BIT(ind))
|
||||
if (valid & BIT(ind))
|
||||
return ind;
|
||||
}
|
||||
return ant;
|
||||
|
@ -457,7 +458,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
|||
if (!sta_ht_inf->ht_supported)
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (priv->disable_ht40)
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -506,11 +507,11 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
}
|
||||
|
||||
beacon_int = iwl_adjust_beacon_interval(beacon_int,
|
||||
priv->hw_params.max_beacon_itrvl * 1024);
|
||||
priv->hw_params.max_beacon_itrvl * TIME_UNIT);
|
||||
priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
|
||||
|
||||
tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
|
||||
interval_tm = beacon_int * 1024;
|
||||
interval_tm = beacon_int * TIME_UNIT;
|
||||
rem = do_div(tsf, interval_tm);
|
||||
priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
|
||||
|
||||
|
@ -854,6 +855,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_set_rxon_chain);
|
||||
|
||||
/* Return valid channel */
|
||||
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
const struct iwl_channel_info *ch_info;
|
||||
int i;
|
||||
u8 channel = 0;
|
||||
|
||||
/* only scan single channel, good enough to reset the RF */
|
||||
/* pick the first valid not in-use channel */
|
||||
if (band == IEEE80211_BAND_5GHZ) {
|
||||
for (i = 14; i < priv->channel_count; i++) {
|
||||
if (priv->channel_info[i].channel !=
|
||||
le16_to_cpu(priv->staging_rxon.channel)) {
|
||||
channel = priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 14; i++) {
|
||||
if (priv->channel_info[i].channel !=
|
||||
le16_to_cpu(priv->staging_rxon.channel)) {
|
||||
channel =
|
||||
priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv,
|
||||
band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_get_single_channel_number);
|
||||
|
||||
/**
|
||||
* iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
|
||||
* @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
|
||||
|
@ -893,9 +933,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_set_rxon_channel);
|
||||
|
||||
static void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif)
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
if (band == IEEE80211_BAND_5GHZ) {
|
||||
priv->staging_rxon.flags &=
|
||||
|
@ -904,19 +944,17 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv,
|
|||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
} else {
|
||||
/* Copied from iwl_post_associate() */
|
||||
if (vif && vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif && vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (vif && vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
|
||||
priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK;
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_flags_for_band);
|
||||
|
||||
/*
|
||||
* initialize rxon structure with default values from eeprom
|
||||
|
@ -982,15 +1020,17 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
|||
/* clear both MIX and PURE40 mode flag */
|
||||
priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
|
||||
RXON_FLG_CHANNEL_MODE_PURE_40);
|
||||
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
|
||||
memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN);
|
||||
|
||||
if (vif)
|
||||
memcpy(priv->staging_rxon.node_addr, vif->addr, ETH_ALEN);
|
||||
|
||||
priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
|
||||
priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff;
|
||||
priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_connection_init_rx_config);
|
||||
|
||||
static void iwl_set_rate(struct iwl_priv *priv)
|
||||
void iwl_set_rate(struct iwl_priv *priv)
|
||||
{
|
||||
const struct ieee80211_supported_band *hw = NULL;
|
||||
struct ieee80211_rate *rate;
|
||||
|
@ -1018,6 +1058,21 @@ static void iwl_set_rate(struct iwl_priv *priv)
|
|||
priv->staging_rxon.ofdm_basic_rates =
|
||||
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_set_rate);
|
||||
|
||||
void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (priv->switch_rxon.switch_in_progress) {
|
||||
ieee80211_chswitch_done(priv->vif, is_success);
|
||||
mutex_lock(&priv->mutex);
|
||||
priv->switch_rxon.switch_in_progress = false;
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_chswitch_done);
|
||||
|
||||
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
|
@ -1032,11 +1087,12 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
|||
priv->staging_rxon.channel = csa->channel;
|
||||
IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
|
||||
le16_to_cpu(csa->channel));
|
||||
} else
|
||||
iwl_chswitch_done(priv, true);
|
||||
} else {
|
||||
IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
|
||||
le16_to_cpu(csa->channel));
|
||||
|
||||
priv->switch_rxon.switch_in_progress = false;
|
||||
iwl_chswitch_done(priv, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_csa);
|
||||
|
@ -1463,130 +1519,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_send_statistics_request);
|
||||
|
||||
/**
|
||||
* iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
|
||||
* using sample data 100 bytes apart. If these sample points are good,
|
||||
* it's a pretty good bet that everything between them is good, too.
|
||||
*/
|
||||
static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
|
||||
{
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
u32 errcnt = 0;
|
||||
u32 i;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
|
||||
|
||||
for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
/* NOTE: Use the debugless read so we don't flood kernel log
|
||||
* if IWL_DL_IO is set */
|
||||
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
|
||||
i + IWL49_RTC_INST_LOWER_BOUND);
|
||||
val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
if (val != le32_to_cpu(*image)) {
|
||||
ret = -EIO;
|
||||
errcnt++;
|
||||
if (errcnt >= 3)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwlcore_verify_inst_full - verify runtime uCode image in card vs. host,
|
||||
* looking at all data.
|
||||
*/
|
||||
static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image,
|
||||
u32 len)
|
||||
{
|
||||
u32 val;
|
||||
u32 save_len = len;
|
||||
int ret = 0;
|
||||
u32 errcnt;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
|
||||
|
||||
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
|
||||
IWL49_RTC_INST_LOWER_BOUND);
|
||||
|
||||
errcnt = 0;
|
||||
for (; len > 0; len -= sizeof(u32), image++) {
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
/* NOTE: Use the debugless read so we don't flood kernel log
|
||||
* if IWL_DL_IO is set */
|
||||
val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
|
||||
if (val != le32_to_cpu(*image)) {
|
||||
IWL_ERR(priv, "uCode INST section is invalid at "
|
||||
"offset 0x%x, is 0x%x, s/b 0x%x\n",
|
||||
save_len - len, val, le32_to_cpu(*image));
|
||||
ret = -EIO;
|
||||
errcnt++;
|
||||
if (errcnt >= 20)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!errcnt)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"ucode image in INSTRUCTION memory is good\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_verify_ucode - determine which instruction image is in SRAM,
|
||||
* and verify its contents
|
||||
*/
|
||||
int iwl_verify_ucode(struct iwl_priv *priv)
|
||||
{
|
||||
__le32 *image;
|
||||
u32 len;
|
||||
int ret;
|
||||
|
||||
/* Try bootstrap */
|
||||
image = (__le32 *)priv->ucode_boot.v_addr;
|
||||
len = priv->ucode_boot.len;
|
||||
ret = iwlcore_verify_inst_sparse(priv, image, len);
|
||||
if (!ret) {
|
||||
IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try initialize */
|
||||
image = (__le32 *)priv->ucode_init.v_addr;
|
||||
len = priv->ucode_init.len;
|
||||
ret = iwlcore_verify_inst_sparse(priv, image, len);
|
||||
if (!ret) {
|
||||
IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try runtime/protocol */
|
||||
image = (__le32 *)priv->ucode_code.v_addr;
|
||||
len = priv->ucode_code.len;
|
||||
ret = iwlcore_verify_inst_sparse(priv, image, len);
|
||||
if (!ret) {
|
||||
IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
|
||||
|
||||
/* Since nothing seems to match, show first several data entries in
|
||||
* instruction SRAM, so maybe visual inspection will give a clue.
|
||||
* Selection of bootstrap image (vs. other images) is arbitrary. */
|
||||
image = (__le32 *)priv->ucode_boot.v_addr;
|
||||
len = priv->ucode_boot.len;
|
||||
ret = iwl_verify_inst_full(priv, image, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_verify_ucode);
|
||||
|
||||
|
||||
void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_ct_kill_config cmd;
|
||||
|
@ -2007,8 +1939,6 @@ static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
||||
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
|
||||
|
||||
return iwlcore_commit_rxon(priv);
|
||||
}
|
||||
|
||||
|
@ -2017,7 +1947,8 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
struct iwl_priv *priv = hw->priv;
|
||||
int err = 0;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type);
|
||||
IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
|
||||
vif->type, vif->addr);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
|
@ -2035,9 +1966,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
priv->vif = vif;
|
||||
priv->iw_mode = vif->type;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr);
|
||||
memcpy(priv->mac_addr, vif->addr, ETH_ALEN);
|
||||
|
||||
err = iwl_set_mode(priv, vif);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
@ -2071,6 +1999,11 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
}
|
||||
if (priv->vif == vif) {
|
||||
priv->vif = NULL;
|
||||
if (priv->scan_vif == vif) {
|
||||
ieee80211_scan_completed(priv->hw, true);
|
||||
priv->scan_vif = NULL;
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
memset(priv->bssid, 0, ETH_ALEN);
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
@ -2171,22 +2104,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
|||
|
||||
iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
if (iwl_is_associated(priv) &&
|
||||
(le16_to_cpu(priv->active_rxon.channel) != ch) &&
|
||||
priv->cfg->ops->lib->set_channel_switch) {
|
||||
iwl_set_rate(priv);
|
||||
/*
|
||||
* at this point, staging_rxon has the
|
||||
* configuration for channel switch
|
||||
*/
|
||||
ret = priv->cfg->ops->lib->set_channel_switch(priv,
|
||||
ch);
|
||||
if (!ret) {
|
||||
iwl_print_rx_config_cmd(priv);
|
||||
goto out;
|
||||
}
|
||||
priv->switch_rxon.switch_in_progress = false;
|
||||
}
|
||||
|
||||
set_ch_out:
|
||||
/* The list of supported rates and rate mask can be different
|
||||
* for each band; since the band may have changed, reset
|
||||
|
@ -2544,7 +2462,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
|
|||
EXPORT_SYMBOL(iwl_update_stats);
|
||||
#endif
|
||||
|
||||
const static char *get_csr_string(int cmd)
|
||||
static const char *get_csr_string(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
IWL_CMD(CSR_HW_IF_CONFIG_REG);
|
||||
|
@ -2615,7 +2533,7 @@ void iwl_dump_csr(struct iwl_priv *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_dump_csr);
|
||||
|
||||
const static char *get_fh_string(int cmd)
|
||||
static const char *get_fh_string(int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
|
||||
|
@ -2837,6 +2755,61 @@ void iwl_bg_monitor_recover(unsigned long data)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_bg_monitor_recover);
|
||||
|
||||
|
||||
/*
|
||||
* extended beacon time format
|
||||
* time in usec will be changed into a 32-bit value in extended:internal format
|
||||
* the extended part is the beacon counts
|
||||
* the internal part is the time in usec within one beacon interval
|
||||
*/
|
||||
u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval)
|
||||
{
|
||||
u32 quot;
|
||||
u32 rem;
|
||||
u32 interval = beacon_interval * TIME_UNIT;
|
||||
|
||||
if (!interval || !usec)
|
||||
return 0;
|
||||
|
||||
quot = (usec / interval) &
|
||||
(iwl_beacon_time_mask_high(priv,
|
||||
priv->hw_params.beacon_time_tsf_bits) >>
|
||||
priv->hw_params.beacon_time_tsf_bits);
|
||||
rem = (usec % interval) & iwl_beacon_time_mask_low(priv,
|
||||
priv->hw_params.beacon_time_tsf_bits);
|
||||
|
||||
return (quot << priv->hw_params.beacon_time_tsf_bits) + rem;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_usecs_to_beacons);
|
||||
|
||||
/* base is usually what we get from ucode with each received frame,
|
||||
* the same as HW timer counter counting down
|
||||
*/
|
||||
__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
|
||||
u32 addon, u32 beacon_interval)
|
||||
{
|
||||
u32 base_low = base & iwl_beacon_time_mask_low(priv,
|
||||
priv->hw_params.beacon_time_tsf_bits);
|
||||
u32 addon_low = addon & iwl_beacon_time_mask_low(priv,
|
||||
priv->hw_params.beacon_time_tsf_bits);
|
||||
u32 interval = beacon_interval * TIME_UNIT;
|
||||
u32 res = (base & iwl_beacon_time_mask_high(priv,
|
||||
priv->hw_params.beacon_time_tsf_bits)) +
|
||||
(addon & iwl_beacon_time_mask_high(priv,
|
||||
priv->hw_params.beacon_time_tsf_bits));
|
||||
|
||||
if (base_low > addon_low)
|
||||
res += base_low - addon_low;
|
||||
else if (base_low < addon_low) {
|
||||
res += interval + base_low - addon_low;
|
||||
res += (1 << priv->hw_params.beacon_time_tsf_bits);
|
||||
} else
|
||||
res += (1 << priv->hw_params.beacon_time_tsf_bits);
|
||||
|
||||
return cpu_to_le32(res);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_add_beacon_time);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
|
|
|
@ -79,6 +79,8 @@ struct iwl_cmd;
|
|||
.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
|
||||
.driver_data = (kernel_ulong_t)&(cfg)
|
||||
|
||||
#define TIME_UNIT 1024
|
||||
|
||||
#define IWL_SKU_G 0x1
|
||||
#define IWL_SKU_A 0x2
|
||||
#define IWL_SKU_N 0x8
|
||||
|
@ -173,7 +175,8 @@ struct iwl_lib_ops {
|
|||
void (*dump_nic_error_log)(struct iwl_priv *priv);
|
||||
void (*dump_csr)(struct iwl_priv *priv);
|
||||
int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
|
||||
int (*set_channel_switch)(struct iwl_priv *priv, u16 channel);
|
||||
int (*set_channel_switch)(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
/* power management */
|
||||
struct iwl_apm_ops apm_ops;
|
||||
|
||||
|
@ -325,7 +328,8 @@ struct iwl_cfg {
|
|||
const bool ucode_tracing;
|
||||
const bool sensitivity_calib_by_driver;
|
||||
const bool chain_noise_calib_by_driver;
|
||||
u8 scan_antennas[IEEE80211_NUM_BANDS];
|
||||
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
|
||||
u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
|
||||
};
|
||||
|
||||
/***************************
|
||||
|
@ -343,11 +347,17 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv);
|
|||
int iwl_full_rxon_required(struct iwl_priv *priv);
|
||||
void iwl_set_rxon_chain(struct iwl_priv *priv);
|
||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif);
|
||||
u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
||||
enum ieee80211_band band);
|
||||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
|
||||
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf);
|
||||
void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_set_rate(struct iwl_priv *priv);
|
||||
int iwl_set_decrypted_flag(struct iwl_priv *priv,
|
||||
struct ieee80211_hdr *hdr,
|
||||
u32 decrypt_res,
|
||||
|
@ -459,6 +469,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl_reply_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
|
||||
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
|
||||
|
||||
/* TX helpers */
|
||||
|
@ -472,8 +483,6 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
|
|||
dma_addr_t addr, u16 len, u8 reset, u8 pad);
|
||||
int iwl_hw_tx_queue_init(struct iwl_priv *priv,
|
||||
struct iwl_tx_queue *txq);
|
||||
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
|
||||
int sta_id, int tid, int freed);
|
||||
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
|
||||
int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
|
||||
int slots_num, u32 txq_id);
|
||||
|
@ -493,7 +502,7 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
|
|||
|
||||
u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv);
|
||||
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx);
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
|
||||
|
||||
static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
|
||||
{
|
||||
|
@ -526,7 +535,7 @@ void iwl_bg_start_internal_scan(struct work_struct *work);
|
|||
void iwl_internal_short_hw_scan(struct iwl_priv *priv);
|
||||
int iwl_force_reset(struct iwl_priv *priv, int mode);
|
||||
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
||||
const u8 *ie, int ie_len, int left);
|
||||
const u8 *ta, const u8 *ie, int ie_len, int left);
|
||||
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
|
||||
u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
|
@ -593,6 +602,9 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
void iwl_bg_monitor_recover(unsigned long data);
|
||||
u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
|
||||
__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
|
||||
u32 addon, u32 beacon_interval);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
|
||||
|
@ -691,7 +703,6 @@ extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
|
|||
extern void iwl_send_bt_config(struct iwl_priv *priv);
|
||||
extern int iwl_send_statistics_request(struct iwl_priv *priv,
|
||||
u8 flags, bool clear);
|
||||
extern int iwl_verify_ucode(struct iwl_priv *priv);
|
||||
extern int iwl_send_lq_cmd(struct iwl_priv *priv,
|
||||
struct iwl_link_quality_cmd *lq, u8 flags, bool init);
|
||||
void iwl_apm_stop(struct iwl_priv *priv);
|
||||
|
|
|
@ -106,27 +106,6 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
|||
.open = iwl_dbgfs_open_file_generic, \
|
||||
};
|
||||
|
||||
int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
|
||||
{
|
||||
int p = 0;
|
||||
|
||||
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
|
||||
le32_to_cpu(priv->statistics.flag));
|
||||
if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
|
||||
p += scnprintf(buf + p, bufsz - p,
|
||||
"\tStatistics have been cleared\n");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
|
||||
(le32_to_cpu(priv->statistics.flag) &
|
||||
UCODE_STATISTICS_FREQUENCY_MSK)
|
||||
? "2.4 GHz" : "5.2 GHz");
|
||||
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
|
||||
(le32_to_cpu(priv->statistics.flag) &
|
||||
UCODE_STATISTICS_NARROW_BAND_MSK)
|
||||
? "enabled" : "disabled");
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_dbgfs_statistics_flag);
|
||||
|
||||
static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
@ -330,45 +309,35 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
|
|||
|
||||
for (i = 0; i < max_sta; i++) {
|
||||
station = &priv->stations[i];
|
||||
if (station->used) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"station %d:\ngeneral data:\n", i+1);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
|
||||
station->sta.sta.sta_id);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
|
||||
station->sta.mode);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"flags: 0x%x\n",
|
||||
station->sta.station_flags_msk);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"seq_num\t\ttxq_id");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tframe_count\twait_for_ba\t");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"start_idx\tbitmap0\t");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"bitmap1\trate_n_flags");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "\n");
|
||||
if (!station->used)
|
||||
continue;
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"station %d - addr: %pM, flags: %#x\n",
|
||||
i, station->sta.sta.addr,
|
||||
station->sta.station_flags_msk);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"TID\tseq_num\ttxq_id\tframes\ttfds\t");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"start_idx\tbitmap\t\t\trate_n_flags\n");
|
||||
|
||||
for (j = 0; j < MAX_TID_COUNT; j++) {
|
||||
for (j = 0; j < MAX_TID_COUNT; j++) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
|
||||
j, station->tid[j].seq_number,
|
||||
station->tid[j].agg.txq_id,
|
||||
station->tid[j].agg.frame_count,
|
||||
station->tid[j].tfds_in_queue,
|
||||
station->tid[j].agg.start_idx,
|
||||
station->tid[j].agg.bitmap,
|
||||
station->tid[j].agg.rate_n_flags);
|
||||
|
||||
if (station->tid[j].agg.wait_for_ba)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"[%d]:\t\t%u", j,
|
||||
station->tid[j].seq_number);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\t%u\t\t%u\t\t%u\t\t",
|
||||
station->tid[j].agg.txq_id,
|
||||
station->tid[j].agg.frame_count,
|
||||
station->tid[j].agg.wait_for_ba);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"%u\t%llu\t%u",
|
||||
station->tid[j].agg.start_idx,
|
||||
(unsigned long long)station->tid[j].agg.bitmap,
|
||||
station->tid[j].agg.rate_n_flags);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "\n");
|
||||
}
|
||||
" - waitforba");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "\n");
|
||||
}
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "\n");
|
||||
}
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
|
|
|
@ -48,25 +48,6 @@
|
|||
#include "iwl-power.h"
|
||||
#include "iwl-agn-rs.h"
|
||||
|
||||
/* configuration for the iwl4965 */
|
||||
extern struct iwl_cfg iwl4965_agn_cfg;
|
||||
extern struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern struct iwl_cfg iwl5100_agn_cfg;
|
||||
extern struct iwl_cfg iwl5350_agn_cfg;
|
||||
extern struct iwl_cfg iwl5100_bgn_cfg;
|
||||
extern struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern struct iwl_cfg iwl5150_abg_cfg;
|
||||
extern struct iwl_cfg iwl6000g2a_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2abg_cfg;
|
||||
extern struct iwl_cfg iwl1000_bgn_cfg;
|
||||
extern struct iwl_cfg iwl1000_bg_cfg;
|
||||
|
||||
struct iwl_tx_queue;
|
||||
|
||||
/* CT-KILL constants */
|
||||
|
@ -133,8 +114,8 @@ struct iwl_cmd_meta {
|
|||
* structure is stored at the end of the shared queue memory. */
|
||||
u32 flags;
|
||||
|
||||
DECLARE_PCI_UNMAP_ADDR(mapping)
|
||||
DECLARE_PCI_UNMAP_LEN(len)
|
||||
DEFINE_DMA_UNMAP_ADDR(mapping);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -161,7 +142,7 @@ struct iwl_queue {
|
|||
|
||||
/* One for each TFD */
|
||||
struct iwl_tx_info {
|
||||
struct sk_buff *skb[IWL_NUM_OF_TBS - 1];
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -433,7 +414,7 @@ struct iwl_ht_agg {
|
|||
|
||||
|
||||
struct iwl_tid_data {
|
||||
u16 seq_number;
|
||||
u16 seq_number; /* agn only */
|
||||
u16 tfds_in_queue;
|
||||
struct iwl_ht_agg agg;
|
||||
};
|
||||
|
@ -583,6 +564,12 @@ enum iwl_ucode_tlv_type {
|
|||
IWL_UCODE_TLV_INIT_DATA = 4,
|
||||
IWL_UCODE_TLV_BOOT = 5,
|
||||
IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */
|
||||
IWL_UCODE_TLV_RUNT_EVTLOG_PTR = 8,
|
||||
IWL_UCODE_TLV_RUNT_EVTLOG_SIZE = 9,
|
||||
IWL_UCODE_TLV_RUNT_ERRLOG_PTR = 10,
|
||||
IWL_UCODE_TLV_INIT_EVTLOG_PTR = 11,
|
||||
IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12,
|
||||
IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13,
|
||||
};
|
||||
|
||||
struct iwl_ucode_tlv {
|
||||
|
@ -675,6 +662,7 @@ struct iwl_sensitivity_ranges {
|
|||
* @sw_crypto: 0 for hw, 1 for sw
|
||||
* @max_xxx_size: for ucode uses
|
||||
* @ct_kill_threshold: temperature threshold
|
||||
* @beacon_time_tsf_bits: number of valid tsf bits for beacon time
|
||||
* @calib_init_cfg: setup initial calibrations for the hw
|
||||
* @struct iwl_sensitivity_ranges: range of sensitivity values
|
||||
*/
|
||||
|
@ -701,6 +689,7 @@ struct iwl_hw_params {
|
|||
u32 ct_kill_threshold; /* value in hw-dependent units */
|
||||
u32 ct_kill_exit_threshold; /* value in hw-dependent units */
|
||||
/* for 1000, 6000 series and up */
|
||||
u16 beacon_time_tsf_bits;
|
||||
u32 calib_init_cfg;
|
||||
const struct iwl_sensitivity_ranges *sens;
|
||||
};
|
||||
|
@ -1075,6 +1064,20 @@ struct iwl_force_reset {
|
|||
unsigned long last_force_reset_jiffies;
|
||||
};
|
||||
|
||||
/* extend beacon time format bit shifting */
|
||||
/*
|
||||
* for _3945 devices
|
||||
* bits 31:24 - extended
|
||||
* bits 23:0 - interval
|
||||
*/
|
||||
#define IWL3945_EXT_BEACON_TIME_POS 24
|
||||
/*
|
||||
* for _agn devices
|
||||
* bits 31:22 - extended
|
||||
* bits 21:0 - interval
|
||||
*/
|
||||
#define IWLAGN_EXT_BEACON_TIME_POS 22
|
||||
|
||||
struct iwl_priv {
|
||||
|
||||
/* ieee device used by generic ieee processing code */
|
||||
|
@ -1109,7 +1112,7 @@ struct iwl_priv {
|
|||
/* force reset */
|
||||
struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
|
||||
|
||||
/* we allocate array of iwl4965_channel_info for NIC's valid channels.
|
||||
/* we allocate array of iwl_channel_info for NIC's valid channels.
|
||||
* Access via channel # using indirect index array */
|
||||
struct iwl_channel_info *channel_info; /* channel info array */
|
||||
u8 channel_count; /* # of channels */
|
||||
|
@ -1127,6 +1130,7 @@ struct iwl_priv {
|
|||
void *scan_cmd;
|
||||
enum ieee80211_band scan_band;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct ieee80211_vif *scan_vif;
|
||||
bool is_internal_short_scan;
|
||||
u8 scan_tx_ant[IEEE80211_NUM_BANDS];
|
||||
u8 mgmt_tx_ant;
|
||||
|
@ -1174,7 +1178,7 @@ struct iwl_priv {
|
|||
struct iwl_switch_rxon switch_rxon;
|
||||
|
||||
/* 1st responses from initialize and runtime uCode images.
|
||||
* 4965's initialize alive response contains some calibration data. */
|
||||
* _agn's initialize alive response contains some calibration data. */
|
||||
struct iwl_init_alive_resp card_alive_init;
|
||||
struct iwl_alive_resp card_alive;
|
||||
|
||||
|
@ -1221,7 +1225,7 @@ struct iwl_priv {
|
|||
struct iwl_tt_mgmt thermal_throttle;
|
||||
|
||||
struct iwl_notif_statistics statistics;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
struct iwl_notif_statistics accum_statistics;
|
||||
struct iwl_notif_statistics delta_statistics;
|
||||
struct iwl_notif_statistics max_delta;
|
||||
|
@ -1229,9 +1233,10 @@ struct iwl_priv {
|
|||
|
||||
/* context information */
|
||||
u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
/*station table variables */
|
||||
/* station table variables */
|
||||
|
||||
/* Note: if lock and sta_lock are needed, lock must be acquired first */
|
||||
spinlock_t sta_lock;
|
||||
int num_stations;
|
||||
struct iwl_station_entry stations[IWL_STATION_COUNT];
|
||||
|
@ -1273,7 +1278,7 @@ struct iwl_priv {
|
|||
struct delayed_work rfkill_poll;
|
||||
|
||||
struct iwl3945_notif_statistics statistics;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
struct iwl3945_notif_statistics accum_statistics;
|
||||
struct iwl3945_notif_statistics delta_statistics;
|
||||
struct iwl3945_notif_statistics max_delta;
|
||||
|
@ -1315,6 +1320,9 @@ struct iwl_priv {
|
|||
bool last_phy_res_valid;
|
||||
|
||||
struct completion firmware_loading_complete;
|
||||
|
||||
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
} _agn;
|
||||
#endif
|
||||
};
|
||||
|
@ -1353,9 +1361,7 @@ struct iwl_priv {
|
|||
/* debugging info */
|
||||
u32 debug_level; /* per device debugging will override global
|
||||
iwl_debug_level if set */
|
||||
u32 framecnt_to_us;
|
||||
atomic_t restrict_refcnt;
|
||||
bool disable_ht40;
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/* debugfs */
|
||||
u16 tx_traffic_idx;
|
||||
|
@ -1364,8 +1370,8 @@ struct iwl_priv {
|
|||
u8 *rx_traffic;
|
||||
struct dentry *debugfs_dir;
|
||||
u32 dbgfs_sram_offset, dbgfs_sram_len;
|
||||
bool disable_ht40;
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
struct work_struct txpower_work;
|
||||
u32 disable_sens_cal;
|
||||
|
@ -1419,9 +1425,9 @@ static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
|
|||
static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv,
|
||||
int txq_id, int idx)
|
||||
{
|
||||
if (priv->txq[txq_id].txb[idx].skb[0])
|
||||
if (priv->txq[txq_id].txb[idx].skb)
|
||||
return (struct ieee80211_hdr *)priv->txq[txq_id].
|
||||
txb[idx].skb[0]->data;
|
||||
txb[idx].skb->data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,11 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
|
|||
static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
|
||||
struct fw_desc *desc)
|
||||
{
|
||||
if (!desc->len) {
|
||||
desc->v_addr = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
|
||||
&desc->p_addr, GFP_KERNEL);
|
||||
return (desc->v_addr != NULL) ? 0 : -ENOMEM;
|
||||
|
@ -170,4 +175,26 @@ static inline void iwl_enable_interrupts(struct iwl_priv *priv)
|
|||
iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
|
||||
* @priv -- pointer to iwl_priv data structure
|
||||
* @tsf_bits -- number of bits need to shift for masking)
|
||||
*/
|
||||
static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
|
||||
u16 tsf_bits)
|
||||
{
|
||||
return (1 << tsf_bits) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
|
||||
* @priv -- pointer to iwl_priv data structure
|
||||
* @tsf_bits -- number of bits need to shift for masking)
|
||||
*/
|
||||
static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
|
||||
u16 tsf_bits)
|
||||
{
|
||||
return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
|
||||
}
|
||||
|
||||
#endif /* __iwl_helpers_h__ */
|
||||
|
|
|
@ -286,7 +286,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)
|
|||
last_rx_noise);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
/*
|
||||
* based on the assumption of all statistics counter are in DWORD
|
||||
* FIXME: This function is for debugging, do not deal with
|
||||
|
@ -448,7 +448,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
|||
STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
|
||||
(pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
|
||||
#endif
|
||||
iwl_recover_from_statistics(priv, pkt);
|
||||
|
@ -480,7 +480,7 @@ void iwl_reply_statistics(struct iwl_priv *priv,
|
|||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
||||
if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
memset(&priv->accum_statistics, 0,
|
||||
sizeof(struct iwl_notif_statistics));
|
||||
memset(&priv->delta_statistics, 0,
|
||||
|
|
|
@ -333,7 +333,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
if (test_bit(STATUS_SCANNING, &priv->status) &&
|
||||
!priv->is_internal_short_scan) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
|
||||
ret = -EAGAIN;
|
||||
goto out_unlock;
|
||||
|
@ -348,8 +349,16 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
|||
/* mac80211 will only ask for one band at a time */
|
||||
priv->scan_band = req->channels[0]->band;
|
||||
priv->scan_request = req;
|
||||
priv->scan_vif = vif;
|
||||
|
||||
ret = iwl_scan_initiate(priv, vif);
|
||||
/*
|
||||
* If an internal scan is in progress, just set
|
||||
* up the scan_request as per above.
|
||||
*/
|
||||
if (priv->is_internal_short_scan)
|
||||
ret = 0;
|
||||
else
|
||||
ret = iwl_scan_initiate(priv, vif);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
|
@ -438,7 +447,7 @@ EXPORT_SYMBOL(iwl_bg_scan_check);
|
|||
*/
|
||||
|
||||
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
||||
const u8 *ies, int ie_len, int left)
|
||||
const u8 *ta, const u8 *ies, int ie_len, int left)
|
||||
{
|
||||
int len = 0;
|
||||
u8 *pos = NULL;
|
||||
|
@ -451,7 +460,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
|||
|
||||
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
|
||||
memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
|
||||
memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
|
||||
memcpy(frame->sa, ta, ETH_ALEN);
|
||||
memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
|
||||
frame->seq_ctrl = 0;
|
||||
|
||||
|
@ -513,7 +522,21 @@ void iwl_bg_scan_completed(struct work_struct *work)
|
|||
priv->is_internal_short_scan = false;
|
||||
IWL_DEBUG_SCAN(priv, "internal short scan completed\n");
|
||||
internal = true;
|
||||
} else {
|
||||
priv->scan_request = NULL;
|
||||
priv->scan_vif = NULL;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
goto out;
|
||||
|
||||
if (internal && priv->scan_request)
|
||||
iwl_scan_initiate(priv, priv->scan_vif);
|
||||
|
||||
/* Since setting the TXPOWER may have been deferred while
|
||||
* performing the scan, fire one off */
|
||||
iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
/*
|
||||
|
@ -523,15 +546,6 @@ void iwl_bg_scan_completed(struct work_struct *work)
|
|||
*/
|
||||
if (!internal)
|
||||
ieee80211_scan_completed(priv->hw, false);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* Since setting the TXPOWER may have been deferred while
|
||||
* performing the scan, fire one off */
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_bg_scan_completed);
|
||||
|
||||
|
|
|
@ -311,10 +311,10 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
|
|||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
u8 *sta_id_r)
|
||||
{
|
||||
struct iwl_station_entry *station;
|
||||
unsigned long flags_spin;
|
||||
int ret = 0;
|
||||
u8 sta_id;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
*sta_id_r = 0;
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
|
@ -347,14 +347,15 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
|
|||
}
|
||||
|
||||
priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
|
||||
station = &priv->stations[sta_id];
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||
|
||||
/* Add station to device's station table */
|
||||
ret = iwl_send_add_sta(priv, &station->sta, CMD_SYNC);
|
||||
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Adding station %pM failed.\n", station->sta.sta.addr);
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
IWL_ERR(priv, "Adding station %pM failed.\n",
|
||||
priv->stations[sta_id].sta.sta.addr);
|
||||
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||
|
@ -488,7 +489,7 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
|
|||
}
|
||||
|
||||
static int iwl_send_remove_station(struct iwl_priv *priv,
|
||||
struct iwl_station_entry *station)
|
||||
const u8 *addr, int sta_id)
|
||||
{
|
||||
struct iwl_rx_packet *pkt;
|
||||
int ret;
|
||||
|
@ -505,7 +506,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
|||
|
||||
memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
|
||||
rm_sta_cmd.num_sta = 1;
|
||||
memcpy(&rm_sta_cmd.addr, &station->sta.sta.addr , ETH_ALEN);
|
||||
memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN);
|
||||
|
||||
cmd.flags |= CMD_WANT_SKB;
|
||||
|
||||
|
@ -525,7 +526,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
|||
switch (pkt->u.rem_sta.status) {
|
||||
case REM_STA_SUCCESS_MSK:
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
iwl_sta_ucode_deactivate(priv, station->sta.sta.sta_id);
|
||||
iwl_sta_ucode_deactivate(priv, sta_id);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||
IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
|
||||
break;
|
||||
|
@ -546,7 +547,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
|||
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr)
|
||||
{
|
||||
struct iwl_station_entry *station;
|
||||
unsigned long flags;
|
||||
|
||||
if (!iwl_is_ready(priv)) {
|
||||
|
@ -592,10 +592,9 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
|||
|
||||
BUG_ON(priv->num_stations < 0);
|
||||
|
||||
station = &priv->stations[sta_id];
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_remove_station(priv, station);
|
||||
return iwl_send_remove_station(priv, addr, sta_id);
|
||||
out_err:
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return -EINVAL;
|
||||
|
@ -643,11 +642,13 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations);
|
|||
*/
|
||||
void iwl_restore_stations(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_station_entry *station;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
struct iwl_link_quality_cmd lq;
|
||||
unsigned long flags_spin;
|
||||
int i;
|
||||
bool found = false;
|
||||
int ret;
|
||||
bool send_lq;
|
||||
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n");
|
||||
|
@ -669,13 +670,20 @@ void iwl_restore_stations(struct iwl_priv *priv)
|
|||
|
||||
for (i = 0; i < priv->hw_params.max_stations; i++) {
|
||||
if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
|
||||
memcpy(&sta_cmd, &priv->stations[i].sta,
|
||||
sizeof(struct iwl_addsta_cmd));
|
||||
send_lq = false;
|
||||
if (priv->stations[i].lq) {
|
||||
memcpy(&lq, priv->stations[i].lq,
|
||||
sizeof(struct iwl_link_quality_cmd));
|
||||
send_lq = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||
station = &priv->stations[i];
|
||||
ret = iwl_send_add_sta(priv, &priv->stations[i].sta, CMD_SYNC);
|
||||
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Adding station %pM failed.\n",
|
||||
station->sta.sta.addr);
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
IWL_ERR(priv, "Adding station %pM failed.\n",
|
||||
priv->stations[i].sta.sta.addr);
|
||||
priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||
|
@ -684,8 +692,8 @@ void iwl_restore_stations(struct iwl_priv *priv)
|
|||
* Rate scaling has already been initialized, send
|
||||
* current LQ command
|
||||
*/
|
||||
if (station->lq)
|
||||
iwl_send_lq_cmd(priv, station->lq, CMD_SYNC, true);
|
||||
if (send_lq)
|
||||
iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true);
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
}
|
||||
|
@ -972,24 +980,16 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
|
|||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (sta) {
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n",
|
||||
sta->addr);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
|
||||
|
||||
if (iwl_scan_cancel(priv)) {
|
||||
/* cancel scan failed, just live w/ bad key and rely
|
||||
briefly on SW decryption */
|
||||
return;
|
||||
}
|
||||
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
|
||||
|
@ -1277,9 +1277,8 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
|
|||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
|
||||
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
|
||||
|
||||
|
@ -1310,7 +1309,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
|||
int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
int sta_id, ret;
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
|
@ -1323,10 +1322,11 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
|||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
|
||||
CMD_ASYNC);
|
||||
return ret;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
|
||||
|
||||
|
@ -1340,9 +1340,9 @@ void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
|||
priv->stations[sta_id].sta.sta.modify_mask = 0;
|
||||
priv->stations[sta_id].sta.sleep_tx_count = 0;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_modify_ps_wake);
|
||||
|
||||
|
@ -1357,9 +1357,9 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
|
|||
STA_MODIFY_SLEEP_TX_COUNT_MSK;
|
||||
priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
|
||||
|
||||
|
|
|
@ -107,4 +107,33 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
|
|||
|
||||
return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_sta_id_or_broadcast - return sta_id or broadcast sta
|
||||
* @priv: iwl priv
|
||||
* @sta: mac80211 station
|
||||
*
|
||||
* In certain circumstances mac80211 passes a station pointer
|
||||
* that may be %NULL, for example during TX or key setup. In
|
||||
* that case, we need to use the broadcast station, so this
|
||||
* inline wraps that pattern.
|
||||
*/
|
||||
static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
int sta_id;
|
||||
|
||||
if (!sta)
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
/*
|
||||
* mac80211 should not be passing a partially
|
||||
* initialised station!
|
||||
*/
|
||||
WARN_ON(sta_id == IWL_INVALID_STATION);
|
||||
|
||||
return sta_id;
|
||||
}
|
||||
#endif /* __iwl_sta_h__ */
|
||||
|
|
|
@ -77,21 +77,6 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_txq_update_write_ptr);
|
||||
|
||||
|
||||
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
|
||||
int sta_id, int tid, int freed)
|
||||
{
|
||||
if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
|
||||
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
|
||||
else {
|
||||
IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
|
||||
priv->stations[sta_id].tid[tid].tfds_in_queue,
|
||||
freed);
|
||||
priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_free_tfds_in_queue);
|
||||
|
||||
/**
|
||||
* iwl_tx_queue_free - Deallocate DMA queue.
|
||||
* @txq: Transmit queue to deallocate.
|
||||
|
@ -169,15 +154,15 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
pci_unmap_single(priv->pci_dev,
|
||||
pci_unmap_addr(&txq->meta[i], mapping),
|
||||
pci_unmap_len(&txq->meta[i], len),
|
||||
dma_unmap_addr(&txq->meta[i], mapping),
|
||||
dma_unmap_len(&txq->meta[i], len),
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
}
|
||||
if (huge) {
|
||||
i = q->n_window;
|
||||
pci_unmap_single(priv->pci_dev,
|
||||
pci_unmap_addr(&txq->meta[i], mapping),
|
||||
pci_unmap_len(&txq->meta[i], len),
|
||||
dma_unmap_addr(&txq->meta[i], mapping),
|
||||
dma_unmap_len(&txq->meta[i], len),
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
|
@ -287,7 +272,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
|
|||
/* 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]) *
|
||||
txq->txb = kzalloc(sizeof(txq->txb[0]) *
|
||||
TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
|
||||
if (!txq->txb) {
|
||||
IWL_ERR(priv, "kmalloc for auxiliary BD "
|
||||
|
@ -531,8 +516,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
|||
|
||||
phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
|
||||
fix_size, PCI_DMA_BIDIRECTIONAL);
|
||||
pci_unmap_addr_set(out_meta, mapping, phys_addr);
|
||||
pci_unmap_len_set(out_meta, len, fix_size);
|
||||
dma_unmap_addr_set(out_meta, mapping, phys_addr);
|
||||
dma_unmap_len_set(out_meta, len, fix_size);
|
||||
|
||||
trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags);
|
||||
|
||||
|
@ -626,8 +611,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
|||
meta = &txq->meta[cmd_index];
|
||||
|
||||
pci_unmap_single(priv->pci_dev,
|
||||
pci_unmap_addr(meta, mapping),
|
||||
pci_unmap_len(meta, len),
|
||||
dma_unmap_addr(meta, mapping),
|
||||
dma_unmap_len(meta, len),
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
/* Input error checking is done when commands are added to queue. */
|
||||
|
|
|
@ -197,6 +197,7 @@ static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
|
|||
static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
|
||||
|
@ -205,11 +206,11 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
|
|||
priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0);
|
||||
return 0;
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
|
||||
|
@ -474,10 +475,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
u8 unicast;
|
||||
u8 sta_id;
|
||||
u8 tid = 0;
|
||||
u16 seq_number = 0;
|
||||
__le16 fc;
|
||||
u8 wait_write_ptr = 0;
|
||||
u8 *qc = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
@ -510,10 +509,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find index into station table for destination station */
|
||||
if (!info->control.sta)
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
else
|
||||
sta_id = iwl_sta_id(info->control.sta);
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
|
@ -523,16 +519,10 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
|
||||
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
qc = ieee80211_get_qos_ctl(hdr);
|
||||
u8 *qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||
if (unlikely(tid >= MAX_TID_COUNT))
|
||||
goto drop;
|
||||
seq_number = priv->stations[sta_id].tid[tid].seq_number &
|
||||
IEEE80211_SCTL_SEQ;
|
||||
hdr->seq_ctrl = cpu_to_le16(seq_number) |
|
||||
(hdr->seq_ctrl &
|
||||
cpu_to_le16(IEEE80211_SCTL_FRAG));
|
||||
seq_number += 0x10;
|
||||
}
|
||||
|
||||
/* Descriptor for chosen Tx queue */
|
||||
|
@ -548,7 +538,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
|
||||
/* Set up driver data for this TFD */
|
||||
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
|
||||
txq->txb[q->write_ptr].skb[0] = skb;
|
||||
txq->txb[q->write_ptr].skb = skb;
|
||||
|
||||
/* Init first empty entry in queue's array of Tx/cmd buffers */
|
||||
out_cmd = txq->cmd[idx];
|
||||
|
@ -591,8 +581,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
|
||||
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||
txq->need_update = 1;
|
||||
if (qc)
|
||||
priv->stations[sta_id].tid[tid].seq_number = seq_number;
|
||||
} else {
|
||||
wait_write_ptr = 1;
|
||||
txq->need_update = 0;
|
||||
|
@ -631,8 +619,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
len, PCI_DMA_TODEVICE);
|
||||
/* we do not map meta data ... so we can safely access address to
|
||||
* provide to unmap command*/
|
||||
pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
pci_unmap_len_set(out_meta, len, len);
|
||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
dma_unmap_len_set(out_meta, len, len);
|
||||
|
||||
/* Add buffer containing Tx command and MAC(!) header to TFD's
|
||||
* first entry */
|
||||
|
@ -677,55 +665,6 @@ drop:
|
|||
return -1;
|
||||
}
|
||||
|
||||
#define BEACON_TIME_MASK_LOW 0x00FFFFFF
|
||||
#define BEACON_TIME_MASK_HIGH 0xFF000000
|
||||
#define TIME_UNIT 1024
|
||||
|
||||
/*
|
||||
* extended beacon time format
|
||||
* time in usec will be changed into a 32-bit value in 8:24 format
|
||||
* the high 1 byte is the beacon counts
|
||||
* the lower 3 bytes is the time in usec within one beacon interval
|
||||
*/
|
||||
|
||||
static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval)
|
||||
{
|
||||
u32 quot;
|
||||
u32 rem;
|
||||
u32 interval = beacon_interval * 1024;
|
||||
|
||||
if (!interval || !usec)
|
||||
return 0;
|
||||
|
||||
quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
|
||||
rem = (usec % interval) & BEACON_TIME_MASK_LOW;
|
||||
|
||||
return (quot << 24) + rem;
|
||||
}
|
||||
|
||||
/* base is usually what we get from ucode with each received frame,
|
||||
* the same as HW timer counter counting down
|
||||
*/
|
||||
|
||||
static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
|
||||
{
|
||||
u32 base_low = base & BEACON_TIME_MASK_LOW;
|
||||
u32 addon_low = addon & BEACON_TIME_MASK_LOW;
|
||||
u32 interval = beacon_interval * TIME_UNIT;
|
||||
u32 res = (base & BEACON_TIME_MASK_HIGH) +
|
||||
(addon & BEACON_TIME_MASK_HIGH);
|
||||
|
||||
if (base_low > addon_low)
|
||||
res += base_low - addon_low;
|
||||
else if (base_low < addon_low) {
|
||||
res += interval + base_low - addon_low;
|
||||
res += (1 << 24);
|
||||
} else
|
||||
res += (1 << 24);
|
||||
|
||||
return cpu_to_le32(res);
|
||||
}
|
||||
|
||||
static int iwl3945_get_measurement(struct iwl_priv *priv,
|
||||
struct ieee80211_measurement_params *params,
|
||||
u8 type)
|
||||
|
@ -743,8 +682,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
int duration = le16_to_cpu(params->duration);
|
||||
|
||||
if (iwl_is_associated(priv))
|
||||
add_time =
|
||||
iwl3945_usecs_to_beacons(
|
||||
add_time = iwl_usecs_to_beacons(priv,
|
||||
le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
|
||||
le16_to_cpu(priv->rxon_timing.beacon_interval));
|
||||
|
||||
|
@ -759,8 +697,8 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
|
||||
if (iwl_is_associated(priv))
|
||||
spectrum.start_time =
|
||||
iwl3945_add_beacon_time(priv->_3945.last_beacon_time,
|
||||
add_time,
|
||||
iwl_add_beacon_time(priv,
|
||||
priv->_3945.last_beacon_time, add_time,
|
||||
le16_to_cpu(priv->rxon_timing.beacon_interval));
|
||||
else
|
||||
spectrum.start_time = 0;
|
||||
|
@ -1844,6 +1782,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_band band,
|
||||
struct iwl3945_scan_channel *scan_ch)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u16 passive_dwell = 0;
|
||||
u16 active_dwell = 0;
|
||||
int added = 0;
|
||||
u8 channel = 0;
|
||||
|
||||
sband = iwl_get_hw_mode(priv, band);
|
||||
if (!sband) {
|
||||
IWL_ERR(priv, "invalid band\n");
|
||||
return added;
|
||||
}
|
||||
|
||||
active_dwell = iwl_get_active_dwell_time(priv, band, 0);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
|
||||
|
||||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
||||
|
||||
channel = iwl_get_single_channel_number(priv, band);
|
||||
|
||||
if (channel) {
|
||||
scan_ch->channel = channel;
|
||||
scan_ch->type = 0; /* passive */
|
||||
scan_ch->active_dwell = cpu_to_le16(active_dwell);
|
||||
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
|
||||
/* Set txpower levels to defaults */
|
||||
scan_ch->tpc.dsp_atten = 110;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
|
||||
else
|
||||
scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
|
||||
added++;
|
||||
} else
|
||||
IWL_ERR(priv, "no valid channel found\n");
|
||||
return added;
|
||||
}
|
||||
|
||||
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
u8 is_active, u8 n_probes,
|
||||
|
@ -2979,22 +2960,31 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
scan->tx_cmd.len = cpu_to_le16(
|
||||
iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
vif->addr,
|
||||
priv->scan_request->ie,
|
||||
priv->scan_request->ie_len,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan)));
|
||||
} else {
|
||||
/* use bcast addr, will not be transmitted but must be valid */
|
||||
scan->tx_cmd.len = cpu_to_le16(
|
||||
iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
NULL, 0,
|
||||
iwl_bcast_addr, NULL, 0,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan)));
|
||||
}
|
||||
/* select Rx antennas */
|
||||
scan->flags |= iwl3945_get_antenna_flags(priv);
|
||||
|
||||
scan->channel_count =
|
||||
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
|
||||
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
|
||||
if (priv->is_internal_short_scan) {
|
||||
scan->channel_count =
|
||||
iwl3945_get_single_channel_for_scan(priv, vif, band,
|
||||
(void *)&scan->data[le16_to_cpu(
|
||||
scan->tx_cmd.len)]);
|
||||
} else {
|
||||
scan->channel_count =
|
||||
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
|
||||
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
|
||||
}
|
||||
|
||||
if (scan->channel_count == 0) {
|
||||
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
|
||||
|
@ -3108,19 +3098,16 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
|
||||
if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
|
@ -3284,8 +3271,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
|
||||
priv->staging_rxon.assoc_id = 0;
|
||||
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
priv->staging_rxon.flags |=
|
||||
RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
|
@ -3293,17 +3279,12 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
priv->staging_rxon.flags |=
|
||||
RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
/* restore RXON assoc */
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
|
@ -3336,17 +3317,9 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
static_key = !iwl_is_associated(priv);
|
||||
|
||||
if (!static_key) {
|
||||
if (!sta) {
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
} else {
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv,
|
||||
"leave - %pM not in station map.\n",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
@ -3973,9 +3946,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
priv->pci_dev = pdev;
|
||||
priv->inta_mask = CSR_INI_SET_MASK;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
atomic_set(&priv->restrict_refcnt, 0);
|
||||
#endif
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(priv, "Not enough memory to generate traffic log\n");
|
||||
|
||||
|
@ -4044,9 +4014,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
}
|
||||
/* MAC Address location in EEPROM same for 3945/4965 */
|
||||
eeprom = (struct iwl3945_eeprom *)priv->eeprom;
|
||||
memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN);
|
||||
IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr);
|
||||
SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
|
||||
IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address);
|
||||
SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address);
|
||||
|
||||
/***********************
|
||||
* 5. Setup HW Constants
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
* LMAC. If you look at LMAC commands you'll se that they
|
||||
* are actually regular iwlwifi target commands encapsulated
|
||||
* into a special UMAC command called UMAC passthrough.
|
||||
* This is due to the fact the the host talks exclusively
|
||||
* This is due to the fact the host talks exclusively
|
||||
* to the UMAC and so there needs to be a special UMAC
|
||||
* command for talking to the LMAC.
|
||||
* This is how a wifi command is layed out:
|
||||
|
|
|
@ -321,14 +321,14 @@ iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket)
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ticket_node->ticket = kzalloc(sizeof(struct iwm_rx_ticket), GFP_KERNEL);
|
||||
ticket_node->ticket = kmemdup(ticket, sizeof(struct iwm_rx_ticket),
|
||||
GFP_KERNEL);
|
||||
if (!ticket_node->ticket) {
|
||||
IWM_ERR(iwm, "Couldn't allocate RX ticket\n");
|
||||
kfree(ticket_node);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
memcpy(ticket_node->ticket, ticket, sizeof(struct iwm_rx_ticket));
|
||||
INIT_LIST_HEAD(&ticket_node->node);
|
||||
|
||||
return ticket_node;
|
||||
|
|
|
@ -70,6 +70,8 @@ static u8 is_command_allowed_in_ps(u16 cmd)
|
|||
switch (cmd) {
|
||||
case CMD_802_11_RSSI:
|
||||
return 1;
|
||||
case CMD_802_11_HOST_SLEEP_CFG:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -185,6 +187,23 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
|
||||
struct cmd_header *resp)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
|
||||
priv->is_host_sleep_configured = 0;
|
||||
if (priv->psstate == PS_STATE_FULL_POWER) {
|
||||
priv->is_host_sleep_activated = 0;
|
||||
wake_up_interruptible(&priv->host_sleep_q);
|
||||
}
|
||||
} else {
|
||||
priv->is_host_sleep_configured = 1;
|
||||
}
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
|
||||
struct wol_config *p_wol_config)
|
||||
{
|
||||
|
@ -202,12 +221,11 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
|
|||
else
|
||||
cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config);
|
||||
ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr,
|
||||
le16_to_cpu(cmd_config.hdr.size),
|
||||
lbs_ret_host_sleep_cfg, 0);
|
||||
if (!ret) {
|
||||
if (criteria) {
|
||||
lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
|
||||
priv->wol_criteria = criteria;
|
||||
} else
|
||||
if (p_wol_config)
|
||||
memcpy((uint8_t *) p_wol_config,
|
||||
(uint8_t *)&cmd_config.wol_conf,
|
||||
sizeof(struct wol_config));
|
||||
|
@ -712,6 +730,10 @@ static void lbs_queue_cmd(struct lbs_private *priv,
|
|||
}
|
||||
}
|
||||
|
||||
if (le16_to_cpu(cmdnode->cmdbuf->command) ==
|
||||
CMD_802_11_WAKEUP_CONFIRM)
|
||||
addtail = 0;
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
if (addtail)
|
||||
|
@ -1353,6 +1375,11 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
|
|||
/* We don't get a response on the sleep-confirmation */
|
||||
priv->dnld_sent = DNLD_RES_RECEIVED;
|
||||
|
||||
if (priv->is_host_sleep_configured) {
|
||||
priv->is_host_sleep_activated = 1;
|
||||
wake_up_interruptible(&priv->host_sleep_q);
|
||||
}
|
||||
|
||||
/* If nothing to do, go back to sleep (?) */
|
||||
if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx])
|
||||
priv->psstate = PS_STATE_SLEEP;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "dev.h"
|
||||
#include "assoc.h"
|
||||
#include "wext.h"
|
||||
#include "cmd.h"
|
||||
|
||||
/**
|
||||
* @brief This function handles disconnect event. it
|
||||
|
@ -341,32 +342,10 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lbs_send_confirmwake(struct lbs_private *priv)
|
||||
{
|
||||
struct cmd_header cmd;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_HOST);
|
||||
|
||||
cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
|
||||
cmd.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.seqnum = cpu_to_le16(++priv->seqnum);
|
||||
cmd.result = 0;
|
||||
|
||||
lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
|
||||
sizeof(cmd));
|
||||
|
||||
ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
|
||||
if (ret)
|
||||
lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_process_event(struct lbs_private *priv, u32 event)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cmd_header cmd;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
|
@ -410,7 +389,10 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
|
|||
if (priv->reset_deep_sleep_wakeup)
|
||||
priv->reset_deep_sleep_wakeup(priv);
|
||||
priv->is_deep_sleep = 0;
|
||||
lbs_send_confirmwake(priv);
|
||||
lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd,
|
||||
sizeof(cmd));
|
||||
priv->is_host_sleep_activated = 0;
|
||||
wake_up_interruptible(&priv->host_sleep_q);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
|
||||
|
|
|
@ -38,7 +38,7 @@ int lbs_set_mac_address(struct net_device *dev, void *addr);
|
|||
void lbs_set_multicast_list(struct net_device *dev);
|
||||
|
||||
int lbs_suspend(struct lbs_private *priv);
|
||||
void lbs_resume(struct lbs_private *priv);
|
||||
int lbs_resume(struct lbs_private *priv);
|
||||
|
||||
void lbs_queue_event(struct lbs_private *priv, u32 event);
|
||||
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
|
||||
|
|
|
@ -75,6 +75,7 @@ struct lbs_private {
|
|||
|
||||
/* Deep sleep */
|
||||
int is_deep_sleep;
|
||||
int deep_sleep_required;
|
||||
int is_auto_deep_sleep_enabled;
|
||||
int wakeup_dev_required;
|
||||
int is_activity_detected;
|
||||
|
@ -82,6 +83,11 @@ struct lbs_private {
|
|||
wait_queue_head_t ds_awake_q;
|
||||
struct timer_list auto_deepsleep_timer;
|
||||
|
||||
/* Host sleep*/
|
||||
int is_host_sleep_configured;
|
||||
int is_host_sleep_activated;
|
||||
wait_queue_head_t host_sleep_q;
|
||||
|
||||
/* Hardware access */
|
||||
void *card;
|
||||
u8 fw_ready;
|
||||
|
|
|
@ -69,14 +69,11 @@ static void lbs_ethtool_get_wol(struct net_device *dev,
|
|||
{
|
||||
struct lbs_private *priv = dev->ml_priv;
|
||||
|
||||
if (priv->wol_criteria == 0xffffffff) {
|
||||
/* Interface driver didn't configure wake */
|
||||
wol->supported = wol->wolopts = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
|
||||
|
||||
if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
|
||||
return;
|
||||
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
|
||||
wol->wolopts |= WAKE_UCAST;
|
||||
if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
|
||||
|
@ -91,23 +88,22 @@ static int lbs_ethtool_set_wol(struct net_device *dev,
|
|||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct lbs_private *priv = dev->ml_priv;
|
||||
uint32_t criteria = 0;
|
||||
|
||||
if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
priv->wol_criteria = 0;
|
||||
if (wol->wolopts & WAKE_UCAST)
|
||||
criteria |= EHS_WAKE_ON_UNICAST_DATA;
|
||||
priv->wol_criteria |= EHS_WAKE_ON_UNICAST_DATA;
|
||||
if (wol->wolopts & WAKE_MCAST)
|
||||
criteria |= EHS_WAKE_ON_MULTICAST_DATA;
|
||||
priv->wol_criteria |= EHS_WAKE_ON_MULTICAST_DATA;
|
||||
if (wol->wolopts & WAKE_BCAST)
|
||||
criteria |= EHS_WAKE_ON_BROADCAST_DATA;
|
||||
priv->wol_criteria |= EHS_WAKE_ON_BROADCAST_DATA;
|
||||
if (wol->wolopts & WAKE_PHY)
|
||||
criteria |= EHS_WAKE_ON_MAC_EVENT;
|
||||
priv->wol_criteria |= EHS_WAKE_ON_MAC_EVENT;
|
||||
if (wol->wolopts == 0)
|
||||
criteria |= EHS_REMOVE_WAKEUP;
|
||||
|
||||
return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
|
||||
priv->wol_criteria |= EHS_REMOVE_WAKEUP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ethtool_ops lbs_ethtool_ops = {
|
||||
|
|
|
@ -1182,11 +1182,69 @@ static void if_sdio_remove(struct sdio_func *func)
|
|||
lbs_deb_leave(LBS_DEB_SDIO);
|
||||
}
|
||||
|
||||
static int if_sdio_suspend(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
int ret;
|
||||
struct if_sdio_card *card = sdio_get_drvdata(func);
|
||||
|
||||
mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
|
||||
|
||||
lbs_pr_info("%s: suspend: PM flags = 0x%x\n",
|
||||
sdio_func_id(func), flags);
|
||||
|
||||
/* If we aren't being asked to wake on anything, we should bail out
|
||||
* and let the SD stack power down the card.
|
||||
*/
|
||||
if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) {
|
||||
lbs_pr_info("Suspend without wake params -- "
|
||||
"powering down card.");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
if (!(flags & MMC_PM_KEEP_POWER)) {
|
||||
lbs_pr_err("%s: cannot remain alive while host is suspended\n",
|
||||
sdio_func_id(func));
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = lbs_suspend(card->priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
|
||||
}
|
||||
|
||||
static int if_sdio_resume(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct if_sdio_card *card = sdio_get_drvdata(func);
|
||||
int ret;
|
||||
|
||||
lbs_pr_info("%s: resume: we're back\n", sdio_func_id(func));
|
||||
|
||||
ret = lbs_resume(card->priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops if_sdio_pm_ops = {
|
||||
.suspend = if_sdio_suspend,
|
||||
.resume = if_sdio_resume,
|
||||
};
|
||||
|
||||
static struct sdio_driver if_sdio_driver = {
|
||||
.name = "libertas_sdio",
|
||||
.id_table = if_sdio_ids,
|
||||
.probe = if_sdio_probe,
|
||||
.remove = if_sdio_remove,
|
||||
.drv = {
|
||||
.pm = &if_sdio_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
/*******************************************************************/
|
||||
|
|
|
@ -613,16 +613,14 @@ static void if_usb_receive_fwload(struct urb *urb)
|
|||
return;
|
||||
}
|
||||
|
||||
syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
|
||||
syncfwheader = kmemdup(skb->data + IPFIELD_ALIGN_OFFSET,
|
||||
sizeof(struct fwsyncheader), GFP_ATOMIC);
|
||||
if (!syncfwheader) {
|
||||
lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
|
||||
sizeof(struct fwsyncheader));
|
||||
|
||||
if (!syncfwheader->cmd) {
|
||||
lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
|
||||
lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
|
||||
|
@ -1043,6 +1041,12 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
if (priv->psstate != PS_STATE_FULL_POWER)
|
||||
return -1;
|
||||
|
||||
if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
|
||||
lbs_pr_info("Suspend attempt without "
|
||||
"configuring wake params!\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
ret = lbs_suspend(priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
|
@ -625,16 +625,13 @@ static int lbs_thread(void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy,
|
||||
struct cmd_header *cmd)
|
||||
static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
|
||||
unsigned long dummy,
|
||||
struct cmd_header *cmd)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_FW);
|
||||
|
||||
netif_device_detach(priv->dev);
|
||||
if (priv->mesh_dev)
|
||||
netif_device_detach(priv->mesh_dev);
|
||||
|
||||
priv->fw_ready = 0;
|
||||
priv->is_host_sleep_activated = 1;
|
||||
wake_up_interruptible(&priv->host_sleep_q);
|
||||
lbs_deb_leave(LBS_DEB_FW);
|
||||
return 0;
|
||||
}
|
||||
|
@ -646,39 +643,65 @@ int lbs_suspend(struct lbs_private *priv)
|
|||
|
||||
lbs_deb_enter(LBS_DEB_FW);
|
||||
|
||||
if (priv->wol_criteria == 0xffffffff) {
|
||||
lbs_pr_info("Suspend attempt without configuring wake params!\n");
|
||||
return -EINVAL;
|
||||
if (priv->is_deep_sleep) {
|
||||
ret = lbs_set_deep_sleep(priv, 0);
|
||||
if (ret) {
|
||||
lbs_pr_err("deep sleep cancellation failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
priv->deep_sleep_required = 1;
|
||||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
ret = lbs_host_sleep_cfg(priv, priv->wol_criteria,
|
||||
(struct wol_config *)NULL);
|
||||
if (ret) {
|
||||
lbs_pr_info("Host sleep configuration failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (priv->psstate == PS_STATE_FULL_POWER) {
|
||||
ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
|
||||
sizeof(cmd), lbs_ret_host_sleep_activate, 0);
|
||||
if (ret)
|
||||
lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
|
||||
}
|
||||
|
||||
ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
|
||||
sizeof(cmd), lbs_suspend_callback, 0);
|
||||
if (ret)
|
||||
lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
|
||||
if (!wait_event_interruptible_timeout(priv->host_sleep_q,
|
||||
priv->is_host_sleep_activated, (10 * HZ))) {
|
||||
lbs_pr_err("host_sleep_q: timer expired\n");
|
||||
ret = -1;
|
||||
}
|
||||
netif_device_detach(priv->dev);
|
||||
if (priv->mesh_dev)
|
||||
netif_device_detach(priv->mesh_dev);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_suspend);
|
||||
|
||||
void lbs_resume(struct lbs_private *priv)
|
||||
int lbs_resume(struct lbs_private *priv)
|
||||
{
|
||||
int ret;
|
||||
uint32_t criteria = EHS_REMOVE_WAKEUP;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_FW);
|
||||
|
||||
priv->fw_ready = 1;
|
||||
|
||||
/* Firmware doesn't seem to give us RX packets any more
|
||||
until we send it some command. Might as well update */
|
||||
lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
|
||||
0, 0, NULL);
|
||||
ret = lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
|
||||
|
||||
netif_device_attach(priv->dev);
|
||||
if (priv->mesh_dev)
|
||||
netif_device_attach(priv->mesh_dev);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_FW);
|
||||
if (priv->deep_sleep_required) {
|
||||
priv->deep_sleep_required = 0;
|
||||
ret = lbs_set_deep_sleep(priv, 1);
|
||||
if (ret)
|
||||
lbs_pr_err("deep sleep activation failed: %d\n", ret);
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_resume);
|
||||
|
||||
|
@ -834,10 +857,13 @@ static int lbs_init_adapter(struct lbs_private *priv)
|
|||
priv->psstate = PS_STATE_FULL_POWER;
|
||||
priv->is_deep_sleep = 0;
|
||||
priv->is_auto_deep_sleep_enabled = 0;
|
||||
priv->deep_sleep_required = 0;
|
||||
priv->wakeup_dev_required = 0;
|
||||
init_waitqueue_head(&priv->ds_awake_q);
|
||||
priv->authtype_auto = 1;
|
||||
|
||||
priv->is_host_sleep_configured = 0;
|
||||
priv->is_host_sleep_activated = 0;
|
||||
init_waitqueue_head(&priv->host_sleep_q);
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
|
||||
|
@ -976,6 +1002,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
|
|||
|
||||
priv->wol_criteria = 0xffffffff;
|
||||
priv->wol_gpio = 0xff;
|
||||
priv->wol_gap = 20;
|
||||
|
||||
goto done;
|
||||
|
||||
|
@ -1031,6 +1058,10 @@ void lbs_remove_card(struct lbs_private *priv)
|
|||
wake_up_interruptible(&priv->ds_awake_q);
|
||||
}
|
||||
|
||||
priv->is_host_sleep_configured = 0;
|
||||
priv->is_host_sleep_activated = 0;
|
||||
wake_up_interruptible(&priv->host_sleep_q);
|
||||
|
||||
/* Stop the thread servicing the interrupts */
|
||||
priv->surpriseremoved = 1;
|
||||
kthread_stop(priv->main_thread);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue