diff --git a/[refs] b/[refs] index 621ec905853e..db1d4749ba8e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9c223f9bbad78aabfe9c4dfd75ca2660f78f20f9 +refs/heads/master: 592245559e9007845ef6603cc930c784031eb076 diff --git a/trunk/drivers/net/ethernet/3com/3c59x.c b/trunk/drivers/net/ethernet/3com/3c59x.c index 9ca45dcba755..6e1f5959a654 100644 --- a/trunk/drivers/net/ethernet/3com/3c59x.c +++ b/trunk/drivers/net/ethernet/3com/3c59x.c @@ -2179,10 +2179,9 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; vp->tx_ring[entry].frag[i+1].addr = - cpu_to_le32(pci_map_single( - VORTEX_PCI(vp), - (void *)skb_frag_address(frag), - frag->size, PCI_DMA_TODEVICE)); + cpu_to_le32(pci_map_single(VORTEX_PCI(vp), + (void*)page_address(frag->page) + frag->page_offset, + frag->size, PCI_DMA_TODEVICE)); if (i == skb_shinfo(skb)->nr_frags-1) vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(frag->size|LAST_FRAG); diff --git a/trunk/drivers/net/ethernet/aeroflex/greth.c b/trunk/drivers/net/ethernet/aeroflex/greth.c index bc3bd34c43f1..a5f6b07f8f3e 100644 --- a/trunk/drivers/net/ethernet/aeroflex/greth.c +++ b/trunk/drivers/net/ethernet/aeroflex/greth.c @@ -113,8 +113,9 @@ static void greth_print_tx_packet(struct sk_buff *skb) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1, - skb_frag_address(&skb_shinfo(skb)->frags[i]), - skb_shinfo(skb)->frags[i].size, true); + phys_to_virt(page_to_phys(skb_shinfo(skb)->frags[i].page)) + + skb_shinfo(skb)->frags[i].page_offset, + length, true); } } @@ -527,8 +528,11 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) greth_write_bd(&bdp->stat, status); - dma_addr = skb_frag_dma_map(greth->dev, frag, 0, frag->size, - DMA_TO_DEVICE); + dma_addr = dma_map_page(greth->dev, + frag->page, + frag->page_offset, + frag->size, + DMA_TO_DEVICE); if (unlikely(dma_mapping_error(greth->dev, dma_addr))) goto frag_map_error; diff --git a/trunk/drivers/net/ethernet/alteon/acenic.c b/trunk/drivers/net/ethernet/alteon/acenic.c index 8794cf831bd0..1d6f2db794fd 100644 --- a/trunk/drivers/net/ethernet/alteon/acenic.c +++ b/trunk/drivers/net/ethernet/alteon/acenic.c @@ -2485,9 +2485,9 @@ static netdev_tx_t ace_start_xmit(struct sk_buff *skb, info = ap->skb->tx_skbuff + idx; desc = ap->tx_ring + idx; - mapping = skb_frag_dma_map(&ap->pdev->dev, frag, 0, - frag->size, - PCI_DMA_TODEVICE); + mapping = pci_map_page(ap->pdev, frag->page, + frag->page_offset, frag->size, + PCI_DMA_TODEVICE); flagsize = (frag->size << 16); if (skb->ip_summed == CHECKSUM_PARTIAL) diff --git a/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 2b9f925fdfc0..acb4c1098cae 100644 --- a/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/trunk/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -2180,10 +2180,11 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); buffer_info->length = frag->size; - buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev, - frag, 0, - buffer_info->length, - PCI_DMA_TODEVICE); + buffer_info->dma = + pci_map_page(adapter->pdev, frag->page, + frag->page_offset, + buffer_info->length, + PCI_DMA_TODEVICE); ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, ATL1C_PCIMAP_TODEVICE); diff --git a/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 7e27eb354f10..1b5dc799348d 100644 --- a/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/trunk/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -1765,11 +1765,12 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, MAX_TX_BUF_LEN : buf_len; buf_len -= tx_buffer->length; - tx_buffer->dma = skb_frag_dma_map(&adapter->pdev->dev, - frag, - (i * MAX_TX_BUF_LEN), - tx_buffer->length, - PCI_DMA_TODEVICE); + tx_buffer->dma = + pci_map_page(adapter->pdev, frag->page, + frag->page_offset + + (i * MAX_TX_BUF_LEN), + tx_buffer->length, + PCI_DMA_TODEVICE); ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE); use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | diff --git a/trunk/drivers/net/ethernet/atheros/atlx/atl1.c b/trunk/drivers/net/ethernet/atheros/atlx/atl1.c index edf826a50281..c34e82391f75 100644 --- a/trunk/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/trunk/drivers/net/ethernet/atheros/atlx/atl1.c @@ -2283,8 +2283,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, buffer_info->length = (buf_len > ATL1_MAX_TX_BUF_LEN) ? ATL1_MAX_TX_BUF_LEN : buf_len; buf_len -= buffer_info->length; - buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev, - frag, i * ATL1_MAX_TX_BUF_LEN, + buffer_info->dma = pci_map_page(adapter->pdev, + frag->page, + frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN), buffer_info->length, PCI_DMA_TODEVICE); if (++next_to_use == tpd_ring->count) diff --git a/trunk/drivers/net/ethernet/brocade/bna/bnad.c b/trunk/drivers/net/ethernet/brocade/bna/bnad.c index b7f96ab8b30c..3a409172992e 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bnad.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bnad.c @@ -2753,8 +2753,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR)); txqent->vector[vect_id].length = htons(size); - dma_addr = skb_frag_dma_map(&bnad->pcidev->dev, frag, - 0, size, DMA_TO_DEVICE); + dma_addr = dma_map_page(&bnad->pcidev->dev, frag->page, + frag->page_offset, size, DMA_TO_DEVICE); dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr, dma_addr); BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr); diff --git a/trunk/drivers/net/ethernet/cisco/enic/enic_main.c b/trunk/drivers/net/ethernet/cisco/enic/enic_main.c index 19c9272b8f12..c751c25d301e 100644 --- a/trunk/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/trunk/drivers/net/ethernet/cisco/enic/enic_main.c @@ -591,9 +591,9 @@ static inline void enic_queue_wq_skb_cont(struct enic *enic, for (frag = skb_shinfo(skb)->frags; len_left; frag++) { len_left -= frag->size; enic_queue_wq_desc_cont(wq, skb, - skb_frag_dma_map(&enic->pdev->dev, - frag, 0, frag->size, - PCI_DMA_TODEVICE), + pci_map_page(enic->pdev, frag->page, + frag->page_offset, frag->size, + PCI_DMA_TODEVICE), frag->size, (len_left == 0), /* EOP? */ loopback); @@ -705,14 +705,14 @@ static inline void enic_queue_wq_skb_tso(struct enic *enic, for (frag = skb_shinfo(skb)->frags; len_left; frag++) { len_left -= frag->size; frag_len_left = frag->size; - offset = 0; + offset = frag->page_offset; while (frag_len_left) { len = min(frag_len_left, (unsigned int)WQ_ENET_MAX_DESC_LEN); - dma_addr = skb_frag_dma_map(&enic->pdev->dev, frag, - offset, len, - PCI_DMA_TODEVICE); + dma_addr = pci_map_page(enic->pdev, frag->page, + offset, len, + PCI_DMA_TODEVICE); enic_queue_wq_desc_cont(wq, skb, dma_addr, len, diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_main.c b/trunk/drivers/net/ethernet/emulex/benet/be_main.c index 2b7d1ba1e13b..3d55b4767ae4 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_main.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_main.c @@ -638,8 +638,8 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; - busaddr = skb_frag_dma_map(dev, frag, 0, - frag->size, DMA_TO_DEVICE); + busaddr = dma_map_page(dev, frag->page, frag->page_offset, + frag->size, DMA_TO_DEVICE); if (dma_mapping_error(dev, busaddr)) goto dma_err; wrb = queue_head_node(txq); @@ -1066,7 +1066,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, skb->tail += curr_frag_len; } else { skb_shinfo(skb)->nr_frags = 1; - skb_frag_set_page(skb, 0, page_info->page); + skb_shinfo(skb)->frags[0].page = page_info->page; skb_shinfo(skb)->frags[0].page_offset = page_info->page_offset + hdr_len; skb_shinfo(skb)->frags[0].size = curr_frag_len - hdr_len; @@ -1091,7 +1091,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo, if (page_info->page_offset == 0) { /* Fresh page */ j++; - skb_frag_set_page(skb, j, page_info->page); + skb_shinfo(skb)->frags[j].page = page_info->page; skb_shinfo(skb)->frags[j].page_offset = page_info->page_offset; skb_shinfo(skb)->frags[j].size = 0; @@ -1173,7 +1173,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, if (i == 0 || page_info->page_offset == 0) { /* First frag or Fresh page */ j++; - skb_frag_set_page(skb, j, page_info->page); + skb_shinfo(skb)->frags[j].page = page_info->page; skb_shinfo(skb)->frags[j].page_offset = page_info->page_offset; skb_shinfo(skb)->frags[j].size = 0; diff --git a/trunk/drivers/net/ethernet/freescale/gianfar.c b/trunk/drivers/net/ethernet/freescale/gianfar.c index 83199fd0d62b..81d409d08c97 100644 --- a/trunk/drivers/net/ethernet/freescale/gianfar.c +++ b/trunk/drivers/net/ethernet/freescale/gianfar.c @@ -2140,11 +2140,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) if (i == nr_frags - 1) lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); - bufaddr = skb_frag_dma_map(&priv->ofdev->dev, - &skb_shinfo(skb)->frags[i], - 0, - length, - DMA_TO_DEVICE); + bufaddr = dma_map_page(&priv->ofdev->dev, + skb_shinfo(skb)->frags[i].page, + skb_shinfo(skb)->frags[i].page_offset, + length, + DMA_TO_DEVICE); /* set the TxBD length and buffer pointer */ txbdp->bufPtr = bufaddr; diff --git a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c index 27f586afcc34..4a32c15524c9 100644 --- a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -2911,10 +2911,9 @@ static int e1000_tx_map(struct e1000_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - offset = 0; + offset = frag->page_offset; while (len) { - unsigned long bufend; i++; if (unlikely(i == tx_ring->count)) i = 0; @@ -2928,19 +2927,18 @@ static int e1000_tx_map(struct e1000_adapter *adapter, /* Workaround for potential 82544 hang in PCI-X. * Avoid terminating buffers within evenly-aligned * dwords. */ - bufend = (unsigned long) - page_to_phys(skb_frag_page(frag)); - bufend += offset + size - 1; if (unlikely(adapter->pcix_82544 && - !(bufend & 4) && - size > 4)) + !((unsigned long)(page_to_phys(frag->page) + offset + + size - 1) & 4) && + size > 4)) size -= 4; buffer_info->length = size; buffer_info->time_stamp = jiffies; buffer_info->mapped_as_page = true; - buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, - offset, size, DMA_TO_DEVICE); + buffer_info->dma = dma_map_page(&pdev->dev, frag->page, + offset, size, + DMA_TO_DEVICE); if (dma_mapping_error(&pdev->dev, buffer_info->dma)) goto dma_error; buffer_info->next_to_watch = i; diff --git a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c index 78c5d21fa34b..4f669995623f 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c @@ -4677,7 +4677,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - offset = 0; + offset = frag->page_offset; while (len) { i++; @@ -4690,8 +4690,9 @@ static int e1000_tx_map(struct e1000_adapter *adapter, buffer_info->length = size; buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; - buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, - offset, size, DMA_TO_DEVICE); + buffer_info->dma = dma_map_page(&pdev->dev, frag->page, + offset, size, + DMA_TO_DEVICE); buffer_info->mapped_as_page = true; if (dma_mapping_error(&pdev->dev, buffer_info->dma)) goto dma_error; diff --git a/trunk/drivers/net/ethernet/intel/igb/igb_main.c b/trunk/drivers/net/ethernet/intel/igb/igb_main.c index 3cb1bc96bf70..801608497409 100644 --- a/trunk/drivers/net/ethernet/intel/igb/igb_main.c +++ b/trunk/drivers/net/ethernet/intel/igb/igb_main.c @@ -4174,7 +4174,10 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb, buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; buffer_info->mapped_as_page = true; - buffer_info->dma = skb_frag_dma_map(dev, frag, 0, len, + buffer_info->dma = dma_map_page(dev, + frag->page, + frag->page_offset, + len, DMA_TO_DEVICE); if (dma_mapping_error(dev, buffer_info->dma)) goto dma_error; diff --git a/trunk/drivers/net/ethernet/intel/igbvf/netdev.c b/trunk/drivers/net/ethernet/intel/igbvf/netdev.c index b3d760b08a5f..a6bdb3c744f0 100644 --- a/trunk/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/trunk/drivers/net/ethernet/intel/igbvf/netdev.c @@ -2061,7 +2061,10 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, buffer_info->time_stamp = jiffies; buffer_info->next_to_watch = i; buffer_info->mapped_as_page = true; - buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, 0, len, + buffer_info->dma = dma_map_page(&pdev->dev, + frag->page, + frag->page_offset, + len, DMA_TO_DEVICE); if (dma_mapping_error(&pdev->dev, buffer_info->dma)) goto dma_error; diff --git a/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c index c8b9c9028bc0..b8ef2c0fc5d0 100644 --- a/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -1341,7 +1341,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - offset = 0; + offset = frag->page_offset; while (len) { i++; @@ -1361,8 +1361,8 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, buffer_info->time_stamp = jiffies; buffer_info->mapped_as_page = true; buffer_info->dma = - skb_frag_dma_map(&pdev->dev, frag, offset, size, - DMA_TO_DEVICE); + dma_map_page(&pdev->dev, frag->page, + offset, size, DMA_TO_DEVICE); if (dma_mapping_error(&pdev->dev, buffer_info->dma)) goto dma_error; buffer_info->next_to_watch = 0; diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 58482fc3024b..3f5a744f7099 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -53,6 +53,7 @@ /* TX/RX descriptor defines */ #define IXGBE_DEFAULT_TXD 512 +#define IXGBE_DEFAULT_TX_WORK 256 #define IXGBE_MAX_TXD 4096 #define IXGBE_MIN_TXD 64 diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index d20e8040d855..0f633ad9e8cd 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -804,7 +804,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_tx_buffer *tx_buffer; union ixgbe_adv_tx_desc *tx_desc; unsigned int total_bytes = 0, total_packets = 0; - u16 budget = q_vector->tx.work_limit; + unsigned int budget = q_vector->tx.work_limit; u16 i = tx_ring->next_to_clean; tx_buffer = &tx_ring->tx_buffer_info[i]; @@ -891,7 +891,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, ixgbe_tx_timeout_reset(adapter); /* the adapter is about to reset, no point in enabling stuff */ - return budget; + return true; } #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) @@ -908,7 +908,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, } } - return budget; + return !!budget; } #ifdef CONFIG_IXGBE_DCA @@ -5091,7 +5091,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->rx_ring_count = IXGBE_DEFAULT_RXD; /* set default work limits */ - adapter->tx_work_limit = adapter->tx_ring_count; + adapter->tx_work_limit = IXGBE_DEFAULT_TX_WORK; /* initialize eeprom parameters */ if (ixgbe_init_eeprom_params_generic(hw)) { @@ -6494,7 +6494,8 @@ static void ixgbe_tx_map(struct ixgbe_ring *tx_ring, offset = 0; tx_flags |= IXGBE_TX_FLAGS_MAPPED_AS_PAGE; - dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE); + dma = dma_map_page(dev, frag->page, frag->page_offset, + size, DMA_TO_DEVICE); if (dma_mapping_error(dev, dma)) goto dma_error; diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index d72905b77aba..98963970206e 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -2918,16 +2918,18 @@ static int ixgbevf_tx_map(struct ixgbevf_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; len = min((unsigned int)frag->size, total); - offset = 0; + offset = frag->page_offset; while (len) { tx_buffer_info = &tx_ring->tx_buffer_info[i]; size = min(len, (unsigned int)IXGBE_MAX_DATA_PER_TXD); tx_buffer_info->length = size; - tx_buffer_info->dma = - skb_frag_dma_map(&adapter->pdev->dev, frag, - offset, size, DMA_TO_DEVICE); + tx_buffer_info->dma = dma_map_page(&adapter->pdev->dev, + frag->page, + offset, + size, + DMA_TO_DEVICE); tx_buffer_info->mapped_as_page = true; if (dma_mapping_error(&pdev->dev, tx_buffer_info->dma)) goto dma_error; diff --git a/trunk/drivers/net/ethernet/nvidia/forcedeth.c b/trunk/drivers/net/ethernet/nvidia/forcedeth.c index 4e39b8c04397..98bb64bc24d9 100644 --- a/trunk/drivers/net/ethernet/nvidia/forcedeth.c +++ b/trunk/drivers/net/ethernet/nvidia/forcedeth.c @@ -2146,11 +2146,8 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) prev_tx = put_tx; prev_tx_ctx = np->put_tx_ctx; bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - np->put_tx_ctx->dma = skb_frag_dma_map( - &np->pci_dev->dev, - frag, offset, - bcnt, - PCI_DMA_TODEVICE); + np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt, + PCI_DMA_TODEVICE); np->put_tx_ctx->dma_len = bcnt; np->put_tx_ctx->dma_single = 0; put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma); @@ -2260,11 +2257,8 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, prev_tx = put_tx; prev_tx_ctx = np->put_tx_ctx; bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size; - np->put_tx_ctx->dma = skb_frag_dma_map( - &np->pci_dev->dev, - frag, offset, - bcnt, - PCI_DMA_TODEVICE); + np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt, + PCI_DMA_TODEVICE); np->put_tx_ctx->dma_len = bcnt; np->put_tx_ctx->dma_single = 0; put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma)); diff --git a/trunk/drivers/net/ethernet/realtek/8139cp.c b/trunk/drivers/net/ethernet/realtek/8139cp.c index c77d5af676a1..5d2d1b8678f6 100644 --- a/trunk/drivers/net/ethernet/realtek/8139cp.c +++ b/trunk/drivers/net/ethernet/realtek/8139cp.c @@ -784,7 +784,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, len = this_frag->size; mapping = dma_map_single(&cp->pdev->dev, - skb_frag_address(this_frag), + ((void *) page_address(this_frag->page) + + this_frag->page_offset), len, PCI_DMA_TODEVICE); eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; diff --git a/trunk/drivers/net/ethernet/sun/cassini.c b/trunk/drivers/net/ethernet/sun/cassini.c index f07a72150c63..1776a37b7aed 100644 --- a/trunk/drivers/net/ethernet/sun/cassini.c +++ b/trunk/drivers/net/ethernet/sun/cassini.c @@ -2048,8 +2048,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, skb->truesize += hlen - swivel; skb->len += hlen - swivel; - __skb_frag_set_page(frag, page->buffer); - __skb_frag_ref(frag); + get_page(page->buffer); + frag->page = page->buffer; frag->page_offset = off; frag->size = hlen - swivel; @@ -2072,8 +2072,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, skb->len += hlen; frag++; - __skb_frag_set_page(frag, page->buffer); - __skb_frag_ref(frag); + get_page(page->buffer); + frag->page = page->buffer; frag->page_offset = 0; frag->size = hlen; RX_USED_ADD(page, hlen + cp->crc_size); @@ -2830,8 +2830,9 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag]; len = fragp->size; - mapping = skb_frag_dma_map(&cp->pdev->dev, fragp, 0, len, - PCI_DMA_TODEVICE); + mapping = pci_map_page(cp->pdev, fragp->page, + fragp->page_offset, len, + PCI_DMA_TODEVICE); tabort = cas_calc_tabort(cp, fragp->page_offset, len); if (unlikely(tabort)) { @@ -2842,7 +2843,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, ctrl, 0); entry = TX_DESC_NEXT(ring, entry); - addr = cas_page_map(skb_frag_page(fragp)); + addr = cas_page_map(fragp->page); memcpy(tx_tiny_buf(cp, ring, entry), addr + fragp->page_offset + len - tabort, tabort); diff --git a/trunk/drivers/net/wireless/ath/ath.h b/trunk/drivers/net/wireless/ath/ath.h index 9891fb605a01..17c4b56c3874 100644 --- a/trunk/drivers/net/wireless/ath/ath.h +++ b/trunk/drivers/net/wireless/ath/ath.h @@ -178,29 +178,23 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry); void ath_hw_cycle_counters_update(struct ath_common *common); int32_t ath_hw_get_listen_time(struct ath_common *common); -extern __attribute__((format (printf, 2, 3))) -void ath_printk(const char *level, const char *fmt, ...); - -#define _ath_printk(level, common, fmt, ...) \ -do { \ - __always_unused struct ath_common *unused = common; \ - ath_printk(level, fmt, ##__VA_ARGS__); \ -} while (0) +extern __attribute__ ((format (printf, 3, 4))) int +ath_printk(const char *level, struct ath_common *common, const char *fmt, ...); #define ath_emerg(common, fmt, ...) \ - _ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) #define ath_alert(common, fmt, ...) \ - _ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) #define ath_crit(common, fmt, ...) \ - _ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) #define ath_err(common, fmt, ...) \ - _ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) #define ath_warn(common, fmt, ...) \ - _ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) #define ath_notice(common, fmt, ...) \ - _ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) #define ath_info(common, fmt, ...) \ - _ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) + ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) /** * enum ath_debug_level - atheros wireless debug level @@ -252,21 +246,27 @@ enum ATH_DEBUG { #ifdef CONFIG_ATH_DEBUG -#define ath_dbg(common, dbg_mask, fmt, ...) \ -do { \ - if ((common)->debug_mask & dbg_mask) \ - _ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \ -} while (0) - +#define ath_dbg(common, dbg_mask, fmt, ...) \ +({ \ + int rtn; \ + if ((common)->debug_mask & dbg_mask) \ + rtn = ath_printk(KERN_DEBUG, common, fmt, \ + ##__VA_ARGS__); \ + else \ + rtn = 0; \ + \ + rtn; \ +}) #define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) #define ATH_DBG_WARN_ON_ONCE(foo) WARN_ON_ONCE(foo) #else -static inline __attribute__((format (printf, 3, 4))) -void ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, - const char *fmt, ...) +static inline __attribute__ ((format (printf, 3, 4))) int +ath_dbg(struct ath_common *common, enum ATH_DEBUG dbg_mask, + const char *fmt, ...) { + return 0; } #define ATH_DBG_WARN(foo, arg...) do {} while (0) #define ATH_DBG_WARN_ON_ONCE(foo) ({ \ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ani.c b/trunk/drivers/net/wireless/ath/ath9k/ani.c index d969a11e3425..bfb6481f01f9 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ani.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ani.c @@ -643,7 +643,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) listenTime = ath_hw_get_listen_time(common); if (listenTime <= 0) { - ah->stats.ast_ani_lneg_or_lzero++; + ah->stats.ast_ani_lneg++; ath9k_ani_restart(ah); return false; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/ani.h b/trunk/drivers/net/wireless/ath/ath9k/ani.h index a547005572e7..dbab5b9ce494 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ani.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ani.h @@ -148,7 +148,8 @@ struct ar5416Stats { u32 ast_ani_ofdmerrs; u32 ast_ani_cckerrs; u32 ast_ani_reset; - u32 ast_ani_lneg_or_lzero; + u32 ast_ani_lzero; + u32 ast_ani_lneg; u32 avgbrssi; struct ath9k_mib_stats ast_mibstats; }; @@ -158,5 +159,7 @@ void ath9k_enable_mib_counters(struct ath_hw *ah); void ath9k_hw_disable_mib_counters(struct ath_hw *ah); void ath9k_hw_ani_setup(struct ath_hw *ah); void ath9k_hw_ani_init(struct ath_hw *ah); +int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, + struct ath9k_channel *chan); #endif /* ANI_H */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 33deb0d574b0..45b262fe2c25 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -273,7 +273,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, u32 pktLen, enum ath9k_pkt_type type, - u32 txPower, u8 keyIx, + u32 txPower, u32 keyIx, enum ath9k_key_type keyType, u32 flags) { struct ar5416_desc *ads = AR5416DESC(ds); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 5f3ac251b486..cb8bcc4e6091 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3318,7 +3318,7 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, word = kzalloc(2048, GFP_KERNEL); if (!word) - return -ENOMEM; + return -1; memcpy(mptr, &ar9300_default, mdata_size); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c index d08ab930e430..8ace36e77399 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -312,7 +312,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, u32 pktlen, enum ath9k_pkt_type type, u32 txpower, - u8 keyIx, enum ath9k_key_type keyType, u32 flags) + u32 keyIx, enum ath9k_key_type keyType, u32 flags) { struct ar9003_txc *ads = (struct ar9003_txc *) ds; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 5d9a9aabe476..3a893e19d6c3 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -206,17 +206,16 @@ struct ath_atx_ac { }; struct ath_frame_info { - struct ath_buf *bf; int framelen; + u32 keyix; enum ath9k_key_type keytype; - u8 keyix; u8 retries; + u16 seqno; }; struct ath_buf_state { u8 bf_type; u8 bfs_paprd; - u16 seqno; unsigned long bfs_paprd_timestamp; }; @@ -236,7 +235,7 @@ struct ath_buf { struct ath_atx_tid { struct list_head list; - struct sk_buff_head buf_q; + struct list_head buf_q; struct ath_node *an; struct ath_atx_ac *ac; unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index 727e8de22fda..da45f325be7d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct file *file, char __user *user_buf, " tid: %p %s %s %i %p %p\n", tid, tid->sched ? "sched" : "idle", tid->paused ? "paused" : "running", - skb_queue_empty(&tid->buf_q), + list_empty(&tid->buf_q), tid->an, tid->ac); if (len >= size) goto done; @@ -828,8 +828,6 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq) { -#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\ - [sc->debug.tsidx].c) int qnum = txq->axq_qnum; TX_STAT_INC(qnum, tx_pkts_all); @@ -859,26 +857,6 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, TX_STAT_INC(qnum, data_underrun); if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) TX_STAT_INC(qnum, delim_underrun); - - spin_lock(&sc->debug.samp_lock); - TX_SAMP_DBG(jiffies) = jiffies; - TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0; - TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1; - TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2; - TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0; - TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1; - TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2; - TX_SAMP_DBG(rateindex) = ts->ts_rateindex; - TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK); - TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry; - TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry; - TX_SAMP_DBG(rssi) = ts->ts_rssi; - TX_SAMP_DBG(tid) = ts->tid; - TX_SAMP_DBG(qid) = ts->qid; - sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock(&sc->debug.samp_lock); - -#undef TX_SAMP_DBG } static const struct file_operations fops_xmit = { @@ -1017,8 +995,6 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) { #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ -#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\ - [sc->debug.rsidx].c) u32 phyerr; @@ -1054,25 +1030,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; - spin_lock(&sc->debug.samp_lock); - RX_SAMP_DBG(jiffies) = jiffies; - RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0; - RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1; - RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2; - RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0; - RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1; - RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2; - RX_SAMP_DBG(antenna) = rs->rs_antenna; - RX_SAMP_DBG(rssi) = rs->rs_rssi; - RX_SAMP_DBG(rate) = rs->rs_rate; - RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon; - - sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock(&sc->debug.samp_lock); - #undef RX_STAT_INC #undef RX_PHY_ERR_INC -#undef RX_SAMP_DBG } static const struct file_operations fops_recv = { @@ -1313,269 +1272,6 @@ static const struct file_operations fops_modal_eeprom = { .llseek = default_llseek, }; -void ath9k_debug_samp_bb_mac(struct ath_softc *sc) -{ -#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c) - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - unsigned long flags; - int i; - - ath9k_ps_wakeup(sc); - - spin_lock_irqsave(&common->cc_lock, flags); - ath_hw_cycle_counters_update(common); - spin_unlock_irqrestore(&common->cc_lock, flags); - - spin_lock_bh(&sc->debug.samp_lock); - - ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles; - ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy; - ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame; - ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame; - ATH_SAMP_DBG(noise) = ah->noise; - - REG_WRITE_D(ah, AR_MACMISC, - ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | - (AR_MACMISC_MISC_OBS_BUS_1 << - AR_MACMISC_MISC_OBS_BUS_MSB_S))); - - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah, - AR_DMADBG_0 + (i * sizeof(u32))); - - ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1); - ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR); - - memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist, - sizeof(ATH_SAMP_DBG(nfCalHist))); - - sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock_bh(&sc->debug.samp_lock); - ath9k_ps_restore(sc); - -#undef ATH_SAMP_DBG -} - -static int open_file_bb_mac_samps(struct inode *inode, struct file *file) -{ -#define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c - struct ath_softc *sc = inode->i_private; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_conf *conf = &common->hw->conf; - struct ath_dbg_bb_mac_samp *bb_mac_samp; - struct ath9k_nfcal_hist *h; - int i, j, qcuOffset = 0, dcuOffset = 0; - u32 *qcuBase, *dcuBase, size = 30000, len = 0; - u32 sampidx = 0; - u8 *buf; - u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; - u8 nread; - - buf = vmalloc(size); - if (!buf) - return -ENOMEM; - bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); - if (!bb_mac_samp) { - vfree(buf); - return -ENOMEM; - } - - spin_lock_bh(&sc->debug.samp_lock); - memcpy(bb_mac_samp, sc->debug.bb_mac_samp, - sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); - spin_unlock_bh(&sc->debug.samp_lock); - - len += snprintf(buf + len, size - len, - "Raw DMA Debug Dump:\n"); - len += snprintf(buf + len, size - len, "Sample |\t"); - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i); - len += snprintf(buf + len, size - len, "\n"); - - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - len += snprintf(buf + len, size - len, "%d\t", sampidx); - - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - len += snprintf(buf + len, size - len, " %08x\t", - ATH_SAMP_DBG(dma_dbg_reg_vals[i])); - len += snprintf(buf + len, size - len, "\n"); - } - len += snprintf(buf + len, size - len, "\n"); - - len += snprintf(buf + len, size - len, - "Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]); - dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]); - - for (i = 0; i < ATH9K_NUM_QUEUES; i++, - qcuOffset += 4, dcuOffset += 5) { - if (i == 8) { - qcuOffset = 0; - qcuBase++; - } - - if (i == 6) { - dcuOffset = 0; - dcuBase++; - } - if (!sc->debug.stats.txstats[i].queued) - continue; - - len += snprintf(buf + len, size - len, - "%4d %7d %2x %1x %2x %2x\n", - sampidx, i, - (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, - (*qcuBase & (0x8 << qcuOffset)) >> - (qcuOffset + 3), - ATH_SAMP_DBG(dma_dbg_reg_vals[2]) & - (0x7 << (i * 3)) >> (i * 3), - (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); - } - len += snprintf(buf + len, size - len, "\n"); - } - len += snprintf(buf + len, size - len, - "samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp " - "ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 " - "txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n"); - - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]); - dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]); - - len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx, - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18, - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22); - len += snprintf(buf + len, size - len, "%7x %8x ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3)); - len += snprintf(buf + len, size - len, "%7x %7x ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25, - (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27); - len += snprintf(buf + len, size - len, "%7d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10); - len += snprintf(buf + len, size - len, "%12d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12); - len += snprintf(buf + len, size - len, "%12d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17); - len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n", - ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr)); - } - - len += snprintf(buf + len, size - len, - "Sample ChNoise Chain privNF #Reading Readings\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - h = ATH_SAMP_DBG(nfCalHist); - if (!ATH_SAMP_DBG(noise)) - continue; - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (!(chainmask & (1 << i)) || - ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) - continue; - - nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - - h[i].invalidNFcount; - len += snprintf(buf + len, size - len, - "%4d %5d %4d\t %d\t %d\t", - sampidx, ATH_SAMP_DBG(noise), - i, h[i].privNF, nread); - for (j = 0; j < nread; j++) - len += snprintf(buf + len, size - len, - " %d", h[i].nfCalBuffer[j]); - len += snprintf(buf + len, size - len, "\n"); - } - } - len += snprintf(buf + len, size - len, "\nCycle counters:\n" - "Sample Total Rxbusy Rxframes Txframes\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - if (!ATH_SAMP_DBG(cc.cycles)) - continue; - len += snprintf(buf + len, size - len, - "%4d %08x %08x %08x %08x\n", - sampidx, ATH_SAMP_DBG(cc.cycles), - ATH_SAMP_DBG(cc.rx_busy), - ATH_SAMP_DBG(cc.rx_frame), - ATH_SAMP_DBG(cc.tx_frame)); - } - - len += snprintf(buf + len, size - len, "Tx status Dump :\n"); - len += snprintf(buf + len, size - len, - "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb " - "isok rts_fail data_fail rate tid qid tx_before(ms)\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { - if (!ATH_SAMP_DBG(ts[i].jiffies)) - continue; - len += snprintf(buf + len, size - len, "%4d \t" - "%8d %4d %4d %4d %4d %4d %4d %4d %4d " - "%4d %4d %2d %2d %d\n", - sampidx, - ATH_SAMP_DBG(ts[i].rssi_ctl0), - ATH_SAMP_DBG(ts[i].rssi_ctl1), - ATH_SAMP_DBG(ts[i].rssi_ctl2), - ATH_SAMP_DBG(ts[i].rssi_ext0), - ATH_SAMP_DBG(ts[i].rssi_ext1), - ATH_SAMP_DBG(ts[i].rssi_ext2), - ATH_SAMP_DBG(ts[i].rssi), - ATH_SAMP_DBG(ts[i].isok), - ATH_SAMP_DBG(ts[i].rts_fail_cnt), - ATH_SAMP_DBG(ts[i].data_fail_cnt), - ATH_SAMP_DBG(ts[i].rateindex), - ATH_SAMP_DBG(ts[i].tid), - ATH_SAMP_DBG(ts[i].qid), - jiffies_to_msecs(jiffies - - ATH_SAMP_DBG(ts[i].jiffies))); - } - } - - len += snprintf(buf + len, size - len, "Rx status Dump :\n"); - len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 " - "ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { - if (!ATH_SAMP_DBG(rs[i].jiffies)) - continue; - len += snprintf(buf + len, size - len, "%4d \t" - "%8d %4d %4d %4d %4d %4d %4d %s %4d %02x %d\n", - sampidx, - ATH_SAMP_DBG(rs[i].rssi_ctl0), - ATH_SAMP_DBG(rs[i].rssi_ctl1), - ATH_SAMP_DBG(rs[i].rssi_ctl2), - ATH_SAMP_DBG(rs[i].rssi_ext0), - ATH_SAMP_DBG(rs[i].rssi_ext1), - ATH_SAMP_DBG(rs[i].rssi_ext2), - ATH_SAMP_DBG(rs[i].rssi), - ATH_SAMP_DBG(rs[i].is_mybeacon) ? - "True" : "False", - ATH_SAMP_DBG(rs[i].antenna), - ATH_SAMP_DBG(rs[i].rate), - jiffies_to_msecs(jiffies - - ATH_SAMP_DBG(rs[i].jiffies))); - } - } - - vfree(bb_mac_samp); - file->private_data = buf; - - return 0; -#undef ATH_SAMP_DBG -} - -static const struct file_operations fops_samps = { - .open = open_file_bb_mac_samps, - .read = ath9k_debugfs_read_buf, - .release = ath9k_debugfs_release_buf, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - - int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -1625,8 +1321,6 @@ int ath9k_init_debug(struct ath_hw *ah) &fops_base_eeprom); debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_modal_eeprom); - debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_samps); debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); @@ -1635,9 +1329,5 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); sc->debug.regidx = 0; - memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp)); - sc->debug.sampidx = 0; - sc->debug.tsidx = 0; - sc->debug.rsidx = 0; return 0; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h index 95f85bdc8db7..4a04510e1111 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h @@ -177,57 +177,14 @@ struct ath_stats { struct ath_rx_stats rxstats; }; -#define ATH_DBG_MAX_SAMPLES 10 -struct ath_dbg_bb_mac_samp { - u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS]; - u32 pcu_obs, pcu_cr, noise; - struct { - u64 jiffies; - int8_t rssi_ctl0; - int8_t rssi_ctl1; - int8_t rssi_ctl2; - int8_t rssi_ext0; - int8_t rssi_ext1; - int8_t rssi_ext2; - int8_t rssi; - bool isok; - u8 rts_fail_cnt; - u8 data_fail_cnt; - u8 rateindex; - u8 qid; - u8 tid; - } ts[ATH_DBG_MAX_SAMPLES]; - struct { - u64 jiffies; - int8_t rssi_ctl0; - int8_t rssi_ctl1; - int8_t rssi_ctl2; - int8_t rssi_ext0; - int8_t rssi_ext1; - int8_t rssi_ext2; - int8_t rssi; - bool is_mybeacon; - u8 antenna; - u8 rate; - } rs[ATH_DBG_MAX_SAMPLES]; - struct ath_cycle_counters cc; - struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; -}; - struct ath9k_debug { struct dentry *debugfs_phy; u32 regidx; struct ath_stats stats; - spinlock_t samp_lock; - struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES]; - u8 sampidx; - u8 tsidx; - u8 rsidx; }; int ath9k_init_debug(struct ath_hw *ah); -void ath9k_debug_samp_bb_mac(struct ath_softc *sc); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq); @@ -240,10 +197,6 @@ static inline int ath9k_init_debug(struct ath_hw *ah) return 0; } -static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc) -{ -} - static inline void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c index b9de1511add9..0248024da56a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1300,7 +1300,6 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, if (priv->op_flags & OP_INVALID) { ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY, "Unable to configure filter on invalid state\n"); - mutex_unlock(&priv->mutex); return; } ath9k_htc_ps_wakeup(priv); diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 3a16ba256ef9..a0d1147844fb 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -440,7 +440,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) if (AR_SREV_9100(ah)) ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; ah->enable_32kHz_clock = DONT_USE_32KHZ; - ah->slottime = ATH9K_SLOT_TIME_9; + ah->slottime = 20; ah->globaltxtimeout = (u32) -1; ah->power_mode = ATH9K_PM_UNDEFINED; } @@ -997,14 +997,8 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) slottime = 21; sifstime = 64; } else { - if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { - eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO; - reg = AR_USEC_ASYNC_FIFO; - } else { - eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/ - common->clockrate; - reg = REG_READ(ah, AR_USEC); - } + eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/common->clockrate; + reg = REG_READ(ah, AR_USEC); rx_lat = MS(reg, AR_USEC_RX_LAT); tx_lat = MS(reg, AR_USEC_TX_LAT); @@ -2760,7 +2754,6 @@ static struct { { AR_SREV_VERSION_9271, "9271" }, { AR_SREV_VERSION_9300, "9300" }, { AR_SREV_VERSION_9330, "9330" }, - { AR_SREV_VERSION_9340, "9340" }, { AR_SREV_VERSION_9485, "9485" }, }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index c8af86c795e5..3aa3fb191775 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -623,7 +623,7 @@ struct ath_hw_ops { struct ath_tx_status *ts); void (*set11n_txdesc)(struct ath_hw *ah, void *ds, u32 pktLen, enum ath9k_pkt_type type, - u32 txPower, u8 keyIx, + u32 txPower, u32 keyIx, enum ath9k_key_type keyType, u32 flags); void (*set11n_ratescenario)(struct ath_hw *ah, void *ds, diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index dd71a5f77516..d7761d1fc5ba 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -572,7 +572,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, mutex_init(&sc->mutex); #ifdef CONFIG_ATH9K_DEBUGFS spin_lock_init(&sc->nodes_lock); - spin_lock_init(&sc->debug.samp_lock); INIT_LIST_HEAD(&sc->nodes); #endif tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.h b/trunk/drivers/net/wireless/ath/ath9k/mac.h index acb83bfd05a0..153859ccc2a1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.h +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.h @@ -146,7 +146,6 @@ struct ath_rx_status { u8 rs_moreaggr; u8 rs_num_delims; u8 rs_flags; - bool is_mybeacon; u32 evm0; u32 evm1; u32 evm2; @@ -195,7 +194,7 @@ struct ath_htc_rx_status { #define ATH9K_RX_DECRYPT_BUSY 0x40 #define ATH9K_RXKEYIX_INVALID ((u8)-1) -#define ATH9K_TXKEYIX_INVALID ((u8)-1) +#define ATH9K_TXKEYIX_INVALID ((u32)-1) enum ath9k_phyerr { ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 7b7864dfab75..5ac4f3f2ad60 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -546,7 +546,6 @@ void ath_ani_calibrate(unsigned long data) * The interval must be the shortest necessary to satisfy ANI, * short calibration and long calibration. */ - ath9k_debug_samp_bb_mac(sc); cal_interval = ATH_LONG_CALINTERVAL; if (sc->sc_ah->config.enable_ani) cal_interval = min(cal_interval, @@ -979,7 +978,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) sc->hw_busy_count = 0; - ath9k_debug_samp_bb_mac(sc); /* Stop ANI */ del_timer_sync(&common->ani.timer); diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index 9c7f905f3871..ad5f9bd2f0b9 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -937,7 +937,7 @@ static int ath9k_process_rate(struct ath_common *common, * No valid hardware bitrate found -- we should not get here * because hardware has already validated this frame as OK. */ - ath_dbg(common, ATH_DBG_ANY, + ath_dbg(common, ATH_DBG_XMIT, "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", rx_stats->rs_rate); @@ -952,12 +952,23 @@ static void ath9k_process_rssi(struct ath_common *common, struct ath_softc *sc = hw->priv; struct ath_hw *ah = common->ah; int last_rssi; + __le16 fc; - if (!rx_stats->is_mybeacon || - ((ah->opmode != NL80211_IFTYPE_STATION) && - (ah->opmode != NL80211_IFTYPE_ADHOC))) + if ((ah->opmode != NL80211_IFTYPE_STATION) && + (ah->opmode != NL80211_IFTYPE_ADHOC)) return; + fc = hdr->frame_control; + if (!ieee80211_is_beacon(fc) || + compare_ether_addr(hdr->addr3, common->curbssid)) { + /* TODO: This doesn't work well if you have stations + * associated to two different APs because curbssid + * is just the last AP that any of the stations associated + * with. + */ + return; + } + if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); @@ -1827,11 +1838,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); rxs = IEEE80211_SKB_RXCB(hdr_skb); - if (ieee80211_is_beacon(hdr->frame_control) && - !compare_ether_addr(hdr->addr3, common->curbssid)) - rs.is_mybeacon = true; - else - rs.is_mybeacon = false; ath_debug_stat_rx(sc, &rs); diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h index 17a272f4d8d6..a3b8bbc6c063 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h @@ -619,7 +619,6 @@ #define AR_D_GBL_IFS_EIFS 0x10b0 #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 -#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363 #define AR_D_GBL_IFS_MISC 0x10f0 #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 @@ -1504,7 +1503,6 @@ enum { #define AR_USEC_TX_LAT_S 14 #define AR_USEC_RX_LAT 0x1F800000 #define AR_USEC_RX_LAT_S 23 -#define AR_USEC_ASYNC_FIFO 0x12E00074 #define AR_RESET_TSF 0x8020 #define AR_RESET_TSF_ONCE 0x01000000 diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index 68066c56e4e5..5e2982938ffc 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -48,9 +48,8 @@ static u16 bits_per_symbol[][2] = { #define IS_HT_RATE(_rate) ((_rate) & 0x80) static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, struct sk_buff *skb); -static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - int tx_flags, struct ath_txq *txq); + struct ath_atx_tid *tid, + struct list_head *bf_head); static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, struct ath_txq *txq, struct list_head *bf_q, struct ath_tx_status *ts, int txok, int sendbar); @@ -62,10 +61,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, int txok, bool update_rc); static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, int seqno); -static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, - struct ath_txq *txq, - struct ath_atx_tid *tid, - struct sk_buff *skb); enum { MCS_HT20, @@ -134,7 +129,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) spin_lock_bh(&txq->axq_lock); tid->paused = false; - if (skb_queue_empty(&tid->buf_q)) + if (list_empty(&tid->buf_q)) goto unlock; ath_tx_queue_tid(txq, tid); @@ -154,7 +149,6 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { struct ath_txq *txq = tid->ac->txq; - struct sk_buff *skb; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; @@ -165,17 +159,17 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) memset(&ts, 0, sizeof(ts)); spin_lock_bh(&txq->axq_lock); - while ((skb = __skb_dequeue(&tid->buf_q))) { - fi = get_frame_info(skb); - bf = fi->bf; + while (!list_empty(&tid->buf_q)) { + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + list_move_tail(&bf->list, &bf_head); spin_unlock_bh(&txq->axq_lock); - if (bf && fi->retries) { - list_add_tail(&bf->list, &bf_head); - ath_tx_update_baw(sc, tid, bf->bf_state.seqno); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) { + ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); } else { - ath_tx_send_normal(sc, txq, NULL, skb); + ath_tx_send_normal(sc, txq, NULL, &bf_head); } spin_lock_bh(&txq->axq_lock); } @@ -225,7 +219,6 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid) { - struct sk_buff *skb; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; @@ -234,21 +227,16 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); - while ((skb = __skb_dequeue(&tid->buf_q))) { - fi = get_frame_info(skb); - bf = fi->bf; - - if (!bf) { - spin_unlock(&txq->axq_lock); - ath_tx_complete(sc, skb, ATH_TX_ERROR, txq); - spin_lock(&txq->axq_lock); - continue; - } + for (;;) { + if (list_empty(&tid->buf_q)) + break; - list_add_tail(&bf->list, &bf_head); + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + list_move_tail(&bf->list, &bf_head); + fi = get_frame_info(bf->bf_mpdu); if (fi->retries) - ath_tx_update_baw(sc, tid, bf->bf_state.seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock(&txq->axq_lock); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@ -338,7 +326,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, while (bf) { fi = get_frame_info(bf->bf_mpdu); - ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno); + ba_index = ATH_BA_INDEX(seq_st, fi->seqno); (*nframes)++; if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) @@ -361,8 +349,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ieee80211_tx_info *tx_info; struct ath_atx_tid *tid = NULL; struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; - struct list_head bf_head; - struct sk_buff_head bf_pending; + struct list_head bf_head, bf_pending; u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; @@ -435,12 +422,11 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, } } - __skb_queue_head_init(&bf_pending); + INIT_LIST_HEAD(&bf_pending); + INIT_LIST_HEAD(&bf_head); ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); while (bf) { - u16 seqno = bf->bf_state.seqno; - txfail = txpending = sendbar = 0; bf_next = bf->bf_next; @@ -448,7 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tx_info = IEEE80211_SKB_CB(skb); fi = get_frame_info(skb); - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) { + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) { /* transmit completion, subframe is * acked by block ack */ acked_cnt++; @@ -481,10 +467,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * Make sure the last desc is reclaimed if it * not a holding desc. */ - INIT_LIST_HEAD(&bf_head); - if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || - bf_next != NULL || !bf_last->bf_stale) + if (!bf_last->bf_stale || bf_next != NULL) list_move_tail(&bf->list, &bf_head); + else + INIT_LIST_HEAD(&bf_head); if (!txpending || (tid->state & AGGR_CLEANUP)) { /* @@ -492,7 +478,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * block-ack window */ spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { @@ -520,7 +506,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, */ if (!tbf) { spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); bf->bf_state.bf_type |= @@ -535,7 +521,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); - fi->bf = tbf; + list_add_tail(&tbf->list, &bf_head); } else { /* * Clear descriptor status words for @@ -550,21 +536,21 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, * Put this buffer to the temporary pending * queue to retain ordering */ - __skb_queue_tail(&bf_pending, skb); + list_splice_tail_init(&bf_head, &bf_pending); } bf = bf_next; } /* prepend un-acked frames to the beginning of the pending frame queue */ - if (!skb_queue_empty(&bf_pending)) { + if (!list_empty(&bf_pending)) { if (an->sleeping) ieee80211_sta_set_tim(sta); spin_lock_bh(&txq->axq_lock); if (clear_filter) tid->ac->clear_ps_filter = true; - skb_queue_splice(&bf_pending, &tid->buf_q); + list_splice(&bf_pending, &tid->buf_q); if (!an->sleeping) ath_tx_queue_tid(txq, tid); spin_unlock_bh(&txq->axq_lock); @@ -596,10 +582,7 @@ static bool ath_lookup_legacy(struct ath_buf *bf) tx_info = IEEE80211_SKB_CB(skb); rates = tx_info->control.rates; - for (i = 0; i < 4; i++) { - if (!rates[i].count || rates[i].idx < 0) - break; - + for (i = 3; i >= 0; i--) { if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) return true; } @@ -757,33 +740,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, int *aggr_len) { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) - struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; + struct ath_buf *bf, *bf_first, *bf_prev = NULL; int rl = 0, nframes = 0, ndelim, prev_al = 0; u16 aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw = tid->baw_size / 2; enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; struct ieee80211_tx_info *tx_info; struct ath_frame_info *fi; - struct sk_buff *skb; - u16 seqno; - - do { - skb = skb_peek(&tid->buf_q); - fi = get_frame_info(skb); - bf = fi->bf; - if (!fi->bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb); - if (!bf) - continue; + bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); - bf->bf_state.bf_type |= BUF_AMPDU; - seqno = bf->bf_state.seqno; - if (!bf_first) - bf_first = bf; + do { + bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + fi = get_frame_info(bf->bf_mpdu); /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { status = ATH_AGGR_BAW_CLOSED; break; } @@ -831,11 +803,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, /* link buffers of this frame to the aggregate */ if (!fi->retries) - ath_tx_addto_baw(sc, tid, seqno); + ath_tx_addto_baw(sc, tid, fi->seqno); ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); - - __skb_unlink(skb, &tid->buf_q); - list_add_tail(&bf->list, bf_q); + list_move_tail(&bf->list, bf_q); if (bf_prev) { bf_prev->bf_next = bf; ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc, @@ -843,7 +813,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, } bf_prev = bf; - } while (!skb_queue_empty(&tid->buf_q)); + } while (!list_empty(&tid->buf_q)); *aggr_len = al; @@ -861,7 +831,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, int aggr_len; do { - if (skb_queue_empty(&tid->buf_q)) + if (list_empty(&tid->buf_q)) return; INIT_LIST_HEAD(&bf_q); @@ -982,7 +952,7 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) spin_lock_bh(&txq->axq_lock); - if (!skb_queue_empty(&tid->buf_q)) + if (!list_empty(&tid->buf_q)) buffered = true; tid->sched = false; @@ -1015,7 +985,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) spin_lock_bh(&txq->axq_lock); ac->clear_ps_filter = true; - if (!skb_queue_empty(&tid->buf_q) && !tid->paused) { + if (!list_empty(&tid->buf_q) && !tid->paused) { ath_tx_queue_tid(txq, tid); ath_txq_schedule(sc, txq); } @@ -1359,7 +1329,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) * add tid to round-robin queue if more frames * are pending for the tid */ - if (!skb_queue_empty(&tid->buf_q)) + if (!list_empty(&tid->buf_q)) ath_tx_queue_tid(txq, tid); if (tid == last_tid || @@ -1451,11 +1421,12 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, } static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct sk_buff *skb, struct ath_tx_control *txctl) + struct ath_buf *bf, struct ath_tx_control *txctl) { - struct ath_frame_info *fi = get_frame_info(skb); + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); struct list_head bf_head; - struct ath_buf *bf; + + bf->bf_state.bf_type |= BUF_AMPDU; /* * Do not queue to h/w when any of the following conditions is true: @@ -1464,30 +1435,26 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * - seqno is not within block-ack window * - h/w queue depth exceeds low water mark */ - if (!skb_queue_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) || + if (!list_empty(&tid->buf_q) || tid->paused || + !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { /* * Add this frame to software queue for scheduling later * for aggregation. */ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); - __skb_queue_tail(&tid->buf_q, skb); + list_add_tail(&bf->list, &tid->buf_q); if (!txctl->an || !txctl->an->sleeping) ath_tx_queue_tid(txctl->txq, tid); return; } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); - if (!bf) - return; - - bf->bf_state.bf_type |= BUF_AMPDU; INIT_LIST_HEAD(&bf_head); list_add(&bf->list, &bf_head); /* Add sub-frame to BAW */ - ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); + if (!fi->retries) + ath_tx_addto_baw(sc, tid, fi->seqno); /* Queue to h/w without aggregation */ TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); @@ -1497,21 +1464,13 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, } static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, struct sk_buff *skb) + struct ath_atx_tid *tid, + struct list_head *bf_head) { - struct ath_frame_info *fi = get_frame_info(skb); - struct list_head bf_head; + struct ath_frame_info *fi; struct ath_buf *bf; - bf = fi->bf; - if (!bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb); - - if (!bf) - return; - - INIT_LIST_HEAD(&bf_head); - list_add_tail(&bf->list, &bf_head); + bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type &= ~BUF_AMPDU; /* update starting sequence number for subsequent ADDBA request */ @@ -1519,8 +1478,9 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, INCR(tid->seq_start, IEEE80211_SEQ_MAX); bf->bf_lastbf = bf; + fi = get_frame_info(bf->bf_mpdu); ath_buf_set_rate(sc, bf, fi->framelen); - ath_tx_txqaddbuf(sc, txq, &bf_head, false); + ath_tx_txqaddbuf(sc, txq, bf_head, false); TX_STAT_INC(txq->axq_qnum, queued); } @@ -1550,19 +1510,39 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, int framelen) { + struct ath_softc *sc = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr; struct ath_frame_info *fi = get_frame_info(skb); struct ath_node *an = NULL; + struct ath_atx_tid *tid; enum ath9k_key_type keytype; + u16 seqno = 0; + u8 tidno; keytype = ath9k_cmn_get_hw_crypto_keytype(skb); if (sta) an = (struct ath_node *) sta->drv_priv; + hdr = (struct ieee80211_hdr *)skb->data; + if (an && ieee80211_is_data_qos(hdr->frame_control) && + conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { + + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + + /* + * Override seqno set by upper layer with the one + * in tx aggregation state. + */ + tid = ATH_AN_2_TID(an, tidno); + seqno = tid->seq_next; + hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT); + INCR(tid->seq_next, IEEE80211_SEQ_MAX); + } + memset(fi, 0, sizeof(*fi)); if (hw_key) fi->keyix = hw_key->hw_key_idx; @@ -1572,6 +1552,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keytype = keytype; fi->framelen = framelen; + fi->seqno = seqno; } static int setup_tx_flags(struct sk_buff *skb) @@ -1743,39 +1724,26 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) } -/* - * Assign a descriptor (and sequence number if necessary, - * and map buffer for DMA. Frees skb on error - */ -static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, +static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_txq *txq, - struct ath_atx_tid *tid, struct sk_buff *skb) { + struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_frame_info *fi = get_frame_info(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_buf *bf; struct ath_desc *ds; int frm_type; - u16 seqno; bf = ath_tx_get_buffer(sc); if (!bf) { ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n"); - goto error; + return NULL; } ATH_TXBUF_RESET(bf); - if (tid) { - seqno = tid->seq_next; - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); - INCR(tid->seq_next, IEEE80211_SEQ_MAX); - bf->bf_state.seqno = seqno; - } - bf->bf_flags = setup_tx_flags(skb); bf->bf_mpdu = skb; @@ -1787,7 +1755,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, ath_err(ath9k_hw_common(sc->sc_ah), "dma_mapping_error() on TX\n"); ath_tx_return_buffer(sc, bf); - goto error; + return NULL; } frm_type = get_hw_packet_type(skb); @@ -1806,23 +1774,19 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, bf->bf_buf_addr, txq->axq_qnum); - fi->bf = bf; return bf; - -error: - dev_kfree_skb_any(skb); - return NULL; } /* FIXME: tx power */ -static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, +static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_control *txctl) { + struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct list_head bf_head; struct ath_atx_tid *tid = NULL; - struct ath_buf *bf; u8 tidno; spin_lock_bh(&txctl->txq->axq_lock); @@ -1840,11 +1804,10 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, * Try aggregation if it's a unicast data frame * and the destination is HT capable. */ - ath_tx_send_ampdu(sc, tid, skb, txctl); + ath_tx_send_ampdu(sc, tid, bf, txctl); } else { - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); - if (!bf) - goto out; + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); bf->bf_state.bfs_paprd = txctl->paprd; @@ -1858,10 +1821,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); - ath_tx_send_normal(sc, txctl->txq, tid, skb); + ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); } -out: spin_unlock_bh(&txctl->txq->axq_lock); } @@ -1875,6 +1837,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_vif *vif = info->control.vif; struct ath_softc *sc = hw->priv; struct ath_txq *txq = txctl->txq; + struct ath_buf *bf; int padpos, padsize; int frmlen = skb->len + FCS_LEN; int q; @@ -1921,6 +1884,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, * info are no longer valid (overwritten by the ath_frame_info data. */ + bf = ath_tx_setup_buffer(hw, txctl->txq, skb); + if (unlikely(!bf)) + return -ENOMEM; + q = skb_get_queue_mapping(skb); spin_lock_bh(&txq->axq_lock); if (txq == sc->tx.txq_map[q] && @@ -1930,7 +1897,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, } spin_unlock_bh(&txq->axq_lock); - ath_tx_start_dma(sc, skb, txctl); + ath_tx_start_dma(sc, bf, txctl); + return 0; } @@ -2423,7 +2391,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->sched = false; tid->paused = false; tid->state &= ~AGGR_CLEANUP; - __skb_queue_head_init(&tid->buf_q); + INIT_LIST_HEAD(&tid->buf_q); acno = TID_TO_WME_AC(tidno); tid->ac = &an->ac[acno]; tid->state &= ~AGGR_ADDBA_COMPLETE; diff --git a/trunk/drivers/net/wireless/ath/main.c b/trunk/drivers/net/wireless/ath/main.c index d9218fe02036..c325202fdc5f 100644 --- a/trunk/drivers/net/wireless/ath/main.c +++ b/trunk/drivers/net/wireless/ath/main.c @@ -57,18 +57,22 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, } EXPORT_SYMBOL(ath_rxbuf_alloc); -void ath_printk(const char *level, const char *fmt, ...) +int ath_printk(const char *level, struct ath_common *common, + const char *fmt, ...) { struct va_format vaf; va_list args; + int rtn; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - printk("%sath: %pV", level, &vaf); + rtn = printk("%sath: %pV", level, &vaf); va_end(args); + + return rtn; } EXPORT_SYMBOL(ath_printk); diff --git a/trunk/drivers/net/wireless/b43/Kconfig b/trunk/drivers/net/wireless/b43/Kconfig index b97a40ed5fff..df2b7c0856ed 100644 --- a/trunk/drivers/net/wireless/b43/Kconfig +++ b/trunk/drivers/net/wireless/b43/Kconfig @@ -124,12 +124,12 @@ config B43_PHY_LP (802.11a support is optional, and currently disabled). config B43_PHY_HT - bool "Support for HT-PHY (high throughput) devices (EXPERIMENTAL)" - depends on B43 && EXPERIMENTAL + bool "Support for HT-PHY devices (BROKEN)" + depends on B43 && BROKEN ---help--- Support for the HT-PHY. - Enables support for BCM4331 and possibly other chipsets with that PHY. + Say N, this is BROKEN and crashes driver. config B43_PHY_LCN bool "Support for LCN-PHY devices (BROKEN)" diff --git a/trunk/drivers/net/wireless/b43/dma.c b/trunk/drivers/net/wireless/b43/dma.c index 5e45604f0f5d..c5d890e74a1e 100644 --- a/trunk/drivers/net/wireless/b43/dma.c +++ b/trunk/drivers/net/wireless/b43/dma.c @@ -419,34 +419,33 @@ static int alloc_ringmemory(struct b43_dmaring *ring) gfp_t flags = GFP_KERNEL; /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K - * alignment and 8K buffers for 64-bit DMA with 8K alignment. - * In practice we could use smaller buffers for the latter, but the - * alignment is really important because of the hardware bug. If bit - * 0x00001000 is used in DMA address, some hardware (like BCM4331) - * copies that bit into B43_DMA64_RXSTATUS and we get false values from - * B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use - * more than 256 slots for ring. + * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing + * has shown that 4K is sufficient for the latter as long as the buffer + * does not cross an 8K boundary. + * + * For unknown reasons - possibly a hardware error - the BCM4311 rev + * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, + * which accounts for the GFP_DMA flag below. + * + * The flags here must match the flags in free_ringmemory below! */ - u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? - B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; - + if (ring->type == B43_DMA_64BIT) + flags |= GFP_DMA; ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, - ring_mem_size, &(ring->dmabase), - flags); + B43_DMA_RINGMEMSIZE, + &(ring->dmabase), flags); if (!ring->descbase) { b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; } - memset(ring->descbase, 0, ring_mem_size); + memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); return 0; } static void free_ringmemory(struct b43_dmaring *ring) { - u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? - B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; - dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size, + dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, ring->descbase, ring->dmabase); } diff --git a/trunk/drivers/net/wireless/b43/dma.h b/trunk/drivers/net/wireless/b43/dma.h index 315b96ed1d90..7e20b04fa51a 100644 --- a/trunk/drivers/net/wireless/b43/dma.h +++ b/trunk/drivers/net/wireless/b43/dma.h @@ -161,8 +161,7 @@ struct b43_dmadesc_generic { } __packed; /* Misc DMA constants */ -#define B43_DMA32_RINGMEMSIZE 4096 -#define B43_DMA64_RINGMEMSIZE 8192 +#define B43_DMA_RINGMEMSIZE PAGE_SIZE /* Offset of frame with actual data */ #define B43_DMA0_RX_FW598_FO 38 #define B43_DMA0_RX_FW351_FO 30 diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index 172294170df8..d2b1d1fe202b 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -4131,13 +4131,10 @@ static void b43_op_configure_filter(struct ieee80211_hw *hw, * because the core might be gone away while we unlocked the mutex. */ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) { - struct b43_wl *wl; + struct b43_wl *wl = dev->wl; struct b43_wldev *orig_dev; u32 mask; - if (!dev) - return NULL; - wl = dev->wl; redo: if (!dev || b43_status(dev) < B43_STAT_STARTED) return dev; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c index 4766c3a1a2f6..ccdbed567171 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -43,8 +43,6 @@ #include "iwl-agn.h" #include "iwl-helpers.h" #include "iwl-agn-hw.h" -#include "iwl-shared.h" -#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL1000_UCODE_API_MAX 6 @@ -78,21 +76,21 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; - hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; + priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } /* NIC configuration for 1000 series */ static void iwl1000_nic_config(struct iwl_priv *priv) { /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); /* Setting digital SVR for 1000 card to 1.32V */ /* locking is acquired in iwl_set_bits_mask_prph() function */ - iwl_set_bits_mask_prph(bus(priv), APMG_DIGITAL_SVR_REG, + iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, APMG_SVR_DIGITAL_VOLTAGE_1_32, ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); } @@ -129,39 +127,43 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - hw_params(priv).rx_chains_num = 1; + priv->hw_params.rx_chains_num = 1; else - hw_params(priv).rx_chains_num = + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl1000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl1000_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl1000_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c index 764d3104e128..54d931d614fb 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -44,8 +44,6 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" -#include "iwl-shared.h" -#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL2030_UCODE_API_MAX 6 @@ -80,8 +78,8 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD; - hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; + priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } /* NIC configuration for 2000 series */ @@ -90,7 +88,7 @@ static void iwl2000_nic_config(struct iwl_priv *priv) iwl_rf_config(priv); if (priv->cfg->iq_invert) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); } @@ -126,40 +124,44 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ); + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - hw_params(priv).rx_chains_num = 1; + priv->hw_params.rx_chains_num = 1; else - hw_params(priv).rx_chains_num = + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl2000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl2000_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl2000_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; + priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; if (priv->cfg->need_temp_offset_calib) - hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -177,7 +179,7 @@ static struct iwl_lib_ops iwl2000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -198,7 +200,7 @@ static struct iwl_lib_ops iwl2030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REGULATORY_BAND_NO_HT40, }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -282,11 +284,6 @@ struct iwl_cfg iwl2000_2bg_cfg = { IWL_DEVICE_2000, }; -struct iwl_cfg iwl2000_2bgn_d_cfg = { - .name = "2000D Series 2x2 BGN", - IWL_DEVICE_2000, -}; - #define IWL_DEVICE_2030 \ .fw_name_pre = IWL2030_FW_PRE, \ .ucode_api_max = IWL2030_UCODE_API_MAX, \ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c index 7cb4d69e0c37..a9adee5634d8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -46,8 +46,6 @@ #include "iwl-agn-hw.h" #include "iwl-5000-hw.h" #include "iwl-trans.h" -#include "iwl-shared.h" -#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL5000_UCODE_API_MAX 5 @@ -70,18 +68,18 @@ static void iwl5000_nic_config(struct iwl_priv *priv) iwl_rf_config(priv); - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* W/A : NIC is stuck in a reset state after Early PCIe power off * (PCIe power is lost before PERST# is asserted), * causing ME FW to lose ownership and not being able to obtain it back. */ - iwl_set_bits_mask_prph(bus(priv), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } static struct iwl_sensitivity_ranges iwl5000_sensitivity = { @@ -141,13 +139,13 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv) s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - iwl_temp_calib_to_offset(priv); - hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef; + priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; } static void iwl5000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; } static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) @@ -157,34 +155,38 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl5000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl5000_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl5000_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_TX_IQ_PERD) | BIT(IWL_CALIB_BASE_BAND); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -196,34 +198,38 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - hw_params(priv).rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl5150_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl5150_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl5150_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -308,7 +314,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return iwl_trans_send_cmd(trans(priv), &hcmd); + return trans_send_cmd(&priv->trans, &hcmd); } static struct iwl_lib_ops iwl5000_lib = { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c index 2a98e65ca84c..339de88d9ae2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -45,8 +45,6 @@ #include "iwl-agn-hw.h" #include "iwl-6000-hw.h" #include "iwl-trans.h" -#include "iwl-shared.h" -#include "iwl-pci.h" /* Highest firmware API version supported */ #define IWL6000_UCODE_API_MAX 4 @@ -76,15 +74,15 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) { /* want Celsius */ - hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD; - hw_params(priv).ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; + priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; + priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } static void iwl6050_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ if (iwlagn_eeprom_calib_version(priv) >= 6) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); } @@ -92,9 +90,9 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv) { /* Indicate calibration version to uCode. */ if (iwlagn_eeprom_calib_version(priv) >= 6) - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); - iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG, + iwl_set_bit(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_6050_1x2); } @@ -106,7 +104,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv) /* no locking required for register write */ if (priv->cfg->pa_type == IWL_PA_INTERNAL) { /* 2x2 IPA phy type */ - iwl_write32(bus(priv), CSR_GP_DRIVER_REG, + iwl_write32(priv, CSR_GP_DRIVER_REG, CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); } /* do additional nic configuration if needed */ @@ -146,41 +144,45 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) priv->cfg->base_params->num_of_queues = iwlagn_mod_params.num_of_queues; - hw_params(priv).max_txq_num = priv->cfg->base_params->num_of_queues; - hw_params(priv).max_stations = IWLAGN_STATION_COUNT; + priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->base_params->num_of_queues * + sizeof(struct iwlagn_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWLAGN_STATION_COUNT; priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; - hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE; - hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE; + priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ); - hw_params(priv).tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); if (priv->cfg->rx_with_siso_diversity) - hw_params(priv).rx_chains_num = 1; + priv->hw_params.rx_chains_num = 1; else - hw_params(priv).rx_chains_num = + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - hw_params(priv).valid_tx_ant = priv->cfg->valid_tx_ant; - hw_params(priv).valid_rx_ant = priv->cfg->valid_rx_ant; + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; iwl6000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ - hw_params(priv).sens = &iwl6000_sensitivity; - hw_params(priv).calib_init_cfg = + priv->hw_params.sens = &iwl6000_sensitivity; + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) - hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; + priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; if (priv->cfg->need_temp_offset_calib) - hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); - hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; + priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; return 0; } @@ -253,7 +255,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return -EFAULT; } - return iwl_trans_send_cmd(trans(priv), &hcmd); + return trans_send_cmd(&priv->trans, &hcmd); } static struct iwl_lib_ops iwl6000_lib = { @@ -270,7 +272,7 @@ static struct iwl_lib_ops iwl6000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -292,7 +294,7 @@ static struct iwl_lib_ops iwl6030_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .update_enhanced_txpower = iwl_eeprom_enhanced_txpower, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, }, .temperature = iwlagn_temperature, }; @@ -393,12 +395,6 @@ struct iwl_cfg iwl6005_2bg_cfg = { IWL_DEVICE_6005, }; -struct iwl_cfg iwl6005_2agn_sff_cfg = { - .name = "Intel(R) Centrino(R) Advanced-N 6205S AGN", - IWL_DEVICE_6005, - .ht_params = &iwl6000_ht_params, -}; - #define IWL_DEVICE_6030 \ .fw_name_pre = IWL6030_FW_PRE, \ .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index b725f6970dee..1789e3af8101 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -93,12 +93,12 @@ int iwl_send_calib_results(struct iwl_priv *priv) }; for (i = 0; i < IWL_CALIB_MAX; i++) { - if ((BIT(i) & hw_params(priv).calib_init_cfg) && + if ((BIT(i) & priv->hw_params.calib_init_cfg) && priv->calib_results[i].buf) { hcmd.len[0] = priv->calib_results[i].buf_len; hcmd.data[0] = priv->calib_results[i].buf; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - ret = iwl_trans_send_cmd(trans(priv), &hcmd); + ret = trans_send_cmd(&priv->trans, &hcmd); if (ret) { IWL_ERR(priv, "Error %d iteration %d\n", ret, i); @@ -174,7 +174,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv, u32 max_false_alarms = MAX_FA_CCK * rx_enable_time; u32 min_false_alarms = MIN_FA_CCK * rx_enable_time; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; + const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; data = &(priv->sensitivity_data); @@ -357,7 +357,7 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time; u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; + const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; data = &(priv->sensitivity_data); @@ -484,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE); - return iwl_trans_send_cmd(trans(priv), &cmd_out); + return trans_send_cmd(&priv->trans, &cmd_out); } /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ @@ -573,7 +573,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]), sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); - return iwl_trans_send_cmd(trans(priv), &cmd_out); + return trans_send_cmd(&priv->trans, &cmd_out); } void iwl_init_sensitivity(struct iwl_priv *priv) @@ -581,7 +581,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) int ret = 0; int i; struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = hw_params(priv).sens; + const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; if (priv->disable_sens_cal) return; @@ -658,13 +658,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) return; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); rx_info = &priv->statistics.rx_non_phy; ofdm = &priv->statistics.rx_ofdm; cck = &priv->statistics.rx_cck; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -688,7 +688,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv) statis.beacon_energy_c = le32_to_cpu(rx_info->beacon_energy_c); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); @@ -821,21 +821,21 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, * To be safe, simply mask out any chains that we know * are not on the device. */ - active_chains &= hw_params(priv).valid_rx_ant; + active_chains &= priv->hw_params.valid_rx_ant; num_tx_chains = 0; for (i = 0; i < NUM_RX_CHAINS; i++) { /* loops on all the bits of * priv->hw_setting.valid_tx_ant */ u8 ant_msk = (1 << i); - if (!(hw_params(priv).valid_tx_ant & ant_msk)) + if (!(priv->hw_params.valid_tx_ant & ant_msk)) continue; num_tx_chains++; if (data->disconn_array[i] == 0) /* there is a Tx antenna connected */ break; - if (num_tx_chains == hw_params(priv).tx_chains_num && + if (num_tx_chains == priv->hw_params.tx_chains_num && data->disconn_array[i]) { /* * If all chains are disconnected @@ -852,13 +852,12 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, } } - if (active_chains != hw_params(priv).valid_rx_ant && + if (active_chains != priv->hw_params.valid_rx_ant && active_chains != priv->chain_noise_data.active_chains) IWL_DEBUG_CALIB(priv, "Detected that not all antennas are connected! " "Connected: %#x, valid: %#x.\n", - active_chains, - hw_params(priv).valid_rx_ant); + active_chains, priv->hw_params.valid_rx_ant); /* Save for use within RXON, TX, SCAN commands, etc. */ data->active_chains = active_chains; @@ -918,7 +917,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, priv->phy_calib_chain_noise_gain_cmd); cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_2 = data->delta_gain_code[2]; - iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD, + trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, CMD_ASYNC, sizeof(cmd), &cmd); data->radio_write = 1; @@ -976,13 +975,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) return; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); rx_info = &priv->statistics.rx_non_phy; if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -997,7 +996,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", rxon_chnum, rxon_band24); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -1016,7 +1015,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER; chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); data->beacon_count++; @@ -1047,7 +1046,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) priv->cfg->bt_params->advanced_bt_coexist) { /* Disable disconnected antenna algorithm for advanced bt coex, assuming valid antennas are connected */ - data->active_chains = hw_params(priv).valid_rx_ant; + data->active_chains = priv->hw_params.valid_rx_ant; for (i = 0; i < NUM_RX_CHAINS; i++) if (!(data->active_chains & (1<disconn_array[i] = 1; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index c62ddc2a31bd..b8347db850e7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -195,7 +195,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, } static void -iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, +iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv, struct iwl_eeprom_enhanced_txpwr *txp, s8 max_txpower_avg) { @@ -235,7 +235,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv, #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \ ? # x " " : "") -void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) +void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) { struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; int idx, entries; @@ -294,6 +294,6 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm) priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm; - iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); + iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg); } } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 33951a11327d..47c43042ba4f 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -95,4 +95,17 @@ #define IWLAGN_NUM_AMPDU_QUEUES 9 #define IWLAGN_FIRST_AMPDU_QUEUE 11 +/* Fixed (non-configurable) rx data from phy */ + +/** + * struct iwlagn_schedq_bc_tbl scheduler byte count table + * base physical address provided by SCD_DRAM_BASE_ADDR + * @tfd_offset 0-12 - tx command byte count + * 12-16 - station index + */ +struct iwlagn_scd_bc_tbl { + __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; +} __packed; + + #endif /* __iwl_agn_hw_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 7c036b9c2b30..4edb6cfc5488 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -40,7 +40,449 @@ #include "iwl-agn.h" #include "iwl-sta.h" #include "iwl-trans.h" -#include "iwl-shared.h" + +static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) +{ + return le32_to_cpup((__le32 *)&tx_resp->status + + tx_resp->frame_count) & MAX_SN; +} + +static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) +{ + status &= TX_STATUS_MSK; + + switch (status) { + case TX_STATUS_POSTPONE_DELAY: + priv->reply_tx_stats.pp_delay++; + break; + case TX_STATUS_POSTPONE_FEW_BYTES: + priv->reply_tx_stats.pp_few_bytes++; + break; + case TX_STATUS_POSTPONE_BT_PRIO: + priv->reply_tx_stats.pp_bt_prio++; + break; + case TX_STATUS_POSTPONE_QUIET_PERIOD: + priv->reply_tx_stats.pp_quiet_period++; + break; + case TX_STATUS_POSTPONE_CALC_TTAK: + priv->reply_tx_stats.pp_calc_ttak++; + break; + case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: + priv->reply_tx_stats.int_crossed_retry++; + break; + case TX_STATUS_FAIL_SHORT_LIMIT: + priv->reply_tx_stats.short_limit++; + break; + case TX_STATUS_FAIL_LONG_LIMIT: + priv->reply_tx_stats.long_limit++; + break; + case TX_STATUS_FAIL_FIFO_UNDERRUN: + priv->reply_tx_stats.fifo_underrun++; + break; + case TX_STATUS_FAIL_DRAIN_FLOW: + priv->reply_tx_stats.drain_flow++; + break; + case TX_STATUS_FAIL_RFKILL_FLUSH: + priv->reply_tx_stats.rfkill_flush++; + break; + case TX_STATUS_FAIL_LIFE_EXPIRE: + priv->reply_tx_stats.life_expire++; + break; + case TX_STATUS_FAIL_DEST_PS: + priv->reply_tx_stats.dest_ps++; + break; + case TX_STATUS_FAIL_HOST_ABORTED: + priv->reply_tx_stats.host_abort++; + break; + case TX_STATUS_FAIL_BT_RETRY: + priv->reply_tx_stats.bt_retry++; + break; + case TX_STATUS_FAIL_STA_INVALID: + priv->reply_tx_stats.sta_invalid++; + break; + case TX_STATUS_FAIL_FRAG_DROPPED: + priv->reply_tx_stats.frag_drop++; + break; + case TX_STATUS_FAIL_TID_DISABLE: + priv->reply_tx_stats.tid_disable++; + break; + case TX_STATUS_FAIL_FIFO_FLUSHED: + priv->reply_tx_stats.fifo_flush++; + break; + case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: + priv->reply_tx_stats.insuff_cf_poll++; + break; + case TX_STATUS_FAIL_PASSIVE_NO_RX: + priv->reply_tx_stats.fail_hw_drop++; + break; + case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: + priv->reply_tx_stats.sta_color_mismatch++; + break; + default: + priv->reply_tx_stats.unknown++; + break; + } +} + +static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) +{ + status &= AGG_TX_STATUS_MSK; + + switch (status) { + case AGG_TX_STATE_UNDERRUN_MSK: + priv->reply_agg_tx_stats.underrun++; + break; + case AGG_TX_STATE_BT_PRIO_MSK: + priv->reply_agg_tx_stats.bt_prio++; + break; + case AGG_TX_STATE_FEW_BYTES_MSK: + priv->reply_agg_tx_stats.few_bytes++; + break; + case AGG_TX_STATE_ABORT_MSK: + priv->reply_agg_tx_stats.abort++; + break; + case AGG_TX_STATE_LAST_SENT_TTL_MSK: + priv->reply_agg_tx_stats.last_sent_ttl++; + break; + case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: + priv->reply_agg_tx_stats.last_sent_try++; + break; + case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: + priv->reply_agg_tx_stats.last_sent_bt_kill++; + break; + case AGG_TX_STATE_SCD_QUERY_MSK: + priv->reply_agg_tx_stats.scd_query++; + break; + case AGG_TX_STATE_TEST_BAD_CRC32_MSK: + priv->reply_agg_tx_stats.bad_crc32++; + break; + case AGG_TX_STATE_RESPONSE_MSK: + priv->reply_agg_tx_stats.response++; + break; + case AGG_TX_STATE_DUMP_TX_MSK: + priv->reply_agg_tx_stats.dump_tx++; + break; + case AGG_TX_STATE_DELAY_TX_MSK: + priv->reply_agg_tx_stats.delay_tx++; + break; + default: + priv->reply_agg_tx_stats.unknown++; + break; + } +} + +static void iwlagn_set_tx_status(struct iwl_priv *priv, + struct ieee80211_tx_info *info, + struct iwl_rxon_context *ctx, + struct iwlagn_tx_resp *tx_resp, + int txq_id, bool is_agg) +{ + u16 status = le16_to_cpu(tx_resp->status.status); + + info->status.rates[0].count = tx_resp->failure_frame + 1; + if (is_agg) + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + info->flags |= iwl_tx_status_to_mac80211(status); + iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), + info); + if (!iwl_is_tx_success(status)) + iwlagn_count_tx_err_status(priv, status); + + if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && + iwl_is_associated_ctx(ctx) && ctx->vif && + ctx->vif->type == NL80211_IFTYPE_STATION) { + ctx->last_tx_rejected = true; + iwl_stop_queue(priv, &priv->txq[txq_id]); + } + + IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " + "0x%x retries %d\n", + txq_id, + iwl_get_tx_fail_reason(status), status, + le32_to_cpu(tx_resp->rate_n_flags), + tx_resp->failure_frame); +} + +#ifdef CONFIG_IWLWIFI_DEBUG +#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x + +const char *iwl_get_agg_tx_fail_reason(u16 status) +{ + status &= AGG_TX_STATUS_MSK; + switch (status) { + case AGG_TX_STATE_TRANSMITTED: + return "SUCCESS"; + AGG_TX_STATE_FAIL(UNDERRUN_MSK); + AGG_TX_STATE_FAIL(BT_PRIO_MSK); + AGG_TX_STATE_FAIL(FEW_BYTES_MSK); + AGG_TX_STATE_FAIL(ABORT_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK); + AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK); + AGG_TX_STATE_FAIL(SCD_QUERY_MSK); + AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK); + AGG_TX_STATE_FAIL(RESPONSE_MSK); + AGG_TX_STATE_FAIL(DUMP_TX_MSK); + AGG_TX_STATE_FAIL(DELAY_TX_MSK); + } + + return "UNKNOWN"; +} +#endif /* CONFIG_IWLWIFI_DEBUG */ + +static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, + struct iwl_ht_agg *agg, + struct iwlagn_tx_resp *tx_resp, + int txq_id, u16 start_idx) +{ + u16 status; + struct agg_tx_status *frame_status = &tx_resp->status; + struct ieee80211_hdr *hdr = NULL; + int i, sh, idx; + u16 seq; + + if (agg->wait_for_ba) + IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); + + agg->frame_count = tx_resp->frame_count; + agg->start_idx = start_idx; + agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + agg->bitmap = 0; + + /* # frames attempted by Tx command */ + if (agg->frame_count == 1) { + struct iwl_tx_info *txb; + + /* Only one frame was attempted; no block-ack will arrive */ + idx = start_idx; + + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", + agg->frame_count, agg->start_idx, idx); + txb = &priv->txq[txq_id].txb[idx]; + iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(txb->skb), + txb->ctx, tx_resp, txq_id, true); + agg->wait_for_ba = 0; + } 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 */ + for (i = 0; i < agg->frame_count; i++) { + u16 sc; + status = le16_to_cpu(frame_status[i].status); + seq = le16_to_cpu(frame_status[i].sequence); + idx = SEQ_TO_INDEX(seq); + txq_id = SEQ_TO_QUEUE(seq); + + if (status & AGG_TX_STATUS_MSK) + iwlagn_count_agg_tx_err_status(priv, status); + + if (status & (AGG_TX_STATE_FEW_BYTES_MSK | + AGG_TX_STATE_ABORT_MSK)) + continue; + + IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", + agg->frame_count, txq_id, idx); + IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " + "try-count (0x%08x)\n", + iwl_get_agg_tx_fail_reason(status), + status & AGG_TX_STATUS_MSK, + status & AGG_TX_TRY_MSK); + + hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); + if (!hdr) { + IWL_ERR(priv, + "BUG_ON idx doesn't point to valid skb" + " idx=%d, txq_id=%d\n", idx, txq_id); + return -1; + } + + sc = le16_to_cpu(hdr->seq_ctrl); + if (idx != (SEQ_TO_SN(sc) & 0xff)) { + IWL_ERR(priv, + "BUG_ON idx doesn't match seq control" + " idx=%d, seq_idx=%d, seq=%d\n", + idx, SEQ_TO_SN(sc), + hdr->seq_ctrl); + return -1; + } + + 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 >= 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; + /* + * 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; + 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", + agg->frame_count, agg->start_idx, + (unsigned long long)agg->bitmap); + + if (bitmap) + agg->wait_for_ba = 1; + } + return 0; +} + +void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status) +{ + if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { + IWL_ERR(priv, "Tx flush command to flush out all frames\n"); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + queue_work(priv->workqueue, &priv->tx_flush); + } +} + +void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + u16 sequence = le16_to_cpu(pkt->hdr.sequence); + int txq_id = SEQ_TO_QUEUE(sequence); + int index = SEQ_TO_INDEX(sequence); + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct ieee80211_tx_info *info; + struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + struct ieee80211_hdr *hdr; + struct iwl_tx_info *txb; + u32 status = le16_to_cpu(tx_resp->status.status); + 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, "%s: Read index for DMA queue txq_id (%d) " + "index %d is out of range [0-%d] %d %d\n", __func__, + txq_id, index, txq->q.n_bd, txq->q.write_ptr, + txq->q.read_ptr); + return; + } + + txq->time_stamp = jiffies; + txb = &txq->txb[txq->q.read_ptr]; + info = IEEE80211_SKB_CB(txb->skb); + memset(&info->status, 0, sizeof(info->status)); + + tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> + IWLAGN_TX_RES_TID_POS; + sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> + IWLAGN_TX_RES_RA_POS; + + spin_lock_irqsave(&priv->sta_lock, flags); + + hdr = (void *)txb->skb->data; + if (!ieee80211_is_data_qos(hdr->frame_control)) + priv->last_seq_ctl = tx_resp->seq_ctl; + + if (txq->sched_retry) { + const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); + struct iwl_ht_agg *agg; + + agg = &priv->stations[sta_id].tid[tid].agg; + /* + * If the BT kill count is non-zero, we'll get this + * notification again. + */ + if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && + priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist) { + IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n"); + } + iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); + + /* check if BAR is needed */ + if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + + if (txq->q.read_ptr != (scd_ssn & 0xff)) { + index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); + IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " + "scd_ssn=%d idx=%d txq=%d swq=%d\n", + scd_ssn , index, txq_id, txq->swq_id); + + freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + + if (priv->mac80211_registered && + (iwl_queue_space(&txq->q) > txq->q.low_mark) && + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq); + } + } else { + iwlagn_set_tx_status(priv, info, txb->ctx, tx_resp, + txq_id, false); + freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); + + if (priv->mac80211_registered && + iwl_queue_space(&txq->q) > txq->q.low_mark && + status != TX_STATUS_FAIL_PASSIVE_NO_RX) + iwl_wake_queue(priv, txq); + } + + 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); +} int iwlagn_hw_valid_rtc_data_addr(u32 addr) { @@ -53,7 +495,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) struct iwlagn_tx_power_dbm_cmd tx_power_cmd; u8 tx_ant_cfg_cmd; - if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status), + if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status), "TX Power requested while scanning!\n")) return -EAGAIN; @@ -83,7 +525,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC, + return trans_send_cmd_pdu(&priv->trans, tx_ant_cfg_cmd, CMD_SYNC, sizeof(tx_power_cmd), &tx_power_cmd); } @@ -167,9 +609,6 @@ struct iwl_mod_params iwlagn_mod_params = { .bt_coex_active = true, .no_sleep_autoadjust = true, .power_level = IWL_POWER_INDEX_1, - .bt_ch_announce = true, - .wanted_ucode_alternative = 1, - .auto_agg = true, /* the rest are 0 by default */ }; @@ -328,15 +767,15 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) u16 rx_chain = 0; enum ieee80211_band band; u8 n_probes = 0; - u8 rx_ant = hw_params(priv).valid_rx_ant; + u8 rx_ant = priv->hw_params.valid_rx_ant; u8 rate; bool is_active = false; int chan_mod; u8 active_chains; - u8 scan_tx_antennas = hw_params(priv).valid_tx_ant; + u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (vif) ctx = iwl_rxon_ctx_from_vif(vif); @@ -503,7 +942,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); /* In power save mode use one chain, otherwise use all chains */ - if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { + if (test_bit(STATUS_POWER_PMI, &priv->status)) { /* rx_ant has been set to all valid chains previously */ active_chains = rx_ant & ((u8)(priv->chain_noise_data.active_chains)); @@ -523,8 +962,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) } /* MIMO is not used here, but value is required */ - rx_chain |= - hw_params(priv).valid_rx_ant << RXON_RX_CHAIN_VALID_POS; + rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; @@ -606,15 +1044,15 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) scan->len = cpu_to_le16(cmd.len[0]); /* set scan bit here for PAN params */ - set_bit(STATUS_SCAN_HW, &priv->shrd->status); + set_bit(STATUS_SCAN_HW, &priv->status); ret = iwlagn_set_pan_params(priv); if (ret) return ret; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) { - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + clear_bit(STATUS_SCAN_HW, &priv->status); iwlagn_set_pan_params(priv); } @@ -634,6 +1072,52 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, vif->bss_conf.bssid); } +void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed) +{ + lockdep_assert_held(&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; + } +} + +#define IWL_FLUSH_WAIT_MS 2000 + +int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) +{ + struct iwl_tx_queue *txq; + struct iwl_queue *q; + int cnt; + unsigned long now = jiffies; + int ret = 0; + + /* waiting for all the tx frames complete might take a while */ + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + if (cnt == priv->cmd_queue) + continue; + txq = &priv->txq[cnt]; + q = &txq->q; + while (q->read_ptr != q->write_ptr && !time_after(jiffies, + now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) + msleep(1); + + if (q->read_ptr != q->write_ptr) { + IWL_ERR(priv, "fail to flush all tx fifo queues\n"); + ret = -ETIMEDOUT; + break; + } + } + return ret; +} + +#define IWL_TX_QUEUE_MSK 0xfffff + /** * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode * @@ -672,22 +1156,22 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) flush_cmd.fifo_control); flush_cmd.flush_control = cpu_to_le16(flush_control); - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ieee80211_stop_queues(priv->hw); if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { IWL_ERR(priv, "flush request fail\n"); goto done; } IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); - iwl_trans_wait_tx_queue_empty(trans(priv)); + iwlagn_wait_tx_queue_empty(priv); done: ieee80211_wake_queues(priv->hw); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /* @@ -866,12 +1350,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) if (priv->cfg->bt_params->bt_session_2) { memcpy(&bt_cmd_2000.basic, &basic, sizeof(basic)); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000); } else { memcpy(&bt_cmd_6000.basic, &basic, sizeof(basic)); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000); } if (ret) @@ -884,7 +1368,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena) struct iwl_rxon_context *ctx, *found_ctx = NULL; bool found_ap = false; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Check whether AP or GO mode is active. */ if (rssi_ena) { @@ -997,7 +1481,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) break; } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* * We can not send command to firmware while scanning. When the scan @@ -1006,7 +1490,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) * STATUS_SCANNING to avoid race when queue_work two times from * different notifications, but quit and not perform any work at all. */ - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) + if (test_bit(STATUS_SCAN_HW, &priv->status)) goto out; iwl_update_chain_flags(priv); @@ -1025,7 +1509,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work) */ iwlagn_bt_coex_rssi_monitor(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /* @@ -1132,7 +1616,7 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv, priv->kill_cts_mask = bt_kill_cts_msg[kill_msk]; /* schedule to send runtime bt_config */ - queue_work(priv->shrd->workqueue, &priv->bt_runtime_config); + queue_work(priv->workqueue, &priv->bt_runtime_config); } } @@ -1176,7 +1660,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, IWL_BT_COEX_TRAFFIC_LOAD_NONE; } priv->bt_status = coex->bt_status; - queue_work(priv->shrd->workqueue, + queue_work(priv->workqueue, &priv->bt_traffic_change_work); } } @@ -1185,9 +1669,9 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, /* FIXME: based on notification, adjust the prio_boost */ - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); priv->bt_ci_compliance = coex->bt_ci_compliance; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv) @@ -1287,7 +1771,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { bool is_single = is_single_rx_stream(priv); - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->shrd->status); + bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; u32 active_chains; u16 rx_chain; @@ -1299,7 +1783,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (priv->chain_noise_data.active_chains) active_chains = priv->chain_noise_data.active_chains; else - active_chains = hw_params(priv).valid_rx_ant; + active_chains = priv->hw_params.valid_rx_ant; if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist && @@ -1364,6 +1848,136 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) return ant; } +static const char *get_csr_string(int cmd) +{ + switch (cmd) { + IWL_CMD(CSR_HW_IF_CONFIG_REG); + IWL_CMD(CSR_INT_COALESCING); + IWL_CMD(CSR_INT); + IWL_CMD(CSR_INT_MASK); + IWL_CMD(CSR_FH_INT_STATUS); + IWL_CMD(CSR_GPIO_IN); + IWL_CMD(CSR_RESET); + IWL_CMD(CSR_GP_CNTRL); + IWL_CMD(CSR_HW_REV); + IWL_CMD(CSR_EEPROM_REG); + IWL_CMD(CSR_EEPROM_GP); + IWL_CMD(CSR_OTP_GP_REG); + IWL_CMD(CSR_GIO_REG); + IWL_CMD(CSR_GP_UCODE_REG); + IWL_CMD(CSR_GP_DRIVER_REG); + IWL_CMD(CSR_UCODE_DRV_GP1); + IWL_CMD(CSR_UCODE_DRV_GP2); + IWL_CMD(CSR_LED_REG); + IWL_CMD(CSR_DRAM_INT_TBL_REG); + IWL_CMD(CSR_GIO_CHICKEN_BITS); + IWL_CMD(CSR_ANA_PLL_CFG); + IWL_CMD(CSR_HW_REV_WA_REG); + IWL_CMD(CSR_DBG_HPET_MEM_REG); + default: + return "UNKNOWN"; + } +} + +void iwl_dump_csr(struct iwl_priv *priv) +{ + int i; + static const u32 csr_tbl[] = { + CSR_HW_IF_CONFIG_REG, + CSR_INT_COALESCING, + CSR_INT, + CSR_INT_MASK, + CSR_FH_INT_STATUS, + CSR_GPIO_IN, + CSR_RESET, + CSR_GP_CNTRL, + CSR_HW_REV, + CSR_EEPROM_REG, + CSR_EEPROM_GP, + CSR_OTP_GP_REG, + CSR_GIO_REG, + CSR_GP_UCODE_REG, + CSR_GP_DRIVER_REG, + CSR_UCODE_DRV_GP1, + CSR_UCODE_DRV_GP2, + CSR_LED_REG, + CSR_DRAM_INT_TBL_REG, + CSR_GIO_CHICKEN_BITS, + CSR_ANA_PLL_CFG, + CSR_HW_REV_WA_REG, + CSR_DBG_HPET_MEM_REG + }; + IWL_ERR(priv, "CSR values:\n"); + IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " + "CSR_INT_PERIODIC_REG)\n"); + for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { + IWL_ERR(priv, " %25s: 0X%08x\n", + get_csr_string(csr_tbl[i]), + iwl_read32(priv, csr_tbl[i])); + } +} + +static const char *get_fh_string(int cmd) +{ + switch (cmd) { + IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); + IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); + IWL_CMD(FH_RSCSR_CHNL0_WPTR); + IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); + IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); + IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); + IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); + IWL_CMD(FH_TSSR_TX_STATUS_REG); + IWL_CMD(FH_TSSR_TX_ERROR_REG); + default: + return "UNKNOWN"; + } +} + +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) +{ + int i; +#ifdef CONFIG_IWLWIFI_DEBUG + int pos = 0; + size_t bufsz = 0; +#endif + static const u32 fh_tbl[] = { + FH_RSCSR_CHNL0_STTS_WPTR_REG, + FH_RSCSR_CHNL0_RBDCB_BASE_REG, + FH_RSCSR_CHNL0_WPTR, + FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_MEM_RSSR_SHARED_CTRL_REG, + FH_MEM_RSSR_RX_STATUS_REG, + FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, + FH_TSSR_TX_STATUS_REG, + FH_TSSR_TX_ERROR_REG + }; +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + pos += scnprintf(*buf + pos, bufsz - pos, + "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + pos += scnprintf(*buf + pos, bufsz - pos, + " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv, fh_tbl[i])); + } + return pos; + } +#endif + IWL_ERR(priv, "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + IWL_ERR(priv, " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv, fh_tbl[i])); + } + return 0; +} + /* notification wait support */ void iwlagn_init_notification_wait(struct iwl_priv *priv, struct iwl_notification_wait *wait_entry, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index ffee15ba06a8..1fa438e20f0a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -297,10 +297,10 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, u8 *qc = ieee80211_get_qos_ctl(hdr); tid = qc[0] & 0xf; } else - return IWL_MAX_TID_COUNT; + return MAX_TID_COUNT; if (unlikely(tid >= TID_MAX_LOAD_COUNT)) - return IWL_MAX_TID_COUNT; + return MAX_TID_COUNT; tl = &lq_data->load[tid]; @@ -313,7 +313,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, tl->queue_count = 1; tl->head = 0; tl->packet_count[0] = 1; - return IWL_MAX_TID_COUNT; + return MAX_TID_COUNT; } time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); @@ -420,7 +420,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, load = rs_tl_get_load(lq_data, tid); - if ((iwlagn_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { + if (load > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); ret = ieee80211_start_tx_ba_session(sta, tid, 5000); @@ -819,7 +819,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, if (num_of_ant(tbl->ant_type) > 1) tbl->ant_type = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); tbl->is_ht40 = 0; tbl->is_SGI = 0; @@ -877,12 +877,12 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, * Is there a need to switch between * full concurrency and 3-wire? */ - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) full_concurrent = true; else full_concurrent = false; - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || (priv->bt_full_concurrent != full_concurrent)) { @@ -893,7 +893,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); - queue_work(priv->shrd->workqueue, &priv->bt_full_concurrency); + queue_work(priv->workqueue, &priv->bt_full_concurrency); } } @@ -1293,7 +1293,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, return -1; /* Need both Tx chains/antennas to support MIMO */ - if (hw_params(priv).tx_chains_num < 2) + if (priv->hw_params.tx_chains_num < 2) return -1; IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n"); @@ -1349,7 +1349,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, return -1; /* Need both Tx chains/antennas to support MIMO */ - if (hw_params(priv).tx_chains_num < 3) + if (priv->hw_params.tx_chains_num < 3) return -1; IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); @@ -1448,8 +1448,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = hw_params(priv).valid_tx_ant; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret = 0; u8 update_search_tbl_counter = 0; @@ -1459,16 +1459,14 @@ static int rs_move_legacy_other(struct iwl_priv *priv, break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; break; case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && tbl->action != IWL_LEGACY_SWITCH_SISO) tbl->action = IWL_LEGACY_SWITCH_SISO; @@ -1491,8 +1489,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_LEGACY_SWITCH_SISO; - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); } start_action = tbl->action; @@ -1626,8 +1623,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = hw_params(priv).valid_tx_ant; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 update_search_tbl_counter = 0; int ret; @@ -1637,16 +1634,14 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, break; case IWL_BT_COEX_TRAFFIC_LOAD_LOW: /* avoid antenna B unless MIMO */ - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) tbl->action = IWL_SISO_SWITCH_ANTENNA1; break; case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: /* avoid antenna B and MIMO */ - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) tbl->action = IWL_SISO_SWITCH_ANTENNA1; break; @@ -1663,8 +1658,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, /* configure as 1x1 if bt full concurrency */ if (priv->bt_full_concurrent) { - valid_tx_ant = - first_antenna(hw_params(priv).valid_tx_ant); + valid_tx_ant = first_antenna(priv->hw_params.valid_tx_ant); if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) tbl->action = IWL_SISO_SWITCH_ANTENNA1; } @@ -1800,8 +1794,8 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = hw_params(priv).valid_tx_ant; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; u8 update_search_tbl_counter = 0; int ret; @@ -1970,8 +1964,8 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, u32 sz = (sizeof(struct iwl_scale_tbl_info) - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action; - u8 valid_tx_ant = hw_params(priv).valid_tx_ant; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 valid_tx_ant = priv->hw_params.valid_tx_ant; + u8 tx_chains_num = priv->hw_params.tx_chains_num; int ret; u8 update_search_tbl_counter = 0; @@ -2214,6 +2208,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) /* * setup rate table in uCode + * return rate_n_flags as used in the table */ static void rs_update_rate_tbl(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -2260,7 +2255,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, u8 done_search = 0; u16 high_low; s32 sr; - u8 tid = IWL_MAX_TID_COUNT; + u8 tid = MAX_TID_COUNT; struct iwl_tid_data *tid_data; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; struct iwl_rxon_context *ctx = sta_priv->common.ctx; @@ -2279,9 +2274,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; tid = rs_tl_add_packet(lq_sta, hdr); - if ((tid != IWL_MAX_TID_COUNT) && - (lq_sta->tx_agg_tid_en & (1 << tid))) { - tid_data = &priv->shrd->tid_data[lq_sta->lq.sta_id][tid]; + if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) { + tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid]; if (tid_data->agg.state == IWL_AGG_OFF) lq_sta->is_agg = 0; else @@ -2651,10 +2645,9 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, iwl_ht_enabled(priv)) { if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && (lq_sta->tx_agg_tid_en & (1 << tid)) && - (tid != IWL_MAX_TID_COUNT)) { - u8 sta_id = lq_sta->lq.sta_id; + (tid != MAX_TID_COUNT)) { tid_data = - &priv->shrd->tid_data[sta_id][tid]; + &priv->stations[lq_sta->lq.sta_id].tid[tid]; if (tid_data->agg.state == IWL_AGG_OFF) { IWL_DEBUG_RATE(priv, "try to aggregate tid %d\n", @@ -2710,7 +2703,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, i = lq_sta->last_txrate_idx; - valid_tx_ant = hw_params(priv).valid_tx_ant; + valid_tx_ant = priv->hw_params.valid_tx_ant; if (!lq_sta->search_better_tbl) active_tbl = lq_sta->active_tbl; @@ -2893,15 +2886,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i /* These values will be overridden later */ lq_sta->lq.general_params.single_stream_ant_msk = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); lq_sta->lq.general_params.dual_stream_ant_msk = - hw_params(priv).valid_tx_ant & - ~first_antenna(hw_params(priv).valid_tx_ant); + priv->hw_params.valid_tx_ant & + ~first_antenna(priv->hw_params.valid_tx_ant); if (!lq_sta->lq.general_params.dual_stream_ant_msk) { lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; - } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) { + } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { lq_sta->lq.general_params.dual_stream_ant_msk = - hw_params(priv).valid_tx_ant; + priv->hw_params.valid_tx_ant; } /* as default allow aggregation for all tids */ @@ -2947,7 +2940,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv && priv->bt_full_concurrent) { /* 1x1 only */ tbl_type.ant_type = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); } /* How many times should we repeat the initial rate? */ @@ -2979,7 +2972,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv->bt_full_concurrent) valid_tx_ant = ANT_A; else - valid_tx_ant = hw_params(priv).valid_tx_ant; + valid_tx_ant = priv->hw_params.valid_tx_ant; } /* Fill rest of rate table */ @@ -3013,7 +3006,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, if (priv && priv->bt_full_concurrent) { /* 1x1 only */ tbl_type.ant_type = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); } /* Indicate to uCode which entries might be MIMO. @@ -3104,7 +3097,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, u8 ant_sel_tx; priv = lq_sta->drv; - valid_tx_ant = hw_params(priv).valid_tx_ant; + valid_tx_ant = priv->hw_params.valid_tx_ant; if (lq_sta->dbg_fixed_rate) { ant_sel_tx = ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) @@ -3175,9 +3168,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, desc += sprintf(buff+desc, "fixed rate 0x%X\n", lq_sta->dbg_fixed_rate); desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", - (hw_params(priv).valid_tx_ant & ANT_A) ? "ANT_A," : "", - (hw_params(priv).valid_tx_ant & ANT_B) ? "ANT_B," : "", - (hw_params(priv).valid_tx_ant & ANT_C) ? "ANT_C" : ""); + (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", + (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", + (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); desc += sprintf(buff+desc, "lq type %s\n", (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); if (is_Ht(tbl->lq_type)) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 1af276739d87..d562e9359d97 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -31,7 +31,6 @@ #include "iwl-agn-calib.h" #include "iwl-helpers.h" #include "iwl-trans.h" -#include "iwl-shared.h" static int iwlagn_disable_bss(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -41,7 +40,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -67,7 +66,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -93,7 +92,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; @@ -122,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->qos_cmd, CMD_SYNC, sizeof(struct iwl_qosparam_cmd), &ctx->qos_data.def_qos_parm); if (ret) @@ -132,7 +131,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv, static int iwlagn_update_beacon(struct iwl_priv *priv, struct ieee80211_vif *vif) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); @@ -181,7 +180,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, ctx->staging.ofdm_ht_triple_stream_basic_rates; rxon_assoc.acquisition_data = ctx->staging.acquisition_data; - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_assoc_cmd, CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc); return ret; } @@ -267,7 +266,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, * Associated RXON doesn't clear the station table in uCode, * so we don't need to restore stations etc. after this. */ - ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, ctx->rxon_cmd, CMD_SYNC, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -316,7 +315,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS]; ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; @@ -363,7 +362,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) slot0 = bcnint / 2; slot1 = bcnint - slot0; - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) || + if (test_bit(STATUS_SCAN_HW, &priv->status) || (!ctx_bss->vif->bss_conf.idle && !ctx_bss->vif->bss_conf.assoc)) { slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; @@ -379,7 +378,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) ctx_pan->beacon_int; slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; slot1 = IWL_MIN_SLOT_TIME; } @@ -388,7 +387,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) cmd.slots[0].width = cpu_to_le16(slot0); cmd.slots[1].width = cpu_to_le16(slot1); - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WIPAN_PARAMS, CMD_SYNC, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret); @@ -421,12 +420,12 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EBUSY; /* This function hardcodes a bunch of dual-mode assumptions */ @@ -435,10 +434,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) if (!ctx->is_active) return 0; - /* override BSSID if necessary due to preauth */ - if (ctx->preauth_bssid) - memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN); - /* always get timestamp with Rx frame */ ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; @@ -467,7 +462,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * receive commit_rxon request * abort any previous channel switch if still in process */ - if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) && + if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && (priv->switch_channel != ctx->staging.channel)) { IWL_DEBUG_11H(priv, "abort channel switch on %d\n", le16_to_cpu(priv->switch_channel)); @@ -541,14 +536,14 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) IWL_DEBUG_MAC80211(priv, "changed %#x", changed); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { + if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); goto out; } - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); goto out; } @@ -580,7 +575,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) goto out; } - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); for_each_context(priv, ctx) { /* Configure HT40 channels */ @@ -624,7 +619,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) ctx->vif); } - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); iwl_update_bcast_stations(priv); @@ -656,7 +651,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) iwlagn_commit_rxon(priv, ctx); } out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -671,7 +666,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_cap; bool need_multiple; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); switch (vif->type) { case NL80211_IFTYPE_STATION: @@ -775,7 +770,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) memset(&cmd, 0, sizeof(cmd)); iwl_set_calib_hdr(&cmd.hdr, priv->phy_calib_chain_noise_reset_cmd); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_PHY_CALIBRATION_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) @@ -796,17 +791,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, int ret; bool force = false; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (unlikely(!iwl_is_ready(priv->shrd))) { + if (unlikely(!iwl_is_ready(priv))) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return; } if (unlikely(!ctx->vif)) { IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n"); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return; } @@ -839,8 +834,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, */ if (ctx->last_tx_rejected) { ctx->last_tx_rejected = false; - iwl_trans_wake_any_queue(trans(priv), - ctx->ctxid); + iwl_wake_any_queue(priv, ctx); } ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -901,7 +895,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, if (!priv->disable_chain_noise_cal) iwlagn_chain_noise_reset(priv); priv->start_calib = 1; - WARN_ON(ctx->preauth_bssid); } if (changes & BSS_CHANGED_IBSS) { @@ -919,7 +912,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, IWL_ERR(priv, "Error sending IBSS beacon\n"); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } void iwlagn_post_scan(struct iwl_priv *priv) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 8f0b86de1863..37e624095e40 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -49,7 +49,7 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id) return NULL; } - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Set up the rate scaling to start at selected rate, fall back * all the way down to 1M in IEEE order, and then spin on 1M */ @@ -63,23 +63,23 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id) if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) rate_flags |= RATE_MCS_CCK_MSK; - rate_flags |= first_antenna(hw_params(priv).valid_tx_ant) << + rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << RATE_MCS_ANT_POS; rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) link_cmd->rs_table[i].rate_n_flags = rate_n_flags; link_cmd->general_params.single_stream_ant_msk = - first_antenna(hw_params(priv).valid_tx_ant); + first_antenna(priv->hw_params.valid_tx_ant); link_cmd->general_params.dual_stream_ant_msk = - hw_params(priv).valid_tx_ant & - ~first_antenna(hw_params(priv).valid_tx_ant); + priv->hw_params.valid_tx_ant & + ~first_antenna(priv->hw_params.valid_tx_ant); if (!link_cmd->general_params.dual_stream_ant_msk) { link_cmd->general_params.dual_stream_ant_msk = ANT_AB; - } else if (num_of_ant(hw_params(priv).valid_tx_ant) == 2) { + } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { link_cmd->general_params.dual_stream_ant_msk = - hw_params(priv).valid_tx_ant; + priv->hw_params.valid_tx_ant; } link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; @@ -116,9 +116,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx if (sta_id_r) *sta_id_r = sta_id; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].used |= IWL_STA_LOCAL; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); /* Set up default rate scaling table in device's station table */ link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); @@ -132,9 +132,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx if (ret) IWL_ERR(priv, "Link quality command failed (%d)\n", ret); - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } @@ -189,7 +189,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, cmd.len[0] = cmd_size; if (not_empty || send_if_empty) - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); else return 0; } @@ -197,7 +197,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, int iwl_restore_default_wep_keys(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); return iwl_send_static_wepkey_cmd(priv, ctx, false); } @@ -208,13 +208,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); - if (iwl_is_rfkill(priv->shrd)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); /* but keys in device are clear anyway so return success */ return 0; @@ -232,7 +232,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (keyconf->keylen != WEP_KEY_LEN_128 && keyconf->keylen != WEP_KEY_LEN_64) { @@ -311,9 +311,9 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv, struct iwl_addsta_cmd sta_cmd; int i; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags |= STA_KEY_FLG_MAP_KEY_MSK; @@ -388,16 +388,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return -ENOENT; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) sta_id = IWL_INVALID_STATION; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); if (sta_id == IWL_INVALID_STATION) return 0; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); ctx->key_mapping_keys--; @@ -430,7 +430,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, if (sta_id == IWL_INVALID_STATION) return -EINVAL; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv); if (keyconf->hw_key_idx == WEP_INVALID_OFFSET) @@ -493,18 +493,18 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, unsigned long flags; u8 sta_id; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare broadcast station\n"); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return -EINVAL; } priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used |= IWL_STA_BCAST; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); if (!link_cmd) { @@ -513,9 +513,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv, return -ENOMEM; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } @@ -539,13 +539,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv, return -ENOMEM; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); if (priv->stations[sta_id].lq) kfree(priv->stations[sta_id].lq); else IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n"); priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return 0; } @@ -572,15 +572,15 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) unsigned long flags; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Remove "disable" flag, to enable Tx for this TID */ - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); 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; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -592,20 +592,20 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, int sta_id; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) return -ENXIO; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); 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->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -617,7 +617,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, int sta_id; struct iwl_addsta_cmd sta_cmd; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); sta_id = iwl_sta_id(sta); if (sta_id == IWL_INVALID_STATION) { @@ -625,13 +625,13 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, return -ENXIO; } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags_msk = 0; 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; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); } @@ -640,14 +640,14 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { unsigned long flags; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; 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->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); } @@ -655,7 +655,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) { unsigned long flags; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; priv->stations[sta_id].sta.sta.modify_mask = @@ -663,7 +663,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) 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->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 92ba8cd0ecd5..f501d742984c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -176,24 +176,24 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) struct iwl_tt_mgmt *tt = &priv->thermal_throttle; unsigned long flags; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (tt->state == IWL_TI_CT_KILL) { if (priv->thermal_throttle.ct_kill_toggle) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = false; } else { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = true; } - iwl_read32(bus(priv), CSR_UCODE_DRV_GP1); - spin_lock_irqsave(&bus(priv)->reg_lock, flags); - if (!iwl_grab_nic_access(bus(priv))) - iwl_release_nic_access(bus(priv)); - spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); + iwl_read32(priv, CSR_UCODE_DRV_GP1); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); /* Reschedule the ct_kill timer to occur in * CT_KILL_EXIT_DURATION seconds to ensure we get a @@ -209,7 +209,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, { if (stop) { IWL_DEBUG_TEMP(priv, "Stop all queues\n"); - if (priv->shrd->mac80211_registered) + if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); IWL_DEBUG_TEMP(priv, "Schedule 5 seconds CT_KILL Timer\n"); @@ -217,7 +217,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, jiffies + CT_KILL_EXIT_DURATION * HZ); } else { IWL_DEBUG_TEMP(priv, "Wake all queues\n"); - if (priv->shrd->mac80211_registered) + if (priv->mac80211_registered) ieee80211_wake_queues(priv->hw); } } @@ -227,7 +227,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data) struct iwl_priv *priv = (struct iwl_priv *)data; struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* temperature timer expired, ready to go into CT_KILL state */ @@ -235,7 +235,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data) IWL_DEBUG_TEMP(priv, "entering CT_KILL state when " "temperature timer expired\n"); tt->state = IWL_TI_CT_KILL; - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } } @@ -313,24 +313,23 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) tt->tt_power_mode = IWL_POWER_INDEX_5; break; } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->shrd->status); + clear_bit(STATUS_CT_KILL, &priv->status); if (tt->state != IWL_TI_CT_KILL && iwl_power_update_mode(priv, true)) { /* TT state not updated * try again during next temperature read */ if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); tt->state = old_state; IWL_ERR(priv, "Cannot update power mode, " "TT state not updated\n"); } else { if (tt->state == IWL_TI_CT_KILL) { if (force) { - set_bit(STATUS_CT_KILL, - &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } else { iwl_prepare_ct_kill_task(priv); @@ -344,7 +343,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) IWL_DEBUG_TEMP(priv, "Power Index change to %u\n", tt->tt_power_mode); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } @@ -454,9 +453,9 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) * in case get disabled before */ iwl_set_rxon_ht(priv, &priv->current_ht_config); } - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (old_state == IWL_TI_CT_KILL) - clear_bit(STATUS_CT_KILL, &priv->shrd->status); + clear_bit(STATUS_CT_KILL, &priv->status); if (tt->state != IWL_TI_CT_KILL && iwl_power_update_mode(priv, true)) { /* TT state not updated @@ -465,7 +464,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) IWL_ERR(priv, "Cannot update power mode, " "TT state not updated\n"); if (old_state == IWL_TI_CT_KILL) - set_bit(STATUS_CT_KILL, &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); tt->state = old_state; } else { IWL_DEBUG_TEMP(priv, @@ -476,8 +475,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) if (force) { IWL_DEBUG_TEMP(priv, "Enter IWL_TI_CT_KILL\n"); - set_bit(STATUS_CT_KILL, - &priv->shrd->status); + set_bit(STATUS_CT_KILL, &priv->status); iwl_perform_ct_kill_task(priv, true); } else { iwl_prepare_ct_kill_task(priv); @@ -489,7 +487,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) iwl_perform_ct_kill_task(priv, false); } } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } @@ -508,10 +506,10 @@ static void iwl_bg_ct_enter(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (!iwl_is_ready(priv->shrd)) + if (!iwl_is_ready(priv)) return; if (tt->state != IWL_TI_CT_KILL) { @@ -537,10 +535,10 @@ static void iwl_bg_ct_exit(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (!iwl_is_ready(priv->shrd)) + if (!iwl_is_ready(priv)) return; /* stop ct_kill_exit_tm timer */ @@ -567,20 +565,20 @@ static void iwl_bg_ct_exit(struct work_struct *work) void iwl_tt_enter_ct_kill(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n"); - queue_work(priv->shrd->workqueue, &priv->ct_enter); + queue_work(priv->workqueue, &priv->ct_enter); } void iwl_tt_exit_ct_kill(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n"); - queue_work(priv->shrd->workqueue, &priv->ct_exit); + queue_work(priv->workqueue, &priv->ct_exit); } static void iwl_bg_tt_work(struct work_struct *work) @@ -588,7 +586,7 @@ static void iwl_bg_tt_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); s32 temp = priv->temperature; /* degrees CELSIUS except specified */ - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (priv->cfg->base_params->temperature_kelvin) @@ -602,11 +600,11 @@ static void iwl_bg_tt_work(struct work_struct *work) void iwl_tt_handler(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n"); - queue_work(priv->shrd->workqueue, &priv->tt_work); + queue_work(priv->workqueue, &priv->tt_work); } /* Thermal throttling initialization diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index f8a4bcf0a34b..9bc26da62768 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -31,7 +31,6 @@ #include #include #include -#include #include "iwl-dev.h" #include "iwl-core.h" @@ -42,6 +41,79 @@ #include "iwl-agn.h" #include "iwl-trans.h" +/* + * mac80211 queues, ACs, hardware queues, FIFOs. + * + * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues + * + * Mac80211 uses the following numbers, which we get as from it + * by way of skb_get_queue_mapping(skb): + * + * VO 0 + * VI 1 + * BE 2 + * BK 3 + * + * + * Regular (not A-MPDU) frames are put into hardware queues corresponding + * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their + * own queue per aggregation session (RA/TID combination), such queues are + * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In + * order to map frames to the right queue, we also need an AC->hw queue + * mapping. This is implemented here. + * + * Due to the way hw queues are set up (by the hw specific modules like + * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity + * mapping. + */ + +static const u8 tid_to_ac[] = { + IEEE80211_AC_BE, + IEEE80211_AC_BK, + IEEE80211_AC_BK, + IEEE80211_AC_BE, + IEEE80211_AC_VI, + IEEE80211_AC_VI, + IEEE80211_AC_VO, + IEEE80211_AC_VO +}; + +static inline int get_ac_from_tid(u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return tid_to_ac[tid]; + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + +static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) +{ + if (likely(tid < ARRAY_SIZE(tid_to_ac))) + return ctx->ac_to_fifo[tid_to_ac[tid]]; + + /* no support for TIDs 8-15 yet */ + return -EINVAL; +} + +static int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, int sta_id, + int tid) +{ + if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || + (IWLAGN_FIRST_AMPDU_QUEUE + + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + IWL_WARN(priv, + "queue number out of range: %d, must be %d to %d\n", + txq_id, IWLAGN_FIRST_AMPDU_QUEUE, + IWLAGN_FIRST_AMPDU_QUEUE + + priv->cfg->base_params->num_of_ampdu_queues - 1); + return -EINVAL; + } + + /* Modify device's station table to Tx this TID */ + return iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); +} + static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, struct ieee80211_tx_info *info, __le16 fc, __le32 *tx_flags) @@ -188,10 +260,10 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, priv->bt_full_concurrent) { /* operated as 1x1 in full concurrency mode */ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - first_antenna(hw_params(priv).valid_tx_ant)); + first_antenna(priv->hw_params.valid_tx_ant)); } else priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - hw_params(priv).valid_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 */ @@ -249,21 +321,23 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_station_priv *sta_priv = NULL; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl_device_cmd *dev_cmd = NULL; struct iwl_tx_cmd *tx_cmd; + int txq_id; + u16 seq_number = 0; __le16 fc; u8 hdr_len; u16 len; u8 sta_id; + u8 tid = 0; unsigned long flags; bool is_agg = false; if (info->control.vif) ctx = iwl_rxon_ctx_from_vif(info->control.vif); - spin_lock_irqsave(&priv->shrd->lock, flags); - if (iwl_is_rfkill(priv->shrd)) { + spin_lock_irqsave(&priv->lock, flags); + if (iwl_is_rfkill(priv)) { IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); goto drop_unlock_priv; } @@ -313,16 +387,51 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); } - /* irqs already disabled/saved above when locking priv->shrd->lock */ - spin_lock(&priv->shrd->sta_lock); + /* + * Send this frame after DTIM -- there's a special queue + * reserved for this for contexts that support AP mode. + */ + if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { + txq_id = ctx->mcast_queue; + /* + * The microcode will clear the more data + * bit in the last frame it transmits. + */ + hdr->frame_control |= + cpu_to_le16(IEEE80211_FCTL_MOREDATA); + } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) + txq_id = IWL_AUX_QUEUE; + else + txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; - dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC); + /* irqs already disabled/saved above when locking priv->lock */ + spin_lock(&priv->sta_lock); - if (unlikely(!dev_cmd)) - goto drop_unlock_sta; + if (ieee80211_is_data_qos(fc)) { + u8 *qc = NULL; + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + + if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) + goto drop_unlock_sta; + + seq_number = priv->stations[sta_id].tid[tid].seq_number; + seq_number &= IEEE80211_SCTL_SEQ; + hdr->seq_ctrl = hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(seq_number); + seq_number += 0x10; + /* aggregation is on for this */ + if (info->flags & IEEE80211_TX_CTL_AMPDU && + priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { + txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; + is_agg = true; + } + } - memset(dev_cmd, 0, sizeof(*dev_cmd)); - tx_cmd = &dev_cmd->cmd.tx; + tx_cmd = trans_get_tx_cmd(&priv->trans, txq_id); + if (unlikely(!tx_cmd)) + goto drop_unlock_sta; /* Copy MAC header from skb into command buffer */ memcpy(tx_cmd->hdr, hdr, hdr_len); @@ -342,14 +451,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) iwl_update_stats(priv, true, fc, len); - info->driver_data[0] = ctx; - info->driver_data[1] = dev_cmd; - - if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id)) + if (trans_tx(&priv->trans, skb, tx_cmd, txq_id, fc, is_agg, ctx)) goto drop_unlock_sta; - spin_unlock(&priv->shrd->sta_lock); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + 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); + spin_unlock_irqrestore(&priv->lock, flags); /* * Avoid atomic ops if it isn't an associated client. @@ -364,20 +476,41 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) return 0; drop_unlock_sta: - if (dev_cmd) - kmem_cache_free(priv->tx_cmd_pool, dev_cmd); - spin_unlock(&priv->shrd->sta_lock); + spin_unlock(&priv->sta_lock); drop_unlock_priv: - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); + return -1; +} + +/* + * Find first available (lowest unused) Tx Queue, mark it "active". + * Called only when finding queue for aggregation. + * Should never return anything < 7, because they should already + * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) + */ +static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) +{ + int txq_id; + + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) + return txq_id; return -1; } int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; int sta_id; + int tx_fifo; + int txq_id; int ret; + unsigned long flags; + struct iwl_tid_data *tid_data; + + tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); + if (unlikely(tx_fifo < 0)) + return tx_fifo; IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n", sta->addr, tid); @@ -387,29 +520,58 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, IWL_ERR(priv, "Start AGG on invalid station\n"); return -ENXIO; } - if (unlikely(tid >= IWL_MAX_TID_COUNT)) + if (unlikely(tid >= MAX_TID_COUNT)) return -EINVAL; - if (priv->shrd->tid_data[sta_id][tid].agg.state != IWL_AGG_OFF) { + if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); return -ENXIO; } - ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); + txq_id = iwlagn_txq_ctx_activate_free(priv); + if (txq_id == -1) { + IWL_ERR(priv, "No free aggregation queue available\n"); + return -ENXIO; + } + + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; + *ssn = SEQ_TO_SN(tid_data->seq_number); + tid_data->agg.txq_id = txq_id; + tid_data->agg.tx_fifo = tx_fifo; + iwl_set_swq_id(&priv->txq[txq_id], get_ac_from_tid(tid), txq_id); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + ret = iwlagn_txq_agg_enable(priv, txq_id, sta_id, tid); if (ret) return ret; - ret = iwl_trans_tx_agg_alloc(trans(priv), vif_priv->ctx->ctxid, sta_id, - tid, ssn); - + 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; + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + } else { + IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", + tid_data->tfds_in_queue); + tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; + } + spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid) { - int sta_id; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; + int tx_fifo_id, txq_id, sta_id, ssn; + struct iwl_tid_data *tid_data; + int write_ptr, read_ptr; + unsigned long flags; + + tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); + if (unlikely(tx_fifo_id < 0)) + return tx_fifo_id; sta_id = iwl_sta_id(sta); @@ -418,8 +580,101 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, return -ENXIO; } - return iwl_trans_tx_agg_disable(trans(priv), vif_priv->ctx->ctxid, - sta_id, tid); + spin_lock_irqsave(&priv->sta_lock, flags); + + tid_data = &priv->stations[sta_id].tid[tid]; + ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; + txq_id = tid_data->agg.txq_id; + + switch (priv->stations[sta_id].tid[tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* + * This can happen if the peer stops aggregation + * again before we've had a chance to drain the + * queue we selected previously, i.e. before the + * session was really started completely. + */ + IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); + goto turn_off; + case IWL_AGG_ON: + break; + default: + IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); + } + + write_ptr = priv->txq[txq_id].q.write_ptr; + read_ptr = priv->txq[txq_id].q.read_ptr; + + /* The queue is not empty */ + if (write_ptr != read_ptr) { + 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"); + turn_off: + priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; + + /* 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 + * information are lost. if it is outside the range, there is no need + * to deactivate the uCode queue, just return "success" to allow + * mac80211 to clean up it own data. + */ + trans_txq_agg_disable(&priv->trans, txq_id, ssn, tx_fifo_id); + spin_unlock_irqrestore(&priv->lock, flags); + + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + + return 0; +} + +int iwlagn_txq_check_empty(struct iwl_priv *priv, + int sta_id, u8 tid, int txq_id) +{ + struct iwl_queue *q = &priv->txq[txq_id].q; + u8 *addr = priv->stations[sta_id].sta.sta.addr; + struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; + struct iwl_rxon_context *ctx; + + ctx = &priv->contexts[priv->stations[sta_id].ctxid]; + + lockdep_assert_held(&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 */ + /* aggregated HW queue */ + if ((txq_id == tid_data->agg.txq_id) && + (q->read_ptr == q->write_ptr)) { + u16 ssn = SEQ_TO_SN(tid_data->seq_number); + int tx_fifo = get_fifo_from_tid(ctx, tid); + IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); + trans_txq_agg_disable(&priv->trans, txq_id, + ssn, tx_fifo); + tid_data->agg.state = IWL_AGG_OFF; + ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); + } + break; + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* We are reclaiming the last packet of the queue */ + if (tid_data->tfds_in_queue == 0) { + IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); + tid_data->agg.state = IWL_AGG_ON; + ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid); + } + break; + } + + return 0; } static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, @@ -441,389 +696,147 @@ static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, rcu_read_unlock(); } -/** - * translate ucode response to mac80211 tx status control values - */ -static void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *info) +static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info, + bool is_agg) { - struct ieee80211_tx_rate *r = &info->control.rates[0]; - - info->antenna_sel_tx = - ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); - if (rate_n_flags & RATE_MCS_HT_MSK) - r->flags |= IEEE80211_TX_RC_MCS; - if (rate_n_flags & RATE_MCS_GF_MSK) - r->flags |= IEEE80211_TX_RC_GREEN_FIELD; - if (rate_n_flags & RATE_MCS_HT40_MSK) - r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (rate_n_flags & RATE_MCS_DUP_MSK) - r->flags |= IEEE80211_TX_RC_DUP_DATA; - if (rate_n_flags & RATE_MCS_SGI_MSK) - r->flags |= IEEE80211_TX_RC_SHORT_GI; - r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); -} - -#ifdef CONFIG_IWLWIFI_DEBUG -const char *iwl_get_tx_fail_reason(u32 status) -{ -#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x -#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x - - switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: - return "SUCCESS"; - TX_STATUS_POSTPONE(DELAY); - TX_STATUS_POSTPONE(FEW_BYTES); - TX_STATUS_POSTPONE(BT_PRIO); - TX_STATUS_POSTPONE(QUIET_PERIOD); - TX_STATUS_POSTPONE(CALC_TTAK); - TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); - TX_STATUS_FAIL(SHORT_LIMIT); - TX_STATUS_FAIL(LONG_LIMIT); - TX_STATUS_FAIL(FIFO_UNDERRUN); - TX_STATUS_FAIL(DRAIN_FLOW); - TX_STATUS_FAIL(RFKILL_FLUSH); - TX_STATUS_FAIL(LIFE_EXPIRE); - TX_STATUS_FAIL(DEST_PS); - TX_STATUS_FAIL(HOST_ABORTED); - TX_STATUS_FAIL(BT_RETRY); - TX_STATUS_FAIL(STA_INVALID); - TX_STATUS_FAIL(FRAG_DROPPED); - TX_STATUS_FAIL(TID_DISABLE); - TX_STATUS_FAIL(FIFO_FLUSHED); - TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); - TX_STATUS_FAIL(PASSIVE_NO_RX); - TX_STATUS_FAIL(NO_BEACON_ON_RADAR); - } + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; - return "UNKNOWN"; + if (!is_agg) + iwlagn_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1); -#undef TX_STATUS_FAIL -#undef TX_STATUS_POSTPONE + ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); } -#endif /* CONFIG_IWLWIFI_DEBUG */ -static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) +int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { - status &= AGG_TX_STATUS_MSK; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_tx_info *tx_info; + int nfreed = 0; + struct ieee80211_hdr *hdr; - switch (status) { - case AGG_TX_STATE_UNDERRUN_MSK: - priv->reply_agg_tx_stats.underrun++; - break; - case AGG_TX_STATE_BT_PRIO_MSK: - priv->reply_agg_tx_stats.bt_prio++; - break; - case AGG_TX_STATE_FEW_BYTES_MSK: - priv->reply_agg_tx_stats.few_bytes++; - break; - case AGG_TX_STATE_ABORT_MSK: - priv->reply_agg_tx_stats.abort++; - break; - case AGG_TX_STATE_LAST_SENT_TTL_MSK: - priv->reply_agg_tx_stats.last_sent_ttl++; - break; - case AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK: - priv->reply_agg_tx_stats.last_sent_try++; - break; - case AGG_TX_STATE_LAST_SENT_BT_KILL_MSK: - priv->reply_agg_tx_stats.last_sent_bt_kill++; - break; - case AGG_TX_STATE_SCD_QUERY_MSK: - priv->reply_agg_tx_stats.scd_query++; - break; - case AGG_TX_STATE_TEST_BAD_CRC32_MSK: - priv->reply_agg_tx_stats.bad_crc32++; - break; - case AGG_TX_STATE_RESPONSE_MSK: - priv->reply_agg_tx_stats.response++; - break; - case AGG_TX_STATE_DUMP_TX_MSK: - priv->reply_agg_tx_stats.dump_tx++; - break; - case AGG_TX_STATE_DELAY_TX_MSK: - priv->reply_agg_tx_stats.delay_tx++; - break; - default: - priv->reply_agg_tx_stats.unknown++; - break; + if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { + IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), " + "index %d is out of range [0-%d] %d %d.\n", __func__, + txq_id, index, q->n_bd, q->write_ptr, q->read_ptr); + return 0; } -} -static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, - struct iwlagn_tx_resp *tx_resp) -{ - struct agg_tx_status *frame_status = &tx_resp->status; - int tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> - IWLAGN_TX_RES_TID_POS; - int sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> - IWLAGN_TX_RES_RA_POS; - struct iwl_ht_agg *agg = &priv->shrd->tid_data[sta_id][tid].agg; - u32 status = le16_to_cpu(tx_resp->status.status); - int i; - - if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY(priv, - "got tx response w/o block-ack\n"); + for (index = iwl_queue_inc_wrap(index, q->n_bd); + q->read_ptr != index; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - agg->wait_for_ba = (tx_resp->frame_count > 1); + tx_info = &txq->txb[txq->q.read_ptr]; - /* - * If the BT kill count is non-zero, we'll get this - * notification again. - */ - if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && - priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { - IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); - } + if (WARN_ON_ONCE(tx_info->skb == NULL)) + continue; - /* Construct bit-map of pending frames within Tx window */ - for (i = 0; i < tx_resp->frame_count; i++) { - u16 fstatus = le16_to_cpu(frame_status[i].status); + hdr = (struct ieee80211_hdr *)tx_info->skb->data; + if (ieee80211_is_data_qos(hdr->frame_control)) + nfreed++; - if (status & AGG_TX_STATUS_MSK) - iwlagn_count_agg_tx_err_status(priv, fstatus); + iwlagn_tx_status(priv, tx_info, + txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); + tx_info->skb = NULL; - if (status & (AGG_TX_STATE_FEW_BYTES_MSK | - AGG_TX_STATE_ABORT_MSK)) - continue; + iwlagn_txq_inval_byte_cnt_tbl(priv, txq); - IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), " - "try-count (0x%08x)\n", - iwl_get_agg_tx_fail_reason(fstatus), - fstatus & AGG_TX_STATUS_MSK, - fstatus & AGG_TX_TRY_MSK); + iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr); } + return nfreed; } -#ifdef CONFIG_IWLWIFI_DEBUG -#define AGG_TX_STATE_FAIL(x) case AGG_TX_STATE_ ## x: return #x +/** + * iwlagn_tx_status_reply_compressed_ba - Update tx status from block-ack + * + * Go through block-ack's bitmap of ACK'd frames, update driver's record of + * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. + */ +static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, + struct iwl_ht_agg *agg, + struct iwl_compressed_ba_resp *ba_resp) -const char *iwl_get_agg_tx_fail_reason(u16 status) { - status &= AGG_TX_STATUS_MSK; - switch (status) { - case AGG_TX_STATE_TRANSMITTED: - return "SUCCESS"; - AGG_TX_STATE_FAIL(UNDERRUN_MSK); - AGG_TX_STATE_FAIL(BT_PRIO_MSK); - AGG_TX_STATE_FAIL(FEW_BYTES_MSK); - AGG_TX_STATE_FAIL(ABORT_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_TTL_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_TRY_CNT_MSK); - AGG_TX_STATE_FAIL(LAST_SENT_BT_KILL_MSK); - AGG_TX_STATE_FAIL(SCD_QUERY_MSK); - AGG_TX_STATE_FAIL(TEST_BAD_CRC32_MSK); - AGG_TX_STATE_FAIL(RESPONSE_MSK); - AGG_TX_STATE_FAIL(DUMP_TX_MSK); - AGG_TX_STATE_FAIL(DELAY_TX_MSK); + int sh; + u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); + u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); + struct ieee80211_tx_info *info; + u64 bitmap, sent_bitmap; + + if (unlikely(!agg->wait_for_ba)) { + if (unlikely(ba_resp->bitmap)) + IWL_ERR(priv, "Received BA when not expected\n"); + return -EINVAL; } - return "UNKNOWN"; -} -#endif /* CONFIG_IWLWIFI_DEBUG */ + /* Mark that the expected block-ack response arrived */ + agg->wait_for_ba = 0; + IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); -static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) -{ - return le32_to_cpup((__le32 *)&tx_resp->status + - tx_resp->frame_count) & MAX_SN; -} + /* Calculate shift to align block-ack bits with our Tx window bits */ + sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); + if (sh < 0) + sh += 0x100; -static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) -{ - status &= TX_STATUS_MSK; + /* + * Check for success or failure according to the + * transmitted bitmap and block-ack bitmap + */ + bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; + sent_bitmap = bitmap & agg->bitmap; - switch (status) { - case TX_STATUS_POSTPONE_DELAY: - priv->reply_tx_stats.pp_delay++; - break; - case TX_STATUS_POSTPONE_FEW_BYTES: - priv->reply_tx_stats.pp_few_bytes++; - break; - case TX_STATUS_POSTPONE_BT_PRIO: - priv->reply_tx_stats.pp_bt_prio++; - break; - case TX_STATUS_POSTPONE_QUIET_PERIOD: - priv->reply_tx_stats.pp_quiet_period++; - break; - case TX_STATUS_POSTPONE_CALC_TTAK: - priv->reply_tx_stats.pp_calc_ttak++; - break; - case TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY: - priv->reply_tx_stats.int_crossed_retry++; - break; - case TX_STATUS_FAIL_SHORT_LIMIT: - priv->reply_tx_stats.short_limit++; - break; - case TX_STATUS_FAIL_LONG_LIMIT: - priv->reply_tx_stats.long_limit++; - break; - case TX_STATUS_FAIL_FIFO_UNDERRUN: - priv->reply_tx_stats.fifo_underrun++; - break; - case TX_STATUS_FAIL_DRAIN_FLOW: - priv->reply_tx_stats.drain_flow++; - break; - case TX_STATUS_FAIL_RFKILL_FLUSH: - priv->reply_tx_stats.rfkill_flush++; - break; - case TX_STATUS_FAIL_LIFE_EXPIRE: - priv->reply_tx_stats.life_expire++; - break; - case TX_STATUS_FAIL_DEST_PS: - priv->reply_tx_stats.dest_ps++; - break; - case TX_STATUS_FAIL_HOST_ABORTED: - priv->reply_tx_stats.host_abort++; - break; - case TX_STATUS_FAIL_BT_RETRY: - priv->reply_tx_stats.bt_retry++; - break; - case TX_STATUS_FAIL_STA_INVALID: - priv->reply_tx_stats.sta_invalid++; - break; - case TX_STATUS_FAIL_FRAG_DROPPED: - priv->reply_tx_stats.frag_drop++; - break; - case TX_STATUS_FAIL_TID_DISABLE: - priv->reply_tx_stats.tid_disable++; - break; - case TX_STATUS_FAIL_FIFO_FLUSHED: - priv->reply_tx_stats.fifo_flush++; - break; - case TX_STATUS_FAIL_INSUFFICIENT_CF_POLL: - priv->reply_tx_stats.insuff_cf_poll++; - break; - case TX_STATUS_FAIL_PASSIVE_NO_RX: - priv->reply_tx_stats.fail_hw_drop++; - break; - case TX_STATUS_FAIL_NO_BEACON_ON_RADAR: - priv->reply_tx_stats.sta_color_mismatch++; - break; - default: - priv->reply_tx_stats.unknown++; - break; + /* Sanity check values reported by uCode */ + if (ba_resp->txed_2_done > ba_resp->txed) { + IWL_DEBUG_TX_REPLY(priv, + "bogus sent(%d) and ack(%d) count\n", + ba_resp->txed, ba_resp->txed_2_done); + /* + * set txed_2_done = txed, + * so it won't impact rate scale + */ + ba_resp->txed = ba_resp->txed_2_done; } -} - -static void iwlagn_set_tx_status(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - struct iwlagn_tx_resp *tx_resp, - bool is_agg) -{ - u16 status = le16_to_cpu(tx_resp->status.status); - - info->status.rates[0].count = tx_resp->failure_frame + 1; - if (is_agg) - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= iwl_tx_status_to_mac80211(status); - iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), - info); - if (!iwl_is_tx_success(status)) - iwlagn_count_tx_err_status(priv, status); -} + IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", + ba_resp->txed, ba_resp->txed_2_done); -static void iwl_check_abort_status(struct iwl_priv *priv, - u8 frame_count, u32 status) -{ - if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { - IWL_ERR(priv, "Tx flush command to flush out all frames\n"); - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - queue_work(priv->shrd->workqueue, &priv->tx_flush); + /* Find the first ACKed frame to store the TX status */ + while (sent_bitmap && !(sent_bitmap & 1)) { + agg->start_idx = (agg->start_idx + 1) & 0xff; + sent_bitmap >>= 1; } + + 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 = ba_resp->txed_2_done; + info->status.ampdu_len = ba_resp->txed; + iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); + + return 0; } -void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +/** + * translate ucode response to mac80211 tx status control values + */ +void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_info *info) { - struct iwl_rx_packet *pkt = rxb_addr(rxb); - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int cmd_index = SEQ_TO_INDEX(sequence); - struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - struct ieee80211_hdr *hdr; - u32 status = le16_to_cpu(tx_resp->status.status); - u32 ssn = iwlagn_get_scd_ssn(tx_resp); - int tid; - int sta_id; - int freed; - struct ieee80211_tx_info *info; - unsigned long flags; - struct sk_buff_head skbs; - struct sk_buff *skb; - struct iwl_rxon_context *ctx; - bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); - - tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> - IWLAGN_TX_RES_TID_POS; - sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >> - IWLAGN_TX_RES_RA_POS; - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - - if (is_agg) - iwl_rx_reply_tx_agg(priv, tx_resp); - - if (tx_resp->frame_count == 1) { - __skb_queue_head_init(&skbs); - /*we can free until ssn % q.n_bd not inclusive */ - iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, - ssn, status, &skbs); - freed = 0; - while (!skb_queue_empty(&skbs)) { - skb = __skb_dequeue(&skbs); - hdr = (struct ieee80211_hdr *)skb->data; - - if (!ieee80211_is_data_qos(hdr->frame_control)) - priv->last_seq_ctl = tx_resp->seq_ctl; - - info = IEEE80211_SKB_CB(skb); - ctx = info->driver_data[0]; - kmem_cache_free(priv->tx_cmd_pool, - (info->driver_data[1])); - - memset(&info->status, 0, sizeof(info->status)); - - if (status == TX_STATUS_FAIL_PASSIVE_NO_RX && - iwl_is_associated_ctx(ctx) && ctx->vif && - ctx->vif->type == NL80211_IFTYPE_STATION) { - ctx->last_tx_rejected = true; - iwl_trans_stop_queue(trans(priv), txq_id); - - IWL_DEBUG_TX_REPLY(priv, - "TXQ %d status %s (0x%08x) " - "rate_n_flags 0x%x retries %d\n", - txq_id, - iwl_get_tx_fail_reason(status), - status, - le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); - - IWL_DEBUG_TX_REPLY(priv, - "FrameCnt = %d, idx=%d\n", - tx_resp->frame_count, cmd_index); - } - - /* check if BAR is needed */ - if (is_agg && !iwl_is_tx_success(status)) - info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - iwlagn_set_tx_status(priv, IEEE80211_SKB_CB(skb), - tx_resp, is_agg); - if (!is_agg) - iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); - - ieee80211_tx_status_irqsafe(priv->hw, skb); - - freed++; - } - - WARN_ON(!is_agg && freed != 1); - } + struct ieee80211_tx_rate *r = &info->control.rates[0]; - iwl_check_abort_status(priv, tx_resp->frame_count, status); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + info->antenna_sel_tx = + ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); + if (rate_n_flags & RATE_MCS_HT_MSK) + r->flags |= IEEE80211_TX_RC_MCS; + if (rate_n_flags & RATE_MCS_GF_MSK) + r->flags |= IEEE80211_TX_RC_GREEN_FIELD; + if (rate_n_flags & RATE_MCS_HT40_MSK) + r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (rate_n_flags & RATE_MCS_DUP_MSK) + r->flags |= IEEE80211_TX_RC_DUP_DATA; + if (rate_n_flags & RATE_MCS_SGI_MSK) + r->flags |= IEEE80211_TX_RC_SHORT_GI; + r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); } /** @@ -837,15 +850,12 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; + struct iwl_tx_queue *txq = NULL; struct iwl_ht_agg *agg; - struct sk_buff_head reclaimed_skbs; - struct ieee80211_tx_info *info; - struct ieee80211_hdr *hdr; - struct sk_buff *skb; - unsigned long flags; + int index; int sta_id; int tid; - int freed; + unsigned long flags; /* "flow" corresponds to Tx queue */ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); @@ -854,18 +864,16 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - if (scd_flow >= hw_params(priv).max_txq_num) { + if (scd_flow >= priv->hw_params.max_txq_num) { IWL_ERR(priv, "BUG_ON scd_flow is bigger than number of queues\n"); return; } + txq = &priv->txq[scd_flow]; sta_id = ba_resp->sta_id; tid = ba_resp->tid; - agg = &priv->shrd->tid_data[sta_id][tid].agg; - - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - + agg = &priv->stations[sta_id].tid[tid].agg; if (unlikely(agg->txq_id != scd_flow)) { /* * FIXME: this is a uCode bug which need to be addressed, @@ -876,83 +884,88 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY(priv, "BA scd_flow %d does not match txq_id %d\n", scd_flow, agg->txq_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); return; } - if (unlikely(!agg->wait_for_ba)) { - if (unlikely(ba_resp->bitmap)) - IWL_ERR(priv, "Received BA when not expected\n"); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - return; - } + /* Find index just before block-ack window */ + index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); + + spin_lock_irqsave(&priv->sta_lock, flags); IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " "sta_id = %d\n", agg->wait_for_ba, (u8 *) &ba_resp->sta_addr_lo32, ba_resp->sta_id); - IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, " - "scd_flow = %d, scd_ssn = %d\n", + IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " + "%d, scd_ssn = %d\n", ba_resp->tid, ba_resp->seq_ctl, (unsigned long long)le64_to_cpu(ba_resp->bitmap), ba_resp->scd_flow, ba_resp->scd_ssn); + IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n", + agg->start_idx, + (unsigned long long)agg->bitmap); - /* Mark that the expected block-ack response arrived */ - agg->wait_for_ba = 0; - - /* Sanity check values reported by uCode */ - if (ba_resp->txed_2_done > ba_resp->txed) { - IWL_DEBUG_TX_REPLY(priv, - "bogus sent(%d) and ack(%d) count\n", - ba_resp->txed, ba_resp->txed_2_done); - /* - * set txed_2_done = txed, - * so it won't impact rate scale - */ - ba_resp->txed = ba_resp->txed_2_done; - } - IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", - ba_resp->txed, ba_resp->txed_2_done); - - __skb_queue_head_init(&reclaimed_skbs); + /* Update driver's record of ACK vs. not for each frame in window */ + iwlagn_tx_status_reply_compressed_ba(priv, agg, ba_resp); /* Release all TFDs before the SSN, i.e. all TFDs in front of * block-ack window (we assume that they've been successfully * transmitted ... if not, it's too late anyway). */ - iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn, - 0, &reclaimed_skbs); - freed = 0; - while (!skb_queue_empty(&reclaimed_skbs)) { + if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { + /* calculate mac80211 ampdu sw queue to wake */ + int freed = iwlagn_tx_queue_reclaim(priv, scd_flow, index); + iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - skb = __skb_dequeue(&reclaimed_skbs); - hdr = (struct ieee80211_hdr *)skb->data; + if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && + priv->mac80211_registered && + (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) + iwl_wake_queue(priv, txq); - if (ieee80211_is_data_qos(hdr->frame_control)) - freed++; - else - WARN_ON_ONCE(1); - - if (freed == 0) { - /* this is the first skb we deliver in this batch */ - /* put the rate scaling data there */ - info = IEEE80211_SKB_CB(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 = ba_resp->txed_2_done; - info->status.ampdu_len = ba_resp->txed; - iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, - info); - } + iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); + } + + spin_unlock_irqrestore(&priv->sta_lock, flags); +} - info = IEEE80211_SKB_CB(skb); - kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1])); +#ifdef CONFIG_IWLWIFI_DEBUG +const char *iwl_get_tx_fail_reason(u32 status) +{ +#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x - ieee80211_tx_status_irqsafe(priv->hw, skb); + switch (status & TX_STATUS_MSK) { + case TX_STATUS_SUCCESS: + return "SUCCESS"; + TX_STATUS_POSTPONE(DELAY); + TX_STATUS_POSTPONE(FEW_BYTES); + TX_STATUS_POSTPONE(BT_PRIO); + TX_STATUS_POSTPONE(QUIET_PERIOD); + TX_STATUS_POSTPONE(CALC_TTAK); + TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); + TX_STATUS_FAIL(SHORT_LIMIT); + TX_STATUS_FAIL(LONG_LIMIT); + TX_STATUS_FAIL(FIFO_UNDERRUN); + TX_STATUS_FAIL(DRAIN_FLOW); + TX_STATUS_FAIL(RFKILL_FLUSH); + TX_STATUS_FAIL(LIFE_EXPIRE); + TX_STATUS_FAIL(DEST_PS); + TX_STATUS_FAIL(HOST_ABORTED); + TX_STATUS_FAIL(BT_RETRY); + TX_STATUS_FAIL(STA_INVALID); + TX_STATUS_FAIL(FRAG_DROPPED); + TX_STATUS_FAIL(TID_DISABLE); + TX_STATUS_FAIL(FIFO_FLUSHED); + TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); + TX_STATUS_FAIL(PASSIVE_NO_RX); + TX_STATUS_FAIL(NO_BEACON_ON_RADAR); } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + return "UNKNOWN"; + +#undef TX_STATUS_FAIL +#undef TX_STATUS_POSTPONE } +#endif /* CONFIG_IWLWIFI_DEBUG */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index ddb255a575df..a895a099d086 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -40,7 +40,6 @@ #include "iwl-agn.h" #include "iwl-agn-calib.h" #include "iwl-trans.h" -#include "iwl-fh.h" static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, @@ -85,29 +84,29 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, priv->ucode_write_complete = 0; - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), (iwl_get_dma_hi_addr(phy_addr) << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - iwl_write_direct32(bus(priv), + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | @@ -194,7 +193,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } void iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -292,7 +291,7 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv) /* coexistence is disabled */ memset(&coex_cmd, 0, sizeof(coex_cmd)); } - return iwl_trans_send_cmd_pdu(trans(priv), + return trans_send_cmd_pdu(&priv->trans, COEX_PRIORITY_TABLE_CMD, CMD_SYNC, sizeof(coex_cmd), &coex_cmd); } @@ -325,7 +324,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv) memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, sizeof(iwlagn_bt_prio_tbl)); - if (iwl_trans_send_cmd_pdu(trans(priv), + if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, sizeof(prio_tbl_cmd), &prio_tbl_cmd)) IWL_ERR(priv, "failed to send BT prio tbl command\n"); @@ -338,7 +337,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) env_cmd.action = action; env_cmd.type = type; - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) @@ -351,16 +350,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) { int ret; - if (!priv->tx_cmd_pool) - priv->tx_cmd_pool = - kmem_cache_create("iwlagn_dev_cmd", - sizeof(struct iwl_device_cmd), - sizeof(void *), 0, NULL); - - if (!priv->tx_cmd_pool) - return -ENOMEM; - - iwl_trans_tx_start(trans(priv)); + trans_tx_start(&priv->trans); ret = iwlagn_send_wimax_coex(priv); if (ret) @@ -379,7 +369,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) * 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 iwl_verify_inst_sparse(struct iwl_priv *priv, +static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, struct fw_desc *fw_desc) { __le32 *image = (__le32 *)fw_desc->v_addr; @@ -393,9 +383,9 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, /* 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(bus(priv), HBUS_TARG_MEM_RADDR, + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, i + IWLAGN_RTC_INST_LOWER_BOUND); - val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) return -EIO; } @@ -414,14 +404,14 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); - iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR, + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, IWLAGN_RTC_INST_LOWER_BOUND); for (offs = 0; offs < len && errors < 20; offs += sizeof(u32), image++) { /* read data comes through single port, auto-incr addr */ - val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + val = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { IWL_ERR(priv, "uCode INST section at " "offset 0x%x, is 0x%x, s/b 0x%x\n", @@ -437,7 +427,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, */ static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) { - if (!iwl_verify_inst_sparse(priv, &img->code)) { + if (!iwlcore_verify_inst_sparse(priv, &img->code)) { IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n"); return 0; } @@ -488,7 +478,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int ret; enum iwlagn_ucode_type old_type; - ret = iwl_trans_start_device(trans(priv)); + ret = trans_start_device(&priv->trans); if (ret) return ret; @@ -505,7 +495,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, return ret; } - iwl_trans_kick_nic(trans(priv)); + trans_kick_nic(&priv->trans); /* * Some things may run in the background now, but we @@ -555,7 +545,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) struct iwl_notification_wait calib_wait; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* No init ucode required? Curious, but maybe ok */ if (!priv->ucode_init.code.len) @@ -590,6 +580,6 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) iwlagn_remove_notification(priv, &calib_wait); out: /* Whatever happened, stop the device */ - iwl_trans_stop_device(trans(priv)); + trans_stop_device(&priv->trans); return ret; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c index 8113fbe770a3..33894dde1ae3 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -51,7 +51,6 @@ #include "iwl-sta.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" -#include "iwl-shared.h" #include "iwl-bus.h" #include "iwl-trans.h" @@ -80,6 +79,9 @@ MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); +static int iwlagn_ant_coupling; +static bool iwlagn_bt_ch_announce = 1; + void iwl_update_chain_flags(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; @@ -135,7 +137,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) * beacon contents. */ - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); @@ -180,7 +182,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) rate = info->control.rates[0].idx; priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, - hw_params(priv).valid_tx_ant); + priv->hw_params.valid_tx_ant); rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); /* In mac80211, rates for 5 GHz start at 0 */ @@ -200,7 +202,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) cmd.data[1] = priv->beacon_skb->data; cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } static void iwl_bg_beacon_update(struct work_struct *work) @@ -209,7 +211,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) container_of(work, struct iwl_priv, beacon_update); struct sk_buff *beacon; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "updating beacon w/o beacon context!\n"); goto out; @@ -239,7 +241,7 @@ static void iwl_bg_beacon_update(struct work_struct *work) iwlagn_send_beacon_cmd(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_bt_runtime_config(struct work_struct *work) @@ -247,11 +249,11 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, bt_runtime_config); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; iwlagn_send_advance_bt_config(priv); } @@ -262,13 +264,13 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) container_of(work, struct iwl_priv, bt_full_concurrency); struct iwl_rxon_context *ctx; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) goto out; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) goto out; IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", @@ -286,7 +288,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) iwlagn_send_advance_bt_config(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /** @@ -303,11 +305,11 @@ static void iwl_bg_statistics_periodic(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; iwl_send_statistics_request(priv, CMD_ASYNC, false); @@ -329,14 +331,14 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags); - if (iwl_grab_nic_access(bus(priv))) { - spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (iwl_grab_nic_access(priv)) { + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); return; } /* Set starting address; reads will auto-increment */ - iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); + iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); rmb(); /* @@ -344,20 +346,20 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); if (mode == 0) { trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev); } else { - data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); + data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); trace_iwlwifi_dev_ucode_cont_event(priv, time, data, ev); } } /* Allow device to power down */ - iwl_release_nic_access(bus(priv)); - spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } static void iwl_continuous_event_trace(struct iwl_priv *priv) @@ -370,12 +372,10 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) base = priv->device_pointers.error_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - capacity = iwl_read_targ_mem(bus(priv), base); - num_wraps = iwl_read_targ_mem(bus(priv), - base + (2 * sizeof(u32))); - mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32))); - next_entry = iwl_read_targ_mem(bus(priv), - base + (3 * sizeof(u32))); + capacity = iwl_read_targ_mem(priv, base); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); } else return; @@ -426,7 +426,7 @@ static void iwl_bg_ucode_trace(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (priv->event_log.ucode_trace) { @@ -442,11 +442,11 @@ static void iwl_bg_tx_flush(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, tx_flush); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; /* do nothing if rf-kill is on */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return; IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); @@ -475,15 +475,14 @@ static void iwl_bg_tx_flush(struct work_struct *work) static ssize_t show_debug_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_shared *shrd = dev_get_drvdata(d); - return sprintf(buf, "0x%08X\n", iwl_get_debug_level(shrd)); + 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_shared *shrd = dev_get_drvdata(d); - struct iwl_priv *priv = shrd->priv; + struct iwl_priv *priv = dev_get_drvdata(d); unsigned long val; int ret; @@ -491,9 +490,9 @@ static ssize_t store_debug_level(struct device *d, if (ret) IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); else { - shrd->dbg_level_dev = val; + priv->debug_level = val; if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(shrd->priv, + IWL_ERR(priv, "Not enough memory to generate traffic log\n"); } return strnlen(buf, count); @@ -509,10 +508,9 @@ static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl_shared *shrd = dev_get_drvdata(d); - struct iwl_priv *priv = shrd->priv; + struct iwl_priv *priv = dev_get_drvdata(d); - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "%d\n", priv->temperature); @@ -525,7 +523,7 @@ static ssize_t show_tx_power(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return sprintf(buf, "off\n"); else return sprintf(buf, "%d\n", priv->tx_power_user_lmt); @@ -617,6 +615,24 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) { + static const u8 iwlagn_bss_ac_to_fifo[] = { + IWL_TX_FIFO_VO, + IWL_TX_FIFO_VI, + IWL_TX_FIFO_BE, + IWL_TX_FIFO_BK, + }; + static const u8 iwlagn_bss_ac_to_queue[] = { + 0, 1, 2, 3, + }; + static const u8 iwlagn_pan_ac_to_fifo[] = { + IWL_TX_FIFO_VO_IPAN, + IWL_TX_FIFO_VI_IPAN, + IWL_TX_FIFO_BE_IPAN, + IWL_TX_FIFO_BK_IPAN, + }; + static const u8 iwlagn_pan_ac_to_queue[] = { + 7, 6, 5, 4, + }; int i; /* @@ -638,6 +654,8 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; + priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo; + priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue; priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = BIT(NL80211_IFTYPE_ADHOC); priv->contexts[IWL_RXON_CTX_BSS].interface_modes = @@ -657,6 +675,9 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; + priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo; + priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue; + priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; priv->contexts[IWL_RXON_CTX_PAN].interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); @@ -797,6 +818,8 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, return 0; } +static int iwlagn_wanted_ucode_alternative = 1; + static int iwlagn_load_firmware(struct iwl_priv *priv, const struct firmware *ucode_raw, struct iwlagn_firmware_pieces *pieces, @@ -806,8 +829,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, struct iwl_ucode_tlv *tlv; size_t len = ucode_raw->size; const u8 *data; - int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative; - int tmp; + int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; u64 alternatives; u32 tlv_len; enum iwl_ucode_tlv_type tlv_type; @@ -1128,25 +1150,25 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) pieces.init_data_size); /* Verify that uCode images will fit in card's SRAM */ - if (pieces.inst_size > hw_params(priv).max_inst_size) { + if (pieces.inst_size > priv->hw_params.max_inst_size) { IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", pieces.inst_size); goto try_again; } - if (pieces.data_size > hw_params(priv).max_data_size) { + if (pieces.data_size > priv->hw_params.max_data_size) { IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", pieces.data_size); goto try_again; } - if (pieces.init_size > hw_params(priv).max_inst_size) { + if (pieces.init_size > priv->hw_params.max_inst_size) { IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", pieces.init_size); goto try_again; } - if (pieces.init_data_size > hw_params(priv).max_data_size) { + if (pieces.init_data_size > priv->hw_params.max_data_size) { IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", pieces.init_data_size); goto try_again; @@ -1223,10 +1245,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; - priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; } else { priv->sta_key_max_num = STA_KEY_MAX_NUM; - priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; } /* @@ -1287,6 +1309,364 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) release_firmware(ucode_raw); } +static const char * const desc_lookup_text[] = { + "OK", + "FAIL", + "BAD_PARAM", + "BAD_CHECKSUM", + "NMI_INTERRUPT_WDG", + "SYSASSERT", + "FATAL_ERROR", + "BAD_COMMAND", + "HW_ERROR_TUNE_LOCK", + "HW_ERROR_TEMPERATURE", + "ILLEGAL_CHAN_FREQ", + "VCC_NOT_STABLE", + "FH_ERROR", + "NMI_INTERRUPT_HOST", + "NMI_INTERRUPT_ACTION_PT", + "NMI_INTERRUPT_UNKNOWN", + "UCODE_VERSION_MISMATCH", + "HW_ERROR_ABS_LOCK", + "HW_ERROR_CAL_LOCK_FAIL", + "NMI_INTERRUPT_INST_ACTION_PT", + "NMI_INTERRUPT_DATA_ACTION_PT", + "NMI_TRM_HW_ER", + "NMI_INTERRUPT_TRM", + "NMI_INTERRUPT_BREAK_POINT", + "DEBUG_0", + "DEBUG_1", + "DEBUG_2", + "DEBUG_3", +}; + +static struct { char *name; u8 num; } advanced_lookup[] = { + { "NMI_INTERRUPT_WDG", 0x34 }, + { "SYSASSERT", 0x35 }, + { "UCODE_VERSION_MISMATCH", 0x37 }, + { "BAD_COMMAND", 0x38 }, + { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, + { "FATAL_ERROR", 0x3D }, + { "NMI_TRM_HW_ERR", 0x46 }, + { "NMI_INTERRUPT_TRM", 0x4C }, + { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, + { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, + { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, + { "NMI_INTERRUPT_HOST", 0x66 }, + { "NMI_INTERRUPT_ACTION_PT", 0x7C }, + { "NMI_INTERRUPT_UNKNOWN", 0x84 }, + { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, + { "ADVANCED_SYSASSERT", 0 }, +}; + +static const char *desc_lookup(u32 num) +{ + int i; + int max = ARRAY_SIZE(desc_lookup_text); + + if (num < max) + return desc_lookup_text[num]; + + max = ARRAY_SIZE(advanced_lookup) - 1; + for (i = 0; i < max; i++) { + if (advanced_lookup[i].num == num) + break; + } + return advanced_lookup[i].name; +} + +#define ERROR_START_OFFSET (1 * sizeof(u32)) +#define ERROR_ELEM_SIZE (7 * sizeof(u32)) + +void iwl_dump_nic_error_log(struct iwl_priv *priv) +{ + u32 base; + struct iwl_error_event_table table; + + base = priv->device_pointers.error_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + if (!base) + base = priv->init_errlog_ptr; + } else { + if (!base) + base = priv->inst_errlog_ptr; + } + + if (!iwlagn_hw_valid_rtc_data_addr(base)) { + IWL_ERR(priv, + "Not valid error log pointer 0x%08X for %s uCode\n", + base, + (priv->ucode_type == IWL_UCODE_INIT) + ? "Init" : "RT"); + return; + } + + iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); + + if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { + IWL_ERR(priv, "Start IWL Error Log Dump:\n"); + IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", + priv->status, table.valid); + } + + priv->isr_stats.err_code = table.error_id; + + trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, + table.data1, table.data2, table.line, + table.blink1, table.blink2, table.ilink1, + table.ilink2, table.bcon_time, table.gp1, + table.gp2, table.gp3, table.ucode_ver, + table.hw_ver, table.brd_ver); + IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, + desc_lookup(table.error_id)); + IWL_ERR(priv, "0x%08X | uPc\n", table.pc); + IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1); + IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2); + IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1); + IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2); + IWL_ERR(priv, "0x%08X | data1\n", table.data1); + IWL_ERR(priv, "0x%08X | data2\n", table.data2); + IWL_ERR(priv, "0x%08X | line\n", table.line); + IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time); + IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low); + IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi); + IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1); + IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2); + IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3); + IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver); + IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver); + IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver); + IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd); +} + +#define EVENT_START_OFFSET (4 * sizeof(u32)) + +/** + * iwl_print_event_log - Dump error event log to syslog + * + */ +static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, + u32 num_events, u32 mode, + int pos, char **buf, size_t bufsz) +{ + u32 i; + u32 base; /* SRAM byte address of event log header */ + u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ + u32 ptr; /* SRAM byte address of log data */ + u32 ev, time, data; /* event log data */ + unsigned long reg_flags; + + if (num_events == 0) + return pos; + + base = priv->device_pointers.log_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + if (!base) + base = priv->init_evtlog_ptr; + } else { + if (!base) + base = priv->inst_evtlog_ptr; + } + + if (mode == 0) + event_size = 2 * sizeof(u32); + else + event_size = 3 * sizeof(u32); + + ptr = base + EVENT_START_OFFSET + (start_idx * event_size); + + /* Make sure device is powered up for SRAM reads */ + spin_lock_irqsave(&priv->reg_lock, reg_flags); + iwl_grab_nic_access(priv); + + /* Set starting address; reads will auto-increment */ + iwl_write32(priv, HBUS_TARG_MEM_RADDR, ptr); + rmb(); + + /* "time" is actually "data" for mode 0 (no timestamp). + * place event id # at far right for easier visual parsing. */ + for (i = 0; i < num_events; i++) { + ev = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + time = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + if (mode == 0) { + /* data, ev */ + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "EVT_LOG:0x%08x:%04u\n", + time, ev); + } else { + trace_iwlwifi_dev_ucode_event(priv, 0, + time, ev); + IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", + time, ev); + } + } else { + data = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); + } else { + IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); + trace_iwlwifi_dev_ucode_event(priv, time, + data, ev); + } + } + } + + /* Allow device to power down */ + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return pos; +} + +/** + * iwl_print_last_event_logs - Dump the newest # of event log to syslog + */ +static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, + u32 num_wraps, u32 next_entry, + u32 size, u32 mode, + int pos, char **buf, size_t bufsz) +{ + /* + * display the newest DEFAULT_LOG_ENTRIES entries + * i.e the entries just before the next ont that uCode would fill. + */ + if (num_wraps) { + if (next_entry < size) { + pos = iwl_print_event_log(priv, + capacity - (size - next_entry), + size - next_entry, mode, + pos, buf, bufsz); + pos = iwl_print_event_log(priv, 0, + next_entry, mode, + pos, buf, bufsz); + } else + pos = iwl_print_event_log(priv, next_entry - size, + size, mode, pos, buf, bufsz); + } else { + if (next_entry < size) { + pos = iwl_print_event_log(priv, 0, next_entry, + mode, pos, buf, bufsz); + } else { + pos = iwl_print_event_log(priv, next_entry - size, + size, mode, pos, buf, bufsz); + } + } + return pos; +} + +#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) + +int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, + char **buf, bool display) +{ + u32 base; /* SRAM byte address of event log header */ + u32 capacity; /* event log capacity in # entries */ + u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ + 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; + + base = priv->device_pointers.log_event_table; + if (priv->ucode_type == IWL_UCODE_INIT) { + logsize = priv->init_evtlog_size; + if (!base) + base = priv->init_evtlog_ptr; + } else { + logsize = priv->inst_evtlog_size; + if (!base) + base = priv->inst_evtlog_ptr; + } + + if (!iwlagn_hw_valid_rtc_data_addr(base)) { + IWL_ERR(priv, + "Invalid event log pointer 0x%08X for %s uCode\n", + base, + (priv->ucode_type == IWL_UCODE_INIT) + ? "Init" : "RT"); + return -EINVAL; + } + + /* event log header */ + capacity = iwl_read_targ_mem(priv, base); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); + + if (capacity > logsize) { + IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", + capacity, logsize); + capacity = logsize; + } + + if (next_entry > logsize) { + IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", + next_entry, logsize); + next_entry = logsize; + } + + size = num_wraps ? capacity : next_entry; + + /* bail out if nothing in log */ + if (size == 0) { + IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); + return pos; + } + + /* enable/disable bt channel inhibition */ + priv->bt_ch_announce = iwlagn_bt_ch_announce; + +#ifdef CONFIG_IWLWIFI_DEBUG + if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) + size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) + ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; +#else + size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) + ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; +#endif + IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", + size); + +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + if (full_log) + bufsz = capacity * 48; + else + bufsz = size * 48; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + } + if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { + /* + * if uCode has wrapped back to top of log, + * start at the oldest entry, + * i.e the next one that uCode would fill. + */ + if (num_wraps) + pos = iwl_print_event_log(priv, next_entry, + capacity - next_entry, mode, + pos, buf, bufsz); + /* (then/else) start at top of log */ + pos = iwl_print_event_log(priv, 0, + next_entry, mode, pos, buf, bufsz); + } else + pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); +#else + pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); +#endif + return pos; +} + static void iwl_rf_kill_ct_config(struct iwl_priv *priv) { struct iwl_ct_kill_config cmd; @@ -1294,43 +1674,44 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) unsigned long flags; int ret = 0; - spin_lock_irqsave(&priv->shrd->lock, flags); - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + spin_lock_irqsave(&priv->lock, flags); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); priv->thermal_throttle.ct_kill_toggle = false; if (priv->cfg->base_params->support_ct_kill_exit) { adv_cmd.critical_temperature_enter = - cpu_to_le32(hw_params(priv).ct_kill_threshold); + cpu_to_le32(priv->hw_params.ct_kill_threshold); adv_cmd.critical_temperature_exit = - cpu_to_le32(hw_params(priv).ct_kill_exit_threshold); + cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(adv_cmd), &adv_cmd); if (ret) IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); else IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, critical temperature enter is %d," - "exit is %d\n", - hw_params(priv).ct_kill_threshold, - hw_params(priv).ct_kill_exit_threshold); + "succeeded, " + "critical temperature enter is %d," + "exit is %d\n", + priv->hw_params.ct_kill_threshold, + priv->hw_params.ct_kill_exit_threshold); } else { cmd.critical_temperature_R = - cpu_to_le32(hw_params(priv).ct_kill_threshold); + cpu_to_le32(priv->hw_params.ct_kill_threshold); - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_CT_KILL_CONFIG_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); else IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, " - "critical temperature is %d\n", - hw_params(priv).ct_kill_threshold); + "succeeded, " + "critical temperature is %d\n", + priv->hw_params.ct_kill_threshold); } } @@ -1347,7 +1728,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } @@ -1359,7 +1740,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) if (IWL_UCODE_API(priv->ucode_ver) > 1) { IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); - return iwl_trans_send_cmd_pdu(trans(priv), + return trans_send_cmd_pdu(&priv->trans, TX_ANT_CONFIGURATION_CMD, CMD_SYNC, sizeof(struct iwl_tx_ant_config_cmd), @@ -1381,17 +1762,17 @@ int iwl_alive_start(struct iwl_priv *priv) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; /*TODO: this should go to the transport layer */ - iwl_reset_ict(trans(priv)); + iwl_reset_ict(priv); IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); /* After the ALIVE response, we can send host commands to the uCode */ - set_bit(STATUS_ALIVE, &priv->shrd->status); + set_bit(STATUS_ALIVE, &priv->status); /* Enable watchdog to monitor the driver tx queues */ iwl_setup_watchdog(priv); - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) return -ERFKILL; /* download priority table before any calibration request */ @@ -1428,9 +1809,8 @@ int iwl_alive_start(struct iwl_priv *priv) iwl_send_bt_config(priv); } - if (hw_params(priv).calib_rt_cfg) - iwlagn_send_calib_cfg_rt(priv, - hw_params(priv).calib_rt_cfg); + if (priv->hw_params.calib_rt_cfg) + iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); ieee80211_wake_queues(priv->hw); @@ -1439,7 +1819,7 @@ int iwl_alive_start(struct iwl_priv *priv) /* Configure Tx antenna selection based on H/W config */ iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant); - if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) { + if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { struct iwl_rxon_cmd *active_rxon = (struct iwl_rxon_cmd *)&ctx->active; /* apply any changes in staging */ @@ -1454,12 +1834,12 @@ int iwl_alive_start(struct iwl_priv *priv) iwlagn_set_rxon_chain(priv, ctx); } - if (!priv->shrd->wowlan) { + if (!priv->wowlan) { /* WoWLAN ucode will not reply in the same way, skip it */ iwl_reset_run_time_calib(priv); } - set_bit(STATUS_READY, &priv->shrd->status); + set_bit(STATUS_READY, &priv->status); /* Configure the adapter for unassociated operation */ ret = iwlagn_commit_rxon(priv, ctx); @@ -1491,8 +1871,7 @@ static void __iwl_down(struct iwl_priv *priv) */ ieee80211_remain_on_channel_expired(priv->hw); - exit_pending = - test_and_set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set * to prevent rearm timer */ @@ -1517,23 +1896,22 @@ static void __iwl_down(struct iwl_priv *priv) /* Wipe out the EXIT_PENDING status bit if we are not actually * exiting the module */ if (!exit_pending) - clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + clear_bit(STATUS_EXIT_PENDING, &priv->status); - if (priv->shrd->mac80211_registered) + if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); /* Clear out all status bits but a few that are stable across reset */ - priv->shrd->status &= - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) << + priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) << + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << STATUS_GEO_CONFIGURED | - test_bit(STATUS_FW_ERROR, &priv->shrd->status) << + test_bit(STATUS_FW_ERROR, &priv->status) << STATUS_FW_ERROR | - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) << + test_bit(STATUS_EXIT_PENDING, &priv->status) << STATUS_EXIT_PENDING; - iwl_trans_stop_device(trans(priv)); + trans_stop_device(&priv->trans); dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; @@ -1541,9 +1919,9 @@ static void __iwl_down(struct iwl_priv *priv) static void iwl_down(struct iwl_priv *priv) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); __iwl_down(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); } @@ -1555,9 +1933,9 @@ static int __iwl_up(struct iwl_priv *priv) struct iwl_rxon_context *ctx; int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); return -EIO; } @@ -1590,9 +1968,9 @@ static int __iwl_up(struct iwl_priv *priv) return 0; error: - set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + set_bit(STATUS_EXIT_PENDING, &priv->status); __iwl_down(priv); - clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + clear_bit(STATUS_EXIT_PENDING, &priv->status); IWL_ERR(priv, "Unable to initialize device.\n"); return ret; @@ -1610,11 +1988,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, run_time_calib_work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || - test_bit(STATUS_SCANNING, &priv->shrd->status)) { - mutex_unlock(&priv->shrd->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + test_bit(STATUS_SCANNING, &priv->status)) { + mutex_unlock(&priv->mutex); return; } @@ -1623,7 +2001,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) iwl_sensitivity_calibration(priv); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwlagn_prepare_restart(struct iwl_priv *priv) @@ -1635,7 +2013,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv) u8 bt_status; bool bt_is_sco; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); for_each_context(priv, ctx) ctx->vif = NULL; @@ -1669,13 +2047,13 @@ static void iwl_bg_restart(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) { - mutex_lock(&priv->shrd->mutex); + if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { + mutex_lock(&priv->mutex); iwlagn_prepare_restart(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); iwl_cancel_deferred_work(priv); ieee80211_restart_hw(priv->hw); } else { @@ -1863,7 +2241,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); return ret; } - priv->shrd->mac80211_registered = 1; + priv->mac80211_registered = 1; return 0; } @@ -1877,16 +2255,16 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) IWL_DEBUG_MAC80211(priv, "enter\n"); /* we should be verifying the device is ready to be opened */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ret = __iwl_up(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); if (ret) return ret; IWL_DEBUG_INFO(priv, "Start UP work done.\n"); /* Now we should be done, and the READY bit should be set. */ - if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status))) + if (WARN_ON(!test_bit(STATUS_READY, &priv->status))) ret = -EIO; iwlagn_led_enable(priv); @@ -1909,11 +2287,11 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw) iwl_down(priv); - flush_workqueue(priv->shrd->workqueue); + flush_workqueue(priv->workqueue); /* User space software may expect getting rfkill changes * even if interface is down */ - iwl_write32(bus(priv), CSR_INT, 0xFFFFFFFF); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); iwl_enable_rfkill_int(priv); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -1957,7 +2335,7 @@ static int iwlagn_send_patterns(struct iwl_priv *priv, } cmd.data[0] = pattern_cmd; - err = iwl_trans_send_cmd(trans(priv), &cmd); + err = trans_send_cmd(&priv->trans, &cmd); kfree(pattern_cmd); return err; } @@ -1972,7 +2350,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, if (iwlagn_mod_params.sw_crypto) return; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) goto out; @@ -1983,7 +2361,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, priv->have_rekey_data = true; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } struct wowlan_key_data { @@ -2021,7 +2399,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, u16 p1k[IWLAGN_P1K_SIZE]; int ret, i; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) && @@ -2126,7 +2504,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static int iwlagn_mac_suspend(struct ieee80211_hw *hw, @@ -2151,7 +2529,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, if (WARN_ON(!wowlan)) return -EINVAL; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* Don't attempt WoWLAN when not associated, tear down instead. */ if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || @@ -2180,7 +2558,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, * since the uCode will add 0x10 before using the value. */ for (i = 0; i < 8; i++) { - seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number; + seq = priv->stations[IWL_AP_ID].tid[i].seq_number; seq -= 0x10; wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq); } @@ -2212,9 +2590,9 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, memcpy(&rxon, &ctx->active, sizeof(rxon)); - iwl_trans_stop_device(trans(priv)); + trans_stop_device(&priv->trans); - priv->shrd->wowlan = true; + priv->wowlan = true; ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_wowlan, IWL_UCODE_WOWLAN); @@ -2245,11 +2623,11 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, * constraints. Since we're in the suspend path * that isn't really a problem though. */ - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); ieee80211_iter_keys(priv->hw, ctx->vif, iwlagn_wowlan_program_keys, &key_data); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (key_data.error) { ret = -EIO; goto error; @@ -2264,13 +2642,13 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, .len[0] = sizeof(*key_data.rsc_tsc), }; - ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd); + ret = trans_send_cmd(&priv->trans, &rsc_tsc_cmd); if (ret) goto error; } if (key_data.use_tkip) { - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_TKIP_PARAMS, CMD_SYNC, sizeof(tkip_cmd), &tkip_cmd); @@ -2286,7 +2664,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); kek_kck_cmd.replay_ctr = priv->replay_ctr; - ret = iwl_trans_send_cmd_pdu(trans(priv), + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_KEK_KCK_MATERIAL, CMD_SYNC, sizeof(kek_kck_cmd), &kek_kck_cmd); @@ -2295,7 +2673,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, } } - ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER, + ret = trans_send_cmd_pdu(&priv->trans, REPLY_WOWLAN_WAKEUP_FILTER, CMD_SYNC, sizeof(wakeup_filter_cmd), &wakeup_filter_cmd); if (ret) @@ -2308,17 +2686,17 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, device_set_wakeup_enable(priv->bus->dev, true); /* Now let the ucode operate on its own */ - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); goto out; error: - priv->shrd->wowlan = false; + priv->wowlan = false; iwlagn_prepare_restart(priv); ieee80211_restart_hw(priv->hw); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); kfree(key_data.rsc_tsc); return ret; } @@ -2332,21 +2710,21 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) u32 base, status = 0xffffffff; int ret = -EIO; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); base = priv->device_pointers.error_event_table; if (iwlagn_hw_valid_rtc_data_addr(base)) { - spin_lock_irqsave(&bus(priv)->reg_lock, flags); - ret = iwl_grab_nic_access_silent(bus(priv)); + spin_lock_irqsave(&priv->reg_lock, flags); + ret = iwl_grab_nic_access_silent(priv); if (ret == 0) { - iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, base); - status = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - iwl_release_nic_access(bus(priv)); + iwl_write32(priv, HBUS_TARG_MEM_RADDR, base); + status = iwl_read32(priv, HBUS_TARG_MEM_RDAT); + iwl_release_nic_access(priv); } - spin_unlock_irqrestore(&bus(priv)->reg_lock, flags); + spin_unlock_irqrestore(&priv->reg_lock, flags); #ifdef CONFIG_IWLWIFI_DEBUGFS if (ret == 0) { @@ -2357,7 +2735,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) if (priv->wowlan_sram) _iwl_read_targ_mem_words( - bus(priv), 0x800000, priv->wowlan_sram, + priv, 0x800000, priv->wowlan_sram, priv->ucode_wowlan.data.len / 4); } #endif @@ -2366,7 +2744,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; - priv->shrd->wowlan = false; + priv->wowlan = false; device_set_wakeup_enable(priv->bus->dev, false); @@ -2376,7 +2754,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) iwl_connection_init_rx_config(priv, ctx); iwlagn_set_rxon_chain(priv, ctx); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); ieee80211_resume_disconnect(vif); @@ -2445,7 +2823,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET) return 0; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT); @@ -2496,7 +2874,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = -EINVAL; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return ret; @@ -2511,7 +2889,6 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; int ret = -EINVAL; struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; - struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", sta->addr, tid); @@ -2519,7 +2896,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)) return -EACCES; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (action) { case IEEE80211_AMPDU_RX_START: @@ -2529,7 +2906,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT(priv, "stop Rx\n"); ret = iwl_sta_rx_agg_stop(priv, sta, tid); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) ret = 0; break; case IEEE80211_AMPDU_TX_START: @@ -2549,7 +2926,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", priv->agg_tids_count); } - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) ret = 0; if (priv->cfg->ht_params && priv->cfg->ht_params->use_rts_for_aggregation) { @@ -2565,8 +2942,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_OPERATIONAL: buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); - iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, iwl_sta_id(sta), - tid, buf_size); + trans_txq_agg_setup(&priv->trans, iwl_sta_id(sta), tid, + buf_size); /* * If the limit is 0, then it wasn't initialised yet, @@ -2610,7 +2987,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, ret = 0; break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -2628,7 +3005,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", sta->addr); sta_priv->common.sta_id = IWL_INVALID_STATION; @@ -2643,7 +3020,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_ERR(priv, "Unable to add station %pM (%d)\n", sta->addr, ret); /* Should we return success if return code is EEXIST ? */ - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -2653,7 +3030,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl_rs_rate_init(priv, sta, sta_id); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return 0; } @@ -2679,14 +3056,14 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) goto out; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || - test_bit(STATUS_SCANNING, &priv->shrd->status) || - test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + test_bit(STATUS_SCANNING, &priv->status) || + test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) goto out; if (!iwl_is_associated_ctx(ctx)) @@ -2705,7 +3082,7 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, goto out; } - spin_lock_irq(&priv->shrd->lock); + spin_lock_irq(&priv->lock); priv->current_ht_config.smps = conf->smps_mode; @@ -2735,23 +3112,23 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, iwl_set_rxon_ht(priv, ht_conf); iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif); - spin_unlock_irq(&priv->shrd->lock); + spin_unlock_irq(&priv->lock); iwl_set_rate(priv); /* * at this point, staging_rxon has the * configuration for channel switch */ - set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); + set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); priv->switch_channel = cpu_to_le16(ch); if (priv->cfg->lib->set_channel_switch(priv, ch_switch)) { - clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status); + clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); priv->switch_channel = 0; ieee80211_chswitch_done(ctx->vif, false); } out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -2781,7 +3158,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, #undef CHK - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); for_each_context(priv, ctx) { ctx->staging.filter_flags &= ~filter_nand; @@ -2793,7 +3170,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw, */ } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); /* * Receiving all multicast frames is always enabled by the @@ -2809,14 +3186,14 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "enter\n"); - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n"); goto done; } - if (iwl_is_rfkill(priv->shrd)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n"); goto done; } @@ -2833,9 +3210,9 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) } } IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); - iwl_trans_wait_tx_queue_empty(trans(priv)); + iwlagn_wait_tx_queue_empty(priv); done: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); } @@ -2843,7 +3220,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv) { struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (!priv->hw_roc_setup) return; @@ -2866,9 +3243,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, hw_roc_disable_work.work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwlagn_disable_roc(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, @@ -2886,7 +3263,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) return -EOPNOTSUPP; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); /* * TODO: Remove this hack! Firmware needs to be updated @@ -2897,7 +3274,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80) duration = 80; - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { err = -EBUSY; goto out; } @@ -2936,7 +3313,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, iwlagn_disable_roc(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return err; } @@ -2948,80 +3325,14 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) return -EOPNOTSUPP; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); iwlagn_disable_roc(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return 0; } -static int iwl_mac_tx_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - const u8 *bssid, enum ieee80211_tx_sync_type type) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - struct iwl_rxon_context *ctx = vif_priv->ctx; - int ret; - u8 sta_id; - - mutex_lock(&priv->shrd->mutex); - - if (iwl_is_associated_ctx(ctx)) { - ret = 0; - goto out; - } - - if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { - ret = -EBUSY; - goto out; - } - - ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id); - if (ret) - goto out; - - if (WARN_ON(sta_id != ctx->ap_sta_id)) { - ret = -EIO; - goto out_remove_sta; - } - - memcpy(ctx->bssid, bssid, ETH_ALEN); - ctx->preauth_bssid = true; - - ret = iwlagn_commit_rxon(priv, ctx); - - if (ret == 0) - goto out; - - out_remove_sta: - iwl_remove_station(priv, sta_id, bssid); - out: - mutex_unlock(&priv->shrd->mutex); - return ret; -} - -static void iwl_mac_finish_tx_sync(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *bssid, - enum ieee80211_tx_sync_type type) -{ - struct iwl_priv *priv = hw->priv; - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - struct iwl_rxon_context *ctx = vif_priv->ctx; - - mutex_lock(&priv->shrd->mutex); - - if (iwl_is_associated_ctx(ctx)) - goto out; - - iwl_remove_station(priv, ctx->ap_sta_id, bssid); - ctx->preauth_bssid = false; - /* no need to commit */ - out: - mutex_unlock(&priv->shrd->mutex); -} - /***************************************************************************** * * driver setup and teardown @@ -3030,7 +3341,7 @@ static void iwl_mac_finish_tx_sync(struct ieee80211_hw *hw, static void iwl_setup_deferred_work(struct iwl_priv *priv) { - priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME); + priv->workqueue = create_singlethread_workqueue(DRV_NAME); init_waitqueue_head(&priv->wait_command_queue); @@ -3104,9 +3415,10 @@ static int iwl_init_drv(struct iwl_priv *priv) { int ret; - spin_lock_init(&priv->shrd->sta_lock); + spin_lock_init(&priv->sta_lock); + spin_lock_init(&priv->hcmd_lock); - mutex_init(&priv->shrd->mutex); + mutex_init(&priv->mutex); priv->ieee_channels = NULL; priv->ieee_rates = NULL; @@ -3147,7 +3459,7 @@ static int iwl_init_drv(struct iwl_priv *priv) goto err; } - ret = iwl_init_geos(priv); + ret = iwlcore_init_geos(priv); if (ret) { IWL_ERR(priv, "initializing geos failed: %d\n", ret); goto err_free_channel_map; @@ -3165,10 +3477,8 @@ static int iwl_init_drv(struct iwl_priv *priv) static void iwl_uninit_drv(struct iwl_priv *priv) { iwl_calib_free_results(priv); - iwl_free_geos(priv); + iwlcore_free_geos(priv); iwl_free_channel_map(priv); - if (priv->tx_cmd_pool) - kmem_cache_destroy(priv->tx_cmd_pool); kfree(priv->scan_cmd); kfree(priv->beacon_cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -3181,7 +3491,7 @@ static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) { @@ -3196,7 +3506,7 @@ static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, "ignoring RSSI callback\n"); } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } struct ieee80211_ops iwlagn_hw_ops = { @@ -3230,38 +3540,27 @@ struct ieee80211_ops iwlagn_hw_ops = { .rssi_callback = iwl_mac_rssi_callback, CFG80211_TESTMODE_CMD(iwl_testmode_cmd) CFG80211_TESTMODE_DUMP(iwl_testmode_dump) - .tx_sync = iwl_mac_tx_sync, - .finish_tx_sync = iwl_mac_finish_tx_sync, }; static u32 iwl_hw_detect(struct iwl_priv *priv) { - return iwl_read32(bus(priv), CSR_HW_REV); + return iwl_read32(priv, CSR_HW_REV); } -/* Size of one Rx buffer in host DRAM */ -#define IWL_RX_BUF_SIZE_4K (4 * 1024) -#define IWL_RX_BUF_SIZE_8K (8 * 1024) - static int iwl_set_hw_params(struct iwl_priv *priv) { + priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; + priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; if (iwlagn_mod_params.amsdu_size_8K) - hw_params(priv).rx_page_order = - get_order(IWL_RX_BUF_SIZE_8K); + priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); else - hw_params(priv).rx_page_order = - get_order(IWL_RX_BUF_SIZE_4K); + priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); + + priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; if (iwlagn_mod_params.disable_11n) priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE; - hw_params(priv).num_ampdu_queues = - priv->cfg->base_params->num_of_ampdu_queues; - hw_params(priv).shadow_reg_enable = - priv->cfg->base_params->shadow_reg_enable; - hw_params(priv).sku = priv->cfg->sku; - hw_params(priv).wd_timeout = priv->cfg->base_params->wd_timeout; - /* Device-specific setup */ return priv->cfg->lib->set_hw_params(priv); } @@ -3288,8 +3587,7 @@ static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) return hw; } -int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, - struct iwl_cfg *cfg) +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) { int err = 0; struct iwl_priv *priv; @@ -3308,17 +3606,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, priv = hw->priv; priv->bus = bus; - priv->shrd = &priv->_shrd; - priv->shrd->bus = bus; - priv->shrd->priv = priv; - priv->shrd->hw = hw; - bus_set_drv_data(priv->bus, priv->shrd); - - priv->shrd->trans = trans_ops->alloc(priv->shrd); - if (priv->shrd->trans == NULL) { - err = -ENOMEM; - goto out_free_traffic_mem; - } + bus_set_drv_data(priv->bus, priv); /* At this point both hw and priv are allocated. */ @@ -3326,15 +3614,15 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; + priv->inta_mask = CSR_INI_SET_MASK; /* is antenna coupling more than 35dB ? */ priv->bt_ant_couple_ok = - (iwlagn_mod_params.ant_coupling > - IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? - true : false; + (iwlagn_ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? + true : false; /* enable/disable bt channel inhibition */ - priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; + priv->bt_ch_announce = iwlagn_bt_ch_announce; IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n", (priv->bt_ch_announce) ? "On" : "Off"); @@ -3344,15 +3632,15 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ - spin_lock_init(&bus(priv)->reg_lock); - spin_lock_init(&priv->shrd->lock); + spin_lock_init(&priv->reg_lock); + spin_lock_init(&priv->lock); /* * stop and reset the on-board processor just in case it is in a * strange state ... like being left stranded by a primary kernel * and this is now the kdump kernel trying to start up */ - iwl_write32(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /*********************** * 3. Read REV register @@ -3361,11 +3649,11 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, IWL_INFO(priv, "Detected %s, REV=0x%X\n", priv->cfg->name, hw_rev); - err = iwl_trans_request_irq(trans(priv)); + err = iwl_trans_register(&priv->trans, priv); if (err) - goto out_free_trans; + goto out_free_traffic_mem; - if (iwl_trans_prepare_card_hw(trans(priv))) { + if (trans_prepare_card_hw(&priv->trans)) { err = -EIO; IWL_WARN(priv, "Failed, HW not ready\n"); goto out_free_trans; @@ -3433,14 +3721,13 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, iwl_enable_rfkill_int(priv); /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(bus(priv), - CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + clear_bit(STATUS_RF_KILL_HW, &priv->status); else - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); + test_bit(STATUS_RF_KILL_HW, &priv->status)); iwl_power_initialize(priv); iwl_tt_initialize(priv); @@ -3454,13 +3741,13 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, return 0; out_destroy_workqueue: - destroy_workqueue(priv->shrd->workqueue); - priv->shrd->workqueue = NULL; + destroy_workqueue(priv->workqueue); + priv->workqueue = NULL; iwl_uninit_drv(priv); out_free_eeprom: iwl_eeprom_free(priv); out_free_trans: - iwl_trans_free(trans(priv)); + trans_free(&priv->trans); out_free_traffic_mem: iwl_free_traffic_mem(priv); ieee80211_free_hw(priv->hw); @@ -3470,6 +3757,8 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, void __devexit iwl_remove(struct iwl_priv * priv) { + unsigned long flags; + wait_for_completion(&priv->firmware_loading_complete); IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); @@ -3482,36 +3771,48 @@ void __devexit iwl_remove(struct iwl_priv * priv) * to be called and iwl_down since we are removing the device * we need to set STATUS_EXIT_PENDING bit. */ - set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); + set_bit(STATUS_EXIT_PENDING, &priv->status); iwl_testmode_cleanup(priv); iwl_leds_exit(priv); - if (priv->shrd->mac80211_registered) { + if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); - priv->shrd->mac80211_registered = 0; + priv->mac80211_registered = 0; } + /* Reset to low power before unloading driver. */ + iwl_apm_stop(priv); + iwl_tt_exit(priv); - /*This will stop the queues, move the device to low power state */ - iwl_trans_stop_device(trans(priv)); + /* make sure we flush any pending irq or + * tasklet for the driver + */ + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + trans_sync_irq(&priv->trans); iwl_dealloc_ucode(priv); + trans_rx_free(&priv->trans); + trans_tx_free(&priv->trans); + iwl_eeprom_free(priv); /*netif_stop_queue(dev); */ - flush_workqueue(priv->shrd->workqueue); + flush_workqueue(priv->workqueue); /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes - * priv->shrd->workqueue... so we can't take down the workqueue + * priv->workqueue... so we can't take down the workqueue * until now... */ - destroy_workqueue(priv->shrd->workqueue); - priv->shrd->workqueue = NULL; + destroy_workqueue(priv->workqueue); + priv->workqueue = NULL; iwl_free_traffic_mem(priv); - iwl_trans_free(trans(priv)); + trans_free(&priv->trans); bus_set_drv_data(priv->bus, NULL); @@ -3562,8 +3863,7 @@ module_exit(iwl_exit); module_init(iwl_init); #ifdef CONFIG_IWLWIFI_DEBUG -module_param_named(debug, iwlagn_mod_params.debug_level, uint, - S_IRUGO | S_IWUSR); +module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "debug output mask"); #endif @@ -3579,21 +3879,18 @@ MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); -module_param_named(ucode_alternative, - iwlagn_mod_params.wanted_ucode_alternative, - int, S_IRUGO); +module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, + S_IRUGO); MODULE_PARM_DESC(ucode_alternative, "specify ucode alternative to use from ucode file"); -module_param_named(antenna_coupling, iwlagn_mod_params.ant_coupling, - int, S_IRUGO); +module_param_named(antenna_coupling, iwlagn_ant_coupling, int, S_IRUGO); MODULE_PARM_DESC(antenna_coupling, "specify antenna coupling in dB (defualt: 0 dB)"); -module_param_named(bt_ch_inhibition, iwlagn_mod_params.bt_ch_announce, - bool, S_IRUGO); +module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO); MODULE_PARM_DESC(bt_ch_inhibition, - "Enable BT channel inhibition (default: enable)"); + "Disable BT channel inhibition (default: enable)"); module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO); MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); @@ -3639,11 +3936,6 @@ module_param_named(power_level, iwlagn_mod_params.power_level, MODULE_PARM_DESC(power_level, "default power save level (range from 1 - 5, default: 1)"); -module_param_named(auto_agg, iwlagn_mod_params.auto_agg, - bool, S_IRUGO); -MODULE_PARM_DESC(auto_agg, - "enable agg w/o check traffic load (default: enable)"); - /* * For now, keep using power level 1 instead of automatically * adjusting ... diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h index a7b4948e43da..df2960ae92aa 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -65,9 +65,54 @@ #include "iwl-dev.h" +/* configuration for the _agn devices */ +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 iwl6005_2agn_cfg; +extern struct iwl_cfg iwl6005_2abg_cfg; +extern struct iwl_cfg iwl6005_2bg_cfg; +extern struct iwl_cfg iwl1030_bgn_cfg; +extern struct iwl_cfg iwl1030_bg_cfg; +extern struct iwl_cfg iwl6030_2agn_cfg; +extern struct iwl_cfg iwl6030_2abg_cfg; +extern struct iwl_cfg iwl6030_2bgn_cfg; +extern struct iwl_cfg iwl6030_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 iwl6150_bgn_cfg; +extern struct iwl_cfg iwl6150_bg_cfg; +extern struct iwl_cfg iwl1000_bgn_cfg; +extern struct iwl_cfg iwl1000_bg_cfg; +extern struct iwl_cfg iwl100_bgn_cfg; +extern struct iwl_cfg iwl100_bg_cfg; +extern struct iwl_cfg iwl130_bgn_cfg; +extern struct iwl_cfg iwl130_bg_cfg; +extern struct iwl_cfg iwl2000_2bgn_cfg; +extern struct iwl_cfg iwl2000_2bg_cfg; +extern struct iwl_cfg iwl2030_2bgn_cfg; +extern struct iwl_cfg iwl2030_2bg_cfg; +extern struct iwl_cfg iwl6035_2agn_cfg; +extern struct iwl_cfg iwl6035_2abg_cfg; +extern struct iwl_cfg iwl6035_2bg_cfg; +extern struct iwl_cfg iwl105_bg_cfg; +extern struct iwl_cfg iwl105_bgn_cfg; +extern struct iwl_cfg iwl135_bg_cfg; +extern struct iwl_cfg iwl135_bgn_cfg; + +extern struct iwl_mod_params iwlagn_mod_params; + extern struct ieee80211_ops iwlagn_hw_ops; -int iwl_reset_ict(struct iwl_trans *trans); +int iwl_reset_ict(struct iwl_priv *priv); static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) { @@ -77,6 +122,10 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) hdr->data_valid = 1; } +/* tx queue */ +void iwl_free_tfds_in_queue(struct iwl_priv *priv, + int sta_id, int tid, int freed); + /* RXON */ int iwlagn_set_pan_params(struct iwl_priv *priv); int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -98,10 +147,13 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, enum iwlagn_ucode_type ucode_type); /* lib */ +void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status); int iwlagn_hw_valid_rtc_data_addr(u32 addr); int iwlagn_send_tx_power(struct iwl_priv *priv); void iwlagn_temperature(struct iwl_priv *priv); u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); +int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); int iwlagn_send_beacon_cmd(struct iwl_priv *priv); @@ -113,14 +165,21 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); /* tx */ +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int index); +void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); +int iwlagn_txq_check_empty(struct iwl_priv *priv, + int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); static inline u32 iwl_tx_status_to_mac80211(u32 status) { @@ -228,7 +287,7 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) } /* eeprom */ -void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); +void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); /* notification wait support */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-bus.h b/trunk/drivers/net/wireless/iwlwifi/iwl-bus.h index 83aed46673e1..f3ee1c0c004c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -60,22 +60,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ -#ifndef __iwl_bus_h__ -#define __iwl_bus_h__ +#ifndef __iwl_pci_h__ +#define __iwl_pci_h__ -/*This file includes the declaration that are exported from the bus layer */ - -#include -#include - -struct iwl_shared; struct iwl_bus; /** * struct iwl_bus_ops - bus specific operations * @get_pm_support: must returns true if the bus can go to sleep * @apm_config: will be called during the config of the APM configuration - * @set_drv_data: set the shared data pointer to the bus layer + * @set_drv_data: set the drv_data pointer to the bus layer * @get_hw_id: prints the hw_id in the provided buffer * @write8: write a byte to register at offset ofs * @write32: write a dword to register at offset ofs @@ -84,29 +78,20 @@ struct iwl_bus; struct iwl_bus_ops { bool (*get_pm_support)(struct iwl_bus *bus); void (*apm_config)(struct iwl_bus *bus); - void (*set_drv_data)(struct iwl_bus *bus, struct iwl_shared *shrd); + void (*set_drv_data)(struct iwl_bus *bus, void *drv_data); void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); u32 (*read32)(struct iwl_bus *bus, u32 ofs); }; -/** - * struct iwl_bus - bus common data - * @dev - pointer to struct device * that represent the device - * @ops - pointer to iwl_bus_ops - * @shrd - pointer to iwl_shared which holds shared data from the upper layer - * @irq - the irq number for the device - * @reg_lock - protect hw register access - */ struct iwl_bus { /* Common data to all buses */ + void *drv_data; /* driver's context */ struct device *dev; - const struct iwl_bus_ops *ops; - struct iwl_shared *shrd; + struct iwl_bus_ops *ops; unsigned int irq; - spinlock_t reg_lock; /* pointer to bus specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ @@ -123,10 +108,9 @@ static inline void bus_apm_config(struct iwl_bus *bus) bus->ops->apm_config(bus); } -static inline void bus_set_drv_data(struct iwl_bus *bus, - struct iwl_shared *shrd) +static inline void bus_set_drv_data(struct iwl_bus *bus, void *drv_data) { - bus->ops->set_drv_data(bus, shrd); + bus->ops->set_drv_data(bus, drv_data); } static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len) @@ -152,4 +136,4 @@ static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs) int __must_check iwl_pci_register_driver(void); void iwl_pci_unregister_driver(void); -#endif /* __iwl_bus_h__ */ +#endif diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h index cb06196e0e80..0016c61b3000 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -69,9 +69,6 @@ #ifndef __iwl_commands_h__ #define __iwl_commands_h__ -#include -#include - struct iwl_priv; /* uCode version contains 4 values: Major/Minor/API/Serial */ @@ -673,6 +670,7 @@ struct iwl_rxon_assoc_cmd { #define IWL_CONN_MAX_LISTEN_INTERVAL 10 #define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */ +#define IWL39_MAX_UCODE_BEACON_INTERVAL 1 /* 1024 */ /* * REPLY_RXON_TIMING = 0x14 (command, has simple generic response) @@ -808,7 +806,6 @@ struct iwl_qosparam_cmd { #define IWLAGN_STATION_COUNT 16 #define IWL_INVALID_STATION 255 -#define IWL_MAX_TID_COUNT 9 #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) @@ -3912,7 +3909,6 @@ struct iwlagn_wowlan_kek_kck_material_cmd { * Union of all expected notifications/responses: * *****************************************************************************/ -#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ struct iwl_rx_packet { /* diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index 20dd1a5506ed..e269987cd64c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -42,21 +42,22 @@ #include "iwl-sta.h" #include "iwl-agn.h" #include "iwl-helpers.h" -#include "iwl-shared.h" #include "iwl-agn.h" #include "iwl-trans.h" +u32 iwl_debug_level; + const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ -static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, +static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, struct ieee80211_sta_ht_cap *ht_info, enum ieee80211_band band) { u16 max_bit_rate = 0; - u8 rx_chains_num = hw_params(priv).rx_chains_num; - u8 tx_chains_num = hw_params(priv).tx_chains_num; + u8 rx_chains_num = priv->hw_params.rx_chains_num; + u8 tx_chains_num = priv->hw_params.tx_chains_num; ht_info->cap = 0; memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); @@ -68,7 +69,7 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= IEEE80211_HT_CAP_SGI_20; max_bit_rate = MAX_BIT_RATE_20_MHZ; - if (hw_params(priv).ht40_channel & BIT(band)) { + if (priv->hw_params.ht40_channel & BIT(band)) { ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; ht_info->cap |= IEEE80211_HT_CAP_SGI_40; ht_info->mcs.rx_mask[4] = 0x01; @@ -106,9 +107,9 @@ static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, } /** - * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom + * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom */ -int iwl_init_geos(struct iwl_priv *priv) +int iwlcore_init_geos(struct iwl_priv *priv) { struct iwl_channel_info *ch; struct ieee80211_supported_band *sband; @@ -121,7 +122,7 @@ int iwl_init_geos(struct iwl_priv *priv) if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); - set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } @@ -145,7 +146,7 @@ int iwl_init_geos(struct iwl_priv *priv) sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) - iwl_init_ht_hw_capab(priv, &sband->ht_cap, + iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, IEEE80211_BAND_5GHZ); sband = &priv->bands[IEEE80211_BAND_2GHZ]; @@ -155,7 +156,7 @@ int iwl_init_geos(struct iwl_priv *priv) sband->n_bitrates = IWL_RATE_COUNT_LEGACY; if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE) - iwl_init_ht_hw_capab(priv, &sband->ht_cap, + iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, IEEE80211_BAND_2GHZ); priv->ieee_channels = channels; @@ -221,19 +222,19 @@ int iwl_init_geos(struct iwl_priv *priv) priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); - set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } /* - * iwl_free_geos - undo allocations in iwl_init_geos + * iwlcore_free_geos - undo allocations in iwlcore_init_geos */ -void iwl_free_geos(struct iwl_priv *priv) +void iwlcore_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); - clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status); + clear_bit(STATUS_GEO_CONFIGURED, &priv->status); } static bool iwl_is_channel_extension(struct iwl_priv *priv, @@ -325,7 +326,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) conf = ieee80211_get_hw_conf(priv->hw); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); @@ -359,7 +360,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) beacon_int = le16_to_cpu(ctx->timing.beacon_interval); } else { beacon_int = iwl_adjust_beacon_interval(beacon_int, - IWL_MAX_UCODE_BEACON_INTERVAL * TIME_UNIT); + priv->hw_params.max_beacon_itrvl * TIME_UNIT); ctx->timing.beacon_interval = cpu_to_le16(beacon_int); } @@ -378,7 +379,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) le32_to_cpu(ctx->timing.beacon_init_val), le16_to_cpu(ctx->timing.atim_window)); - return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd, + return trans_send_cmd_pdu(&priv->trans, ctx->rxon_timing_cmd, CMD_SYNC, sizeof(ctx->timing), &ctx->timing); } @@ -808,11 +809,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, - &priv->shrd->status)) + if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) ieee80211_chswitch_done(ctx->vif, is_success); } @@ -857,16 +857,16 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) unsigned long reload_jiffies; /* Set the FW error flag -- cleared on iwl_down */ - set_bit(STATUS_FW_ERROR, &priv->shrd->status); + set_bit(STATUS_FW_ERROR, &priv->status); /* Cancel currently queued command. */ - clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); iwlagn_abort_notification_waits(priv); /* Keep the restart process from trying to send host * commands by clearing the ready bit */ - clear_bit(STATUS_READY, &priv->shrd->status); + clear_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); @@ -891,26 +891,63 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) priv->reload_count = 0; } - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) { + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { if (iwlagn_mod_params.restart_fw) { - IWL_DEBUG_FW_ERRORS(priv, + IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Restarting adapter due to uCode error.\n"); - queue_work(priv->shrd->workqueue, &priv->restart); + queue_work(priv->workqueue, &priv->restart); } else - IWL_DEBUG_FW_ERRORS(priv, + IWL_DEBUG(priv, IWL_DL_FW_ERRORS, "Detected FW error, but not restarting\n"); } } +/** + * iwl_irq_handle_error - called for HW or SW error interrupt from card + */ +void iwl_irq_handle_error(struct iwl_priv *priv) +{ + /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ + if (priv->cfg->internal_wimax_coex && + (!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) & + APMS_CLK_VAL_MRB_FUNC_MODE) || + (iwl_read_prph(priv, APMG_PS_CTRL_REG) & + APMG_PS_CTRL_VAL_RESET_REQ))) { + /* + * Keep the restart process from trying to send host + * commands by clearing the ready bit. + */ + clear_bit(STATUS_READY, &priv->status); + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + wake_up_interruptible(&priv->wait_command_queue); + IWL_ERR(priv, "RF is used by WiMAX\n"); + return; + } + + IWL_ERR(priv, "Loaded firmware version: %s\n", + priv->hw->wiphy->fw_version); + + iwl_dump_nic_error_log(priv); + iwl_dump_csr(priv); + iwl_dump_fh(priv, NULL, false); + iwl_dump_nic_event_log(priv, false, NULL, false); +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) + iwl_print_rx_config_cmd(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); +#endif + + iwlagn_fw_error(priv, false); +} + static int iwl_apm_stop_master(struct iwl_priv *priv) { int ret = 0; /* stop device's busmaster DMA activity */ - iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - ret = iwl_poll_bit(bus(priv), CSR_RESET, - CSR_RESET_REG_FLAG_MASTER_DISABLED, + ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); if (ret) IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n"); @@ -924,13 +961,13 @@ void iwl_apm_stop(struct iwl_priv *priv) { IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); - clear_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); + clear_bit(STATUS_DEVICE_ENABLED, &priv->status); /* Stop device's DMA activity */ iwl_apm_stop_master(priv); /* Reset the entire device */ - iwl_set_bit(bus(priv), CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); @@ -938,7 +975,7 @@ void iwl_apm_stop(struct iwl_priv *priv) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } @@ -958,45 +995,45 @@ int iwl_apm_init(struct iwl_priv *priv) */ /* Disable L0S exit timer (platform NMI Work/Around) */ - iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); /* * Disable L0s without affecting L1; * don't wait for ICH L0s (ICH bug W/A) */ - iwl_set_bit(bus(priv), CSR_GIO_CHICKEN_BITS, + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); /* Set FH wait threshold to maximum (HW error during stress W/A) */ - iwl_set_bit(bus(priv), CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); bus_apm_config(priv->bus); /* Configure analog phase-lock-loop before activating to D0A */ if (priv->cfg->base_params->pll_cfg_val) - iwl_set_bit(bus(priv), CSR_ANA_PLL_CFG, + iwl_set_bit(priv, CSR_ANA_PLL_CFG, priv->cfg->base_params->pll_cfg_val); /* * Set "initialization complete" bit to move adapter from * D0U* --> D0A* (powered-up active) state. */ - iwl_set_bit(bus(priv), CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* * Wait for clock stabilization; once stabilized, access to * device-internal resources is supported, e.g. iwl_write_prph() * and accesses to uCode SRAM. */ - ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL, + ret = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) { @@ -1011,14 +1048,14 @@ int iwl_apm_init(struct iwl_priv *priv) * do not disable clocks. This preserves any hardware bits already * set by default in "CLK_CTRL_REG" after reset. */ - iwl_write_prph(bus(priv), APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); + iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(20); /* Disable L1-Active */ - iwl_set_bits_prph(bus(priv), APMG_PCIDEV_STT_REG, + iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - set_bit(STATUS_DEVICE_ENABLED, &priv->shrd->status); + set_bit(STATUS_DEVICE_ENABLED, &priv->status); out: return ret; @@ -1032,7 +1069,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) bool defer; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (priv->tx_power_user_lmt == tx_power && !force) return 0; @@ -1052,7 +1089,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) return -EINVAL; } - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EIO; /* scan complete and commit_rxon use tx_power_next value, @@ -1060,7 +1097,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) priv->tx_power_next = tx_power; /* do not set tx power when scanning or channel changing */ - defer = test_bit(STATUS_SCANNING, &priv->shrd->status) || + defer = test_bit(STATUS_SCANNING, &priv->status) || memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); if (defer && !force) { IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); @@ -1098,7 +1135,7 @@ void iwl_send_bt_config(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "BT coex %s\n", (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); - if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG, + if (trans_send_cmd_pdu(&priv->trans, REPLY_BT_CONFIG, CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); } @@ -1111,17 +1148,22 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) }; if (flags & CMD_ASYNC) - return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, + return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, CMD_ASYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); else - return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, + return trans_send_cmd_pdu(&priv->trans, REPLY_STATISTICS_CMD, CMD_SYNC, sizeof(struct iwl_statistics_cmd), &statistics_cmd); } +void iwl_clear_isr_stats(struct iwl_priv *priv) +{ + memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); +} + int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { @@ -1132,7 +1174,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, IWL_DEBUG_MAC80211(priv, "enter\n"); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; } @@ -1144,7 +1186,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, q = AC_NUM - 1 - queue; - spin_lock_irqsave(&priv->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* * MULTI-FIXME @@ -1162,7 +1204,7 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; } - spin_unlock_irqrestore(&priv->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_MAC80211(priv, "leave\n"); return 0; @@ -1190,7 +1232,7 @@ static int iwl_setup_interface(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; int err; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* * This variable will be correct only when there's just @@ -1234,11 +1276,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) cancel_delayed_work_sync(&priv->hw_roc_disable_work); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwlagn_disable_roc(priv); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_WARN(priv, "Try to add interface when device not ready\n"); err = -EINVAL; goto out; @@ -1281,7 +1323,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ctx->vif = NULL; priv->iw_mode = NL80211_IFTYPE_STATION; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); return err; @@ -1293,7 +1335,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv, { struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); if (priv->scan_vif == vif) { iwl_scan_cancel_timeout(priv, 200); @@ -1325,14 +1367,14 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); WARN_ON(ctx->vif != vif); ctx->vif = NULL; iwl_teardown_interface(priv, vif, false); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -1356,7 +1398,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) { u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE; - if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) { + if (iwl_debug_level & IWL_DL_TX) { if (!priv->tx_traffic) { priv->tx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1364,7 +1406,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv) return -ENOMEM; } } - if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) { + if (iwl_debug_level & IWL_DL_RX) { if (!priv->rx_traffic) { priv->rx_traffic = kzalloc(traffic_size, GFP_KERNEL); @@ -1391,7 +1433,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX))) + if (likely(!(iwl_debug_level & IWL_DL_TX))) return; if (!priv->tx_traffic) @@ -1415,7 +1457,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, __le16 fc; u16 len; - if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX))) + if (likely(!(iwl_debug_level & IWL_DL_RX))) return; if (!priv->rx_traffic) @@ -1572,7 +1614,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) static void iwl_force_rf_reset(struct iwl_priv *priv) { - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; if (!iwl_is_any_associated(priv)) { @@ -1597,7 +1639,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) { struct iwl_force_reset *force_reset; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; if (mode >= IWL_MAX_FORCE_RESET) { @@ -1656,9 +1698,9 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, newtype = ieee80211_iftype_p2p(newtype, newp2p); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) { + if (!ctx->vif || !iwl_is_ready_rf(priv)) { /* * Huh? But wait ... this can maybe happen when * we're in the middle of a firmware restart! @@ -1720,16 +1762,36 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = 0; out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return err; } -static inline int iwl_check_stuck_queue(struct iwl_priv *priv, int txq) +/* + * On every watchdog tick we check (latest) time stamp. If it does not + * change during timeout period and queue is not empty we reset firmware. + */ +static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) { - if (iwl_trans_check_stuck_queue(trans(priv), txq)) { - int ret = iwl_force_reset(priv, IWL_FW_RESET, false); + struct iwl_tx_queue *txq = &priv->txq[cnt]; + struct iwl_queue *q = &txq->q; + unsigned long timeout; + int ret; + + if (q->read_ptr == q->write_ptr) { + txq->time_stamp = jiffies; + return 0; + } + + timeout = txq->time_stamp + + msecs_to_jiffies(priv->cfg->base_params->wd_timeout); + + if (time_after(jiffies, timeout)) { + IWL_ERR(priv, "Queue %d stuck for %u ms.\n", + q->id, priv->cfg->base_params->wd_timeout); + ret = iwl_force_reset(priv, IWL_FW_RESET, false); return (ret == -EAGAIN) ? 0 : 1; } + return 0; } @@ -1749,7 +1811,7 @@ void iwl_bg_watchdog(unsigned long data) int cnt; unsigned long timeout; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; timeout = priv->cfg->base_params->wd_timeout; @@ -1757,14 +1819,14 @@ void iwl_bg_watchdog(unsigned long data) return; /* monitor and check for stuck cmd queue */ - if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue)) + if (iwl_check_stuck_queue(priv, priv->cmd_queue)) return; /* monitor and check for other stuck queues */ if (iwl_is_any_associated(priv)) { - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { /* skip as we already checked the command queue */ - if (cnt == priv->shrd->cmd_queue) + if (cnt == priv->cmd_queue) continue; if (iwl_check_stuck_queue(priv, cnt)) return; @@ -1803,12 +1865,12 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval) quot = (usec / interval) & (iwl_beacon_time_mask_high(priv, - hw_params(priv).beacon_time_tsf_bits) >> - hw_params(priv).beacon_time_tsf_bits); + priv->hw_params.beacon_time_tsf_bits) >> + priv->hw_params.beacon_time_tsf_bits); rem = (usec % interval) & iwl_beacon_time_mask_low(priv, - hw_params(priv).beacon_time_tsf_bits); + priv->hw_params.beacon_time_tsf_bits); - return (quot << hw_params(priv).beacon_time_tsf_bits) + rem; + return (quot << priv->hw_params.beacon_time_tsf_bits) + rem; } /* base is usually what we get from ucode with each received frame, @@ -1818,50 +1880,64 @@ __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, - hw_params(priv).beacon_time_tsf_bits); + priv->hw_params.beacon_time_tsf_bits); u32 addon_low = addon & iwl_beacon_time_mask_low(priv, - hw_params(priv).beacon_time_tsf_bits); + priv->hw_params.beacon_time_tsf_bits); u32 interval = beacon_interval * TIME_UNIT; u32 res = (base & iwl_beacon_time_mask_high(priv, - hw_params(priv).beacon_time_tsf_bits)) + + priv->hw_params.beacon_time_tsf_bits)) + (addon & iwl_beacon_time_mask_high(priv, - hw_params(priv).beacon_time_tsf_bits)); + 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 << hw_params(priv).beacon_time_tsf_bits); + res += (1 << priv->hw_params.beacon_time_tsf_bits); } else - res += (1 << hw_params(priv).beacon_time_tsf_bits); + res += (1 << priv->hw_params.beacon_time_tsf_bits); return cpu_to_le32(res); } -void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - u8 sta_id, u8 tid) -{ - struct ieee80211_vif *vif = priv->contexts[ctx].vif; - u8 *addr = priv->stations[sta_id].sta.sta.addr; +#ifdef CONFIG_PM - if (ctx == NUM_IWL_RXON_CTX) - ctx = priv->stations[sta_id].ctxid; - vif = priv->contexts[ctx].vif; +int iwl_suspend(struct iwl_priv *priv) +{ + /* + * This function is called when system goes into suspend state + * mac80211 will call iwl_mac_stop() from the mac80211 suspend function + * first but since iwl_mac_stop() has no knowledge of who the caller is, + * it will not call apm_ops.stop() to stop the DMA operation. + * Calling apm_ops.stop here to make sure we stop the DMA. + * + * But of course ... if we have configured WoWLAN then we did other + * things already :-) + */ + if (!priv->wowlan) + iwl_apm_stop(priv); - ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); + return 0; } -void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - u8 sta_id, u8 tid) +int iwl_resume(struct iwl_priv *priv) { - struct ieee80211_vif *vif; - u8 *addr = priv->stations[sta_id].sta.sta.addr; + bool hw_rfkill = false; + + iwl_enable_interrupts(priv); - if (ctx == NUM_IWL_RXON_CTX) - ctx = priv->stations[sta_id].ctxid; - vif = priv->contexts[ctx].vif; + if (!(iwl_read32(priv, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) + hw_rfkill = true; - ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); + if (hw_rfkill) + set_bit(STATUS_RF_KILL_HW, &priv->status); + else + clear_bit(STATUS_RF_KILL_HW, &priv->status); + + wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill); + + return 0; } + +#endif /* CONFIG_PM */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h index 2ea8a2e0dfbc..42bcb469d32c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h @@ -71,6 +71,11 @@ struct iwl_host_cmd; struct iwl_cmd; + +#define IWLWIFI_VERSION "in-tree:" +#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" +#define DRV_AUTHOR "" + #define TIME_UNIT 1024 #define IWL_CMD(x) case x: return #x @@ -96,6 +101,23 @@ struct iwl_lib_ops { void (*temperature)(struct iwl_priv *priv); }; +struct iwl_mod_params { + int sw_crypto; /* def: 0 = using hardware encryption */ + int num_of_queues; /* def: HW dependent */ + int disable_11n; /* def: 0 = 11n capabilities enabled */ + int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ + int antenna; /* def: 0 = both antennas (use diversity) */ + int restart_fw; /* def: 1 = restart firmware */ + bool plcp_check; /* def: true = enable plcp health check */ + bool ack_check; /* def: false = disable ack health check */ + bool wd_disable; /* def: false = enable stuck queue check */ + bool bt_coex_active; /* def: true = enable bt coex */ + int led_mode; /* def: 0 = system default */ + bool no_sleep_autoadjust; /* def: true = disable autoadjust */ + bool power_save; /* def: false = disable power save */ + int power_level; /* def: 1 = power level */ +}; + /* * @max_ll_items: max number of OTP blocks * @shadow_ram_support: shadow support for OTP memory @@ -200,7 +222,16 @@ struct iwl_ht_params { * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the * highest and @ucode_api_min the lowest). Firmware will only be loaded if - * it has a supported API version. + * it has a supported API version. The firmware's API version will be + * stored in @iwl_priv, enabling the driver to make runtime changes based + * on firmware version used. + * + * For example, + * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { + * Driver interacts with Firmware API version >= 2. + * } else { + * Driver interacts with Firmware API version 1. + * } * * The ideal usage of this infrastructure is to treat a new ucode API * release as a new hardware revision. @@ -261,6 +292,7 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, void iwl_connection_init_rx_config(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwl_set_rate(struct iwl_priv *priv); +void iwl_irq_handle_error(struct iwl_priv *priv); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, @@ -366,10 +398,22 @@ 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_suspend(struct iwl_priv *priv); +int iwl_resume(struct iwl_priv *priv); +#endif /* !CONFIG_PM */ + +int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg); +void __devexit iwl_remove(struct iwl_priv * priv); /***************************************************** * Error Handling Debugging ******************************************************/ +void iwl_dump_nic_error_log(struct iwl_priv *priv); +int iwl_dump_nic_event_log(struct iwl_priv *priv, + bool full_log, char **buf, bool display); +void iwl_dump_csr(struct iwl_priv *priv); +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); @@ -380,11 +424,79 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, } #endif +void iwl_clear_isr_stats(struct iwl_priv *priv); + /***************************************************** * GEOS ******************************************************/ -int iwl_init_geos(struct iwl_priv *priv); -void iwl_free_geos(struct iwl_priv *priv); +int iwlcore_init_geos(struct iwl_priv *priv); +void iwlcore_free_geos(struct iwl_priv *priv); + +/*************** DRIVER STATUS FUNCTIONS *****/ + +#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ +/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ +#define STATUS_INT_ENABLED 2 +#define STATUS_RF_KILL_HW 3 +#define STATUS_CT_KILL 4 +#define STATUS_INIT 5 +#define STATUS_ALIVE 6 +#define STATUS_READY 7 +#define STATUS_TEMPERATURE 8 +#define STATUS_GEO_CONFIGURED 9 +#define STATUS_EXIT_PENDING 10 +#define STATUS_STATISTICS 12 +#define STATUS_SCANNING 13 +#define STATUS_SCAN_ABORTING 14 +#define STATUS_SCAN_HW 15 +#define STATUS_POWER_PMI 16 +#define STATUS_FW_ERROR 17 +#define STATUS_DEVICE_ENABLED 18 +#define STATUS_CHANNEL_SWITCH_PENDING 19 + + +static inline int iwl_is_ready(struct iwl_priv *priv) +{ + /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are + * set but EXIT_PENDING is not */ + return test_bit(STATUS_READY, &priv->status) && + test_bit(STATUS_GEO_CONFIGURED, &priv->status) && + !test_bit(STATUS_EXIT_PENDING, &priv->status); +} + +static inline int iwl_is_alive(struct iwl_priv *priv) +{ + return test_bit(STATUS_ALIVE, &priv->status); +} + +static inline int iwl_is_init(struct iwl_priv *priv) +{ + return test_bit(STATUS_INIT, &priv->status); +} + +static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) +{ + return test_bit(STATUS_RF_KILL_HW, &priv->status); +} + +static inline int iwl_is_rfkill(struct iwl_priv *priv) +{ + return iwl_is_rfkill_hw(priv); +} + +static inline int iwl_is_ctkill(struct iwl_priv *priv) +{ + return test_bit(STATUS_CT_KILL, &priv->status); +} + +static inline int iwl_is_ready_rf(struct iwl_priv *priv) +{ + + if (iwl_is_rfkill(priv)) + return 0; + + return iwl_is_ready(priv); +} extern void iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h index 7014f4124484..f9a407e40aff 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -29,51 +29,50 @@ #ifndef __iwl_debug_h__ #define __iwl_debug_h__ -#include "iwl-bus.h" -#include "iwl-shared.h" - struct iwl_priv; +extern u32 iwl_debug_level; -/*No matter what is m (priv, bus, trans), this will work */ -#define IWL_ERR(m, f, a...) dev_err(bus(m)->dev, f, ## a) -#define IWL_WARN(m, f, a...) dev_warn(bus(m)->dev, f, ## a) -#define IWL_INFO(m, f, a...) dev_info(bus(m)->dev, f, ## a) -#define IWL_CRIT(m, f, a...) dev_crit(bus(m)->dev, f, ## a) +#define IWL_ERR(p, f, a...) dev_err(p->bus->dev, f, ## a) +#define IWL_WARN(p, f, a...) dev_warn(p->bus->dev, f, ## a) +#define IWL_INFO(p, f, a...) dev_info(p->bus->dev, f, ## a) +#define IWL_CRIT(p, f, a...) dev_crit(p->bus->dev, f, ## a) -#define iwl_print_hex_error(m, p, len) \ +#define iwl_print_hex_error(priv, p, len) \ do { \ print_hex_dump(KERN_ERR, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) #ifdef CONFIG_IWLWIFI_DEBUG -#define IWL_DEBUG(m, level, fmt, args...) \ +#define IWL_DEBUG(__priv, level, fmt, args...) \ do { \ - if (iwl_get_debug_level((m)->shrd) & (level)) \ - dev_printk(KERN_ERR, bus(m)->dev, \ + if (iwl_get_debug_level(__priv) & (level)) \ + dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ } while (0) -#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \ +#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ do { \ - if (iwl_get_debug_level((m)->shrd) & (level) && net_ratelimit())\ - dev_printk(KERN_ERR, bus(m)->dev, \ + if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit()) \ + dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ __func__ , ## args); \ } while (0) -#define iwl_print_hex_dump(m, level, p, len) \ +#define iwl_print_hex_dump(priv, level, p, len) \ do { \ - if (iwl_get_debug_level((m)->shrd) & level) \ + if (iwl_get_debug_level(priv) & level) \ print_hex_dump(KERN_DEBUG, "iwl data: ", \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) #else -#define IWL_DEBUG(m, level, fmt, args...) -#define IWL_DEBUG_LIMIT(m, level, fmt, args...) -#define iwl_print_hex_dump(m, level, p, len) +#define IWL_DEBUG(__priv, level, fmt, args...) +#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) +static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, + const void *p, u32 len) +{} #endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -167,7 +166,6 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) -#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a) #define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) #define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c index e320cc10167e..ec1485b2d3fe 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -254,7 +254,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, sram = priv->dbgfs_sram_offset & ~0x3; /* read the first u32 from sram */ - val = iwl_read_targ_mem(bus(priv), sram); + val = iwl_read_targ_mem(priv, sram); for (; len; len--) { /* put the address at the start of every line */ @@ -273,7 +273,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, if (++offset == 4) { sram += 4; offset = 0; - val = iwl_read_targ_mem(bus(priv), sram); + val = iwl_read_targ_mem(priv, sram); } /* put in extra spaces and split lines for human readability */ @@ -340,8 +340,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, { struct iwl_priv *priv = file->private_data; struct iwl_station_entry *station; - struct iwl_tid_data *tid_data; - int max_sta = hw_params(priv).max_stations; + int max_sta = priv->hw_params.max_stations; char *buf; int i, j, pos = 0; ssize_t ret; @@ -364,18 +363,22 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, i, station->sta.sta.addr, station->sta.station_flags_msk); pos += scnprintf(buf + pos, bufsz - pos, - "TID\tseq_num\ttxq_id\ttfds\trate_n_flags\n"); + "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 < IWL_MAX_TID_COUNT; j++) { - tid_data = &priv->shrd->tid_data[i][j]; + for (j = 0; j < MAX_TID_COUNT; j++) { pos += scnprintf(buf + pos, bufsz - pos, - "%d:\t%#x\t%#x\t%u\t%#x", - j, tid_data->seq_number, - tid_data->agg.txq_id, - tid_data->tfds_in_queue, - tid_data->agg.rate_n_flags); - - if (tid_data->agg.wait_for_ba) + "%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, " - waitforba"); pos += scnprintf(buf + pos, bufsz - pos, "\n"); @@ -439,6 +442,46 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, return ret; } +static ssize_t iwl_dbgfs_log_event_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char *buf; + int pos = 0; + ssize_t ret = -ENOMEM; + + ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + } + return ret; +} + +static ssize_t iwl_dbgfs_log_event_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + u32 event_log_flag; + char buf[8]; + int buf_size; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &event_log_flag) != 1) + return -EFAULT; + if (event_log_flag == 1) + iwl_dump_nic_event_log(priv, true, NULL, false); + + return count; +} + + + static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -449,7 +492,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, char *buf; ssize_t ret; - if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)) + if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -519,46 +562,45 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, const size_t bufsz = sizeof(buf); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", - test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status)); + test_bit(STATUS_HCMD_ACTIVE, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", - test_bit(STATUS_INT_ENABLED, &priv->shrd->status)); + test_bit(STATUS_INT_ENABLED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); + test_bit(STATUS_RF_KILL_HW, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", - test_bit(STATUS_CT_KILL, &priv->shrd->status)); + test_bit(STATUS_CT_KILL, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", - test_bit(STATUS_INIT, &priv->shrd->status)); + test_bit(STATUS_INIT, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", - test_bit(STATUS_ALIVE, &priv->shrd->status)); + test_bit(STATUS_ALIVE, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", - test_bit(STATUS_READY, &priv->shrd->status)); + test_bit(STATUS_READY, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", - test_bit(STATUS_TEMPERATURE, &priv->shrd->status)); + test_bit(STATUS_TEMPERATURE, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", - test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)); + test_bit(STATUS_GEO_CONFIGURED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)); + test_bit(STATUS_EXIT_PENDING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", - test_bit(STATUS_STATISTICS, &priv->shrd->status)); + test_bit(STATUS_STATISTICS, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", - test_bit(STATUS_SCANNING, &priv->shrd->status)); + test_bit(STATUS_SCANNING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", - test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)); + test_bit(STATUS_SCAN_ABORTING, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", - test_bit(STATUS_SCAN_HW, &priv->shrd->status)); + test_bit(STATUS_SCAN_HW, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", - test_bit(STATUS_POWER_PMI, &priv->shrd->status)); + test_bit(STATUS_POWER_PMI, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", - test_bit(STATUS_FW_ERROR, &priv->shrd->status)); + test_bit(STATUS_FW_ERROR, &priv->status)); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file, +static ssize_t iwl_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - int pos = 0; int cnt = 0; char *buf; @@ -571,25 +613,61 @@ static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file, return -ENOMEM; } + pos += scnprintf(buf + pos, bufsz - pos, + "Interrupt Statistics Report:\n"); + + pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", + priv->isr_stats.hw); + pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", + priv->isr_stats.sw); + if (priv->isr_stats.sw || priv->isr_stats.hw) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tLast Restarting Code: 0x%X\n", + priv->isr_stats.err_code); + } +#ifdef CONFIG_IWLWIFI_DEBUG + pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", + priv->isr_stats.sch); + pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", + priv->isr_stats.alive); +#endif + pos += scnprintf(buf + pos, bufsz - pos, + "HW RF KILL switch toggled:\t %u\n", + priv->isr_stats.rfkill); + + pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", + priv->isr_stats.ctkill); + + pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", + priv->isr_stats.wakeup); + + pos += scnprintf(buf + pos, bufsz - pos, + "Rx command responses:\t\t %u\n", + priv->isr_stats.rx); for (cnt = 0; cnt < REPLY_MAX; cnt++) { - if (priv->rx_handlers_stats[cnt] > 0) + if (priv->isr_stats.rx_handlers[cnt] > 0) pos += scnprintf(buf + pos, bufsz - pos, "\tRx handler[%36s]:\t\t %u\n", get_cmd_string(cnt), - priv->rx_handlers_stats[cnt]); + priv->isr_stats.rx_handlers[cnt]); } + pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", + priv->isr_stats.tx); + + pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", + priv->isr_stats.unhandled); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; } -static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file, +static ssize_t iwl_dbgfs_interrupt_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_priv *priv = file->private_data; - char buf[8]; int buf_size; u32 reset_flag; @@ -601,8 +679,7 @@ static ssize_t iwl_dbgfs_rx_handlers_write(struct file *file, if (sscanf(buf, "%x", &reset_flag) != 1) return -EFAULT; if (reset_flag == 0) - memset(&priv->rx_handlers_stats[0], 0, - sizeof(priv->rx_handlers_stats)); + iwl_clear_isr_stats(priv); return count; } @@ -737,14 +814,14 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) return -EINVAL; - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EAGAIN; priv->power_data.debug_sleep_level_override = value; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_power_update_mode(priv, true); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return count; } @@ -793,17 +870,188 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, DEBUGFS_READ_WRITE_FILE_OPS(sram); DEBUGFS_READ_FILE_OPS(wowlan_sram); +DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(stations); DEBUGFS_READ_FILE_OPS(channels); DEBUGFS_READ_FILE_OPS(status); -DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers); +DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_FILE_OPS(qos); DEBUGFS_READ_FILE_OPS(thermal_throttling); DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); DEBUGFS_READ_FILE_OPS(current_sleep_command); +static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + int pos = 0, ofs = 0; + int cnt = 0, entry; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + struct iwl_rx_queue *rxq = &priv->rxq; + char *buf; + int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + + (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; + const u8 *ptr; + ssize_t ret; + + if (!priv->txq) { + IWL_ERR(priv, "txq not ready\n"); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate buffer\n"); + return -ENOMEM; + } + pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + txq = &priv->txq[cnt]; + q = &txq->q; + pos += scnprintf(buf + pos, bufsz - pos, + "q[%d]: read_ptr: %u, write_ptr: %u\n", + cnt, q->read_ptr, q->write_ptr); + } + if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { + ptr = priv->tx_traffic; + pos += scnprintf(buf + pos, bufsz - pos, + "Tx Traffic idx: %u\n", priv->tx_traffic_idx); + for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { + for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; + entry++, ofs += 16) { + pos += scnprintf(buf + pos, bufsz - pos, + "0x%.4x ", ofs); + hex_dump_to_buffer(ptr + ofs, 16, 16, 2, + buf + pos, bufsz - pos, 0); + pos += strlen(buf + pos); + if (bufsz - pos > 0) + buf[pos++] = '\n'; + } + } + } + + pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "read: %u, write: %u\n", + rxq->read, rxq->write); + + if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { + ptr = priv->rx_traffic; + pos += scnprintf(buf + pos, bufsz - pos, + "Rx Traffic idx: %u\n", priv->rx_traffic_idx); + for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { + for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; + entry++, ofs += 16) { + pos += scnprintf(buf + pos, bufsz - pos, + "0x%.4x ", ofs); + hex_dump_to_buffer(ptr + ofs, 16, 16, 2, + buf + pos, bufsz - pos, 0); + pos += strlen(buf + pos); + if (bufsz - pos > 0) + buf[pos++] = '\n'; + } + } + } + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int traffic_log; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &traffic_log) != 1) + return -EFAULT; + if (traffic_log == 0) + iwl_reset_traffic_log(priv); + + return count; +} + +static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + struct iwl_tx_queue *txq; + struct iwl_queue *q; + char *buf; + int pos = 0; + int cnt; + int ret; + const size_t bufsz = sizeof(char) * 64 * + priv->cfg->base_params->num_of_queues; + + if (!priv->txq) { + IWL_ERR(priv, "txq not ready\n"); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { + txq = &priv->txq[cnt]; + q = &txq->q; + pos += scnprintf(buf + pos, bufsz - pos, + "hwq %.2d: read=%u write=%u stop=%d" + " swq_id=%#.2x (ac %d/hwq %d)\n", + cnt, q->read_ptr, q->write_ptr, + !!test_bit(cnt, priv->queue_stopped), + txq->swq_id, txq->swq_id & 3, + (txq->swq_id >> 2) & 0x1f); + if (cnt >= 4) + continue; + /* for the ACs, display the stop count too */ + pos += scnprintf(buf + pos, bufsz - pos, + " stop-count: %d\n", + atomic_read(&priv->queue_stop_count[cnt])); + } + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + struct iwl_rx_queue *rxq = &priv->rxq; + char buf[256]; + int pos = 0; + const size_t bufsz = sizeof(buf); + + pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", + rxq->read); + pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", + rxq->write); + pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", + rxq->free_count); + if (rxq->rb_stts) { + pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", + le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); + } else { + pos += scnprintf(buf + pos, bufsz - pos, + "closed_rb_num: Not Allocated\n"); + } + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + static const char *fmt_value = " %-30s %10u\n"; static const char *fmt_hex = " %-30s 0x%02X\n"; static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; @@ -848,7 +1096,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, struct statistics_rx_non_phy *delta_general, *max_general; struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1274,7 +1522,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, ssize_t ret; struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1468,7 +1716,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; struct statistics_div *div, *accum_div, *delta_div, *max_div; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1581,16 +1829,16 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, ssize_t ret; struct statistics_bt_activity *bt, *accum_bt; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; if (!priv->bt_enable_flag) return -EINVAL; /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); if (ret) { IWL_ERR(priv, @@ -1669,7 +1917,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file, (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; ssize_t ret; - if (!iwl_is_alive(priv->shrd)) + if (!iwl_is_alive(priv)) return -EAGAIN; buf = kzalloc(bufsz, GFP_KERNEL); @@ -1951,7 +2199,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, const size_t bufsz = sizeof(buf); u32 pwrsave_status; - pwrsave_status = iwl_read32(bus(priv), CSR_GP_CNTRL) & + pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); @@ -1981,9 +2229,30 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, return -EFAULT; /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_send_statistics_request(priv, CMD_SYNC, true); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); + + return count; +} + +static ssize_t iwl_dbgfs_csr_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int csr; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &csr) != 1) + return -EFAULT; + + iwl_dump_csr(priv); return count; } @@ -2064,6 +2333,25 @@ static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, len); } +static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char *buf; + int pos = 0; + ssize_t ret = -EFAULT; + + ret = pos = iwl_dump_fh(priv, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, + count, ppos, buf, pos); + kfree(buf); + } + + return ret; +} + static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -2216,7 +2504,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, if (sscanf(buf, "%d", &flush) != 1) return -EINVAL; - if (iwl_is_rfkill(priv->shrd)) + if (iwl_is_rfkill(priv)) return -EFAULT; iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); @@ -2340,6 +2628,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); +DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); +DEBUGFS_READ_FILE_OPS(rx_queue); +DEBUGFS_READ_FILE_OPS(tx_queue); DEBUGFS_READ_FILE_OPS(ucode_rx_stats); DEBUGFS_READ_FILE_OPS(ucode_tx_stats); DEBUGFS_READ_FILE_OPS(ucode_general_stats); @@ -2348,7 +2639,9 @@ DEBUGFS_READ_FILE_OPS(chain_noise); DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); +DEBUGFS_WRITE_FILE_OPS(csr); DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); +DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); DEBUGFS_READ_WRITE_FILE_OPS(force_reset); @@ -2389,10 +2682,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(wowlan_sram, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); - DEBUGFS_ADD_FILE(rx_handlers, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); @@ -2400,9 +2694,14 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); @@ -2426,9 +2725,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &priv->disable_chain_noise_cal); - - if (iwl_trans_dbgfs_register(trans(priv), dir_debug)) - goto err; return 0; err: diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h index 1e54293532b0..dd34c7c502fa 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -36,12 +36,12 @@ #include #include #include -#include #include #include "iwl-eeprom.h" #include "iwl-csr.h" #include "iwl-prph.h" +#include "iwl-fh.h" #include "iwl-debug.h" #include "iwl-agn-hw.h" #include "iwl-led.h" @@ -50,7 +50,8 @@ #include "iwl-agn-tt.h" #include "iwl-bus.h" #include "iwl-trans.h" -#include "iwl-shared.h" + +#define DRV_NAME "iwlagn" struct iwl_tx_queue; @@ -89,6 +90,14 @@ struct iwl_tx_queue; #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U +struct iwl_rx_mem_buffer { + dma_addr_t page_dma; + struct page *page; + struct list_head list; +}; + +#define rxb_addr(r) page_address(r->page) + /* defined below */ struct iwl_device_cmd; @@ -147,6 +156,12 @@ struct iwl_queue { * space less than this */ }; +/* One for each TFD */ +struct iwl_tx_info { + struct sk_buff *skb; + struct iwl_rxon_context *ctx; +}; + /** * struct iwl_tx_queue - Tx Queue for DMA * @q: generic Rx/Tx queue descriptor @@ -158,8 +173,6 @@ struct iwl_queue { * @time_stamp: time (in jiffies) of last read_ptr change * @need_update: indicates need to update read/write index * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled - * @sta_id: valid if sched_retry is set - * @tid: valid if sched_retry is set * * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame * descriptors) and required locking structures. @@ -172,15 +185,12 @@ struct iwl_tx_queue { struct iwl_tfd *tfds; struct iwl_device_cmd **cmd; struct iwl_cmd_meta *meta; - struct sk_buff **skbs; + struct iwl_tx_info *txb; unsigned long time_stamp; u8 need_update; u8 sched_retry; u8 active; u8 swq_id; - - u16 sta_id; - u16 tid; }; #define IWL_NUM_SCAN_RATES (2) @@ -244,6 +254,13 @@ struct iwl_channel_info { #define IWL_DEFAULT_CMD_QUEUE_NUM 4 #define IWL_IPAN_CMD_QUEUE_NUM 9 +/* + * This queue number is required for proper operation + * because the ucode will stop/start the scheduler as + * required. + */ +#define IWL_IPAN_MCAST_QUEUE 8 + #define IEEE80211_DATA_LEN 2304 #define IEEE80211_4ADDR_LEN 30 #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) @@ -317,11 +334,81 @@ struct iwl_host_cmd { #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 +/** + * struct iwl_rx_queue - Rx queue + * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) + * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) + * @read: Shared index to newest available Rx buffer + * @write: Shared index to oldest written Rx packet + * @free_count: Number of pre-allocated buffers in rx_free + * @rx_free: list of free SKBs for use + * @rx_used: List of Rx buffers with no SKB + * @need_update: flag to indicate we need to update read/write index + * @rb_stts: driver's pointer to receive buffer status + * @rb_stts_dma: bus address of receive buffer status + * + * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers + */ +struct iwl_rx_queue { + __le32 *bd; + dma_addr_t bd_dma; + struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; + struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; + u32 read; + u32 write; + u32 free_count; + u32 write_actual; + struct list_head rx_free; + struct list_head rx_used; + int need_update; + struct iwl_rb_status *rb_stts; + dma_addr_t rb_stts_dma; + spinlock_t lock; +}; + #define IWL_SUPPORTED_RATES_IE_LEN 8 +#define MAX_TID_COUNT 9 + #define IWL_INVALID_RATE 0xFF #define IWL_INVALID_VALUE -1 +/** + * struct iwl_ht_agg -- aggregation status while waiting for block-ack + * @txq_id: Tx queue used for Tx attempt + * @frame_count: # frames attempted by Tx command + * @wait_for_ba: Expect block-ack before next Tx reply + * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window + * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window + * @bitmap1: High order, one bit for each frame pending ACK in Tx window + * @rate_n_flags: Rate at which Tx was attempted + * + * If REPLY_TX indicates that aggregation was attempted, driver must wait + * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info + * until block ack arrives. + */ +struct iwl_ht_agg { + u16 txq_id; + u16 frame_count; + u16 wait_for_ba; + u16 start_idx; + u64 bitmap; + u32 rate_n_flags; +#define IWL_AGG_OFF 0 +#define IWL_AGG_ON 1 +#define IWL_EMPTYING_HW_QUEUE_ADDBA 2 +#define IWL_EMPTYING_HW_QUEUE_DELBA 3 + u8 state; + u8 tx_fifo; +}; + + +struct iwl_tid_data { + u16 seq_number; /* agn only */ + u16 tfds_in_queue; + struct iwl_ht_agg agg; +}; + union iwl_ht_rate_supp { u16 rates; struct { @@ -372,6 +459,7 @@ struct iwl_qos_info { */ struct iwl_station_entry { struct iwl_addsta_cmd sta; + struct iwl_tid_data tid[MAX_TID_COUNT]; u8 used, ctxid; struct iwl_link_quality_cmd *lq; }; @@ -559,6 +647,54 @@ struct iwl_sensitivity_ranges { #define CELSIUS_TO_KELVIN(x) ((x)+273) +/** + * struct iwl_hw_params + * @max_txq_num: Max # Tx queues supported + * @scd_bc_tbls_size: size of scheduler byte count tables + * @tfd_size: TFD size + * @tx/rx_chains_num: Number of TX/RX chains + * @valid_tx/rx_ant: usable antennas + * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) + * @max_rxq_log: Log-base-2 of max_rxq_size + * @rx_page_order: Rx buffer page order + * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR + * @max_stations: + * @ht40_channel: is 40MHz width possible in band 2.4 + * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) + * @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 + * @calib_rt_cfg: setup runtime calibrations for the hw + * @struct iwl_sensitivity_ranges: range of sensitivity values + */ +struct iwl_hw_params { + u8 max_txq_num; + u16 scd_bc_tbls_size; + u32 tfd_size; + u8 tx_chains_num; + u8 rx_chains_num; + u8 valid_tx_ant; + u8 valid_rx_ant; + u16 max_rxq_size; + u16 max_rxq_log; + u32 rx_page_order; + u8 max_stations; + u8 ht40_channel; + u8 max_beacon_itrvl; /* in 1024 ms */ + u32 max_inst_size; + u32 max_data_size; + 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; + u32 calib_rt_cfg; + const struct iwl_sensitivity_ranges *sens; +}; + + /****************************************************************************** * * Functions implemented in core module which are forward declared here @@ -574,6 +710,26 @@ struct iwl_sensitivity_ranges { ****************************************************************************/ extern void iwl_update_chain_flags(struct iwl_priv *priv); extern const u8 iwl_bcast_addr[ETH_ALEN]; +extern int iwl_queue_space(const struct iwl_queue *q); +static inline int iwl_queue_used(const struct iwl_queue *q, int i) +{ + return q->write_ptr >= q->read_ptr ? + (i >= q->read_ptr && i < q->write_ptr) : + !(i < q->read_ptr && i >= q->write_ptr); +} + + +static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) +{ + return index & (q->n_window - 1); +} + + +struct iwl_dma_ptr { + dma_addr_t dma; + void *addr; + size_t size; +}; #define IWL_OPERATION_MODE_AUTO 0 #define IWL_OPERATION_MODE_HT_ONLY 1 @@ -741,6 +897,22 @@ enum iwl_pa_type { IWL_PA_INTERNAL = 1, }; +/* interrupt statistics */ +struct isr_statistics { + u32 hw; + u32 sw; + u32 err_code; + u32 sch; + u32 alive; + u32 rfkill; + u32 ctkill; + u32 wakeup; + u32 rx; + u32 rx_handlers[REPLY_MAX]; + u32 tx; + u32 unhandled; +}; + /* reply_tx_statistics (for _agn devices) */ struct reply_tx_error_statistics { u32 pp_delay; @@ -942,9 +1114,20 @@ struct iwl_notification_wait { bool triggered, aborted; }; +enum iwl_rxon_context_id { + IWL_RXON_CTX_BSS, + IWL_RXON_CTX_PAN, + + NUM_IWL_RXON_CTX +}; + struct iwl_rxon_context { struct ieee80211_vif *vif; + const u8 *ac_to_fifo; + const u8 *ac_to_queue; + u8 mcast_queue; + /* * We could use the vif to indicate active, but we * also need it to be active during disabling when @@ -992,9 +1175,6 @@ struct iwl_rxon_context { u8 extension_chan_offset; } ht; - u8 bssid[ETH_ALEN]; - bool preauth_bssid; - bool last_tx_rejected; }; @@ -1023,17 +1203,16 @@ struct iwl_testmode_trace { }; #endif -struct iwl_priv { +/* uCode ownership */ +#define IWL_OWNERSHIP_DRIVER 0 +#define IWL_OWNERSHIP_TM 1 - /*data shared among all the driver's layers */ - struct iwl_shared _shrd; - struct iwl_shared *shrd; +struct iwl_priv { /* ieee device used by generic ieee processing code */ struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; - struct kmem_cache *tx_cmd_pool; struct iwl_cfg *cfg; enum ieee80211_band band; @@ -1059,9 +1238,6 @@ struct iwl_priv { /* jiffies when last recovery from statistics was performed */ unsigned long rx_statistics_jiffies; - /*counters */ - u32 rx_handlers_stats[REPLY_MAX]; - /* force reset */ struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; @@ -1092,12 +1268,21 @@ struct iwl_priv { u8 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 mgmt_tx_ant; - /*TODO: remove these pointers - use bus(priv) instead */ + /* spinlock */ + spinlock_t lock; /* protect general shared data */ + spinlock_t hcmd_lock; /* protect hcmd */ + spinlock_t reg_lock; /* protect hw register access */ + struct mutex mutex; + struct iwl_bus *bus; /* bus specific data */ + struct iwl_trans trans; /* microcode/device supports multiple contexts */ u8 valid_contexts; + /* command queue number */ + u8 cmd_queue; + /* max number of station keys */ u8 sta_key_max_num; @@ -1111,6 +1296,9 @@ struct iwl_priv { u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ + /* uCode owner: default: IWL_OWNERSHIP_DRIVER */ + u8 ucode_owner; + struct fw_img ucode_rt; struct fw_img ucode_init; struct fw_img ucode_wowlan; @@ -1146,21 +1334,48 @@ struct iwl_priv { int activity_timer_active; + /* Rx and Tx DMA processing queues */ + struct iwl_rx_queue rxq; + struct iwl_tx_queue *txq; + unsigned long txq_ctx_active_msk; + struct iwl_dma_ptr kw; /* keep warm address */ + struct iwl_dma_ptr scd_bc_tbls; + + u32 scd_base_addr; /* scheduler sram base address */ + + unsigned long status; + /* counts mgmt, ctl, and data packets */ struct traffic_stats tx_stats; struct traffic_stats rx_stats; + /* counts interrupts */ + struct isr_statistics isr_stats; + struct iwl_power_mgr power_data; struct iwl_tt_mgmt thermal_throttle; /* 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[IWLAGN_STATION_COUNT]; unsigned long ucode_key_table; + /* queue refcounts */ +#define IWL_MAX_HW_QUEUES 32 + unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; + /* for each AC */ + atomic_t queue_stop_count[4]; + /* Indication if ieee80211_ops->open has been called */ u8 is_open; + u8 mac80211_registered; + + bool wowlan; + /* eeprom -- this is in the card's little endian byte order */ u8 *eeprom; int nvm_device_type; @@ -1196,6 +1411,14 @@ struct iwl_priv { } accum_stats, delta_stats, max_delta_stats; #endif + /* INT ICT Table */ + __le32 *ict_tbl; + void *ict_tbl_vir; + dma_addr_t ict_tbl_dma; + dma_addr_t aligned_ict_tbl_dma; + int ict_index; + u32 inta; + bool use_ict; /* * reporting the number of tids has AGG on. 0 means * no AGGREGATION @@ -1252,8 +1475,15 @@ struct iwl_priv { struct iwl_rxon_context *cur_rssi_ctx; bool bt_is_sco; + struct iwl_hw_params hw_params; + + u32 inta_mask; + + struct workqueue_struct *workqueue; + struct work_struct restart; struct work_struct scan_completed; + struct work_struct rx_replenish; struct work_struct abort_scan; struct work_struct beacon_update; @@ -1269,6 +1499,8 @@ struct iwl_priv { struct work_struct bt_full_concurrency; struct work_struct bt_runtime_config; + struct tasklet_struct irq_tasklet; + struct delayed_work scan_check; /* TX Power */ @@ -1277,6 +1509,12 @@ struct iwl_priv { s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ s8 tx_power_next; + +#ifdef CONFIG_IWLWIFI_DEBUG + /* debugging info */ + u32 debug_level; /* per device debugging will override global + iwl_debug_level if set */ +#endif /* CONFIG_IWLWIFI_DEBUG */ #ifdef CONFIG_IWLWIFI_DEBUGFS /* debugfs */ u16 tx_traffic_idx; @@ -1314,7 +1552,47 @@ struct iwl_priv { bool have_rekey_data; }; /*iwl_priv */ -extern struct iwl_mod_params iwlagn_mod_params; +static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) +{ + set_bit(txq_id, &priv->txq_ctx_active_msk); +} + +static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) +{ + clear_bit(txq_id, &priv->txq_ctx_active_msk); +} + +#ifdef CONFIG_IWLWIFI_DEBUG +/* + * iwl_get_debug_level: Return active debug level for device + * + * Using sysfs it is possible to set per device debug level. This debug + * level will be used if set, otherwise the global debug level which can be + * set via module parameter is used. + */ +static inline u32 iwl_get_debug_level(struct iwl_priv *priv) +{ + if (priv->debug_level) + return priv->debug_level; + else + return iwl_debug_level; +} +#else +static inline u32 iwl_get_debug_level(struct iwl_priv *priv) +{ + return iwl_debug_level; +} +#endif + + +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) + return (struct ieee80211_hdr *)priv->txq[txq_id]. + txb[idx].skb->data; + return NULL; +} static inline struct iwl_rxon_context * iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) @@ -1381,4 +1659,13 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; } +static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) +{ + __free_pages(page, priv->hw_params.rx_page_order); +} + +static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) +{ + free_pages(page, priv->hw_params.rx_page_order); +} #endif /* __iwl_dev_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 8a51c5ccda1e..2c84ba95afca 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -29,8 +29,6 @@ #include -struct iwl_priv; - #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) #undef TRACE_EVENT #define TRACE_EVENT(name, proto, ...) \ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 80ee65be9cd1..19d31a5e32e5 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -155,11 +155,11 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { /* Request semaphore */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); /* See if we got it */ - ret = iwl_poll_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, EEPROM_SEM_TIMEOUT); @@ -176,14 +176,14 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) static void iwl_eeprom_release_semaphore(struct iwl_priv *priv) { - iwl_clear_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); } static int iwl_eeprom_verify_signature(struct iwl_priv *priv) { - u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; + u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; int ret = 0; IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp); @@ -216,17 +216,17 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv) static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) { - iwl_read32(bus(priv), CSR_OTP_GP_REG); + iwl_read32(priv, CSR_OTP_GP_REG); if (mode == IWL_OTP_ACCESS_ABSOLUTE) - iwl_clear_bit(bus(priv), CSR_OTP_GP_REG, + iwl_clear_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); else - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); } -static int iwl_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) +static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) { u32 otpgp; int nvm_type; @@ -243,7 +243,7 @@ static int iwl_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) nvm_type = NVM_DEVICE_TYPE_EEPROM; break; default: - otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG); + otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) nvm_type = NVM_DEVICE_TYPE_OTP; else @@ -258,22 +258,22 @@ static int iwl_init_otp_access(struct iwl_priv *priv) int ret; /* Enable 40MHz radio clock */ - iwl_write32(bus(priv), CSR_GP_CNTRL, - iwl_read32(bus(priv), CSR_GP_CNTRL) | + iwl_write32(priv, CSR_GP_CNTRL, + iwl_read32(priv, CSR_GP_CNTRL) | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* wait for clock to be ready */ - ret = iwl_poll_bit(bus(priv), CSR_GP_CNTRL, + ret = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (ret < 0) IWL_ERR(priv, "Time out access OTP\n"); else { - iwl_set_bits_prph(bus(priv), APMG_PS_CTRL_REG, + iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); udelay(5); - iwl_clear_bits_prph(bus(priv), APMG_PS_CTRL_REG, + iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); /* @@ -281,7 +281,7 @@ static int iwl_init_otp_access(struct iwl_priv *priv) * this is only applicable for HW with OTP shadow RAM */ if (priv->cfg->base_params->shadow_ram_support) - iwl_set_bit(bus(priv), CSR_DBG_LINK_PWR_MGMT_REG, + iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG, CSR_RESET_LINK_PWR_MGMT_DISABLED); } return ret; @@ -293,9 +293,9 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat u32 r; u32 otpgp; - iwl_write32(bus(priv), CSR_EEPROM_REG, + iwl_write32(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG, + ret = iwl_poll_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -303,13 +303,13 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); return ret; } - r = iwl_read32(bus(priv), CSR_EEPROM_REG); + r = iwl_read32(priv, CSR_EEPROM_REG); /* check for ECC errors: */ - otpgp = iwl_read32(bus(priv), CSR_OTP_GP_REG); + otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { /* stop in this case */ /* set the uncorrectable OTP ECC bit for acknowledgement */ - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n"); return -EINVAL; @@ -317,7 +317,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { /* continue in this case */ /* set the correctable OTP ECC bit for acknowledgement */ - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); } @@ -424,14 +424,14 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) { __le16 *e; - u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP); + u32 gp = iwl_read32(priv, CSR_EEPROM_GP); int sz; int ret; u16 addr; u16 validblockaddr = 0; u16 cache_addr = 0; - priv->nvm_device_type = iwl_get_nvm_type(priv, hw_rev); + priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev); if (priv->nvm_device_type == -ENOENT) return -ENOENT; /* allocate eeprom */ @@ -469,11 +469,11 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) ret = -ENOENT; goto done; } - iwl_write32(bus(priv), CSR_EEPROM_GP, - iwl_read32(bus(priv), CSR_EEPROM_GP) & + iwl_write32(priv, CSR_EEPROM_GP, + iwl_read32(priv, CSR_EEPROM_GP) & ~CSR_EEPROM_GP_IF_OWNER_MSK); - iwl_set_bit(bus(priv), CSR_OTP_GP_REG, + iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); /* traversing the linked list if no shadow ram supported */ @@ -498,10 +498,10 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - iwl_write32(bus(priv), CSR_EEPROM_REG, + iwl_write32(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bit(bus(priv), CSR_EEPROM_REG, + ret = iwl_poll_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -509,7 +509,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } - r = iwl_read32(bus(priv), CSR_EEPROM_REG); + r = iwl_read32(priv, CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } @@ -838,7 +838,7 @@ void iwl_rf_config(struct iwl_priv *priv) /* write radio config values to register */ if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); @@ -850,7 +850,7 @@ void iwl_rf_config(struct iwl_priv *priv) WARN_ON(1); /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(bus(priv), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h index e2b5e0ea5d9c..e4bf8ac5e64e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -301,6 +301,7 @@ void iwl_eeprom_free(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv); int iwl_eeprom_check_sku(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); +int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); int iwl_init_channel_map(struct iwl_priv *priv); void iwl_free_channel_map(struct iwl_priv *priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h index 5bede9d7f955..0ad60b3c04db 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -63,8 +63,6 @@ #ifndef __iwl_fh_h__ #define __iwl_fh_h__ -#include - /****************************/ /* Flow Handler Definitions */ /****************************/ @@ -268,6 +266,8 @@ #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) #define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) +#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ + /** * Rx Shared Status Registers (RSSR) * @@ -422,6 +422,10 @@ #define RX_FREE_BUFFERS 64 #define RX_LOW_WATERMARK 8 +/* Size of one Rx buffer in host DRAM */ +#define IWL_RX_BUF_SIZE_4K (4 * 1024) +#define IWL_RX_BUF_SIZE_8K (8 * 1024) + /** * struct iwl_rb_status - reseve buffer status * host memory mapped FH registers @@ -504,16 +508,4 @@ struct iwl_tfd { /* Keep Warm Size */ #define IWL_KW_SIZE 0x1000 /* 4k */ -/* Fixed (non-configurable) rx data from phy */ - -/** - * struct iwlagn_schedq_bc_tbl scheduler byte count table - * base physical address provided by SCD_DRAM_BASE_ADDR - * @tfd_offset 0-12 - tx command byte count - * 12-16 - station index - */ -struct iwlagn_scd_bc_tbl { - __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; -} __packed; - #endif /* !__iwl_fh_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h b/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h index d3feac9e45b4..9d91552d13c1 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -64,10 +64,99 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) return --index & (n_bd - 1); } +/* + * we have 8 bits used like this: + * + * 7 6 5 4 3 2 1 0 + * | | | | | | | | + * | | | | | | +-+-------- AC queue (0-3) + * | | | | | | + * | +-+-+-+-+------------ HW queue ID + * | + * +---------------------- unused + */ +static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) +{ + BUG_ON(ac > 3); /* only have 2 bits */ + BUG_ON(hwq > 31); /* only use 5 bits */ + + txq->swq_id = (hwq << 2) | ac; +} + +static inline void iwl_wake_queue(struct iwl_priv *priv, + struct iwl_tx_queue *txq) +{ + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; + + if (test_and_clear_bit(hwq, priv->queue_stopped)) + if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) + ieee80211_wake_queue(priv->hw, ac); +} + +static inline void iwl_stop_queue(struct iwl_priv *priv, + struct iwl_tx_queue *txq) +{ + u8 queue = txq->swq_id; + u8 ac = queue & 3; + u8 hwq = (queue >> 2) & 0x1f; + + if (!test_and_set_bit(hwq, priv->queue_stopped)) + if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) + ieee80211_stop_queue(priv->hw, ac); +} + +static inline void iwl_wake_any_queue(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + u8 ac; + + for (ac = 0; ac < AC_NUM; ac++) { + IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n", + ac, (atomic_read(&priv->queue_stop_count[ac]) > 0) + ? "stopped" : "awake"); + iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]); + } +} + +#ifdef ieee80211_stop_queue +#undef ieee80211_stop_queue +#endif + +#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue + +#ifdef ieee80211_wake_queue +#undef ieee80211_wake_queue +#endif + +#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue + +static inline void iwl_disable_interrupts(struct iwl_priv *priv) +{ + clear_bit(STATUS_INT_ENABLED, &priv->status); + + /* disable interrupts from uCode/NIC to host */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); + + /* acknowledge/clear/reset any interrupts still pending + * from uCode or flow handler (Rx/Tx DMA) */ + iwl_write32(priv, CSR_INT, 0xffffffff); + iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); + IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); +} + static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) { IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); - iwl_write32(bus(priv), CSR_INT_MASK, CSR_INT_BIT_RF_KILL); + iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); +} + +static inline void iwl_enable_interrupts(struct iwl_priv *priv) +{ + IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); + set_bit(STATUS_INT_ENABLED, &priv->status); + iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); } /** diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-io.c b/trunk/drivers/net/wireless/iwlwifi/iwl-io.c index 3ffa8e62b856..aa4a90674452 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-io.c @@ -25,50 +25,46 @@ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * *****************************************************************************/ -#include -#include #include "iwl-io.h" -#include"iwl-csr.h" -#include "iwl-debug.h" #define IWL_POLL_INTERVAL 10 /* microseconds */ -static inline void __iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) +static inline void __iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) { - iwl_write32(bus, reg, iwl_read32(bus, reg) | mask); + iwl_write32(priv, reg, iwl_read32(priv, reg) | mask); } -static inline void __iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) +static inline void __iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) { - iwl_write32(bus, reg, iwl_read32(bus, reg) & ~mask); + iwl_write32(priv, reg, iwl_read32(priv, reg) & ~mask); } -void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - __iwl_set_bit(bus, reg, mask); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + __iwl_set_bit(priv, reg, mask); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - __iwl_clear_bit(bus, reg, mask); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + __iwl_clear_bit(priv, reg, mask); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -int iwl_poll_bit(struct iwl_bus *bus, u32 addr, +int iwl_poll_bit(struct iwl_priv *priv, u32 addr, u32 bits, u32 mask, int timeout) { int t = 0; do { - if ((iwl_read32(bus, addr) & mask) == (bits & mask)) + if ((iwl_read32(priv, addr) & mask) == (bits & mask)) return t; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -77,14 +73,14 @@ int iwl_poll_bit(struct iwl_bus *bus, u32 addr, return -ETIMEDOUT; } -int iwl_grab_nic_access_silent(struct iwl_bus *bus) +int iwl_grab_nic_access_silent(struct iwl_priv *priv) { int ret; - lockdep_assert_held(&bus->reg_lock); + lockdep_assert_held(&priv->reg_lock); /* this bit wakes up the NIC */ - __iwl_set_bit(bus, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + __iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* * These bits say the device is running, and should keep running for @@ -105,70 +101,70 @@ int iwl_grab_nic_access_silent(struct iwl_bus *bus) * 5000 series and later (including 1000 series) have non-volatile SRAM, * and do not save/restore SRAM when power cycling. */ - ret = iwl_poll_bit(bus, CSR_GP_CNTRL, + ret = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); if (ret < 0) { - iwl_write32(bus, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); return -EIO; } return 0; } -int iwl_grab_nic_access(struct iwl_bus *bus) +int iwl_grab_nic_access(struct iwl_priv *priv) { - int ret = iwl_grab_nic_access_silent(bus); + int ret = iwl_grab_nic_access_silent(priv); if (ret) { - u32 val = iwl_read32(bus, CSR_GP_CNTRL); - IWL_ERR(bus, + u32 val = iwl_read32(priv, CSR_GP_CNTRL); + IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); } return ret; } -void iwl_release_nic_access(struct iwl_bus *bus) +void iwl_release_nic_access(struct iwl_priv *priv) { - lockdep_assert_held(&bus->reg_lock); - __iwl_clear_bit(bus, CSR_GP_CNTRL, + lockdep_assert_held(&priv->reg_lock); + __iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } -u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg) +u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) { u32 value; unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - value = iwl_read32(bus(bus), reg); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + value = iwl_read32(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); return value; } -void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value) +void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - iwl_write32(bus, reg, value); - iwl_release_nic_access(bus); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + iwl_write32(priv, reg, value); + iwl_release_nic_access(priv); } - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, +int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int timeout) { int t = 0; do { - if ((iwl_read_direct32(bus, addr) & mask) == mask) + if ((iwl_read_direct32(priv, addr) & mask) == mask) return t; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -177,122 +173,122 @@ int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, return -ETIMEDOUT; } -static inline u32 __iwl_read_prph(struct iwl_bus *bus, u32 reg) +static inline u32 __iwl_read_prph(struct iwl_priv *priv, u32 reg) { - iwl_write32(bus, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); + iwl_write32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); rmb(); - return iwl_read32(bus, HBUS_TARG_PRPH_RDAT); + return iwl_read32(priv, HBUS_TARG_PRPH_RDAT); } -static inline void __iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) +static inline void __iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) { - iwl_write32(bus, HBUS_TARG_PRPH_WADDR, + iwl_write32(priv, HBUS_TARG_PRPH_WADDR, ((addr & 0x0000FFFF) | (3 << 24))); wmb(); - iwl_write32(bus, HBUS_TARG_PRPH_WDAT, val); + iwl_write32(priv, HBUS_TARG_PRPH_WDAT, val); } -u32 iwl_read_prph(struct iwl_bus *bus, u32 reg) +u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) { unsigned long flags; u32 val; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - val = __iwl_read_prph(bus, reg); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + val = __iwl_read_prph(priv, reg); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); return val; } -void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val) +void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - __iwl_write_prph(bus, addr, val); - iwl_release_nic_access(bus); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + __iwl_write_prph(priv, addr, val); + iwl_release_nic_access(priv); } - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - __iwl_write_prph(bus, reg, __iwl_read_prph(bus, reg) | mask); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + __iwl_write_prph(priv, reg, __iwl_read_prph(priv, reg) | mask); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, +void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - __iwl_write_prph(bus, reg, - (__iwl_read_prph(bus, reg) & mask) | bits); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + __iwl_write_prph(priv, reg, + (__iwl_read_prph(priv, reg) & mask) | bits); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask) +void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) { unsigned long flags; u32 val; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); - val = __iwl_read_prph(bus, reg); - __iwl_write_prph(bus, reg, (val & ~mask)); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); + val = __iwl_read_prph(priv, reg); + __iwl_write_prph(priv, reg, (val & ~mask)); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, +void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, void *buf, int words) { unsigned long flags; int offs; u32 *vals = buf; - spin_lock_irqsave(&bus->reg_lock, flags); - iwl_grab_nic_access(bus); + spin_lock_irqsave(&priv->reg_lock, flags); + iwl_grab_nic_access(priv); - iwl_write32(bus, HBUS_TARG_MEM_RADDR, addr); + iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); rmb(); for (offs = 0; offs < words; offs++) - vals[offs] = iwl_read32(bus, HBUS_TARG_MEM_RDAT); + vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT); - iwl_release_nic_access(bus); - spin_unlock_irqrestore(&bus->reg_lock, flags); + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, flags); } -u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr) +u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) { u32 value; - _iwl_read_targ_mem_words(bus, addr, &value, 1); + _iwl_read_targ_mem_words(priv, addr, &value, 1); return value; } -void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val) +void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) { unsigned long flags; - spin_lock_irqsave(&bus->reg_lock, flags); - if (!iwl_grab_nic_access(bus)) { - iwl_write32(bus, HBUS_TARG_MEM_WADDR, addr); + spin_lock_irqsave(&priv->reg_lock, flags); + if (!iwl_grab_nic_access(priv)) { + iwl_write32(priv, HBUS_TARG_MEM_WADDR, addr); wmb(); - iwl_write32(bus, HBUS_TARG_MEM_WDAT, val); - iwl_release_nic_access(bus); + iwl_write32(priv, HBUS_TARG_MEM_WDAT, val); + iwl_release_nic_access(priv); } - spin_unlock_irqrestore(&bus->reg_lock, flags); + spin_unlock_irqrestore(&priv->reg_lock, flags); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-io.h b/trunk/drivers/net/wireless/iwlwifi/iwl-io.h index ced2cbeb6eae..19a093101122 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-io.h @@ -29,62 +29,65 @@ #ifndef __iwl_io_h__ #define __iwl_io_h__ +#include + +#include "iwl-dev.h" +#include "iwl-debug.h" #include "iwl-devtrace.h" -#include "iwl-shared.h" #include "iwl-bus.h" -static inline void iwl_write8(struct iwl_bus *bus, u32 ofs, u8 val) +static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) { - trace_iwlwifi_dev_iowrite8(priv(bus), ofs, val); - bus_write8(bus, ofs, val); + trace_iwlwifi_dev_iowrite8(priv, ofs, val); + bus_write8(priv->bus, ofs, val); } -static inline void iwl_write32(struct iwl_bus *bus, u32 ofs, u32 val) +static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) { - trace_iwlwifi_dev_iowrite32(priv(bus), ofs, val); - bus_write32(bus, ofs, val); + trace_iwlwifi_dev_iowrite32(priv, ofs, val); + bus_write32(priv->bus, ofs, val); } -static inline u32 iwl_read32(struct iwl_bus *bus, u32 ofs) +static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs) { - u32 val = bus_read32(bus, ofs); - trace_iwlwifi_dev_ioread32(priv(bus), ofs, val); + u32 val = bus_read32(priv->bus, ofs); + trace_iwlwifi_dev_ioread32(priv, ofs, val); return val; } -void iwl_set_bit(struct iwl_bus *bus, u32 reg, u32 mask); -void iwl_clear_bit(struct iwl_bus *bus, u32 reg, u32 mask); +void iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask); +void iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask); -int iwl_poll_bit(struct iwl_bus *bus, u32 addr, +int iwl_poll_bit(struct iwl_priv *priv, u32 addr, u32 bits, u32 mask, int timeout); -int iwl_poll_direct_bit(struct iwl_bus *bus, u32 addr, u32 mask, +int iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int timeout); -int iwl_grab_nic_access_silent(struct iwl_bus *bus); -int iwl_grab_nic_access(struct iwl_bus *bus); -void iwl_release_nic_access(struct iwl_bus *bus); +int iwl_grab_nic_access_silent(struct iwl_priv *priv); +int iwl_grab_nic_access(struct iwl_priv *priv); +void iwl_release_nic_access(struct iwl_priv *priv); -u32 iwl_read_direct32(struct iwl_bus *bus, u32 reg); -void iwl_write_direct32(struct iwl_bus *bus, u32 reg, u32 value); +u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg); +void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value); -u32 iwl_read_prph(struct iwl_bus *bus, u32 reg); -void iwl_write_prph(struct iwl_bus *bus, u32 addr, u32 val); -void iwl_set_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); -void iwl_set_bits_mask_prph(struct iwl_bus *bus, u32 reg, +u32 iwl_read_prph(struct iwl_priv *priv, u32 reg); +void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val); +void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); +void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, u32 bits, u32 mask); -void iwl_clear_bits_prph(struct iwl_bus *bus, u32 reg, u32 mask); +void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); -void _iwl_read_targ_mem_words(struct iwl_bus *bus, u32 addr, +void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr, void *buf, int words); -#define iwl_read_targ_mem_words(bus, addr, buf, bufsize) \ +#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \ do { \ BUILD_BUG_ON((bufsize) % sizeof(u32)); \ - _iwl_read_targ_mem_words(bus, addr, buf, \ + _iwl_read_targ_mem_words(priv, addr, buf, \ (bufsize) / sizeof(u32));\ } while (0) -u32 iwl_read_targ_mem(struct iwl_bus *bus, u32 addr); -void iwl_write_targ_mem(struct iwl_bus *bus, u32 addr, u32 val); +u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); +void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); #endif diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c index 7dffed186f0a..1a5252d8ca73 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-led.c @@ -40,7 +40,6 @@ #include "iwl-agn.h" #include "iwl-io.h" #include "iwl-trans.h" -#include "iwl-shared.h" /* Throughput OFF time(ms) ON time (ms) * >300 25 25 @@ -71,7 +70,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { /* Set led register off */ void iwlagn_led_enable(struct iwl_priv *priv) { - iwl_write32(bus(priv), CSR_LED_REG, CSR_LED_REG_TRUN_ON); + iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); } /* @@ -108,11 +107,11 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) }; u32 reg; - reg = iwl_read32(bus(priv), CSR_LED_REG); + reg = iwl_read32(priv, CSR_LED_REG); if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl_write32(bus(priv), CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } /* Set led pattern command */ @@ -126,7 +125,7 @@ static int iwl_led_cmd(struct iwl_priv *priv, }; int ret; - if (!test_bit(STATUS_READY, &priv->shrd->status)) + if (!test_bit(STATUS_READY, &priv->status)) return -EBUSY; if (priv->blink_on == on && priv->blink_off == off) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-pci.c b/trunk/drivers/net/wireless/iwlwifi/iwl-pci.c index e41f53e5c307..69d4ec467dca 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -64,11 +64,9 @@ #include #include "iwl-bus.h" +#include "iwl-agn.h" +#include "iwl-core.h" #include "iwl-io.h" -#include "iwl-shared.h" -#include "iwl-trans.h" -#include "iwl-csr.h" -#include "iwl-pci.h" /* PCI registers */ #define PCI_CFG_RETRY_TIMEOUT 0x041 @@ -93,7 +91,6 @@ static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus) { int pos; u16 pci_lnk_ctl; - struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); pos = pci_pcie_cap(pci_dev); @@ -123,21 +120,21 @@ static void iwl_pci_apm_config(struct iwl_bus *bus) if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) { /* L1-ASPM enabled; disable(!) L0S */ - iwl_set_bit(bus, CSR_GIO_REG, + iwl_set_bit(bus->drv_data, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Enabled; Disabling L0S\n"); } else { /* L1-ASPM disabled; enable(!) L0S */ - iwl_clear_bit(bus, CSR_GIO_REG, + iwl_clear_bit(bus->drv_data, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); dev_printk(KERN_INFO, bus->dev, "L1 Disabled; Enabling L0S\n"); } } -static void iwl_pci_set_drv_data(struct iwl_bus *bus, struct iwl_shared *shrd) +static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_data) { - bus->shrd = shrd; - pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), shrd); + bus->drv_data = drv_data; + pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_data); } static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], @@ -165,7 +162,7 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) return val; } -static const struct iwl_bus_ops bus_ops_pci = { +static struct iwl_bus_ops pci_ops = { .get_pm_support = iwl_pci_is_pm_supported, .apm_config = iwl_pci_apm_config, .set_drv_data = iwl_pci_set_drv_data, @@ -259,7 +256,6 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, - {IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)}, /* 6x30 Series */ {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, @@ -332,7 +328,6 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)}, {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)}, - {IWL_PCI_DEVICE(0x0890, 0x4822, iwl2000_2bgn_d_cfg)}, /* 2x30 Series */ {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)}, @@ -462,9 +457,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bus->dev = &pdev->dev; bus->irq = pdev->irq; - bus->ops = &bus_ops_pci; + bus->ops = &pci_ops; - err = iwl_probe(bus, &trans_ops_pcie, cfg); + err = iwl_probe(bus, cfg); if (err) goto out_disable_msi; return 0; @@ -498,33 +493,33 @@ static void iwl_pci_down(struct iwl_bus *bus) static void __devexit iwl_pci_remove(struct pci_dev *pdev) { - struct iwl_shared *shrd = pci_get_drvdata(pdev); - struct iwl_bus *bus = shrd->bus; + struct iwl_priv *priv = pci_get_drvdata(pdev); + void *bus_specific = priv->bus->bus_specific; - iwl_remove(shrd->priv); + iwl_remove(priv); - iwl_pci_down(bus); + iwl_pci_down(bus_specific); } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int iwl_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_shared *shrd = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if * WoWLAN is enabled - don't kill the NIC, someone may need it in Sx. */ - return iwl_trans_suspend(shrd->trans); + return iwl_suspend(priv); } static int iwl_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); - struct iwl_shared *shrd = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); /* Before you put code here, think about WoWLAN. You cannot check here * whether WoWLAN is enabled or not, and your code will run even if @@ -537,7 +532,7 @@ static int iwl_pci_resume(struct device *device) */ pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - return iwl_trans_resume(shrd->trans); + return iwl_resume(priv); } static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-pci.h b/trunk/drivers/net/wireless/iwlwifi/iwl-pci.h deleted file mode 100644 index c0aea9e092cb..000000000000 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-pci.h +++ /dev/null @@ -1,116 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __iwl_pci_h__ -#define __iwl_pci_h__ - - -/* This file includes the declaration that are internal to the PCI - * implementation of the bus layer - */ - -/* configuration for the _agn devices */ -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 iwl6005_2agn_cfg; -extern struct iwl_cfg iwl6005_2abg_cfg; -extern struct iwl_cfg iwl6005_2bg_cfg; -extern struct iwl_cfg iwl6005_2agn_sff_cfg; -extern struct iwl_cfg iwl1030_bgn_cfg; -extern struct iwl_cfg iwl1030_bg_cfg; -extern struct iwl_cfg iwl6030_2agn_cfg; -extern struct iwl_cfg iwl6030_2abg_cfg; -extern struct iwl_cfg iwl6030_2bgn_cfg; -extern struct iwl_cfg iwl6030_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 iwl6150_bgn_cfg; -extern struct iwl_cfg iwl6150_bg_cfg; -extern struct iwl_cfg iwl1000_bgn_cfg; -extern struct iwl_cfg iwl1000_bg_cfg; -extern struct iwl_cfg iwl100_bgn_cfg; -extern struct iwl_cfg iwl100_bg_cfg; -extern struct iwl_cfg iwl130_bgn_cfg; -extern struct iwl_cfg iwl130_bg_cfg; -extern struct iwl_cfg iwl2000_2bgn_cfg; -extern struct iwl_cfg iwl2000_2bg_cfg; -extern struct iwl_cfg iwl2000_2bgn_d_cfg; -extern struct iwl_cfg iwl2030_2bgn_cfg; -extern struct iwl_cfg iwl2030_2bg_cfg; -extern struct iwl_cfg iwl6035_2agn_cfg; -extern struct iwl_cfg iwl6035_2abg_cfg; -extern struct iwl_cfg iwl6035_2bg_cfg; -extern struct iwl_cfg iwl105_bg_cfg; -extern struct iwl_cfg iwl105_bgn_cfg; -extern struct iwl_cfg iwl135_bg_cfg; -extern struct iwl_cfg iwl135_bgn_cfg; - -#endif /* __iwl_pci_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-power.c b/trunk/drivers/net/wireless/iwlwifi/iwl-power.c index 62cd781192b0..cd64df05f9ed 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-power.c @@ -43,7 +43,6 @@ #include "iwl-debug.h" #include "iwl-power.h" #include "iwl-trans.h" -#include "iwl-shared.h" /* * Setting power level allows the card to go to sleep when not busy. @@ -215,7 +214,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, else cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; - if (hw_params(priv).shadow_reg_enable) + if (priv->cfg->base_params->shadow_reg_enable) cmd->flags |= IWL_POWER_SHADOW_REG_ENA; else cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; @@ -301,7 +300,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, if (priv->power_data.bus_pm) cmd->flags |= IWL_POWER_PCI_PM_MSK; - if (hw_params(priv).shadow_reg_enable) + if (priv->cfg->base_params->shadow_reg_enable) cmd->flags |= IWL_POWER_SHADOW_REG_ENA; else cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; @@ -336,7 +335,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); - return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC, + return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC, sizeof(struct iwl_powertable_cmd), cmd); } @@ -348,7 +347,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, dtimper = priv->hw->conf.ps_dtim_period ?: 1; - if (priv->shrd->wowlan) + if (priv->wowlan) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); else if (!priv->cfg->base_params->no_idle_support && priv->hw->conf.flags & IEEE80211_CONF_IDLE) @@ -383,7 +382,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, int ret; bool update_chains; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* Don't update the RX chain when chain noise calibration is running */ update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || @@ -392,23 +391,23 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force) return 0; - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) return -EIO; /* scan complete use sleep_power_next, need to be updated */ memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd)); - if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) { + if (test_bit(STATUS_SCANNING, &priv->status) && !force) { IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n"); return 0; } if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) - set_bit(STATUS_POWER_PMI, &priv->shrd->status); + set_bit(STATUS_POWER_PMI, &priv->status); ret = iwl_set_power(priv, cmd); if (!ret) { if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) - clear_bit(STATUS_POWER_PMI, &priv->shrd->status); + clear_bit(STATUS_POWER_PMI, &priv->status); if (update_chains) iwl_update_chain_flags(priv); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h index bebdd828f324..2f267b8aabbb 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -217,8 +217,8 @@ ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) #define SCD_QUEUECHAIN_SEL_ALL(priv) \ - (((1<shrd->cmd_queue))) + (((1<<(priv)->hw_params.max_txq_num) - 1) &\ + (~(1<<(priv)->cmd_queue))) #define SCD_BASE (PRPH_BASE + 0xa02c00) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c index 8572548dd4a2..8e314003b63a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -40,7 +40,6 @@ #include "iwl-helpers.h" #include "iwl-agn-calib.h" #include "iwl-agn.h" -#include "iwl-shared.h" /****************************************************************************** @@ -74,7 +73,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_cmd *rxon = (void *)&ctx->active; - if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) + if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) return; if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { @@ -122,8 +121,7 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - u32 __maybe_unused len = - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " "notification for %s:\n", len, get_cmd_string(pkt->hdr.cmd)); @@ -150,8 +148,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); - if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) - queue_work(priv->shrd->workqueue, &priv->beacon_update); + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + queue_work(priv->workqueue, &priv->beacon_update); } /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ @@ -260,7 +258,7 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv, { unsigned int msecs; - if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); @@ -476,7 +474,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv, priv->rx_statistics_jiffies = stamp; - set_bit(STATUS_STATISTICS, &priv->shrd->status); + set_bit(STATUS_STATISTICS, &priv->status); /* Reschedule the statistics timer to occur in * reg_recalib_period seconds to ensure we get a @@ -485,10 +483,10 @@ static void iwl_rx_statistics(struct iwl_priv *priv, mod_timer(&priv->statistics_periodic, jiffies + msecs_to_jiffies(reg_recalib_period * 1000)); - if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) && + if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { iwl_rx_calc_noise(priv); - queue_work(priv->shrd->workqueue, &priv->run_time_calib_work); + queue_work(priv->workqueue, &priv->run_time_calib_work); } if (priv->cfg->lib->temperature && change) priv->cfg->lib->temperature(priv); @@ -520,7 +518,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, { struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); - unsigned long status = priv->shrd->status; + unsigned long status = priv->status; IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", (flags & HW_CARD_DISABLED) ? "Kill" : "On", @@ -531,16 +529,16 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | CT_CARD_DISABLED)) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, + iwl_write_direct32(priv, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); if (!(flags & RXON_CARD_DISABLED)) { - iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(bus(priv), HBUS_TARG_MBX_C, + iwl_write_direct32(priv, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); } if (flags & CT_CARD_DISABLED) @@ -550,18 +548,18 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, iwl_tt_exit_ct_kill(priv); if (flags & HW_CARD_DISABLED) - set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); else - clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); + clear_bit(STATUS_RF_KILL_HW, &priv->status); if (!(flags & RXON_CARD_DISABLED)) iwl_scan_cancel(priv); if ((test_bit(STATUS_RF_KILL_HW, &status) != - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status))) + test_bit(STATUS_RF_KILL_HW, &priv->status))) wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)); + test_bit(STATUS_RF_KILL_HW, &priv->status)); else wake_up_interruptible(&priv->wait_command_queue); } @@ -582,7 +580,7 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, le32_to_cpu(missed_beacon->total_missed_becons), le32_to_cpu(missed_beacon->num_recvd_beacons), le32_to_cpu(missed_beacon->num_expected_beacons)); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) + if (!test_bit(STATUS_SCANNING, &priv->status)) iwl_init_sensitivity(priv); } } @@ -699,7 +697,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, ctx->active.bssid_addr)) continue; ctx->last_tx_rejected = false; - iwl_trans_wake_any_queue(trans(priv), ctx->ctxid); + iwl_wake_any_queue(priv, ctx); } } @@ -1020,7 +1018,7 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) * handle those that need handling via function in * rx_handlers table. See iwl_setup_rx_handlers() */ if (priv->rx_handlers[pkt->hdr.cmd]) { - priv->rx_handlers_stats[pkt->hdr.cmd]++; + priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); } else { /* No handling needed */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c index fc5af3475392..28e59319f581 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -68,14 +68,14 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) /* Exit instantly with error when device is not ready * to receive scan abort command or it does not perform * hardware scan currently */ - if (!test_bit(STATUS_READY, &priv->shrd->status) || - !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) || - !test_bit(STATUS_SCAN_HW, &priv->shrd->status) || - test_bit(STATUS_FW_ERROR, &priv->shrd->status) || - test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) + if (!test_bit(STATUS_READY, &priv->status) || + !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || + !test_bit(STATUS_SCAN_HW, &priv->status) || + test_bit(STATUS_FW_ERROR, &priv->status) || + test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EIO; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) return ret; @@ -91,7 +91,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) ret = -EIO; } - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_pages(priv, cmd.reply_page); return ret; } @@ -116,17 +116,17 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) void iwl_force_scan_end(struct iwl_priv *priv) { - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n"); return; } IWL_DEBUG_SCAN(priv, "Forcing scan end\n"); - clear_bit(STATUS_SCANNING, &priv->shrd->status); - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); - clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); + clear_bit(STATUS_SCANNING, &priv->status); + clear_bit(STATUS_SCAN_HW, &priv->status); + clear_bit(STATUS_SCAN_ABORTING, &priv->status); iwl_complete_scan(priv, true); } @@ -134,14 +134,14 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); - if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n"); return; } - if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) { + if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan abort in progress\n"); return; } @@ -160,7 +160,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv) int iwl_scan_cancel(struct iwl_priv *priv) { IWL_DEBUG_SCAN(priv, "Queuing abort scan\n"); - queue_work(priv->shrd->workqueue, &priv->abort_scan); + queue_work(priv->workqueue, &priv->abort_scan); return 0; } @@ -173,19 +173,19 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) { unsigned long timeout = jiffies + msecs_to_jiffies(ms); - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n"); iwl_do_scan_abort(priv); while (time_before_eq(jiffies, timeout)) { - if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status)) + if (!test_bit(STATUS_SCAN_HW, &priv->status)) break; msleep(20); } - return test_bit(STATUS_SCAN_HW, &priv->shrd->status); + return test_bit(STATUS_SCAN_HW, &priv->status); } /* Service response to REPLY_SCAN_CMD (0x80) */ @@ -257,13 +257,13 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, scan_notif->tsf_high, scan_notif->status); /* The HW is no longer scanning */ - clear_bit(STATUS_SCAN_HW, &priv->shrd->status); + clear_bit(STATUS_SCAN_HW, &priv->status); IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n", (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", jiffies_to_msecs(jiffies - priv->scan_start)); - queue_work(priv->shrd->workqueue, &priv->scan_completed); + queue_work(priv->workqueue, &priv->scan_completed); if (priv->iw_mode != NL80211_IFTYPE_ADHOC && iwl_advanced_bt_coexist(priv) && @@ -283,8 +283,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, IWL_BT_COEX_TRAFFIC_LOAD_NONE; } priv->bt_status = scan_notif->bt_status; - queue_work(priv->shrd->workqueue, - &priv->bt_traffic_change_work); + queue_work(priv->workqueue, &priv->bt_traffic_change_work); } } @@ -344,7 +343,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, void iwl_init_scan_params(struct iwl_priv *priv) { - u8 ant_idx = fls(hw_params(priv).valid_tx_ant) - 1; + u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) @@ -358,22 +357,22 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, { int ret; - lockdep_assert_held(&priv->shrd->mutex); + lockdep_assert_held(&priv->mutex); cancel_delayed_work(&priv->scan_check); - if (!iwl_is_ready_rf(priv->shrd)) { + if (!iwl_is_ready_rf(priv)) { IWL_WARN(priv, "Request scan called when driver not ready.\n"); return -EIO; } - if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_HW, &priv->status)) { IWL_DEBUG_SCAN(priv, "Multiple concurrent scan requests in parallel.\n"); return -EBUSY; } - if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) { + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n"); return -EBUSY; } @@ -383,19 +382,19 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, scan_type == IWL_SCAN_ROC ? "remain-on-channel " : "internal short "); - set_bit(STATUS_SCANNING, &priv->shrd->status); + set_bit(STATUS_SCANNING, &priv->status); priv->scan_type = scan_type; priv->scan_start = jiffies; priv->scan_band = band; ret = iwlagn_request_scan(priv, vif); if (ret) { - clear_bit(STATUS_SCANNING, &priv->shrd->status); + clear_bit(STATUS_SCANNING, &priv->status); priv->scan_type = IWL_SCAN_NORMAL; return ret; } - queue_delayed_work(priv->shrd->workqueue, &priv->scan_check, + queue_delayed_work(priv->workqueue, &priv->scan_check, IWL_SCAN_CHECK_WATCHDOG); return 0; @@ -413,9 +412,9 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, if (req->n_channels == 0) return -EINVAL; - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->shrd->status) && + if (test_bit(STATUS_SCANNING, &priv->status) && priv->scan_type != IWL_SCAN_NORMAL) { IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); ret = -EAGAIN; @@ -440,7 +439,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "leave\n"); out_unlock: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -451,7 +450,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, */ void iwl_internal_short_hw_scan(struct iwl_priv *priv) { - queue_work(priv->shrd->workqueue, &priv->start_internal_scan); + queue_work(priv->workqueue, &priv->start_internal_scan); } static void iwl_bg_start_internal_scan(struct work_struct *work) @@ -461,14 +460,14 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) IWL_DEBUG_SCAN(priv, "Start internal scan\n"); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); if (priv->scan_type == IWL_SCAN_RADIO_RESET) { IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); goto unlock; } - if (test_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (test_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); goto unlock; } @@ -476,7 +475,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band)) IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); unlock: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_scan_check(struct work_struct *data) @@ -489,9 +488,9 @@ static void iwl_bg_scan_check(struct work_struct *data) /* Since we are here firmware does not finish scan and * most likely is in bad shape, so we don't bother to * send abort command, just force scan complete to mac80211 */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_force_scan_end(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } /** @@ -549,9 +548,9 @@ static void iwl_bg_abort_scan(struct work_struct *work) /* We keep scan_check work queued in case when firmware will not * report back scan completed notification */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 200); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } static void iwl_bg_scan_completed(struct work_struct *work) @@ -564,13 +563,13 @@ static void iwl_bg_scan_completed(struct work_struct *work) cancel_delayed_work(&priv->scan_check); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); - aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); + aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status); if (aborted) IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); - if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { + if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) { IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); goto out_settings; } @@ -606,13 +605,13 @@ static void iwl_bg_scan_completed(struct work_struct *work) out_settings: /* Can we still talk to firmware ? */ - if (!iwl_is_ready_rf(priv->shrd)) + if (!iwl_is_ready_rf(priv)) goto out; iwlagn_post_scan(priv); out: - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } void iwl_setup_scan_deferred_work(struct iwl_priv *priv) @@ -630,8 +629,8 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->scan_completed); if (cancel_delayed_work_sync(&priv->scan_check)) { - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); iwl_force_scan_end(priv); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); } } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h b/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h deleted file mode 100644 index 8b8cd54a32e0..000000000000 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h +++ /dev/null @@ -1,430 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __iwl_shared_h__ -#define __iwl_shared_h__ - -#include -#include -#include -#include -#include - -#include "iwl-commands.h" - -/*This files includes all the types / functions that are exported by the - * upper layer to the bus and transport layer */ - -struct iwl_cfg; -struct iwl_bus; -struct iwl_priv; -struct iwl_sensitivity_ranges; -struct iwl_trans_ops; - -#define DRV_NAME "iwlagn" -#define IWLWIFI_VERSION "in-tree:" -#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" -#define DRV_AUTHOR "" - -extern struct iwl_mod_params iwlagn_mod_params; - -/** - * struct iwl_mod_params - * @sw_crypto: using hardware encryption, default = 0 - * @num_of_queues: number of tx queue, HW dependent - * @disable_11n: 11n capabilities enabled, default = 0 - * @amsdu_size_8K: enable 8K amsdu size, default = 1 - * @antenna: both antennas (use diversity), default = 0 - * @restart_fw: restart firmware, default = 1 - * @plcp_check: enable plcp health check, default = true - * @ack_check: disable ack health check, default = false - * @wd_disable: enable stuck queue check, default = false - * @bt_coex_active: enable bt coex, default = true - * @led_mode: system default, default = 0 - * @no_sleep_autoadjust: disable autoadjust, default = true - * @power_save: disable power save, default = false - * @power_level: power level, default = 1 - * @debug_level: levels are IWL_DL_* - * @ant_coupling: antenna coupling in dB, default = 0 - * @bt_ch_announce: BT channel inhibition, default = enable - * @wanted_ucode_alternative: ucode alternative to use, default = 1 - * @auto_agg: enable agg. without check, default = true - */ -struct iwl_mod_params { - int sw_crypto; - int num_of_queues; - int disable_11n; - int amsdu_size_8K; - int antenna; - int restart_fw; - bool plcp_check; - bool ack_check; - bool wd_disable; - bool bt_coex_active; - int led_mode; - bool no_sleep_autoadjust; - bool power_save; - int power_level; - u32 debug_level; - int ant_coupling; - bool bt_ch_announce; - int wanted_ucode_alternative; - bool auto_agg; -}; - -/** - * struct iwl_hw_params - * @max_txq_num: Max # Tx queues supported - * @num_ampdu_queues: num of ampdu queues - * @tx/rx_chains_num: Number of TX/RX chains - * @valid_tx/rx_ant: usable antennas - * @max_stations: - * @ht40_channel: is 40MHz width possible in band 2.4 - * @beacon_time_tsf_bits: number of valid tsf bits for beacon time - * @sku: - * @rx_page_order: Rx buffer page order - * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR - * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) - * @sw_crypto: 0 for hw, 1 for sw - * @max_xxx_size: for ucode uses - * @ct_kill_threshold: temperature threshold - * @wd_timeout: TX queues watchdog timeout - * @calib_init_cfg: setup initial calibrations for the hw - * @calib_rt_cfg: setup runtime calibrations for the hw - * @struct iwl_sensitivity_ranges: range of sensitivity values - */ -struct iwl_hw_params { - u8 max_txq_num; - u8 num_ampdu_queues; - u8 tx_chains_num; - u8 rx_chains_num; - u8 valid_tx_ant; - u8 valid_rx_ant; - u8 max_stations; - u8 ht40_channel; - bool shadow_reg_enable; - u16 beacon_time_tsf_bits; - u16 sku; - u32 rx_page_order; - u32 max_inst_size; - u32 max_data_size; - 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 */ - unsigned int wd_timeout; - - u32 calib_init_cfg; - u32 calib_rt_cfg; - const struct iwl_sensitivity_ranges *sens; -}; - -/** - * struct iwl_ht_agg - aggregation status while waiting for block-ack - * @txq_id: Tx queue used for Tx attempt - * @wait_for_ba: Expect block-ack before next Tx reply - * @rate_n_flags: Rate at which Tx was attempted - * - * If REPLY_TX indicates that aggregation was attempted, driver must wait - * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info - * until block ack arrives. - */ -struct iwl_ht_agg { - u16 txq_id; - u16 wait_for_ba; - u32 rate_n_flags; -#define IWL_AGG_OFF 0 -#define IWL_AGG_ON 1 -#define IWL_EMPTYING_HW_QUEUE_ADDBA 2 -#define IWL_EMPTYING_HW_QUEUE_DELBA 3 - u8 state; -}; - -struct iwl_tid_data { - u16 seq_number; /* agn only */ - u16 tfds_in_queue; - struct iwl_ht_agg agg; -}; - -/** - * struct iwl_shared - shared fields for all the layers of the driver - * - * @dbg_level_dev: dbg level set per device. Prevails on - * iwlagn_mod_params.debug_level if set (!= 0) - * @ucode_owner: IWL_OWNERSHIP_* - * @cmd_queue: command queue number - * @status: STATUS_* - * @bus: pointer to the bus layer data - * @priv: pointer to the upper layer data - * @hw_params: see struct iwl_hw_params - * @workqueue: the workqueue used by all the layers of the driver - * @lock: protect general shared data - * @sta_lock: protects the station table. - * If lock and sta_lock are needed, lock must be acquired first. - * @mutex: - */ -struct iwl_shared { -#ifdef CONFIG_IWLWIFI_DEBUG - u32 dbg_level_dev; -#endif /* CONFIG_IWLWIFI_DEBUG */ - -#define IWL_OWNERSHIP_DRIVER 0 -#define IWL_OWNERSHIP_TM 1 - u8 ucode_owner; - u8 cmd_queue; - unsigned long status; - bool wowlan; - - struct iwl_bus *bus; - struct iwl_priv *priv; - struct iwl_trans *trans; - struct iwl_hw_params hw_params; - - struct workqueue_struct *workqueue; - spinlock_t lock; - spinlock_t sta_lock; - struct mutex mutex; - - /*these 2 shouldn't really be here, but they are needed for - * iwl_queue_stop, which is called from the upper layer too - */ - u8 mac80211_registered; - struct ieee80211_hw *hw; - - struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; -}; - -/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ -#define priv(_m) ((_m)->shrd->priv) -#define bus(_m) ((_m)->shrd->bus) -#define trans(_m) ((_m)->shrd->trans) -#define hw_params(_m) ((_m)->shrd->hw_params) - -#ifdef CONFIG_IWLWIFI_DEBUG -/* - * iwl_get_debug_level: Return active debug level for device - * - * Using sysfs it is possible to set per device debug level. This debug - * level will be used if set, otherwise the global debug level which can be - * set via module parameter is used. - */ -static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) -{ - if (shrd->dbg_level_dev) - return shrd->dbg_level_dev; - else - return iwlagn_mod_params.debug_level; -} -#else -static inline u32 iwl_get_debug_level(struct iwl_shared *shrd) -{ - return iwlagn_mod_params.debug_level; -} -#endif - -static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page) -{ - free_pages(page, shrd->hw_params.rx_page_order); -} - -struct iwl_rx_mem_buffer { - dma_addr_t page_dma; - struct page *page; - struct list_head list; -}; - -#define rxb_addr(r) page_address(r->page) - -/* - * mac80211 queues, ACs, hardware queues, FIFOs. - * - * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues - * - * Mac80211 uses the following numbers, which we get as from it - * by way of skb_get_queue_mapping(skb): - * - * VO 0 - * VI 1 - * BE 2 - * BK 3 - * - * - * Regular (not A-MPDU) frames are put into hardware queues corresponding - * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their - * own queue per aggregation session (RA/TID combination), such queues are - * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In - * order to map frames to the right queue, we also need an AC->hw queue - * mapping. This is implemented here. - * - * Due to the way hw queues are set up (by the hw specific modules like - * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity - * mapping. - */ - -static const u8 tid_to_ac[] = { - IEEE80211_AC_BE, - IEEE80211_AC_BK, - IEEE80211_AC_BK, - IEEE80211_AC_BE, - IEEE80211_AC_VI, - IEEE80211_AC_VI, - IEEE80211_AC_VO, - IEEE80211_AC_VO -}; - -static inline int get_ac_from_tid(u16 tid) -{ - if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return tid_to_ac[tid]; - - /* no support for TIDs 8-15 yet */ - return -EINVAL; -} - -enum iwl_rxon_context_id { - IWL_RXON_CTX_BSS, - IWL_RXON_CTX_PAN, - - NUM_IWL_RXON_CTX -}; - -#ifdef CONFIG_PM -int iwl_suspend(struct iwl_priv *priv); -int iwl_resume(struct iwl_priv *priv); -#endif /* !CONFIG_PM */ - -int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, - struct iwl_cfg *cfg); -void __devexit iwl_remove(struct iwl_priv * priv); - -void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - u8 sta_id, u8 tid); -void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv, - enum iwl_rxon_context_id ctx, - u8 sta_id, u8 tid); - -/***************************************************** -* DRIVER STATUS FUNCTIONS -******************************************************/ -#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ -#define STATUS_INT_ENABLED 2 -#define STATUS_RF_KILL_HW 3 -#define STATUS_CT_KILL 4 -#define STATUS_INIT 5 -#define STATUS_ALIVE 6 -#define STATUS_READY 7 -#define STATUS_TEMPERATURE 8 -#define STATUS_GEO_CONFIGURED 9 -#define STATUS_EXIT_PENDING 10 -#define STATUS_STATISTICS 12 -#define STATUS_SCANNING 13 -#define STATUS_SCAN_ABORTING 14 -#define STATUS_SCAN_HW 15 -#define STATUS_POWER_PMI 16 -#define STATUS_FW_ERROR 17 -#define STATUS_DEVICE_ENABLED 18 -#define STATUS_CHANNEL_SWITCH_PENDING 19 - -static inline int iwl_is_ready(struct iwl_shared *shrd) -{ - /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are - * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &shrd->status) && - test_bit(STATUS_GEO_CONFIGURED, &shrd->status) && - !test_bit(STATUS_EXIT_PENDING, &shrd->status); -} - -static inline int iwl_is_alive(struct iwl_shared *shrd) -{ - return test_bit(STATUS_ALIVE, &shrd->status); -} - -static inline int iwl_is_init(struct iwl_shared *shrd) -{ - return test_bit(STATUS_INIT, &shrd->status); -} - -static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd) -{ - return test_bit(STATUS_RF_KILL_HW, &shrd->status); -} - -static inline int iwl_is_rfkill(struct iwl_shared *shrd) -{ - return iwl_is_rfkill_hw(shrd); -} - -static inline int iwl_is_ctkill(struct iwl_shared *shrd) -{ - return test_bit(STATUS_CT_KILL, &shrd->status); -} - -static inline int iwl_is_ready_rf(struct iwl_shared *shrd) -{ - if (iwl_is_rfkill(shrd)) - return 0; - - return iwl_is_ready(shrd); -} - -#endif /* #__iwl_shared_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c index 26b2bd4db6b4..1ef3b7106ad5 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -38,7 +38,7 @@ #include "iwl-trans.h" #include "iwl-agn.h" -/* priv->shrd->sta_lock must be held */ +/* priv->sta_lock must be held */ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { @@ -75,7 +75,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", sta_id); - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); switch (pkt->u.add_sta.status) { case ADD_STA_SUCCESS_MSK: @@ -118,7 +118,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, priv->stations[sta_id].sta.mode == STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", addsta->sta.addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return ret; } @@ -168,7 +168,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, } cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data); - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret || (flags & CMD_ASYNC)) return ret; @@ -177,7 +177,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, pkt = (struct iwl_rx_packet *)cmd.reply_page; ret = iwl_process_add_sta_resp(priv, sta, pkt, true); } - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_pages(priv, cmd.reply_page); return ret; } @@ -251,8 +251,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, else if (is_broadcast_ether_addr(addr)) sta_id = ctx->bcast_sta_id; else - for (i = IWL_STA_ID; - i < hw_params(priv).max_stations; i++) { + for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { if (!compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { sta_id = i; @@ -337,12 +336,12 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_addsta_cmd sta_cmd; *sta_id_r = 0; - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Unable to prepare station %pM for addition\n", addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return -EINVAL; } @@ -354,7 +353,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", sta_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return -EEXIST; } @@ -362,23 +361,23 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", sta_id, addr); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return -EEXIST; } priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); /* Add station to device's station table */ ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + 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->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } *sta_id_r = sta_id; return ret; @@ -387,7 +386,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, /** * iwl_sta_ucode_deactivate - deactivate ucode status for a station * - * priv->shrd->sta_lock must be held + * priv->sta_lock must be held */ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) { @@ -425,7 +424,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, cmd.flags |= CMD_WANT_SKB; - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); if (ret) return ret; @@ -441,11 +440,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: if (!temporary) { - spin_lock_irqsave(&priv->shrd->sta_lock, - flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); iwl_sta_ucode_deactivate(priv, sta_id); - spin_unlock_irqrestore(&priv->shrd->sta_lock, - flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); break; @@ -455,7 +452,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, break; } } - iwl_free_pages(priv->shrd, cmd.reply_page); + iwl_free_pages(priv, cmd.reply_page); return ret; } @@ -468,7 +465,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, { unsigned long flags; - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Unable to remove station %pM, device not ready.\n", addr); @@ -486,7 +483,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, if (WARN_ON(sta_id == IWL_INVALID_STATION)) return -EINVAL; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", @@ -512,11 +509,11 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, if (WARN_ON(priv->num_stations < 0)) priv->num_stations = 0; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_remove_station(priv, addr, sta_id, false); out_err: - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return -EINVAL; } @@ -537,8 +534,8 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); - for (i = 0; i < hw_params(priv).max_stations; i++) { + spin_lock_irqsave(&priv->sta_lock, flags_spin); + for (i = 0; i < priv->hw_params.max_stations; i++) { if (ctx && ctx->ctxid != priv->stations[i].ctxid) continue; @@ -548,7 +545,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, cleared = true; } } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); if (!cleared) IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); @@ -572,14 +569,14 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) int ret; bool send_lq; - if (!iwl_is_ready(priv->shrd)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); return; } IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); - for (i = 0; i < hw_params(priv).max_stations; i++) { + spin_lock_irqsave(&priv->sta_lock, flags_spin); + for (i = 0; i < priv->hw_params.max_stations; i++) { if (ctx->ctxid != priv->stations[i].ctxid) continue; if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && @@ -592,7 +589,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) } } - for (i = 0; i < hw_params(priv).max_stations; i++) { + 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)); @@ -602,18 +599,15 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) sizeof(struct iwl_link_quality_cmd)); send_lq = true; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, - flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) { - spin_lock_irqsave(&priv->shrd->sta_lock, - flags_spin); + 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->shrd->sta_lock, - flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } /* * Rate scaling has already been initialized, send @@ -621,12 +615,12 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx) */ if (send_lq) iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; } } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); if (!found) IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n"); else @@ -642,9 +636,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) struct iwl_link_quality_cmd lq; bool active; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); return; } @@ -654,7 +648,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); if (active) { ret = iwl_send_remove_station( @@ -664,9 +658,9 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx) IWL_ERR(priv, "failed to remove STA %pM (%d)\n", priv->stations[sta_id].sta.sta.addr, ret); } - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); if (ret) @@ -691,8 +685,8 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) unsigned long flags; int i; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); - for (i = 0; i < hw_params(priv).max_stations; i++) { + spin_lock_irqsave(&priv->sta_lock, flags); + for (i = 0; i < priv->hw_params.max_stations; i++) { if (!(priv->stations[i].used & IWL_STA_BCAST)) continue; @@ -703,7 +697,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv) kfree(priv->stations[i].lq); priv->stations[i].lq = NULL; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); } #ifdef CONFIG_IWLWIFI_DEBUG @@ -787,19 +781,19 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return -EINVAL; - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); return -EINVAL; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); iwl_dump_lq_cmd(priv, lq); if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) return -EINVAL; if (is_lq_table_valid(priv, ctx, lq)) - ret = iwl_trans_send_cmd(trans(priv), &cmd); + ret = trans_send_cmd(&priv->trans, &cmd); else ret = -EINVAL; @@ -809,9 +803,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if (init) { IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n", lq->sta_id); - spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin); + spin_lock_irqsave(&priv->sta_lock, flags_spin); priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); + spin_unlock_irqrestore(&priv->sta_lock, flags_spin); } return ret; } @@ -826,13 +820,13 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", sta->addr); - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", sta->addr); ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); if (ret) IWL_ERR(priv, "Error removing station %pM\n", sta->addr); - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return ret; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h index 9641eb6b1d0a..9a6768d66851 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -76,7 +76,7 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv) unsigned long flags; struct iwl_rxon_context *ctx; - spin_lock_irqsave(&priv->shrd->sta_lock, flags); + spin_lock_irqsave(&priv->sta_lock, flags); memset(priv->stations, 0, sizeof(priv->stations)); priv->num_stations = 0; @@ -94,7 +94,7 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv) ctx->key_mapping_keys = 0; } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); } static inline int iwl_sta_id(struct ieee80211_sta *sta) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 848fc18befc2..b11f60de4f1e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -72,6 +72,7 @@ #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-debug.h" +#include "iwl-fh.h" #include "iwl-io.h" #include "iwl-agn.h" #include "iwl-testmode.h" @@ -238,7 +239,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ - return iwl_trans_send_cmd(trans(priv), &cmd); + return trans_send_cmd(&priv->trans, &cmd); } @@ -276,7 +277,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_REG_READ32: - val32 = iwl_read32(bus(priv), ofs); + val32 = iwl_read32(priv, ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); @@ -298,7 +299,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write32(bus(priv), ofs, val32); + iwl_write32(priv, ofs, val32); } break; case IWL_TM_CMD_APP2DEV_REG_WRITE8: @@ -308,7 +309,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); IWL_INFO(priv, "8bit value to write 0x%x\n", val8); - iwl_write8(bus(priv), ofs, val8); + iwl_write8(priv, ofs, val8); } break; default: @@ -404,7 +405,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: iwl_testmode_cfg_init_calib(priv); - iwl_trans_stop_device(trans(priv)); + trans_stop_device(&priv->trans); break; case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: @@ -612,7 +613,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) - priv->shrd->ucode_owner = owner; + priv->ucode_owner = owner; else { IWL_DEBUG_INFO(priv, "Invalid owner\n"); return -EINVAL; @@ -660,7 +661,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) return -ENOMSG; } /* in case multiple accesses to the device happens */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_UCODE: @@ -701,7 +702,7 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return result; } @@ -737,7 +738,7 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, } /* in case multiple accesses to the device happens */ - mutex_lock(&priv->shrd->mutex); + mutex_lock(&priv->mutex); switch (cmd) { case IWL_TM_CMD_APP2DEV_READ_TRACE: IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); @@ -748,6 +749,6 @@ int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, break; } - mutex_unlock(&priv->shrd->mutex); + mutex_unlock(&priv->mutex); return result; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index ec4e73737681..b79330d84185 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h @@ -29,318 +29,54 @@ #ifndef __iwl_trans_int_pcie_h__ #define __iwl_trans_int_pcie_h__ -#include -#include -#include - -#include "iwl-fh.h" -#include "iwl-csr.h" -#include "iwl-shared.h" -#include "iwl-trans.h" -#include "iwl-debug.h" -#include "iwl-io.h" - -struct iwl_tx_queue; -struct iwl_queue; -struct iwl_host_cmd; - /*This file includes the declaration that are internal to the * trans_pcie layer */ -/** - * struct isr_statistics - interrupt statistics - * - */ -struct isr_statistics { - u32 hw; - u32 sw; - u32 err_code; - u32 sch; - u32 alive; - u32 rfkill; - u32 ctkill; - u32 wakeup; - u32 rx; - u32 tx; - u32 unhandled; -}; - -/** - * struct iwl_rx_queue - Rx queue - * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) - * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) - * @pool: - * @queue: - * @read: Shared index to newest available Rx buffer - * @write: Shared index to oldest written Rx packet - * @free_count: Number of pre-allocated buffers in rx_free - * @write_actual: - * @rx_free: list of free SKBs for use - * @rx_used: List of Rx buffers with no SKB - * @need_update: flag to indicate we need to update read/write index - * @rb_stts: driver's pointer to receive buffer status - * @rb_stts_dma: bus address of receive buffer status - * @lock: - * - * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers - */ -struct iwl_rx_queue { - __le32 *bd; - dma_addr_t bd_dma; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; - struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; - u32 read; - u32 write; - u32 free_count; - u32 write_actual; - struct list_head rx_free; - struct list_head rx_used; - int need_update; - struct iwl_rb_status *rb_stts; - dma_addr_t rb_stts_dma; - spinlock_t lock; -}; - -struct iwl_dma_ptr { - dma_addr_t dma; - void *addr; - size_t size; -}; - -/* - * This queue number is required for proper operation - * because the ucode will stop/start the scheduler as - * required. - */ -#define IWL_IPAN_MCAST_QUEUE 8 - -/** - * struct iwl_trans_pcie - PCIe transport specific data - * @rxq: all the RX queue data - * @rx_replenish: work that will be called when buffers need to be allocated - * @trans: pointer to the generic transport area - * @scd_base_addr: scheduler sram base address in SRAM - * @scd_bc_tbls: pointer to the byte count table of the scheduler - * @kw: keep warm address - * @ac_to_fifo: to what fifo is a specifc AC mapped ? - * @ac_to_queue: to what tx queue is a specifc AC mapped ? - * @mcast_queue: - * @txq: Tx DMA processing queues - * @txq_ctx_active_msk: what queue is active - * queue_stopped: tracks what queue is stopped - * queue_stop_count: tracks what SW queue is stopped - */ -struct iwl_trans_pcie { - struct iwl_rx_queue rxq; - struct work_struct rx_replenish; - struct iwl_trans *trans; - - /* INT ICT Table */ - __le32 *ict_tbl; - void *ict_tbl_vir; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - u32 inta; - bool use_ict; - struct tasklet_struct irq_tasklet; - struct isr_statistics isr_stats; - - u32 inta_mask; - u32 scd_base_addr; - struct iwl_dma_ptr scd_bc_tbls; - struct iwl_dma_ptr kw; - - const u8 *ac_to_fifo[NUM_IWL_RXON_CTX]; - const u8 *ac_to_queue[NUM_IWL_RXON_CTX]; - u8 mcast_queue[NUM_IWL_RXON_CTX]; - - struct iwl_tx_queue *txq; - unsigned long txq_ctx_active_msk; -#define IWL_MAX_HW_QUEUES 32 - unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; - atomic_t queue_stop_count[4]; -}; - -#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ - ((struct iwl_trans_pcie *) ((_iwl_trans)->trans_specific)) - /***************************************************** * RX ******************************************************/ void iwl_bg_rx_replenish(struct work_struct *data); -void iwl_irq_tasklet(struct iwl_trans *trans); -void iwlagn_rx_replenish(struct iwl_trans *trans); -void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, +void iwl_irq_tasklet(struct iwl_priv *priv); +void iwlagn_rx_replenish(struct iwl_priv *priv); +void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q); /***************************************************** * ICT ******************************************************/ -int iwl_reset_ict(struct iwl_trans *trans); -void iwl_disable_ict(struct iwl_trans *trans); -int iwl_alloc_isr_ict(struct iwl_trans *trans); -void iwl_free_isr_ict(struct iwl_trans *trans); +int iwl_reset_ict(struct iwl_priv *priv); +void iwl_disable_ict(struct iwl_priv *priv); +int iwl_alloc_isr_ict(struct iwl_priv *priv); +void iwl_free_isr_ict(struct iwl_priv *priv); irqreturn_t iwl_isr_ict(int irq, void *data); + /***************************************************** * TX / HCMD ******************************************************/ -void iwl_txq_update_write_ptr(struct iwl_trans *trans, - struct iwl_tx_queue *txq); -int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, +void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int index); +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset); -int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id); -int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); -int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, - u32 flags, u16 len, const void *data); +int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, + int count, int slots_num, u32 id); +int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, + u16 len, const void *data); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq, u16 byte_cnt); -void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id); -int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid); -void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); -void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, +int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); +void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, + int txq_id, u32 index); +void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry); -int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid, u16 *ssn); -void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - int sta_id, int tid, int frame_limit); -void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, - int index); -int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, - struct sk_buff_head *skbs); -int iwl_queue_space(const struct iwl_queue *q); - -/***************************************************** -* Error handling -******************************************************/ -int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, - char **buf, bool display); -int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); -void iwl_dump_csr(struct iwl_trans *trans); - -/***************************************************** -* Helpers -******************************************************/ -static inline void iwl_disable_interrupts(struct iwl_trans *trans) -{ - clear_bit(STATUS_INT_ENABLED, &trans->shrd->status); - - /* disable interrupts from uCode/NIC to host */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); - - /* acknowledge/clear/reset any interrupts still pending - * from uCode or flow handler (Rx/Tx DMA) */ - iwl_write32(bus(trans), CSR_INT, 0xffffffff); - iwl_write32(bus(trans), CSR_FH_INT_STATUS, 0xffffffff); - IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); -} - -static inline void iwl_enable_interrupts(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - IWL_DEBUG_ISR(trans, "Enabling interrupts\n"); - set_bit(STATUS_INT_ENABLED, &trans->shrd->status); - iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask); -} - -/* - * we have 8 bits used like this: - * - * 7 6 5 4 3 2 1 0 - * | | | | | | | | - * | | | | | | +-+-------- AC queue (0-3) - * | | | | | | - * | +-+-+-+-+------------ HW queue ID - * | - * +---------------------- unused - */ -static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) -{ - BUG_ON(ac > 3); /* only have 2 bits */ - BUG_ON(hwq > 31); /* only use 5 bits */ - - txq->swq_id = (hwq << 2) | ac; -} - -static inline void iwl_wake_queue(struct iwl_trans *trans, - struct iwl_tx_queue *txq) -{ - u8 queue = txq->swq_id; - u8 ac = queue & 3; - u8 hwq = (queue >> 2) & 0x1f; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - if (unlikely(!trans->shrd->mac80211_registered)) - return; - - if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) - if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) - ieee80211_wake_queue(trans->shrd->hw, ac); -} - -static inline void iwl_stop_queue(struct iwl_trans *trans, - struct iwl_tx_queue *txq) -{ - u8 queue = txq->swq_id; - u8 ac = queue & 3; - u8 hwq = (queue >> 2) & 0x1f; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - if (unlikely(!trans->shrd->mac80211_registered)) - return; - - if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) - if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) - ieee80211_stop_queue(trans->shrd->hw, ac); -} - -#ifdef ieee80211_stop_queue -#undef ieee80211_stop_queue -#endif - -#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue - -#ifdef ieee80211_wake_queue -#undef ieee80211_wake_queue -#endif - -#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue - -static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie, - int txq_id) -{ - set_bit(txq_id, &trans_pcie->txq_ctx_active_msk); -} - -static inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie, - int txq_id) -{ - clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk); -} - -static inline int iwl_queue_used(const struct iwl_queue *q, int i) -{ - return q->write_ptr >= q->read_ptr ? - (i >= q->read_ptr && i < q->write_ptr) : - !(i < q->read_ptr && i >= q->write_ptr); -} - -static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) -{ - return index & (q->n_window - 1); -} +void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c index 2d0ddb8d422d..474860290404 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-rx-pcie.c @@ -127,7 +127,7 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q) /** * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue */ -void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, +void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) { unsigned long flags; @@ -138,34 +138,34 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, if (q->need_update == 0) goto exit_unlock; - if (hw_params(trans).shadow_reg_enable) { + if (priv->cfg->base_params->shadow_reg_enable) { /* shadow register enabled */ /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write32(bus(trans), FH_RSCSR_CHNL0_WPTR, q->write_actual); + iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); } else { /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { - reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); + if (test_bit(STATUS_POWER_PMI, &priv->status)) { + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(trans, + IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup," " GP1 = 0x%x\n", reg); - iwl_set_bit(bus(trans), CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); goto exit_unlock; } q->write_actual = (q->write & ~0x7); - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); /* Else device is assumed to be awake */ } else { /* Device expects a multiple of 8 */ q->write_actual = (q->write & ~0x7); - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); } } @@ -178,7 +178,8 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, /** * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ -static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) +static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, + dma_addr_t dma_addr) { return cpu_to_le32((u32)(dma_addr >> 8)); } @@ -194,12 +195,9 @@ static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) * also updates the memory address in the firmware to reference the new * target buffer. */ -static void iwlagn_rx_queue_restock(struct iwl_trans *trans) +static void iwlagn_rx_queue_restock(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; @@ -216,7 +214,8 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) list_del(element); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma); + rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, + rxb->page_dma); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -225,7 +224,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) /* If the pre-allocated buffer pool is dropping low, schedule to * refill it */ if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(trans->shrd->workqueue, &trans_pcie->rx_replenish); + queue_work(priv->workqueue, &priv->rx_replenish); /* If we've added more space for the firmware to place data, tell it. @@ -234,7 +233,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; spin_unlock_irqrestore(&rxq->lock, flags); - iwl_rx_queue_update_write_ptr(trans, rxq); + iwl_rx_queue_update_write_ptr(priv, rxq); } } @@ -246,12 +245,9 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) * Also restock the Rx queue via iwl_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) +static void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; struct page *page; @@ -269,21 +265,20 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) if (rxq->free_count > RX_LOW_WATERMARK) gfp_mask |= __GFP_NOWARN; - if (hw_params(trans).rx_page_order > 0) + if (priv->hw_params.rx_page_order > 0) gfp_mask |= __GFP_COMP; /* Alloc a new receive buffer */ - page = alloc_pages(gfp_mask, - hw_params(trans).rx_page_order); + page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); if (!page) { if (net_ratelimit()) - IWL_DEBUG_INFO(trans, "alloc_pages failed, " - "order: %d\n", - hw_params(trans).rx_page_order); + IWL_DEBUG_INFO(priv, "alloc_pages failed, " + "order: %d\n", + priv->hw_params.rx_page_order); if ((rxq->free_count <= RX_LOW_WATERMARK) && net_ratelimit()) - IWL_CRIT(trans, "Failed to alloc_pages with %s." + IWL_CRIT(priv, "Failed to alloc_pages with %s." "Only %u free buffers remaining.\n", priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", @@ -298,7 +293,7 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) if (list_empty(&rxq->rx_used)) { spin_unlock_irqrestore(&rxq->lock, flags); - __free_pages(page, hw_params(trans).rx_page_order); + __free_pages(page, priv->hw_params.rx_page_order); return; } element = rxq->rx_used.next; @@ -310,8 +305,8 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) BUG_ON(rxb->page); rxb->page = page; /* Get physical address of the RB */ - rxb->page_dma = dma_map_page(bus(trans)->dev, page, 0, - PAGE_SIZE << hw_params(trans).rx_page_order, + rxb->page_dma = dma_map_page(priv->bus->dev, page, 0, + PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); /* dma address must be no more than 36 bits */ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); @@ -327,36 +322,35 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) } } -void iwlagn_rx_replenish(struct iwl_trans *trans) +void iwlagn_rx_replenish(struct iwl_priv *priv) { unsigned long flags; - iwlagn_rx_allocate(trans, GFP_KERNEL); + iwlagn_rx_allocate(priv, GFP_KERNEL); - spin_lock_irqsave(&trans->shrd->lock, flags); - iwlagn_rx_queue_restock(trans); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); + iwlagn_rx_queue_restock(priv); + spin_unlock_irqrestore(&priv->lock, flags); } -static void iwlagn_rx_replenish_now(struct iwl_trans *trans) +static void iwlagn_rx_replenish_now(struct iwl_priv *priv) { - iwlagn_rx_allocate(trans, GFP_ATOMIC); + iwlagn_rx_allocate(priv, GFP_ATOMIC); - iwlagn_rx_queue_restock(trans); + iwlagn_rx_queue_restock(priv); } void iwl_bg_rx_replenish(struct work_struct *data) { - struct iwl_trans_pcie *trans_pcie = - container_of(data, struct iwl_trans_pcie, rx_replenish); - struct iwl_trans *trans = trans_pcie->trans; + struct iwl_priv *priv = + container_of(data, struct iwl_priv, rx_replenish); - if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - mutex_lock(&trans->shrd->mutex); - iwlagn_rx_replenish(trans); - mutex_unlock(&trans->shrd->mutex); + mutex_lock(&priv->mutex); + iwlagn_rx_replenish(priv); + mutex_unlock(&priv->mutex); } /** @@ -366,13 +360,11 @@ void iwl_bg_rx_replenish(struct work_struct *data) * the appropriate handlers, including command responses, * frame-received notifications, and other notifications. */ -static void iwl_rx_handle(struct iwl_trans *trans) +static void iwl_rx_handle(struct iwl_priv *priv) { struct iwl_rx_mem_buffer *rxb; struct iwl_rx_packet *pkt; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; u32 r, i; int reclaim; unsigned long flags; @@ -387,7 +379,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) /* Rx interrupt, but nothing sent from uCode */ if (i == r) - IWL_DEBUG_RX(trans, "r = %d, i = %d\n", r, i); + IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); /* calculate total frames need to be restock after handling RX */ total_empty = r - rxq->write_actual; @@ -412,17 +404,17 @@ static void iwl_rx_handle(struct iwl_trans *trans) rxq->queue[i] = NULL; - dma_unmap_page(bus(trans)->dev, rxb->page_dma, - PAGE_SIZE << hw_params(trans).rx_page_order, + dma_unmap_page(priv->bus->dev, rxb->page_dma, + PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); - IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r, + IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; len += sizeof(u32); /* account for status word */ - trace_iwlwifi_dev_rx(priv(trans), pkt, len); + trace_iwlwifi_dev_rx(priv, pkt, len); /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. @@ -438,7 +430,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && (pkt->hdr.cmd != REPLY_TX); - iwl_rx_dispatch(priv(trans), rxb); + iwl_rx_dispatch(priv, rxb); /* * XXX: After here, we should always check rxb->page @@ -450,12 +442,12 @@ static void iwl_rx_handle(struct iwl_trans *trans) if (reclaim) { /* Invoke any callbacks, transfer the buffer to caller, * and fire off the (possibly) blocking - * iwl_trans_send_cmd() + * trans_send_cmd() * as we reclaim the driver command queue */ if (rxb->page) - iwl_tx_cmd_complete(priv(trans), rxb); + iwl_tx_cmd_complete(priv, rxb); else - IWL_WARN(trans, "Claim null rxb?\n"); + IWL_WARN(priv, "Claim null rxb?\n"); } /* Reuse the page if possible. For notification packets and @@ -463,9 +455,8 @@ static void iwl_rx_handle(struct iwl_trans *trans) * rx_free list for reuse later. */ spin_lock_irqsave(&rxq->lock, flags); if (rxb->page != NULL) { - rxb->page_dma = dma_map_page(bus(trans)->dev, rxb->page, - 0, PAGE_SIZE << - hw_params(trans).rx_page_order, + rxb->page_dma = dma_map_page(priv->bus->dev, rxb->page, + 0, PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; @@ -481,7 +472,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) count++; if (count >= 8) { rxq->read = i; - iwlagn_rx_replenish_now(trans); + iwlagn_rx_replenish_now(priv); count = 0; } } @@ -490,415 +481,13 @@ static void iwl_rx_handle(struct iwl_trans *trans) /* Backtrack one entry */ rxq->read = i; if (fill_rx) - iwlagn_rx_replenish_now(trans); + iwlagn_rx_replenish_now(priv); else - iwlagn_rx_queue_restock(trans); -} - -static const char * const desc_lookup_text[] = { - "OK", - "FAIL", - "BAD_PARAM", - "BAD_CHECKSUM", - "NMI_INTERRUPT_WDG", - "SYSASSERT", - "FATAL_ERROR", - "BAD_COMMAND", - "HW_ERROR_TUNE_LOCK", - "HW_ERROR_TEMPERATURE", - "ILLEGAL_CHAN_FREQ", - "VCC_NOT_STABLE", - "FH_ERROR", - "NMI_INTERRUPT_HOST", - "NMI_INTERRUPT_ACTION_PT", - "NMI_INTERRUPT_UNKNOWN", - "UCODE_VERSION_MISMATCH", - "HW_ERROR_ABS_LOCK", - "HW_ERROR_CAL_LOCK_FAIL", - "NMI_INTERRUPT_INST_ACTION_PT", - "NMI_INTERRUPT_DATA_ACTION_PT", - "NMI_TRM_HW_ER", - "NMI_INTERRUPT_TRM", - "NMI_INTERRUPT_BREAK_POINT", - "DEBUG_0", - "DEBUG_1", - "DEBUG_2", - "DEBUG_3", -}; - -static struct { char *name; u8 num; } advanced_lookup[] = { - { "NMI_INTERRUPT_WDG", 0x34 }, - { "SYSASSERT", 0x35 }, - { "UCODE_VERSION_MISMATCH", 0x37 }, - { "BAD_COMMAND", 0x38 }, - { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, - { "FATAL_ERROR", 0x3D }, - { "NMI_TRM_HW_ERR", 0x46 }, - { "NMI_INTERRUPT_TRM", 0x4C }, - { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, - { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, - { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, - { "NMI_INTERRUPT_HOST", 0x66 }, - { "NMI_INTERRUPT_ACTION_PT", 0x7C }, - { "NMI_INTERRUPT_UNKNOWN", 0x84 }, - { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, - { "ADVANCED_SYSASSERT", 0 }, -}; - -static const char *desc_lookup(u32 num) -{ - int i; - int max = ARRAY_SIZE(desc_lookup_text); - - if (num < max) - return desc_lookup_text[num]; - - max = ARRAY_SIZE(advanced_lookup) - 1; - for (i = 0; i < max; i++) { - if (advanced_lookup[i].num == num) - break; - } - return advanced_lookup[i].name; -} - -#define ERROR_START_OFFSET (1 * sizeof(u32)) -#define ERROR_ELEM_SIZE (7 * sizeof(u32)) - -static void iwl_dump_nic_error_log(struct iwl_trans *trans) -{ - u32 base; - struct iwl_error_event_table table; - struct iwl_priv *priv = priv(trans); - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - base = priv->device_pointers.error_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - if (!base) - base = priv->init_errlog_ptr; - } else { - if (!base) - base = priv->inst_errlog_ptr; - } - - if (!iwlagn_hw_valid_rtc_data_addr(base)) { - IWL_ERR(trans, - "Not valid error log pointer 0x%08X for %s uCode\n", - base, - (priv->ucode_type == IWL_UCODE_INIT) - ? "Init" : "RT"); - return; - } - - iwl_read_targ_mem_words(bus(priv), base, &table, sizeof(table)); - - if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { - IWL_ERR(trans, "Start IWL Error Log Dump:\n"); - IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", - trans->shrd->status, table.valid); - } - - trans_pcie->isr_stats.err_code = table.error_id; - - trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, - table.data1, table.data2, table.line, - table.blink1, table.blink2, table.ilink1, - table.ilink2, table.bcon_time, table.gp1, - table.gp2, table.gp3, table.ucode_ver, - table.hw_ver, table.brd_ver); - IWL_ERR(trans, "0x%08X | %-28s\n", table.error_id, - desc_lookup(table.error_id)); - IWL_ERR(trans, "0x%08X | uPc\n", table.pc); - IWL_ERR(trans, "0x%08X | branchlink1\n", table.blink1); - IWL_ERR(trans, "0x%08X | branchlink2\n", table.blink2); - IWL_ERR(trans, "0x%08X | interruptlink1\n", table.ilink1); - IWL_ERR(trans, "0x%08X | interruptlink2\n", table.ilink2); - IWL_ERR(trans, "0x%08X | data1\n", table.data1); - IWL_ERR(trans, "0x%08X | data2\n", table.data2); - IWL_ERR(trans, "0x%08X | line\n", table.line); - IWL_ERR(trans, "0x%08X | beacon time\n", table.bcon_time); - IWL_ERR(trans, "0x%08X | tsf low\n", table.tsf_low); - IWL_ERR(trans, "0x%08X | tsf hi\n", table.tsf_hi); - IWL_ERR(trans, "0x%08X | time gp1\n", table.gp1); - IWL_ERR(trans, "0x%08X | time gp2\n", table.gp2); - IWL_ERR(trans, "0x%08X | time gp3\n", table.gp3); - IWL_ERR(trans, "0x%08X | uCode version\n", table.ucode_ver); - IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver); - IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver); - IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd); -} - -/** - * iwl_irq_handle_error - called for HW or SW error interrupt from card - */ -static void iwl_irq_handle_error(struct iwl_trans *trans) -{ - struct iwl_priv *priv = priv(trans); - /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ - if (priv->cfg->internal_wimax_coex && - (!(iwl_read_prph(bus(trans), APMG_CLK_CTRL_REG) & - APMS_CLK_VAL_MRB_FUNC_MODE) || - (iwl_read_prph(bus(trans), APMG_PS_CTRL_REG) & - APMG_PS_CTRL_VAL_RESET_REQ))) { - /* - * Keep the restart process from trying to send host - * commands by clearing the ready bit. - */ - clear_bit(STATUS_READY, &trans->shrd->status); - clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - wake_up_interruptible(&priv->wait_command_queue); - IWL_ERR(trans, "RF is used by WiMAX\n"); - return; - } - - IWL_ERR(trans, "Loaded firmware version: %s\n", - priv->hw->wiphy->fw_version); - - iwl_dump_nic_error_log(trans); - iwl_dump_csr(trans); - iwl_dump_fh(trans, NULL, false); - iwl_dump_nic_event_log(trans, false, NULL, false); -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) - iwl_print_rx_config_cmd(priv, - &priv->contexts[IWL_RXON_CTX_BSS]); -#endif - - iwlagn_fw_error(priv, false); -} - -#define EVENT_START_OFFSET (4 * sizeof(u32)) - -/** - * iwl_print_event_log - Dump error event log to syslog - * - */ -static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, - u32 num_events, u32 mode, - int pos, char **buf, size_t bufsz) -{ - u32 i; - u32 base; /* SRAM byte address of event log header */ - u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ - u32 ptr; /* SRAM byte address of log data */ - u32 ev, time, data; /* event log data */ - unsigned long reg_flags; - struct iwl_priv *priv = priv(trans); - - if (num_events == 0) - return pos; - - base = priv->device_pointers.log_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - if (!base) - base = priv->init_evtlog_ptr; - } else { - if (!base) - base = priv->inst_evtlog_ptr; - } - - if (mode == 0) - event_size = 2 * sizeof(u32); - else - event_size = 3 * sizeof(u32); - - ptr = base + EVENT_START_OFFSET + (start_idx * event_size); - - /* Make sure device is powered up for SRAM reads */ - spin_lock_irqsave(&bus(priv)->reg_lock, reg_flags); - iwl_grab_nic_access(bus(priv)); - - /* Set starting address; reads will auto-increment */ - iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr); - rmb(); - - /* "time" is actually "data" for mode 0 (no timestamp). - * place event id # at far right for easier visual parsing. */ - for (i = 0; i < num_events; i++) { - ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - if (mode == 0) { - /* data, ev */ - if (bufsz) { - pos += scnprintf(*buf + pos, bufsz - pos, - "EVT_LOG:0x%08x:%04u\n", - time, ev); - } else { - trace_iwlwifi_dev_ucode_event(priv, 0, - time, ev); - IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n", - time, ev); - } - } else { - data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); - if (bufsz) { - pos += scnprintf(*buf + pos, bufsz - pos, - "EVT_LOGT:%010u:0x%08x:%04u\n", - time, data, ev); - } else { - IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n", - time, data, ev); - trace_iwlwifi_dev_ucode_event(priv, time, - data, ev); - } - } - } - - /* Allow device to power down */ - iwl_release_nic_access(bus(priv)); - spin_unlock_irqrestore(&bus(priv)->reg_lock, reg_flags); - return pos; -} - -/** - * iwl_print_last_event_logs - Dump the newest # of event log to syslog - */ -static int iwl_print_last_event_logs(struct iwl_trans *trans, u32 capacity, - u32 num_wraps, u32 next_entry, - u32 size, u32 mode, - int pos, char **buf, size_t bufsz) -{ - /* - * display the newest DEFAULT_LOG_ENTRIES entries - * i.e the entries just before the next ont that uCode would fill. - */ - if (num_wraps) { - if (next_entry < size) { - pos = iwl_print_event_log(trans, - capacity - (size - next_entry), - size - next_entry, mode, - pos, buf, bufsz); - pos = iwl_print_event_log(trans, 0, - next_entry, mode, - pos, buf, bufsz); - } else - pos = iwl_print_event_log(trans, next_entry - size, - size, mode, pos, buf, bufsz); - } else { - if (next_entry < size) { - pos = iwl_print_event_log(trans, 0, next_entry, - mode, pos, buf, bufsz); - } else { - pos = iwl_print_event_log(trans, next_entry - size, - size, mode, pos, buf, bufsz); - } - } - return pos; -} - -#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) - -int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, - char **buf, bool display) -{ - u32 base; /* SRAM byte address of event log header */ - u32 capacity; /* event log capacity in # entries */ - u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ - 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; - struct iwl_priv *priv = priv(trans); - - base = priv->device_pointers.log_event_table; - if (priv->ucode_type == IWL_UCODE_INIT) { - logsize = priv->init_evtlog_size; - if (!base) - base = priv->init_evtlog_ptr; - } else { - logsize = priv->inst_evtlog_size; - if (!base) - base = priv->inst_evtlog_ptr; - } - - if (!iwlagn_hw_valid_rtc_data_addr(base)) { - IWL_ERR(trans, - "Invalid event log pointer 0x%08X for %s uCode\n", - base, - (priv->ucode_type == IWL_UCODE_INIT) - ? "Init" : "RT"); - return -EINVAL; - } - - /* event log header */ - capacity = iwl_read_targ_mem(bus(priv), base); - mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32))); - num_wraps = iwl_read_targ_mem(bus(priv), base + (2 * sizeof(u32))); - next_entry = iwl_read_targ_mem(bus(priv), base + (3 * sizeof(u32))); - - if (capacity > logsize) { - IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " - "entries\n", capacity, logsize); - capacity = logsize; - } - - if (next_entry > logsize) { - IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n", - next_entry, logsize); - next_entry = logsize; - } - - size = num_wraps ? capacity : next_entry; - - /* bail out if nothing in log */ - if (size == 0) { - IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n"); - return pos; - } - - /* enable/disable bt channel inhibition */ - priv->bt_ch_announce = iwlagn_mod_params.bt_ch_announce; - -#ifdef CONFIG_IWLWIFI_DEBUG - if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log) - size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) - ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#else - size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) - ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#endif - IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n", - size); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - if (full_log) - bufsz = capacity * 48; - else - bufsz = size * 48; - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - } - if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) { - /* - * if uCode has wrapped back to top of log, - * start at the oldest entry, - * i.e the next one that uCode would fill. - */ - if (num_wraps) - pos = iwl_print_event_log(trans, next_entry, - capacity - next_entry, mode, - pos, buf, bufsz); - /* (then/else) start at top of log */ - pos = iwl_print_event_log(trans, 0, - next_entry, mode, pos, buf, bufsz); - } else - pos = iwl_print_last_event_logs(trans, capacity, num_wraps, - next_entry, size, mode, - pos, buf, bufsz); -#else - pos = iwl_print_last_event_logs(trans, capacity, num_wraps, - next_entry, size, mode, - pos, buf, bufsz); -#endif - return pos; + iwlagn_rx_queue_restock(priv); } /* tasklet for iwlagn interrupt */ -void iwl_irq_tasklet(struct iwl_trans *trans) +void iwl_irq_tasklet(struct iwl_priv *priv) { u32 inta = 0; u32 handled = 0; @@ -908,12 +497,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) u32 inta_mask; #endif - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct isr_statistics *isr_stats = &trans_pcie->isr_stats; - - - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Ack/clear/reset pending uCode interrupts. * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, @@ -926,34 +510,33 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * hardware bugs here by ACKing all the possible interrupts so that * interrupt coalescing can still be achieved. */ - iwl_write32(bus(trans), CSR_INT, - trans_pcie->inta | ~trans_pcie->inta_mask); + iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); - inta = trans_pcie->inta; + inta = priv->inta; #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) { + if (iwl_get_debug_level(priv) & IWL_DL_ISR) { /* just for debug */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); - IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", + inta_mask = iwl_read32(priv, CSR_INT_MASK); + IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", inta, inta_mask); } #endif - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); - /* saved interrupt in inta variable now we can reset trans_pcie->inta */ - trans_pcie->inta = 0; + /* saved interrupt in inta variable now we can reset priv->inta */ + priv->inta = 0; /* Now service all interrupt bits discovered above. */ if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(trans, "Hardware error detected. Restarting.\n"); + IWL_ERR(priv, "Hardware error detected. Restarting.\n"); /* Tell the device to stop sending interrupts */ - iwl_disable_interrupts(trans); + iwl_disable_interrupts(priv); - isr_stats->hw++; - iwl_irq_handle_error(trans); + priv->isr_stats.hw++; + iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_HW_ERR; @@ -961,18 +544,18 @@ void iwl_irq_tasklet(struct iwl_trans *trans) } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " + IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " "the frame/frames.\n"); - isr_stats->sch++; + priv->isr_stats.sch++; } /* Alive notification via Rx interrupt will do the real work */ if (inta & CSR_INT_BIT_ALIVE) { - IWL_DEBUG_ISR(trans, "Alive interrupt\n"); - isr_stats->alive++; + IWL_DEBUG_ISR(priv, "Alive interrupt\n"); + priv->isr_stats.alive++; } } #endif @@ -982,29 +565,26 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0; - if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & + if (!(iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; - IWL_WARN(trans, "RF_KILL bit toggled to %s.\n", + IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", hw_rf_kill ? "disable radio" : "enable radio"); - isr_stats->rfkill++; + priv->isr_stats.rfkill++; /* driver only loads ucode once setting the interface up. * the driver allows loading the ucode even if the radio * is killed. Hence update the killswitch state here. The * rfkill handler will care about restarting if needed. */ - if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) { + if (!test_bit(STATUS_ALIVE, &priv->status)) { if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, - &trans->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); else - clear_bit(STATUS_RF_KILL_HW, - &trans->shrd->status); - wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy, - hw_rf_kill); + clear_bit(STATUS_RF_KILL_HW, &priv->status); + wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); } handled |= CSR_INT_BIT_RF_KILL; @@ -1012,29 +592,28 @@ void iwl_irq_tasklet(struct iwl_trans *trans) /* Chip got too hot and stopped itself */ if (inta & CSR_INT_BIT_CT_KILL) { - IWL_ERR(trans, "Microcode CT kill error detected.\n"); - isr_stats->ctkill++; + IWL_ERR(priv, "Microcode CT kill error detected.\n"); + priv->isr_stats.ctkill++; handled |= CSR_INT_BIT_CT_KILL; } /* Error detected by uCode */ if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERR(trans, "Microcode SW error detected. " + IWL_ERR(priv, "Microcode SW error detected. " " Restarting 0x%X.\n", inta); - isr_stats->sw++; - iwl_irq_handle_error(trans); + priv->isr_stats.sw++; + iwl_irq_handle_error(priv); handled |= CSR_INT_BIT_SW_ERR; } /* uCode wakes up after power-down sleep */ if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR(trans, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq); - for (i = 0; i < hw_params(trans).max_txq_num; i++) - iwl_txq_update_write_ptr(trans, - &trans_pcie->txq[i]); + IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); + iwl_rx_queue_update_write_ptr(priv, &priv->rxq); + for (i = 0; i < priv->hw_params.max_txq_num; i++) + iwl_txq_update_write_ptr(priv, &priv->txq[i]); - isr_stats->wakeup++; + priv->isr_stats.wakeup++; handled |= CSR_INT_BIT_WAKEUP; } @@ -1044,16 +623,15 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * notifications from uCode come through here*/ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | CSR_INT_BIT_RX_PERIODIC)) { - IWL_DEBUG_ISR(trans, "Rx interrupt\n"); + IWL_DEBUG_ISR(priv, "Rx interrupt\n"); if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(bus(trans), CSR_FH_INT_STATUS, + iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_RX_MASK); } if (inta & CSR_INT_BIT_RX_PERIODIC) { handled |= CSR_INT_BIT_RX_PERIODIC; - iwl_write32(bus(trans), - CSR_INT, CSR_INT_BIT_RX_PERIODIC); + iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC); } /* Sending RX interrupt require many steps to be done in the * the device: @@ -1067,9 +645,9 @@ void iwl_irq_tasklet(struct iwl_trans *trans) */ /* Disable periodic interrupt; we use it as just a one-shot. */ - iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, + iwl_write8(priv, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_DIS); - iwl_rx_handle(trans); + iwl_rx_handle(priv); /* * Enable periodic interrupt in 8 msec only if we received @@ -1079,40 +657,40 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * to extend the periodic interrupt; one-shot is enough. */ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write8(bus(trans), CSR_INT_PERIODIC_REG, + iwl_write8(priv, CSR_INT_PERIODIC_REG, CSR_INT_PERIODIC_ENA); - isr_stats->rx++; + priv->isr_stats.rx++; } /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(bus(trans), CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); - IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); - isr_stats->tx++; + iwl_write32(priv, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); + IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); + priv->isr_stats.tx++; handled |= CSR_INT_BIT_FH_TX; /* Wake up uCode load routine, now that load is complete */ - priv(trans)->ucode_write_complete = 1; - wake_up_interruptible(&priv(trans)->wait_command_queue); + priv->ucode_write_complete = 1; + wake_up_interruptible(&priv->wait_command_queue); } if (inta & ~handled) { - IWL_ERR(trans, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - isr_stats->unhandled++; + IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); + priv->isr_stats.unhandled++; } - if (inta & ~(trans_pcie->inta_mask)) { - IWL_WARN(trans, "Disabled INTA bits 0x%08x were pending\n", - inta & ~trans_pcie->inta_mask); + if (inta & ~(priv->inta_mask)) { + IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", + inta & ~priv->inta_mask); } /* Re-enable all interrupts */ /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status)) - iwl_enable_interrupts(trans); + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl_enable_interrupts(priv); /* Re-enable RF_KILL if it occurred */ else if (handled & CSR_INT_BIT_RF_KILL) - iwl_enable_rfkill_int(priv(trans)); + iwl_enable_rfkill_int(priv); } /****************************************************************************** @@ -1123,21 +701,18 @@ void iwl_irq_tasklet(struct iwl_trans *trans) #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) /* Free dram table */ -void iwl_free_isr_ict(struct iwl_trans *trans) +void iwl_free_isr_ict(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - if (trans_pcie->ict_tbl_vir) { - dma_free_coherent(bus(trans)->dev, + if (priv->ict_tbl_vir) { + dma_free_coherent(priv->bus->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - trans_pcie->ict_tbl_vir, - trans_pcie->ict_tbl_dma); - trans_pcie->ict_tbl_vir = NULL; - memset(&trans_pcie->ict_tbl_dma, 0, - sizeof(trans_pcie->ict_tbl_dma)); - memset(&trans_pcie->aligned_ict_tbl_dma, 0, - sizeof(trans_pcie->aligned_ict_tbl_dma)); + priv->ict_tbl_vir, + priv->ict_tbl_dma); + priv->ict_tbl_vir = NULL; + memset(&priv->ict_tbl_dma, 0, + sizeof(priv->ict_tbl_dma)); + memset(&priv->aligned_ict_tbl_dma, 0, + sizeof(priv->aligned_ict_tbl_dma)); } } @@ -1145,168 +720,157 @@ void iwl_free_isr_ict(struct iwl_trans *trans) /* allocate dram shared table it is a PAGE_SIZE aligned * also reset all data related to ICT table interrupt. */ -int iwl_alloc_isr_ict(struct iwl_trans *trans) +int iwl_alloc_isr_ict(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); /* allocate shrared data table */ - trans_pcie->ict_tbl_vir = - dma_alloc_coherent(bus(trans)->dev, + priv->ict_tbl_vir = + dma_alloc_coherent(priv->bus->dev, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &trans_pcie->ict_tbl_dma, GFP_KERNEL); - if (!trans_pcie->ict_tbl_vir) + &priv->ict_tbl_dma, GFP_KERNEL); + if (!priv->ict_tbl_vir) return -ENOMEM; /* align table to PAGE_SIZE boundary */ - trans_pcie->aligned_ict_tbl_dma = - ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE); + priv->aligned_ict_tbl_dma = + ALIGN(priv->ict_tbl_dma, PAGE_SIZE); - IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)trans_pcie->ict_tbl_dma, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", + (unsigned long long)priv->ict_tbl_dma, + (unsigned long long)priv->aligned_ict_tbl_dma, + (int)(priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma)); - trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir + - (trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma); + priv->ict_tbl = priv->ict_tbl_vir + + (priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma); - IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n", - trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", + priv->ict_tbl, priv->ict_tbl_vir, + (int)(priv->aligned_ict_tbl_dma - + priv->ict_tbl_dma)); /* reset table and index to all 0 */ - memset(trans_pcie->ict_tbl_vir, 0, + memset(priv->ict_tbl_vir, 0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); - trans_pcie->ict_index = 0; + priv->ict_index = 0; /* add periodic RX interrupt */ - trans_pcie->inta_mask |= CSR_INT_BIT_RX_PERIODIC; + priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; return 0; } /* Device is going up inform it about using ICT interrupt table, * also we need to tell the driver to start using ICT interrupt. */ -int iwl_reset_ict(struct iwl_trans *trans) +int iwl_reset_ict(struct iwl_priv *priv) { u32 val; unsigned long flags; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - if (!trans_pcie->ict_tbl_vir) + if (!priv->ict_tbl_vir) return 0; - spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_disable_interrupts(trans); + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); - memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); - val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT; + val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; val |= CSR_DRAM_INT_TBL_ENABLE; val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X " + IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " "aligned dma address %Lx\n", val, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma); + (unsigned long long)priv->aligned_ict_tbl_dma); - iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val); - trans_pcie->use_ict = true; - trans_pcie->ict_index = 0; - iwl_write32(bus(trans), CSR_INT, trans_pcie->inta_mask); - iwl_enable_interrupts(trans); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); + priv->use_ict = true; + priv->ict_index = 0; + iwl_write32(priv, CSR_INT, priv->inta_mask); + iwl_enable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); return 0; } /* Device is going down disable ict interrupt usage */ -void iwl_disable_ict(struct iwl_trans *trans) +void iwl_disable_ict(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - unsigned long flags; - spin_lock_irqsave(&trans->shrd->lock, flags); - trans_pcie->use_ict = false; - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); + priv->use_ict = false; + spin_unlock_irqrestore(&priv->lock, flags); } static irqreturn_t iwl_isr(int irq, void *data) { - struct iwl_trans *trans = data; - struct iwl_trans_pcie *trans_pcie; + struct iwl_priv *priv = data; u32 inta, inta_mask; unsigned long flags; #ifdef CONFIG_IWLWIFI_DEBUG u32 inta_fh; #endif - if (!trans) + if (!priv) return IRQ_NONE; - trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); /* Discover which interrupts are active/pending */ - inta = iwl_read32(bus(trans), CSR_INT); + inta = iwl_read32(priv, CSR_INT); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ if (!inta) { - IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); goto none; } if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { /* Hardware disappeared. It might have already raised * an interrupt */ - IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta); + IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); goto unplugged; } #ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) { - inta_fh = iwl_read32(bus(trans), CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " + if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " "fh 0x%08x\n", inta, inta_mask, inta_fh); } #endif - trans_pcie->inta |= inta; + priv->inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) - tasklet_schedule(&trans_pcie->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) - iwl_enable_interrupts(trans); + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && + !priv->inta) + iwl_enable_interrupts(priv); unplugged: - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_HANDLED; none: /* re-enable interrupts here since we don't have anything to service. */ /* only Re-enable if disabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) - iwl_enable_interrupts(trans); + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_NONE; } @@ -1320,53 +884,50 @@ static irqreturn_t iwl_isr(int irq, void *data) */ irqreturn_t iwl_isr_ict(int irq, void *data) { - struct iwl_trans *trans = data; - struct iwl_trans_pcie *trans_pcie; + struct iwl_priv *priv = data; u32 inta, inta_mask; u32 val = 0; unsigned long flags; - if (!trans) + if (!priv) return IRQ_NONE; - trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - /* dram interrupt table not set yet, * use legacy interrupt. */ - if (!trans_pcie->use_ict) + if (!priv->use_ict) return iwl_isr(irq, data); - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Disable (but don't clear!) interrupts here to avoid * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(bus(trans), CSR_INT_MASK); /* just for debug */ - iwl_write32(bus(trans), CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, * or due to sporadic interrupts thrown from our NIC. */ - if (!trans_pcie->ict_tbl[trans_pcie->ict_index]) { - IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n"); + if (!priv->ict_tbl[priv->ict_index]) { + IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); goto none; } /* read all entries that not 0 start with ict_index */ - while (trans_pcie->ict_tbl[trans_pcie->ict_index]) { + while (priv->ict_tbl[priv->ict_index]) { - val |= le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]); - IWL_DEBUG_ISR(trans, "ICT index %d value 0x%08X\n", - trans_pcie->ict_index, + val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); + IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", + priv->ict_index, le32_to_cpu( - trans_pcie->ict_tbl[trans_pcie->ict_index])); - trans_pcie->ict_tbl[trans_pcie->ict_index] = 0; - trans_pcie->ict_index = - iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT); + priv->ict_tbl[priv->ict_index])); + priv->ict_tbl[priv->ict_index] = 0; + priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, + ICT_COUNT); } @@ -1385,35 +946,34 @@ irqreturn_t iwl_isr_ict(int irq, void *data) val |= 0x8000; inta = (0xff & val) | ((0xff00 & val) << 16); - IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", + IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", inta, inta_mask, val); - inta &= trans_pcie->inta_mask; - trans_pcie->inta |= inta; + inta &= priv->inta_mask; + priv->inta |= inta; /* iwl_irq_tasklet() will service interrupts and re-enable them */ if (likely(inta)) - tasklet_schedule(&trans_pcie->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) { + tasklet_schedule(&priv->irq_tasklet); + else if (test_bit(STATUS_INT_ENABLED, &priv->status) && + !priv->inta) { /* Allow interrupt if was disabled by this handler and * no tasklet was schedules, We should not enable interrupt, * tasklet will enable it. */ - iwl_enable_interrupts(trans); + iwl_enable_interrupts(priv); } - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_HANDLED; none: /* re-enable interrupts here since we don't have anything to service. * only Re-enable if disabled by irq. */ - if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) && - !trans_pcie->inta) - iwl_enable_interrupts(trans); + if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) + iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_NONE; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 5dd6a6d1dfd7..a6b2b1db0b1d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "iwl-agn.h" #include "iwl-dev.h" @@ -40,13 +41,11 @@ /** * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ -void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, +void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq, u16 byte_cnt) { - struct iwlagn_scd_bc_tbl *scd_bc_tbl; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; int write_ptr = txq->q.write_ptr; int txq_id = txq->q.id; u8 sec_ctl = 0; @@ -54,8 +53,6 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; __le16 bc_ent; - scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; - WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; @@ -85,7 +82,7 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, /** * iwl_txq_update_write_ptr - Send new write index to hardware */ -void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) +void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) { u32 reg = 0; int txq_id = txq->q.id; @@ -93,28 +90,28 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) if (txq->need_update == 0) return; - if (hw_params(trans).shadow_reg_enable) { + if (priv->cfg->base_params->shadow_reg_enable) { /* shadow register enabled */ - iwl_write32(bus(trans), HBUS_TARG_WRPTR, + iwl_write32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } else { /* if we're trying to save power */ - if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { + if (test_bit(STATUS_POWER_PMI, &priv->status)) { /* wake up nic if it's powered down ... * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ - reg = iwl_read32(bus(trans), CSR_UCODE_DRV_GP1); + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(trans, + IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup," " GP1 = 0x%x\n", txq_id, reg); - iwl_set_bit(bus(trans), CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); return; } - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, + iwl_write_direct32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); /* @@ -123,7 +120,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) * trying to tx (during RFKILL, we're not trying to tx). */ } else - iwl_write32(bus(trans), HBUS_TARG_WRPTR, + iwl_write32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); } txq->need_update = 0; @@ -168,7 +165,7 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) return tfd->num_tbs & 0x1f; } -static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, +static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, struct iwl_tfd *tfd, enum dma_data_direction dma_dir) { int i; @@ -178,56 +175,56 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, num_tbs = iwl_tfd_get_num_tbs(tfd); if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); + IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); /* @todo issue fatal error, it is quite serious situation */ return; } /* Unmap tx_cmd */ if (num_tbs) - dma_unmap_single(bus(trans)->dev, + dma_unmap_single(priv->bus->dev, dma_unmap_addr(meta, mapping), dma_unmap_len(meta, len), DMA_BIDIRECTIONAL); /* Unmap chunks, if any. */ for (i = 1; i < num_tbs; i++) - dma_unmap_single(bus(trans)->dev, iwl_tfd_tb_get_addr(tfd, i), + dma_unmap_single(priv->bus->dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), dma_dir); } /** * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * @trans - transport private data + * @priv - driver private data * @txq - tx queue * @index - the index of the TFD to be freed * * Does NOT advance any TFD circular buffer read/write indexes * Does NOT free the TFD itself (which is within circular buffer) */ -void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, int index) { struct iwl_tfd *tfd_tmp = txq->tfds; - iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], + iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index], DMA_TO_DEVICE); /* free SKB */ - if (txq->skbs) { + if (txq->txb) { struct sk_buff *skb; - skb = txq->skbs[index]; + skb = txq->txb[index].skb; /* can be called from irqs-disabled context */ if (skb) { dev_kfree_skb_any(skb); - txq->skbs[index] = NULL; + txq->txb[index].skb = NULL; } } } -int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, dma_addr_t addr, u16 len, u8 reset) @@ -247,7 +244,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, /* Each TFD can point to a maximum 20 Tx buffers */ if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(trans, "Error can not send more than %d chunks\n", + IWL_ERR(priv, "Error can not send more than %d chunks\n", IWL_NUM_OF_TBS); return -EINVAL; } @@ -256,7 +253,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans, return -EINVAL; if (unlikely(addr & ~IWL_TX_DMA_MASK)) - IWL_ERR(trans, "Unaligned address = %llx\n", + IWL_ERR(priv, "Unaligned address = %llx\n", (unsigned long long)addr); iwl_tfd_set_tb(tfd, num_tbs, addr, len); @@ -305,7 +302,8 @@ int iwl_queue_space(const struct iwl_queue *q) /** * iwl_queue_init - Initialize queue's high/low-water and read/write indexes */ -int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id) +int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, + int count, int slots_num, u32 id) { q->n_bd = count; q->n_window = slots_num; @@ -334,12 +332,16 @@ int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id) return 0; } -static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, +/*TODO: this functions should NOT be exported from trans module - export it + * until the reclaim flow will be brought to the transport module too. + * Add a declaration to make sparse happy */ +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); + +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, struct iwl_tx_queue *txq) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->scd_bc_tbls.addr; + struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; int txq_id = txq->q.id; int read_ptr = txq->q.read_ptr; u8 sta_id = 0; @@ -347,7 +349,7 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - if (txq_id != trans->shrd->cmd_queue) + if (txq_id != priv->cmd_queue) sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; bc_ent = cpu_to_le16(1 | (sta_id << 12)); @@ -358,61 +360,56 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; } -static int iwlagn_tx_queue_set_q2ratid(struct iwl_trans *trans, u16 ra_tid, +static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, u16 txq_id) { u32 tbl_dw_addr; u32 tbl_dw; u16 scd_q2ratid; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; - tbl_dw_addr = trans_pcie->scd_base_addr + + tbl_dw_addr = priv->scd_base_addr + SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); - tbl_dw = iwl_read_targ_mem(bus(trans), tbl_dw_addr); + tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); if (txq_id & 0x1) tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); else tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - iwl_write_targ_mem(bus(trans), tbl_dw_addr, tbl_dw); + iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); return 0; } -static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) +static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) { /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(bus(trans), + iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } -void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, +void iwl_trans_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index) { - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, + iwl_write_direct32(priv, HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(priv, SCD_QUEUE_RDPTR(txq_id), index); } -void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, +void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, struct iwl_tx_queue *txq, int tx_fifo_id, int scd_retry) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int txq_id = txq->q.id; - int active = - test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0; + int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - iwl_write_prph(bus(trans), SCD_QUEUE_STATUS_BITS(txq_id), + iwl_write_prph(priv, SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | @@ -420,75 +417,55 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, txq->sched_retry = scd_retry; - IWL_DEBUG_INFO(trans, "%s %s Queue %d on FIFO %d\n", + IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", active ? "Activate" : "Deactivate", scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); } -static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, - u8 ctx, u16 tid) -{ - const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx]; - if (likely(tid < ARRAY_SIZE(tid_to_ac))) - return ac_to_fifo[tid_to_ac[tid]]; - - /* no support for TIDs 8-15 yet */ - return -EINVAL; -} - -void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid, int frame_limit) +void iwl_trans_txq_agg_setup(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit) { int tx_fifo, txq_id, ssn_idx; u16 ra_tid; unsigned long flags; struct iwl_tid_data *tid_data; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - if (WARN_ON(sta_id == IWL_INVALID_STATION)) return; - if (WARN_ON(tid >= IWL_MAX_TID_COUNT)) + if (WARN_ON(tid >= MAX_TID_COUNT)) return; - tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid); - if (WARN_ON(tx_fifo < 0)) { - IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo); - return; - } - - spin_lock_irqsave(&trans->shrd->sta_lock, flags); - tid_data = &trans->shrd->tid_data[sta_id][tid]; + spin_lock_irqsave(&priv->sta_lock, flags); + tid_data = &priv->stations[sta_id].tid[tid]; ssn_idx = SEQ_TO_SN(tid_data->seq_number); txq_id = tid_data->agg.txq_id; - spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); + tx_fifo = tid_data->agg.tx_fifo; + spin_unlock_irqrestore(&priv->sta_lock, flags); ra_tid = BUILD_RAxTID(sta_id, tid); - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Stop this Tx queue before configuring it */ - iwlagn_tx_queue_stop_scheduler(trans, txq_id); + iwlagn_tx_queue_stop_scheduler(priv, txq_id); /* Map receiver-address / traffic-ID to this queue */ - iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); + iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(bus(trans), SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - trans_pcie->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - iwl_trans_set_wr_ptrs(trans, txq_id, ssn_idx); + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), ((frame_limit << @@ -498,159 +475,40 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - iwl_set_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], - tx_fifo, 1); - - trans_pcie->txq[txq_id].sta_id = sta_id; - trans_pcie->txq[txq_id].tid = tid; - - spin_unlock_irqrestore(&trans->shrd->lock, flags); -} - -/* - * Find first available (lowest unused) Tx Queue, mark it "active". - * Called only when finding queue for aggregation. - * Should never return anything < 7, because they should already - * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) - */ -static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int txq_id; - - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) - if (!test_and_set_bit(txq_id, - &trans_pcie->txq_ctx_active_msk)) - return txq_id; - return -1; -} - -int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid, u16 *ssn) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tid_data *tid_data; - unsigned long flags; - u16 txq_id; - struct iwl_priv *priv = priv(trans); - - txq_id = iwlagn_txq_ctx_activate_free(trans); - if (txq_id == -1) { - IWL_ERR(trans, "No free aggregation queue available\n"); - return -ENXIO; - } - - spin_lock_irqsave(&trans->shrd->sta_lock, flags); - tid_data = &trans->shrd->tid_data[sta_id][tid]; - *ssn = SEQ_TO_SN(tid_data->seq_number); - tid_data->agg.txq_id = txq_id; - iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id); - - tid_data = &trans->shrd->tid_data[sta_id][tid]; - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(trans, "HW queue is empty\n"); - tid_data->agg.state = IWL_AGG_ON; - iwl_start_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid); - } else { - IWL_DEBUG_HT(trans, "HW queue is NOT empty: %d packets in HW" - "queue\n", tid_data->tfds_in_queue); - tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; - } - spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); - - return 0; -} - -void iwl_trans_pcie_txq_agg_disable(struct iwl_trans *trans, int txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - iwlagn_tx_queue_stop_scheduler(trans, txq_id); - - iwl_clear_bits_prph(bus(trans), SCD_AGGR_SEL, (1 << txq_id)); - - trans_pcie->txq[txq_id].q.read_ptr = 0; - trans_pcie->txq[txq_id].q.write_ptr = 0; - /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwl_trans_set_wr_ptrs(trans, txq_id, 0); + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - iwl_clear_bits_prph(bus(trans), SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(trans_pcie, txq_id); - iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0); + spin_unlock_irqrestore(&priv->lock, flags); } -int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid) +int iwl_trans_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - unsigned long flags; - int read_ptr, write_ptr; - struct iwl_tid_data *tid_data; - int txq_id; - - spin_lock_irqsave(&trans->shrd->sta_lock, flags); - - tid_data = &trans->shrd->tid_data[sta_id][tid]; - txq_id = tid_data->agg.txq_id; - if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || (IWLAGN_FIRST_AMPDU_QUEUE + - hw_params(trans).num_ampdu_queues <= txq_id)) { - IWL_ERR(trans, + priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) { + IWL_ERR(priv, "queue number out of range: %d, must be %d to %d\n", txq_id, IWLAGN_FIRST_AMPDU_QUEUE, IWLAGN_FIRST_AMPDU_QUEUE + - hw_params(trans).num_ampdu_queues - 1); - spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); + priv->cfg->base_params->num_of_ampdu_queues - 1); return -EINVAL; } - switch (trans->shrd->tid_data[sta_id][tid].agg.state) { - case IWL_EMPTYING_HW_QUEUE_ADDBA: - /* - * This can happen if the peer stops aggregation - * again before we've had a chance to drain the - * queue we selected previously, i.e. before the - * session was really started completely. - */ - IWL_DEBUG_HT(trans, "AGG stop before setup done\n"); - goto turn_off; - case IWL_AGG_ON: - break; - default: - IWL_WARN(trans, "Stopping AGG while state not ON" - "or starting\n"); - } - - write_ptr = trans_pcie->txq[txq_id].q.write_ptr; - read_ptr = trans_pcie->txq[txq_id].q.read_ptr; - - /* The queue is not empty */ - if (write_ptr != read_ptr) { - IWL_DEBUG_HT(trans, "Stopping a non empty AGG HW QUEUE\n"); - trans->shrd->tid_data[sta_id][tid].agg.state = - IWL_EMPTYING_HW_QUEUE_DELBA; - spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); - return 0; - } - - IWL_DEBUG_HT(trans, "HW queue is empty\n"); -turn_off: - trans->shrd->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; + iwlagn_tx_queue_stop_scheduler(priv, txq_id); - /* do not restore/save irqs */ - spin_unlock(&trans->shrd->sta_lock); - spin_lock(&trans->shrd->lock); + iwl_clear_bits_prph(priv, SCD_AGGR_SEL, (1 << txq_id)); - iwl_trans_pcie_txq_agg_disable(trans, txq_id); - - spin_unlock_irqrestore(&trans->shrd->lock, flags); + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + /* supposes that ssn_idx is valid (!= 0xFFF) */ + iwl_trans_set_wr_ptrs(priv, txq_id, ssn_idx); - iwl_stop_tx_ba_trans_ready(priv(trans), ctx, sta_id, tid); + iwl_clear_bits_prph(priv, SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_txq_ctx_deactivate(priv, txq_id); + iwl_trans_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); return 0; } @@ -666,10 +524,9 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, * failed. On success, it turns the index (> 0) of command in the * command queue. */ -static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; + struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; struct iwl_queue *q = &txq->q; struct iwl_device_cmd *out_cmd; struct iwl_cmd_meta *out_meta; @@ -687,14 +544,14 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) int trace_idx; #endif - if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { - IWL_WARN(trans, "fw recovery, no hcmd send\n"); + if (test_bit(STATUS_FW_ERROR, &priv->status)) { + IWL_WARN(priv, "fw recovery, no hcmd send\n"); return -EIO; } - if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) && + if ((priv->ucode_owner == IWL_OWNERSHIP_TM) && !(cmd->flags & CMD_ON_DEMAND)) { - IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n"); + IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n"); return -EIO; } @@ -727,22 +584,22 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) return -EINVAL; - if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) { - IWL_WARN(trans, "Not sending command - %s KILL\n", - iwl_is_rfkill(trans->shrd) ? "RF" : "CT"); + if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { + IWL_WARN(priv, "Not sending command - %s KILL\n", + iwl_is_rfkill(priv) ? "RF" : "CT"); return -EIO; } - spin_lock_irqsave(&trans->hcmd_lock, flags); + spin_lock_irqsave(&priv->hcmd_lock, flags); if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock_irqrestore(&priv->hcmd_lock, flags); - IWL_ERR(trans, "No space in command queue\n"); - is_ct_kill = iwl_check_for_ct_kill(priv(trans)); + IWL_ERR(priv, "No space in command queue\n"); + is_ct_kill = iwl_check_for_ct_kill(priv); if (!is_ct_kill) { - IWL_ERR(trans, "Restarting adapter queue is full\n"); - iwlagn_fw_error(priv(trans), false); + IWL_ERR(priv, "Restarting adapter due to queue full\n"); + iwlagn_fw_error(priv, false); } return -ENOSPC; } @@ -761,9 +618,8 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) out_cmd->hdr.cmd = cmd->id; out_cmd->hdr.flags = 0; - out_cmd->hdr.sequence = - cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) | - INDEX_TO_SEQ(q->write_ptr)); + out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | + INDEX_TO_SEQ(q->write_ptr)); /* and copy the data that needs to be copied */ @@ -777,16 +633,16 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) cmd_dest += cmd->len[i]; } - IWL_DEBUG_HC(trans, "Sending command %s (#%x), seq: 0x%04X, " + IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " "%d bytes at %d[%d]:%d\n", get_cmd_string(out_cmd->hdr.cmd), out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), cmd_size, - q->write_ptr, idx, trans->shrd->cmd_queue); + q->write_ptr, idx, priv->cmd_queue); - phys_addr = dma_map_single(bus(trans)->dev, &out_cmd->hdr, copy_size, + phys_addr = dma_map_single(priv->bus->dev, &out_cmd->hdr, copy_size, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { + if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { idx = -ENOMEM; goto out; } @@ -794,8 +650,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) dma_unmap_addr_set(out_meta, mapping, phys_addr); dma_unmap_len_set(out_meta, len, copy_size); - iwlagn_txq_attach_buf_to_tfd(trans, txq, - phys_addr, copy_size, 1); + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING trace_bufs[0] = &out_cmd->hdr; trace_lens[0] = copy_size; @@ -807,18 +662,17 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) continue; if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) continue; - phys_addr = dma_map_single(bus(trans)->dev, - (void *)cmd->data[i], + phys_addr = dma_map_single(priv->bus->dev, (void *)cmd->data[i], cmd->len[i], DMA_BIDIRECTIONAL); - if (dma_mapping_error(bus(trans)->dev, phys_addr)) { - iwlagn_unmap_tfd(trans, out_meta, + if (dma_mapping_error(priv->bus->dev, phys_addr)) { + iwlagn_unmap_tfd(priv, out_meta, &txq->tfds[q->write_ptr], DMA_BIDIRECTIONAL); idx = -ENOMEM; goto out; } - iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, cmd->len[i], 0); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING trace_bufs[trace_idx] = cmd->data[i]; @@ -834,7 +688,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) /* check that tracing gets all possible blocks */ BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); #ifdef CONFIG_IWLWIFI_DEVICE_TRACING - trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags, + trace_iwlwifi_dev_hcmd(priv, cmd->flags, trace_bufs[0], trace_lens[0], trace_bufs[1], trace_lens[1], trace_bufs[2], trace_lens[2]); @@ -842,10 +696,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(trans, txq); + iwl_txq_update_write_ptr(priv, txq); out: - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock_irqrestore(&priv->hcmd_lock, flags); return idx; } @@ -858,9 +712,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) */ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans(priv)); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; int nfreed = 0; @@ -900,19 +752,17 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) int cmd_index; struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; - struct iwl_trans *trans = trans(priv); - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue]; + struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; unsigned long flags; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (WARN(txq_id != trans->shrd->cmd_queue, + if (WARN(txq_id != priv->cmd_queue, "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", - txq_id, trans->shrd->cmd_queue, sequence, - trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr, - trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) { + txq_id, priv->cmd_queue, sequence, + priv->txq[priv->cmd_queue].q.read_ptr, + priv->txq[priv->cmd_queue].q.write_ptr)) { iwl_print_hex_error(priv, pkt, 32); return; } @@ -921,8 +771,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; - iwlagn_unmap_tfd(trans, meta, &txq->tfds[index], - DMA_BIDIRECTIONAL); + iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { @@ -931,20 +780,20 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) } else if (meta->callback) meta->callback(priv, cmd, pkt); - spin_lock_irqsave(&trans->hcmd_lock, flags); + spin_lock_irqsave(&priv->hcmd_lock, flags); iwl_hcmd_queue_reclaim(priv, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { - clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->hdr.cmd)); wake_up_interruptible(&priv->wait_command_queue); } meta->flags = 0; - spin_unlock_irqrestore(&trans->hcmd_lock, flags); + spin_unlock_irqrestore(&priv->hcmd_lock, flags); } const char *get_cmd_string(u8 cmd) @@ -1055,7 +904,7 @@ static void iwl_generic_cmd_callback(struct iwl_priv *priv, #endif } -static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { int ret; @@ -1067,78 +916,77 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (!cmd->callback) cmd->callback = iwl_generic_cmd_callback; - if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status)) + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EBUSY; - ret = iwl_enqueue_hcmd(trans, cmd); + ret = iwl_enqueue_hcmd(priv, cmd); if (ret < 0) { - IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", + IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; } return 0; } -static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int cmd_idx; int ret; - lockdep_assert_held(&trans->shrd->mutex); + lockdep_assert_held(&priv->mutex); /* A synchronous command can not have a callback set. */ if (WARN_ON(cmd->callback)) return -EINVAL; - IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", + IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); - set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", + set_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->id)); - cmd_idx = iwl_enqueue_hcmd(trans, cmd); + cmd_idx = iwl_enqueue_hcmd(priv, cmd); if (cmd_idx < 0) { ret = cmd_idx; - clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; } - ret = wait_event_interruptible_timeout(priv(trans)->wait_command_queue, - !test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status), + ret = wait_event_interruptible_timeout(priv->wait_command_queue, + !test_bit(STATUS_HCMD_ACTIVE, &priv->status), HOST_COMPLETE_TIMEOUT); if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) { - IWL_ERR(trans, + if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { + IWL_ERR(priv, "Error sending %s: time out after %dms.\n", get_cmd_string(cmd->id), jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); - IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command" + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command" "%s\n", get_cmd_string(cmd->id)); ret = -ETIMEDOUT; goto cancel; } } - if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) { - IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n", + if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { + IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", get_cmd_string(cmd->id)); ret = -ECANCELED; goto fail; } - if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { - IWL_ERR(trans, "Command %s failed: FW Error\n", + if (test_bit(STATUS_FW_ERROR, &priv->status)) { + IWL_ERR(priv, "Command %s failed: FW Error\n", get_cmd_string(cmd->id)); ret = -EIO; goto fail; } if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { - IWL_ERR(trans, "Error: Response NULL in '%s'\n", + IWL_ERR(priv, "Error: Response NULL in '%s'\n", get_cmd_string(cmd->id)); ret = -EIO; goto cancel; @@ -1154,28 +1002,28 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) * in later, it will possibly set an invalid * address (cmd->meta.source). */ - trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &= + priv->txq[priv->cmd_queue].meta[cmd_idx].flags &= ~CMD_WANT_SKB; } fail: if (cmd->reply_page) { - iwl_free_pages(trans->shrd, cmd->reply_page); + iwl_free_pages(priv, cmd->reply_page); cmd->reply_page = 0; } return ret; } -int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) +int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { if (cmd->flags & CMD_ASYNC) - return iwl_send_cmd_async(trans, cmd); + return iwl_send_cmd_async(priv, cmd); - return iwl_send_cmd_sync(trans, cmd); + return iwl_send_cmd_sync(priv, cmd); } -int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, - u16 len, const void *data) +int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, + const void *data) { struct iwl_host_cmd cmd = { .id = id, @@ -1184,53 +1032,5 @@ int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, .flags = flags, }; - return iwl_trans_pcie_send_cmd(trans, &cmd); -} - -/* Frees buffers until index _not_ inclusive */ -int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, - struct sk_buff_head *skbs) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; - struct iwl_queue *q = &txq->q; - int last_to_free; - int freed = 0; - - /*Since we free until index _not_ inclusive, the one before index is - * the last we will free. This one must be used */ - last_to_free = iwl_queue_dec_wrap(index, q->n_bd); - - if ((index >= q->n_bd) || - (iwl_queue_used(q, last_to_free) == 0)) { - IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), " - "last_to_free %d is out of range [0-%d] %d %d.\n", - __func__, txq_id, last_to_free, q->n_bd, - q->write_ptr, q->read_ptr); - return 0; - } - - IWL_DEBUG_TX_REPLY(trans, "reclaim: [%d, %d, %d]\n", txq_id, - q->read_ptr, index); - - if (WARN_ON(!skb_queue_empty(skbs))) - return 0; - - for (; - q->read_ptr != index; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - - if (WARN_ON_ONCE(txq->skbs[txq->q.read_ptr] == NULL)) - continue; - - __skb_queue_tail(skbs, txq->skbs[txq->q.read_ptr]); - - txq->skbs[txq->q.read_ptr] = NULL; - - iwlagn_txq_inval_byte_cnt_tbl(trans, txq); - - iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr); - freed++; - } - return freed; + return iwl_send_cmd(priv, &cmd); } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.c index cec13adb018e..3001bfb46e25 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -60,11 +60,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ -#include -#include -#include -#include - #include "iwl-dev.h" #include "iwl-trans.h" #include "iwl-core.h" @@ -72,16 +67,14 @@ #include "iwl-trans-int-pcie.h" /*TODO remove uneeded includes when the transport layer tx_free will be here */ #include "iwl-agn.h" -#include "iwl-shared.h" +#include "iwl-core.h" -static int iwl_trans_rx_alloc(struct iwl_trans *trans) +static int iwl_trans_rx_alloc(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - struct device *dev = bus(trans)->dev; + struct iwl_rx_queue *rxq = &priv->rxq; + struct device *dev = priv->bus->dev; - memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); + memset(&priv->rxq, 0, sizeof(priv->rxq)); spin_lock_init(&rxq->lock); INIT_LIST_HEAD(&rxq->rx_free); @@ -115,11 +108,9 @@ static int iwl_trans_rx_alloc(struct iwl_trans *trans) return -ENOMEM; } -static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) +static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; + struct iwl_rx_queue *rxq = &priv->rxq; int i; /* Fill the rx_used queue with _all_ of the Rx buffers */ @@ -127,18 +118,17 @@ static void iwl_trans_rxq_free_rx_bufs(struct iwl_trans *trans) /* In the reset function, these buffers may have been allocated * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].page != NULL) { - dma_unmap_page(bus(trans)->dev, rxq->pool[i].page_dma, - PAGE_SIZE << hw_params(trans).rx_page_order, + dma_unmap_page(priv->bus->dev, rxq->pool[i].page_dma, + PAGE_SIZE << priv->hw_params.rx_page_order, DMA_FROM_DEVICE); - __free_pages(rxq->pool[i].page, - hw_params(trans).rx_page_order); + __iwl_free_pages(priv, rxq->pool[i].page); rxq->pool[i].page = NULL; } list_add_tail(&rxq->pool[i].list, &rxq->rx_used); } } -static void iwl_trans_rx_hw_init(struct iwl_trans *trans, +static void iwl_trans_rx_hw_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) { u32 rb_size; @@ -153,17 +143,17 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; /* Stop Rx DMA */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); /* Reset driver's Rx queue write index */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_RBDCB_BASE_REG, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, (u32)(rxq->bd_dma >> 8)); /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(bus(trans), FH_RSCSR_CHNL0_STTS_WPTR_REG, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, rxq->rb_stts_dma >> 4); /* Enable Rx DMA @@ -174,7 +164,7 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, * RB timeout 0x10 * 256 RBDs */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | @@ -184,20 +174,17 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(bus(trans), CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } -static int iwl_rx_init(struct iwl_trans *trans) +static int iwl_rx_init(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - + struct iwl_rx_queue *rxq = &priv->rxq; int i, err; unsigned long flags; if (!rxq->bd) { - err = iwl_trans_rx_alloc(trans); + err = iwl_trans_rx_alloc(priv); if (err) return err; } @@ -206,7 +193,7 @@ static int iwl_rx_init(struct iwl_trans *trans) INIT_LIST_HEAD(&rxq->rx_free); INIT_LIST_HEAD(&rxq->rx_used); - iwl_trans_rxq_free_rx_bufs(trans); + iwl_trans_rxq_free_rx_bufs(priv); for (i = 0; i < RX_QUEUE_SIZE; i++) rxq->queue[i] = NULL; @@ -218,68 +205,65 @@ static int iwl_rx_init(struct iwl_trans *trans) rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); - iwlagn_rx_replenish(trans); + iwlagn_rx_replenish(priv); - iwl_trans_rx_hw_init(trans, rxq); + iwl_trans_rx_hw_init(priv, rxq); - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); rxq->need_update = 1; - iwl_rx_queue_update_write_ptr(trans, rxq); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + iwl_rx_queue_update_write_ptr(priv, rxq); + spin_unlock_irqrestore(&priv->lock, flags); return 0; } -static void iwl_trans_pcie_rx_free(struct iwl_trans *trans) +static void iwl_trans_rx_free(struct iwl_priv *priv) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - + struct iwl_rx_queue *rxq = &priv->rxq; unsigned long flags; /*if rxq->bd is NULL, it means that nothing has been allocated, * exit now */ if (!rxq->bd) { - IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); + IWL_DEBUG_INFO(priv, "Free NULL rx context\n"); return; } spin_lock_irqsave(&rxq->lock, flags); - iwl_trans_rxq_free_rx_bufs(trans); + iwl_trans_rxq_free_rx_bufs(priv); spin_unlock_irqrestore(&rxq->lock, flags); - dma_free_coherent(bus(trans)->dev, sizeof(__le32) * RX_QUEUE_SIZE, + dma_free_coherent(priv->bus->dev, sizeof(__le32) * RX_QUEUE_SIZE, rxq->bd, rxq->bd_dma); memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); rxq->bd = NULL; if (rxq->rb_stts) - dma_free_coherent(bus(trans)->dev, + dma_free_coherent(priv->bus->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); else - IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); + IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n"); memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); rxq->rb_stts = NULL; } -static int iwl_trans_rx_stop(struct iwl_trans *trans) +static int iwl_trans_rx_stop(struct iwl_priv *priv) { /* stop Rx DMA */ - iwl_write_direct32(bus(trans), FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - return iwl_poll_direct_bit(bus(trans), FH_MEM_RSSR_RX_STATUS_REG, + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + return iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); } -static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, +static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, struct iwl_dma_ptr *ptr, size_t size) { if (WARN_ON(ptr->addr)) return -EINVAL; - ptr->addr = dma_alloc_coherent(bus(trans)->dev, size, + ptr->addr = dma_alloc_coherent(priv->bus->dev, size, &ptr->dma, GFP_KERNEL); if (!ptr->addr) return -ENOMEM; @@ -287,24 +271,23 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_trans *trans, return 0; } -static inline void iwlagn_free_dma_ptr(struct iwl_trans *trans, +static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, struct iwl_dma_ptr *ptr) { if (unlikely(!ptr->addr)) return; - dma_free_coherent(bus(trans)->dev, ptr->size, ptr->addr, ptr->dma); + dma_free_coherent(priv->bus->dev, ptr->size, ptr->addr, ptr->dma); memset(ptr, 0, sizeof(*ptr)); } -static int iwl_trans_txq_alloc(struct iwl_trans *trans, - struct iwl_tx_queue *txq, int slots_num, - u32 txq_id) +static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int slots_num, u32 txq_id) { - size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; + size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; int i; - if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds)) + if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) return -EINVAL; txq->q.n_window = slots_num; @@ -317,46 +300,45 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, if (!txq->meta || !txq->cmd) goto error; - if (txq_id == trans->shrd->cmd_queue) - for (i = 0; i < slots_num; i++) { - txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), - GFP_KERNEL); - if (!txq->cmd[i]) - goto error; - } + for (i = 0; i < slots_num; i++) { + txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), + GFP_KERNEL); + if (!txq->cmd[i]) + goto error; + } /* Alloc driver data array and TFD circular buffer */ /* Driver private data, only for Tx (not command) queues, * not shared with device. */ - if (txq_id != trans->shrd->cmd_queue) { - txq->skbs = kzalloc(sizeof(txq->skbs[0]) * + if (txq_id != priv->cmd_queue) { + txq->txb = kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, GFP_KERNEL); - if (!txq->skbs) { - IWL_ERR(trans, "kmalloc for auxiliary BD " + if (!txq->txb) { + IWL_ERR(priv, "kmalloc for auxiliary BD " "structures failed\n"); goto error; } } else { - txq->skbs = NULL; + txq->txb = NULL; } /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = dma_alloc_coherent(bus(trans)->dev, tfd_sz, - &txq->q.dma_addr, GFP_KERNEL); + txq->tfds = dma_alloc_coherent(priv->bus->dev, tfd_sz, &txq->q.dma_addr, + GFP_KERNEL); if (!txq->tfds) { - IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); + IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz); goto error; } txq->q.id = txq_id; return 0; error: - kfree(txq->skbs); - txq->skbs = NULL; + kfree(txq->txb); + txq->txb = NULL; /* since txq->cmd has been zeroed, * all non allocated cmd[i] will be NULL */ - if (txq->cmd && txq_id == trans->shrd->cmd_queue) + if (txq->cmd) for (i = 0; i < slots_num; i++) kfree(txq->cmd[i]); kfree(txq->meta); @@ -368,7 +350,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans, } -static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, +static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { int ret; @@ -389,7 +371,7 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); /* Initialize queue's high/low-water marks, and head/tail indexes */ - ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num, + ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); if (ret) return ret; @@ -398,7 +380,7 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, * Tell nic where to find circular buffer of Tx Frame Descriptors for * given Tx queue, and enable the DMA channel used for that queue. * Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(bus(trans), FH_MEM_CBBC_QUEUE(txq_id), + iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8); return 0; @@ -407,10 +389,9 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, /** * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's */ -static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) +static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; if (!q->n_bd) @@ -418,7 +399,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) while (q->write_ptr != q->read_ptr) { /* The read_ptr needs to bound by q->n_window */ - iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr)); + iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr)); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } } @@ -431,33 +412,30 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) +static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; - struct device *dev = bus(trans)->dev; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct device *dev = priv->bus->dev; int i; if (WARN_ON(!txq)) return; - iwl_tx_queue_unmap(trans, txq_id); + iwl_tx_queue_unmap(priv, txq_id); /* De-alloc array of command/tx buffers */ - - if (txq_id == trans->shrd->cmd_queue) - for (i = 0; i < txq->q.n_window; i++) - kfree(txq->cmd[i]); + for (i = 0; i < txq->q.n_window; i++) + kfree(txq->cmd[i]); /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) { - dma_free_coherent(dev, sizeof(struct iwl_tfd) * + dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd, txq->tfds, txq->q.dma_addr); memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); } /* De-alloc array of per-TFD driver data */ - kfree(txq->skbs); - txq->skbs = NULL; + kfree(txq->txb); + txq->txb = NULL; /* deallocate arrays */ kfree(txq->cmd); @@ -474,24 +452,22 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id) * * Destroy all TX DMA queues and structures */ -static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) +static void iwl_trans_tx_free(struct iwl_priv *priv) { int txq_id; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); /* Tx queues */ - if (trans_pcie->txq) { - for (txq_id = 0; - txq_id < hw_params(trans).max_txq_num; txq_id++) - iwl_tx_queue_free(trans, txq_id); + if (priv->txq) { + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + iwl_tx_queue_free(priv, txq_id); } - kfree(trans_pcie->txq); - trans_pcie->txq = NULL; + kfree(priv->txq); + priv->txq = NULL; - iwlagn_free_dma_ptr(trans, &trans_pcie->kw); + iwlagn_free_dma_ptr(priv, &priv->kw); - iwlagn_free_dma_ptr(trans, &trans_pcie->scd_bc_tbls); + iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); } /** @@ -501,52 +477,48 @@ static void iwl_trans_pcie_tx_free(struct iwl_trans *trans) * @param priv * @return error code */ -static int iwl_trans_tx_alloc(struct iwl_trans *trans) +static int iwl_trans_tx_alloc(struct iwl_priv *priv) { int ret; int txq_id, slots_num; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - u16 scd_bc_tbls_size = hw_params(trans).max_txq_num * - sizeof(struct iwlagn_scd_bc_tbl); /*It is not allowed to alloc twice, so warn when this happens. * We cannot rely on the previous allocation, so free and fail */ - if (WARN_ON(trans_pcie->txq)) { + if (WARN_ON(priv->txq)) { ret = -EINVAL; goto error; } - ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->scd_bc_tbls, - scd_bc_tbls_size); + ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, + priv->hw_params.scd_bc_tbls_size); if (ret) { - IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); + IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); goto error; } /* Alloc keep-warm buffer */ - ret = iwlagn_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE); + ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); if (ret) { - IWL_ERR(trans, "Keep Warm allocation failed\n"); + IWL_ERR(priv, "Keep Warm allocation failed\n"); goto error; } - trans_pcie->txq = kzalloc(sizeof(struct iwl_tx_queue) * - hw_params(trans).max_txq_num, GFP_KERNEL); - if (!trans_pcie->txq) { - IWL_ERR(trans, "Not enough memory for txq\n"); + priv->txq = kzalloc(sizeof(struct iwl_tx_queue) * + priv->cfg->base_params->num_of_queues, GFP_KERNEL); + if (!priv->txq) { + IWL_ERR(priv, "Not enough memory for txq\n"); ret = ENOMEM; goto error; } /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { - slots_num = (txq_id == trans->shrd->cmd_queue) ? + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + slots_num = (txq_id == priv->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id], - slots_num, txq_id); + ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num, + txq_id); if (ret) { - IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); + IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id); goto error; } } @@ -554,44 +526,42 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans) return 0; error: - iwl_trans_pcie_tx_free(trans); + trans_tx_free(&priv->trans); return ret; } -static int iwl_tx_init(struct iwl_trans *trans) +static int iwl_tx_init(struct iwl_priv *priv) { int ret; int txq_id, slots_num; unsigned long flags; bool alloc = false; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (!trans_pcie->txq) { - ret = iwl_trans_tx_alloc(trans); + if (!priv->txq) { + ret = iwl_trans_tx_alloc(priv); if (ret) goto error; alloc = true; } - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* Turn off all Tx DMA fifos */ - iwl_write_prph(bus(trans), SCD_TXFACT, 0); + iwl_write_prph(priv, SCD_TXFACT, 0); /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(bus(trans), FH_KW_MEM_ADDR_REG, - trans_pcie->kw.dma >> 4); + iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); /* Alloc and init all Tx queues, including the command queue (#4/#9) */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) { - slots_num = (txq_id == trans->shrd->cmd_queue) ? + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + slots_num = (txq_id == priv->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id], - slots_num, txq_id); + ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num, + txq_id); if (ret) { - IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); + IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); goto error; } } @@ -600,61 +570,58 @@ static int iwl_tx_init(struct iwl_trans *trans) error: /*Upon error, free only if we allocated something */ if (alloc) - iwl_trans_pcie_tx_free(trans); + trans_tx_free(&priv->trans); return ret; } static void iwl_set_pwr_vmain(struct iwl_priv *priv) { - struct iwl_trans *trans = trans(priv); /* * (for documentation purposes) * to set power to V_AUX, do: if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) - iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VAUX, ~APMG_PS_CTRL_MSK_PWR_SRC); */ - iwl_set_bits_mask_prph(bus(trans), APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~APMG_PS_CTRL_MSK_PWR_SRC); } -static int iwl_nic_init(struct iwl_trans *trans) +static int iwl_nic_init(struct iwl_priv *priv) { unsigned long flags; - struct iwl_priv *priv = priv(trans); /* nic_init */ - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); iwl_apm_init(priv); /* Set interrupt coalescing calibration timer to default (512 usecs) */ - iwl_write8(bus(trans), CSR_INT_COALESCING, - IWL_HOST_INT_CALIB_TIMEOUT_DEF); + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); iwl_set_pwr_vmain(priv); priv->cfg->lib->nic_config(priv); /* Allocate the RX queue, or reset if it is already allocated */ - iwl_rx_init(trans); + iwl_rx_init(priv); /* Allocate or reset and init all Tx and Command queues */ - if (iwl_tx_init(trans)) + if (iwl_tx_init(priv)) return -ENOMEM; - if (hw_params(trans).shadow_reg_enable) { + if (priv->cfg->base_params->shadow_reg_enable) { /* enable shadow regs in HW */ - iwl_set_bit(bus(trans), CSR_MAC_SHADOW_REG_CTRL, + iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); } - set_bit(STATUS_INIT, &trans->shrd->status); + set_bit(STATUS_INIT, &priv->status); return 0; } @@ -662,39 +629,39 @@ static int iwl_nic_init(struct iwl_trans *trans) #define HW_READY_TIMEOUT (50) /* Note: returns poll_bit return value, which is >= 0 if success */ -static int iwl_set_hw_ready(struct iwl_trans *trans) +static int iwl_set_hw_ready(struct iwl_priv *priv) { int ret; - iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); /* See if we got it */ - ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT); - IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); + IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : ""); return ret; } /* Note: returns standard 0/-ERROR code */ -static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) +static int iwl_trans_prepare_card_hw(struct iwl_priv *priv) { int ret; - IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n"); + IWL_DEBUG_INFO(priv, "iwl_trans_prepare_card_hw enter\n"); - ret = iwl_set_hw_ready(trans); + ret = iwl_set_hw_ready(priv); if (ret >= 0) return 0; /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE); - ret = iwl_poll_bit(bus(trans), CSR_HW_IF_CONFIG_REG, + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); @@ -702,189 +669,153 @@ static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) return ret; /* HW should be ready by now, check again. */ - ret = iwl_set_hw_ready(trans); + ret = iwl_set_hw_ready(priv); if (ret >= 0) return 0; return ret; } -#define IWL_AC_UNSET -1 - -struct queue_to_fifo_ac { - s8 fifo, ac; -}; - -static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, - { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, -}; - -static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { - { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, - { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, - { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, - { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, - { IWL_TX_FIFO_BE_IPAN, 2, }, - { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, - { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, -}; - -static const u8 iwlagn_bss_ac_to_fifo[] = { - IWL_TX_FIFO_VO, - IWL_TX_FIFO_VI, - IWL_TX_FIFO_BE, - IWL_TX_FIFO_BK, -}; -static const u8 iwlagn_bss_ac_to_queue[] = { - 0, 1, 2, 3, -}; -static const u8 iwlagn_pan_ac_to_fifo[] = { - IWL_TX_FIFO_VO_IPAN, - IWL_TX_FIFO_VI_IPAN, - IWL_TX_FIFO_BE_IPAN, - IWL_TX_FIFO_BK_IPAN, -}; -static const u8 iwlagn_pan_ac_to_queue[] = { - 7, 6, 5, 4, -}; - -static int iwl_trans_pcie_start_device(struct iwl_trans *trans) +static int iwl_trans_start_device(struct iwl_priv *priv) { int ret; - struct iwl_priv *priv = priv(trans); - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; - trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; - trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; + priv->ucode_owner = IWL_OWNERSHIP_DRIVER; - trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo; - trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo; - - trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; - trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; - - if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) && - iwl_trans_pcie_prepare_card_hw(trans)) { - IWL_WARN(trans, "Exit HW not ready\n"); + if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && + iwl_trans_prepare_card_hw(priv)) { + IWL_WARN(priv, "Exit HW not ready\n"); return -EIO; } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(bus(trans), CSR_GP_CNTRL) & + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + clear_bit(STATUS_RF_KILL_HW, &priv->status); else - set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); + set_bit(STATUS_RF_KILL_HW, &priv->status); - if (iwl_is_rfkill(trans->shrd)) { + if (iwl_is_rfkill(priv)) { wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - iwl_enable_interrupts(trans); + iwl_enable_interrupts(priv); return -ERFKILL; } - iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - ret = iwl_nic_init(trans); + ret = iwl_nic_init(priv); if (ret) { - IWL_ERR(trans, "Unable to init nic\n"); + IWL_ERR(priv, "Unable to init nic\n"); return ret; } /* make sure rfkill handshake bits are cleared */ - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); /* clear (again), then enable host interrupts */ - iwl_write32(bus(trans), CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(trans); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_enable_interrupts(priv); /* really make sure rfkill handshake bits are cleared */ - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(bus(trans), CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); return 0; } /* * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - * must be called under priv->shrd->lock and mac access + * must be called under priv->lock and mac access */ -static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) +static void iwl_trans_txq_set_sched(struct iwl_priv *priv, u32 mask) { - iwl_write_prph(bus(trans), SCD_TXFACT, mask); + iwl_write_prph(priv, SCD_TXFACT, mask); } -static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) +#define IWL_AC_UNSET -1 + +struct queue_to_fifo_ac { + s8 fifo, ac; +}; + +static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, + { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, +}; + +static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { + { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, + { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, + { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, + { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, + { IWL_TX_FIFO_BE_IPAN, 2, }, + { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, + { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, +}; +static void iwl_trans_tx_start(struct iwl_priv *priv) { const struct queue_to_fifo_ac *queue_to_fifo; struct iwl_rxon_context *ctx; - struct iwl_priv *priv = priv(trans); - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); u32 a; unsigned long flags; int i, chan; u32 reg_val; - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); - trans_pcie->scd_base_addr = - iwl_read_prph(bus(trans), SCD_SRAM_BASE_ADDR); - a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; + priv->scd_base_addr = iwl_read_prph(priv, SCD_SRAM_BASE_ADDR); + a = priv->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; /* reset conext data memory */ - for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; + for (; a < priv->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND; a += 4) - iwl_write_targ_mem(bus(trans), a, 0); + iwl_write_targ_mem(priv, a, 0); /* reset tx status memory */ - for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; + for (; a < priv->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND; a += 4) - iwl_write_targ_mem(bus(trans), a, 0); - for (; a < trans_pcie->scd_base_addr + - SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num); - a += 4) - iwl_write_targ_mem(bus(trans), a, 0); + iwl_write_targ_mem(priv, a, 0); + for (; a < priv->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) + iwl_write_targ_mem(priv, a, 0); - iwl_write_prph(bus(trans), SCD_DRAM_BASE_ADDR, - trans_pcie->scd_bc_tbls.dma >> 10); + iwl_write_prph(priv, SCD_DRAM_BASE_ADDR, + priv->scd_bc_tbls.dma >> 10); /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(bus(trans), FH_TCSR_CHNL_TX_CONFIG_REG(chan), + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); /* Update FH chicken bits */ - reg_val = iwl_read_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(bus(trans), FH_TX_CHICKEN_BITS_REG, + reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); + iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - iwl_write_prph(bus(trans), SCD_QUEUECHAIN_SEL, - SCD_QUEUECHAIN_SEL_ALL(trans)); - iwl_write_prph(bus(trans), SCD_AGGR_SEL, 0); + iwl_write_prph(priv, SCD_QUEUECHAIN_SEL, + SCD_QUEUECHAIN_SEL_ALL(priv)); + iwl_write_prph(priv, SCD_AGGR_SEL, 0); /* initiate the queues */ - for (i = 0; i < hw_params(trans).max_txq_num; i++) { - iwl_write_prph(bus(trans), SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(bus(trans), HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + + for (i = 0; i < priv->hw_params.max_txq_num; i++) { + iwl_write_prph(priv, SCD_QUEUE_RDPTR(i), 0); + iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(bus(trans), trans_pcie->scd_base_addr + + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof(u32), ((SCD_WIN_SIZE << @@ -895,11 +826,11 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); } - iwl_write_prph(bus(trans), SCD_INTERRUPT_MASK, - IWL_MASK(0, hw_params(trans).max_txq_num)); + iwl_write_prph(priv, SCD_INTERRUPT_MASK, + IWL_MASK(0, priv->hw_params.max_txq_num)); /* Activate all Tx DMA/FIFO channels */ - iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); + iwl_trans_txq_set_sched(priv, IWL_MASK(0, 7)); /* map queues to FIFOs */ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) @@ -907,111 +838,96 @@ static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) else queue_to_fifo = iwlagn_default_queue_to_tx_fifo; - iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0); + iwl_trans_set_wr_ptrs(priv, priv->cmd_queue, 0); /* make sure all queue are not stopped */ - memset(&trans_pcie->queue_stopped[0], 0, - sizeof(trans_pcie->queue_stopped)); + memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); for (i = 0; i < 4; i++) - atomic_set(&trans_pcie->queue_stop_count[i], 0); + atomic_set(&priv->queue_stop_count[i], 0); for_each_context(priv, ctx) ctx->last_tx_rejected = false; /* reset to 0 to enable all the queue first */ - trans_pcie->txq_ctx_active_msk = 0; + priv->txq_ctx_active_msk = 0; - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) < + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != IWLAGN_FIRST_AMPDU_QUEUE); - BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) < + BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != IWLAGN_FIRST_AMPDU_QUEUE); for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) { int fifo = queue_to_fifo[i].fifo; int ac = queue_to_fifo[i].ac; - iwl_txq_ctx_activate(trans_pcie, i); + iwl_txq_ctx_activate(priv, i); if (fifo == IWL_TX_FIFO_UNUSED) continue; if (ac != IWL_AC_UNSET) - iwl_set_swq_id(&trans_pcie->txq[i], ac, i); - iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], - fifo, 0); + iwl_set_swq_id(&priv->txq[i], ac, i); + iwl_trans_tx_queue_set_status(priv, &priv->txq[i], fifo, 0); } - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); /* Enable L1-Active */ - iwl_clear_bits_prph(bus(trans), APMG_PCIDEV_STT_REG, + iwl_clear_bits_prph(priv, APMG_PCIDEV_STT_REG, APMG_PCIDEV_STT_VAL_L1_ACT_DIS); } /** * iwlagn_txq_ctx_stop - Stop all Tx DMA channels */ -static int iwl_trans_tx_stop(struct iwl_trans *trans) +static int iwl_trans_tx_stop(struct iwl_priv *priv) { int ch, txq_id; unsigned long flags; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); /* Turn off all Tx DMA fifos */ - spin_lock_irqsave(&trans->shrd->lock, flags); + spin_lock_irqsave(&priv->lock, flags); - iwl_trans_txq_set_sched(trans, 0); + iwl_trans_txq_set_sched(priv, 0); /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { - iwl_write_direct32(bus(trans), - FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - if (iwl_poll_direct_bit(bus(trans), FH_TSSR_TX_STATUS_REG, + iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); + if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000)) - IWL_ERR(trans, "Failing on timeout while stopping" + IWL_ERR(priv, "Failing on timeout while stopping" " DMA channel %d [0x%08x]", ch, - iwl_read_direct32(bus(trans), - FH_TSSR_TX_STATUS_REG)); + iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); } - spin_unlock_irqrestore(&trans->shrd->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); - if (!trans_pcie->txq) { - IWL_WARN(trans, "Stopping tx queues that aren't allocated..."); + if (!priv->txq) { + IWL_WARN(priv, "Stopping tx queues that aren't allocated..."); return 0; } /* Unmap DMA from host system and free skb's */ - for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) - iwl_tx_queue_unmap(trans, txq_id); + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) + iwl_tx_queue_unmap(priv, txq_id); return 0; } -static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans) +static void iwl_trans_stop_device(struct iwl_priv *priv) { unsigned long flags; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - spin_lock_irqsave(&trans->shrd->lock, flags); - iwl_disable_interrupts(trans); - spin_unlock_irqrestore(&trans->shrd->lock, flags); - - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(bus(trans)->irq); - tasklet_kill(&trans_pcie->irq_tasklet); -} -static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) -{ /* stop and reset the on-board processor */ - iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ - iwl_trans_pcie_disable_sync_irq(trans); + spin_lock_irqsave(&priv->lock, flags); + iwl_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + trans_sync_irq(&priv->trans); /* device going down, Stop using ICT table */ - iwl_disable_ict(trans); + iwl_disable_ict(priv); /* * If a HW restart happens during firmware loading, @@ -1020,100 +936,67 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) * restart. So don't process again if the device is * already dead. */ - if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) { - iwl_trans_tx_stop(trans); - iwl_trans_rx_stop(trans); + if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { + iwl_trans_tx_stop(priv); + iwl_trans_rx_stop(priv); /* Power-down device's busmaster DMA clocks */ - iwl_write_prph(bus(trans), APMG_CLK_DIS_REG, + iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); } /* Make sure (redundant) we've released our request to stay awake */ - iwl_clear_bit(bus(trans), CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ - iwl_apm_stop(priv(trans)); + iwl_apm_stop(priv); +} + +static struct iwl_tx_cmd *iwl_trans_get_tx_cmd(struct iwl_priv *priv, + int txq_id) +{ + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_device_cmd *dev_cmd; + + if (unlikely(iwl_queue_space(q) < q->high_mark)) + return NULL; + + /* + * Set up the Tx-command (not MAC!) header. + * Store the chosen Tx queue and TFD index within the sequence field; + * after Tx, uCode's Tx response will return this value so driver can + * locate the frame within the tx queue and do post-tx processing. + */ + dev_cmd = txq->cmd[q->write_ptr]; + memset(dev_cmd, 0, sizeof(*dev_cmd)); + dev_cmd->hdr.cmd = REPLY_TX; + dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | + INDEX_TO_SEQ(q->write_ptr))); + return &dev_cmd->cmd.tx; } -static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) +static int iwl_trans_tx(struct iwl_priv *priv, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx; + struct iwl_tx_queue *txq = &priv->txq[txq_id]; + struct iwl_queue *q = &txq->q; + struct iwl_device_cmd *dev_cmd = txq->cmd[q->write_ptr]; struct iwl_cmd_meta *out_meta; - struct iwl_tx_queue *txq; - struct iwl_queue *q; dma_addr_t phys_addr = 0; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; u16 len, firstlen, secondlen; - u16 seq_number = 0; u8 wait_write_ptr = 0; - u8 txq_id; - u8 tid = 0; - bool is_agg = false; - __le16 fc = hdr->frame_control; u8 hdr_len = ieee80211_hdrlen(fc); - /* - * Send this frame after DTIM -- there's a special queue - * reserved for this for contexts that support AP mode. - */ - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - txq_id = trans_pcie->mcast_queue[ctx]; - - /* - * The microcode will clear the more data - * bit in the last frame it transmits. - */ - hdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) - txq_id = IWL_AUX_QUEUE; - else - txq_id = - trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)]; - - if (ieee80211_is_data_qos(fc)) { - u8 *qc = NULL; - struct iwl_tid_data *tid_data; - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - tid_data = &trans->shrd->tid_data[sta_id][tid]; - - if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) - return -1; - - seq_number = tid_data->seq_number; - seq_number &= IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(seq_number); - seq_number += 0x10; - /* aggregation is on for this */ - if (info->flags & IEEE80211_TX_CTL_AMPDU && - tid_data->agg.state == IWL_AGG_ON) { - txq_id = tid_data->agg.txq_id; - is_agg = true; - } - } - - txq = &trans_pcie->txq[txq_id]; - q = &txq->q; - /* Set up driver data for this TFD */ - txq->skbs[q->write_ptr] = skb; - txq->cmd[q->write_ptr] = dev_cmd; - - dev_cmd->hdr.cmd = REPLY_TX; - dev_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | - INDEX_TO_SEQ(q->write_ptr))); + memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); + txq->txb[q->write_ptr].skb = skb; + txq->txb[q->write_ptr].ctx = ctx; /* Set up first empty entry in queue's array of Tx/cmd buffers */ out_meta = &txq->meta[q->write_ptr]; @@ -1137,10 +1020,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = dma_map_single(bus(trans)->dev, + txcmd_phys = dma_map_single(priv->bus->dev, &dev_cmd->hdr, firstlen, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys))) + if (unlikely(dma_mapping_error(priv->bus->dev, txcmd_phys))) return -1; dma_unmap_addr_set(out_meta, mapping, txcmd_phys); dma_unmap_len_set(out_meta, len, firstlen); @@ -1156,10 +1039,10 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * if any (802.11 null frames have no payload). */ secondlen = skb->len - hdr_len; if (secondlen > 0) { - phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len, + phys_addr = dma_map_single(priv->bus->dev, skb->data + hdr_len, secondlen, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { - dma_unmap_single(bus(trans)->dev, + if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { + dma_unmap_single(priv->bus->dev, dma_unmap_addr(out_meta, mapping), dma_unmap_len(out_meta, len), DMA_BIDIRECTIONAL); @@ -1168,35 +1051,35 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, } /* Attach buffers to TFD */ - iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1); + iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1); if (secondlen > 0) - iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, secondlen, 0); scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); /* take back ownership of DMA buffer to enable update */ - dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen, + dma_sync_single_for_cpu(priv->bus->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); - IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", + IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", le16_to_cpu(dev_cmd->hdr.sequence)); - IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); - iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); - iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); + IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); + iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); /* Set up entry for this TFD in Tx byte-count array */ - if (is_agg) - iwl_trans_txq_update_byte_cnt_tbl(trans, txq, + if (ampdu) + iwl_trans_txq_update_byte_cnt_tbl(priv, txq, le16_to_cpu(tx_cmd->len)); - dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, + dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen, DMA_BIDIRECTIONAL); - trace_iwlwifi_dev_tx(priv(trans), + trace_iwlwifi_dev_tx(priv, &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], sizeof(struct iwl_tfd), &dev_cmd->hdr, firstlen, @@ -1204,14 +1087,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_txq_update_write_ptr(trans, txq); - - if (ieee80211_is_data_qos(fc)) { - trans->shrd->tid_data[sta_id][tid].tfds_in_queue++; - if (!ieee80211_has_morefrags(fc)) - trans->shrd->tid_data[sta_id][tid].seq_number = - seq_number; - } + iwl_txq_update_write_ptr(priv, txq); /* * At this point the frame is "transmitted" successfully @@ -1219,883 +1095,82 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * regardless of the value of ret. "ret" only indicates * whether or not we should update the write pointer. */ - if (iwl_queue_space(q) < q->high_mark) { + if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { if (wait_write_ptr) { txq->need_update = 1; - iwl_txq_update_write_ptr(trans, txq); + iwl_txq_update_write_ptr(priv, txq); } else { - iwl_stop_queue(trans, txq); + iwl_stop_queue(priv, txq); } } return 0; } -static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans) +static void iwl_trans_kick_nic(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ - iwl_write32(bus(trans), CSR_RESET, 0); -} - -static int iwl_trans_pcie_request_irq(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - int err; - - trans_pcie->inta_mask = CSR_INI_SET_MASK; - - tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)trans); - - iwl_alloc_isr_ict(trans); - - err = request_irq(bus(trans)->irq, iwl_isr_ict, IRQF_SHARED, - DRV_NAME, trans); - if (err) { - IWL_ERR(trans, "Error allocating IRQ %d\n", bus(trans)->irq); - iwl_free_isr_ict(trans); - return err; - } - - INIT_WORK(&trans_pcie->rx_replenish, iwl_bg_rx_replenish); - return 0; -} - -static int iwlagn_txq_check_empty(struct iwl_trans *trans, - int sta_id, u8 tid, int txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_queue *q = &trans_pcie->txq[txq_id].q; - struct iwl_tid_data *tid_data = &trans->shrd->tid_data[sta_id][tid]; - - lockdep_assert_held(&trans->shrd->sta_lock); - - switch (trans->shrd->tid_data[sta_id][tid].agg.state) { - case IWL_EMPTYING_HW_QUEUE_DELBA: - /* We are reclaiming the last packet of the */ - /* aggregated HW queue */ - if ((txq_id == tid_data->agg.txq_id) && - (q->read_ptr == q->write_ptr)) { - IWL_DEBUG_HT(trans, - "HW queue empty: continue DELBA flow\n"); - iwl_trans_pcie_txq_agg_disable(trans, txq_id); - tid_data->agg.state = IWL_AGG_OFF; - iwl_stop_tx_ba_trans_ready(priv(trans), - NUM_IWL_RXON_CTX, - sta_id, tid); - iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); - } - break; - case IWL_EMPTYING_HW_QUEUE_ADDBA: - /* We are reclaiming the last packet of the queue */ - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(trans, - "HW queue empty: continue ADDBA flow\n"); - tid_data->agg.state = IWL_AGG_ON; - iwl_start_tx_ba_trans_ready(priv(trans), - NUM_IWL_RXON_CTX, - sta_id, tid); - } - break; - } - - return 0; -} - -static void iwl_free_tfds_in_queue(struct iwl_trans *trans, - int sta_id, int tid, int freed) -{ - lockdep_assert_held(&trans->shrd->sta_lock); - - if (trans->shrd->tid_data[sta_id][tid].tfds_in_queue >= freed) - trans->shrd->tid_data[sta_id][tid].tfds_in_queue -= freed; - else { - IWL_DEBUG_TX(trans, "free more than tfds_in_queue (%u:%d)\n", - trans->shrd->tid_data[sta_id][tid].tfds_in_queue, - freed); - trans->shrd->tid_data[sta_id][tid].tfds_in_queue = 0; - } -} - -static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, - int txq_id, int ssn, u32 status, - struct sk_buff_head *skbs) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; - /* n_bd is usually 256 => n_bd - 1 = 0xff */ - int tfd_num = ssn & (txq->q.n_bd - 1); - int freed = 0; - u8 agg_state; - bool cond; - - txq->time_stamp = jiffies; - - if (txq->sched_retry) { - agg_state = - trans->shrd->tid_data[txq->sta_id][txq->tid].agg.state; - cond = (agg_state != IWL_EMPTYING_HW_QUEUE_DELBA); - } else { - cond = (status != TX_STATUS_FAIL_PASSIVE_NO_RX); - } - - if (txq->q.read_ptr != tfd_num) { - IWL_DEBUG_TX_REPLY(trans, "Retry scheduler reclaim " - "scd_ssn=%d idx=%d txq=%d swq=%d\n", - ssn , tfd_num, txq_id, txq->swq_id); - freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); - if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond) - iwl_wake_queue(trans, txq); - } - - iwl_free_tfds_in_queue(trans, sta_id, tid, freed); - iwlagn_txq_check_empty(trans, sta_id, tid, txq_id); -} - -static void iwl_trans_pcie_free(struct iwl_trans *trans) -{ - iwl_trans_pcie_tx_free(trans); - iwl_trans_pcie_rx_free(trans); - free_irq(bus(trans)->irq, trans); - iwl_free_isr_ict(trans); - trans->shrd->trans = NULL; - kfree(trans); -} - -#ifdef CONFIG_PM - -static int iwl_trans_pcie_suspend(struct iwl_trans *trans) -{ - /* - * This function is called when system goes into suspend state - * mac80211 will call iwl_mac_stop() from the mac80211 suspend function - * first but since iwl_mac_stop() has no knowledge of who the caller is, - * it will not call apm_ops.stop() to stop the DMA operation. - * Calling apm_ops.stop here to make sure we stop the DMA. - * - * But of course ... if we have configured WoWLAN then we did other - * things already :-) - */ - if (!trans->shrd->wowlan) - iwl_apm_stop(priv(trans)); - - return 0; -} - -static int iwl_trans_pcie_resume(struct iwl_trans *trans) -{ - bool hw_rfkill = false; - - iwl_enable_interrupts(trans); - - if (!(iwl_read32(bus(trans), CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rfkill = true; - - if (hw_rfkill) - set_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - else - clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status); - - wiphy_rfkill_set_hw_state(priv(trans)->hw->wiphy, hw_rfkill); - - return 0; + iwl_write32(priv, CSR_RESET, 0); } -#else /* CONFIG_PM */ -static int iwl_trans_pcie_suspend(struct iwl_trans *trans) -{ return 0; } -static int iwl_trans_pcie_resume(struct iwl_trans *trans) -{ return 0; } - -#endif /* CONFIG_PM */ - -static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, - u8 ctx) +static void iwl_trans_sync_irq(struct iwl_priv *priv) { - u8 ac, txq_id; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - - for (ac = 0; ac < AC_NUM; ac++) { - txq_id = trans_pcie->ac_to_queue[ctx][ac]; - IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n", - ac, - (atomic_read(&trans_pcie->queue_stop_count[ac]) > 0) - ? "stopped" : "awake"); - iwl_wake_queue(trans, &trans_pcie->txq[txq_id]); - } + /* wait to make sure we flush pending tasklet*/ + synchronize_irq(priv->bus->irq); + tasklet_kill(&priv->irq_tasklet); } -const struct iwl_trans_ops trans_ops_pcie; - -static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) +static void iwl_trans_free(struct iwl_priv *priv) { - struct iwl_trans *iwl_trans = kzalloc(sizeof(struct iwl_trans) + - sizeof(struct iwl_trans_pcie), - GFP_KERNEL); - if (iwl_trans) { - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(iwl_trans); - iwl_trans->ops = &trans_ops_pcie; - iwl_trans->shrd = shrd; - trans_pcie->trans = iwl_trans; - spin_lock_init(&iwl_trans->hcmd_lock); - } - - return iwl_trans; + free_irq(priv->bus->irq, priv); + iwl_free_isr_ict(priv); } -static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - iwl_stop_queue(trans, &trans_pcie->txq[txq_id]); -} +static const struct iwl_trans_ops trans_ops = { + .start_device = iwl_trans_start_device, + .prepare_card_hw = iwl_trans_prepare_card_hw, + .stop_device = iwl_trans_stop_device, -#define IWL_FLUSH_WAIT_MS 2000 + .tx_start = iwl_trans_tx_start, -static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq; - struct iwl_queue *q; - int cnt; - unsigned long now = jiffies; - int ret = 0; - - /* waiting for all the tx frames complete might take a while */ - for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - if (cnt == trans->shrd->cmd_queue) - continue; - txq = &trans_pcie->txq[cnt]; - q = &txq->q; - while (q->read_ptr != q->write_ptr && !time_after(jiffies, - now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) - msleep(1); - - if (q->read_ptr != q->write_ptr) { - IWL_ERR(trans, "fail to flush all tx fifo queues\n"); - ret = -ETIMEDOUT; - break; - } - } - return ret; -} + .rx_free = iwl_trans_rx_free, + .tx_free = iwl_trans_tx_free, -/* - * On every watchdog tick we check (latest) time stamp. If it does not - * change during timeout period and queue is not empty we reset firmware. - */ -static int iwl_trans_pcie_check_stuck_queue(struct iwl_trans *trans, int cnt) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq = &trans_pcie->txq[cnt]; - struct iwl_queue *q = &txq->q; - unsigned long timeout; + .send_cmd = iwl_send_cmd, + .send_cmd_pdu = iwl_send_cmd_pdu, - if (q->read_ptr == q->write_ptr) { - txq->time_stamp = jiffies; - return 0; - } + .get_tx_cmd = iwl_trans_get_tx_cmd, + .tx = iwl_trans_tx, - timeout = txq->time_stamp + - msecs_to_jiffies(hw_params(trans).wd_timeout); + .txq_agg_disable = iwl_trans_txq_agg_disable, + .txq_agg_setup = iwl_trans_txq_agg_setup, - if (time_after(jiffies, timeout)) { - IWL_ERR(trans, "Queue %d stuck for %u ms.\n", q->id, - hw_params(trans).wd_timeout); - return 1; - } + .kick_nic = iwl_trans_kick_nic, - return 0; -} - -#ifdef CONFIG_IWLWIFI_DEBUGFS -/* create and remove of files */ -#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, trans, \ - &iwl_dbgfs_##name##_ops)) \ - return -ENOMEM; \ -} while (0) - -/* file operation */ -#define DEBUGFS_READ_FUNC(name) \ -static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ - char __user *user_buf, \ - size_t count, loff_t *ppos); - -#define DEBUGFS_WRITE_FUNC(name) \ -static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ - const char __user *user_buf, \ - size_t count, loff_t *ppos); - - -static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -#define DEBUGFS_READ_FILE_OPS(name) \ - DEBUGFS_READ_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ - .llseek = generic_file_llseek, \ -}; - -#define DEBUGFS_WRITE_FILE_OPS(name) \ - DEBUGFS_WRITE_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ - .open = iwl_dbgfs_open_file_generic, \ - .llseek = generic_file_llseek, \ -}; - -#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ - DEBUGFS_READ_FUNC(name); \ - DEBUGFS_WRITE_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ - .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ - .llseek = generic_file_llseek, \ + .sync_irq = iwl_trans_sync_irq, + .free = iwl_trans_free, }; -static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - struct iwl_priv *priv = priv(trans); - int pos = 0, ofs = 0; - int cnt = 0, entry; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_tx_queue *txq; - struct iwl_queue *q; - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - char *buf; - int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + - (hw_params(trans).max_txq_num * 32 * 8) + 400; - const u8 *ptr; - ssize_t ret; - - if (!trans_pcie->txq) { - IWL_ERR(trans, "txq not ready\n"); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(trans, "Can not allocate buffer\n"); - return -ENOMEM; - } - pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); - for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - txq = &trans_pcie->txq[cnt]; - q = &txq->q; - pos += scnprintf(buf + pos, bufsz - pos, - "q[%d]: read_ptr: %u, write_ptr: %u\n", - cnt, q->read_ptr, q->write_ptr); - } - if (priv->tx_traffic && - (iwl_get_debug_level(trans->shrd) & IWL_DL_TX)) { - ptr = priv->tx_traffic; - pos += scnprintf(buf + pos, bufsz - pos, - "Tx Traffic idx: %u\n", priv->tx_traffic_idx); - for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { - for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; - entry++, ofs += 16) { - pos += scnprintf(buf + pos, bufsz - pos, - "0x%.4x ", ofs); - hex_dump_to_buffer(ptr + ofs, 16, 16, 2, - buf + pos, bufsz - pos, 0); - pos += strlen(buf + pos); - if (bufsz - pos > 0) - buf[pos++] = '\n'; - } - } - } - - pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "read: %u, write: %u\n", - rxq->read, rxq->write); - - if (priv->rx_traffic && - (iwl_get_debug_level(trans->shrd) & IWL_DL_RX)) { - ptr = priv->rx_traffic; - pos += scnprintf(buf + pos, bufsz - pos, - "Rx Traffic idx: %u\n", priv->rx_traffic_idx); - for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { - for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; - entry++, ofs += 16) { - pos += scnprintf(buf + pos, bufsz - pos, - "0x%.4x ", ofs); - hex_dump_to_buffer(ptr + ofs, 16, 16, 2, - buf + pos, bufsz - pos, 0); - pos += strlen(buf + pos); - if (bufsz - pos > 0) - buf[pos++] = '\n'; - } - } - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - char buf[8]; - int buf_size; - int traffic_log; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &traffic_log) != 1) - return -EFAULT; - if (traffic_log == 0) - iwl_reset_traffic_log(priv(trans)); - - return count; -} - -static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_priv *priv = priv(trans); - struct iwl_tx_queue *txq; - struct iwl_queue *q; - char *buf; - int pos = 0; - int cnt; - int ret; - const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num; - - if (!trans_pcie->txq) { - IWL_ERR(priv, "txq not ready\n"); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { - txq = &trans_pcie->txq[cnt]; - q = &txq->q; - pos += scnprintf(buf + pos, bufsz - pos, - "hwq %.2d: read=%u write=%u stop=%d" - " swq_id=%#.2x (ac %d/hwq %d)\n", - cnt, q->read_ptr, q->write_ptr, - !!test_bit(cnt, trans_pcie->queue_stopped), - txq->swq_id, txq->swq_id & 3, - (txq->swq_id >> 2) & 0x1f); - if (cnt >= 4) - continue; - /* for the ACs, display the stop count too */ - pos += scnprintf(buf + pos, bufsz - pos, - " stop-count: %d\n", - atomic_read(&trans_pcie->queue_stop_count[cnt])); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rx_queue *rxq = &trans_pcie->rxq; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", - rxq->read); - pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", - rxq->write); - pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", - rxq->free_count); - if (rxq->rb_stts) { - pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", - le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); - } else { - pos += scnprintf(buf + pos, bufsz - pos, - "closed_rb_num: Not Allocated\n"); - } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_log_event_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - char *buf; - int pos = 0; - ssize_t ret = -ENOMEM; - - ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true); - if (buf) { - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - } - return ret; -} - -static ssize_t iwl_dbgfs_log_event_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - u32 event_log_flag; - char buf[8]; - int buf_size; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &event_log_flag) != 1) - return -EFAULT; - if (event_log_flag == 1) - iwl_dump_nic_event_log(trans, true, NULL, false); - - return count; -} - -static ssize_t iwl_dbgfs_interrupt_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct isr_statistics *isr_stats = &trans_pcie->isr_stats; - - int pos = 0; - char *buf; - int bufsz = 24 * 64; /* 24 items * 64 char per item */ - ssize_t ret; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(trans, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - pos += scnprintf(buf + pos, bufsz - pos, - "Interrupt Statistics Report:\n"); - - pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", - isr_stats->hw); - pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", - isr_stats->sw); - if (isr_stats->sw || isr_stats->hw) { - pos += scnprintf(buf + pos, bufsz - pos, - "\tLast Restarting Code: 0x%X\n", - isr_stats->err_code); - } -#ifdef CONFIG_IWLWIFI_DEBUG - pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", - isr_stats->sch); - pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", - isr_stats->alive); -#endif - pos += scnprintf(buf + pos, bufsz - pos, - "HW RF KILL switch toggled:\t %u\n", isr_stats->rfkill); - - pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", - isr_stats->ctkill); - - pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", - isr_stats->wakeup); - - pos += scnprintf(buf + pos, bufsz - pos, - "Rx command responses:\t\t %u\n", isr_stats->rx); - - pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", - isr_stats->tx); - - pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", - isr_stats->unhandled); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_interrupt_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) +int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv) { - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(trans); - struct isr_statistics *isr_stats = &trans_pcie->isr_stats; - - char buf[8]; - int buf_size; - u32 reset_flag; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%x", &reset_flag) != 1) - return -EFAULT; - if (reset_flag == 0) - memset(isr_stats, 0, sizeof(*isr_stats)); - - return count; -} - -static const char *get_csr_string(int cmd) -{ - switch (cmd) { - IWL_CMD(CSR_HW_IF_CONFIG_REG); - IWL_CMD(CSR_INT_COALESCING); - IWL_CMD(CSR_INT); - IWL_CMD(CSR_INT_MASK); - IWL_CMD(CSR_FH_INT_STATUS); - IWL_CMD(CSR_GPIO_IN); - IWL_CMD(CSR_RESET); - IWL_CMD(CSR_GP_CNTRL); - IWL_CMD(CSR_HW_REV); - IWL_CMD(CSR_EEPROM_REG); - IWL_CMD(CSR_EEPROM_GP); - IWL_CMD(CSR_OTP_GP_REG); - IWL_CMD(CSR_GIO_REG); - IWL_CMD(CSR_GP_UCODE_REG); - IWL_CMD(CSR_GP_DRIVER_REG); - IWL_CMD(CSR_UCODE_DRV_GP1); - IWL_CMD(CSR_UCODE_DRV_GP2); - IWL_CMD(CSR_LED_REG); - IWL_CMD(CSR_DRAM_INT_TBL_REG); - IWL_CMD(CSR_GIO_CHICKEN_BITS); - IWL_CMD(CSR_ANA_PLL_CFG); - IWL_CMD(CSR_HW_REV_WA_REG); - IWL_CMD(CSR_DBG_HPET_MEM_REG); - default: - return "UNKNOWN"; - } -} - -void iwl_dump_csr(struct iwl_trans *trans) -{ - int i; - static const u32 csr_tbl[] = { - CSR_HW_IF_CONFIG_REG, - CSR_INT_COALESCING, - CSR_INT, - CSR_INT_MASK, - CSR_FH_INT_STATUS, - CSR_GPIO_IN, - CSR_RESET, - CSR_GP_CNTRL, - CSR_HW_REV, - CSR_EEPROM_REG, - CSR_EEPROM_GP, - CSR_OTP_GP_REG, - CSR_GIO_REG, - CSR_GP_UCODE_REG, - CSR_GP_DRIVER_REG, - CSR_UCODE_DRV_GP1, - CSR_UCODE_DRV_GP2, - CSR_LED_REG, - CSR_DRAM_INT_TBL_REG, - CSR_GIO_CHICKEN_BITS, - CSR_ANA_PLL_CFG, - CSR_HW_REV_WA_REG, - CSR_DBG_HPET_MEM_REG - }; - IWL_ERR(trans, "CSR values:\n"); - IWL_ERR(trans, "(2nd byte of CSR_INT_COALESCING is " - "CSR_INT_PERIODIC_REG)\n"); - for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { - IWL_ERR(trans, " %25s: 0X%08x\n", - get_csr_string(csr_tbl[i]), - iwl_read32(bus(trans), csr_tbl[i])); - } -} - -static ssize_t iwl_dbgfs_csr_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - char buf[8]; - int buf_size; - int csr; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &csr) != 1) - return -EFAULT; + int err; - iwl_dump_csr(trans); + priv->trans.ops = &trans_ops; + priv->trans.priv = priv; - return count; -} + tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) + iwl_irq_tasklet, (unsigned long)priv); -static const char *get_fh_string(int cmd) -{ - switch (cmd) { - IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); - IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); - IWL_CMD(FH_RSCSR_CHNL0_WPTR); - IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); - IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); - IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); - IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); - IWL_CMD(FH_TSSR_TX_STATUS_REG); - IWL_CMD(FH_TSSR_TX_ERROR_REG); - default: - return "UNKNOWN"; - } -} + iwl_alloc_isr_ict(priv); -int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display) -{ - int i; -#ifdef CONFIG_IWLWIFI_DEBUG - int pos = 0; - size_t bufsz = 0; -#endif - static const u32 fh_tbl[] = { - FH_RSCSR_CHNL0_STTS_WPTR_REG, - FH_RSCSR_CHNL0_RBDCB_BASE_REG, - FH_RSCSR_CHNL0_WPTR, - FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_MEM_RSSR_SHARED_CTRL_REG, - FH_MEM_RSSR_RX_STATUS_REG, - FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, - FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_ERROR_REG - }; -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - pos += scnprintf(*buf + pos, bufsz - pos, - "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { - pos += scnprintf(*buf + pos, bufsz - pos, - " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(bus(trans), fh_tbl[i])); - } - return pos; - } -#endif - IWL_ERR(trans, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { - IWL_ERR(trans, " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(bus(trans), fh_tbl[i])); + err = request_irq(priv->bus->irq, iwl_isr_ict, IRQF_SHARED, + DRV_NAME, priv); + if (err) { + IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus->irq); + iwl_free_isr_ict(priv); + return err; } - return 0; -} -static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - char *buf; - int pos = 0; - ssize_t ret = -EFAULT; - - ret = pos = iwl_dump_fh(trans, &buf, true); - if (buf) { - ret = simple_read_from_buffer(user_buf, - count, ppos, buf, pos); - kfree(buf); - } + INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); - return ret; -} - -DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); -DEBUGFS_READ_WRITE_FILE_OPS(log_event); -DEBUGFS_READ_WRITE_FILE_OPS(interrupt); -DEBUGFS_READ_FILE_OPS(fh_reg); -DEBUGFS_READ_FILE_OPS(rx_queue); -DEBUGFS_READ_FILE_OPS(tx_queue); -DEBUGFS_WRITE_FILE_OPS(csr); - -/* - * Create the debugfs files and directories - * - */ -static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, - struct dentry *dir) -{ - DEBUGFS_ADD_FILE(traffic_log, dir, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); - DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); - DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); - DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); return 0; } -#else -static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, - struct dentry *dir) -{ return 0; } - -#endif /*CONFIG_IWLWIFI_DEBUGFS */ - -const struct iwl_trans_ops trans_ops_pcie = { - .alloc = iwl_trans_pcie_alloc, - .request_irq = iwl_trans_pcie_request_irq, - .start_device = iwl_trans_pcie_start_device, - .prepare_card_hw = iwl_trans_pcie_prepare_card_hw, - .stop_device = iwl_trans_pcie_stop_device, - - .tx_start = iwl_trans_pcie_tx_start, - .wake_any_queue = iwl_trans_pcie_wake_any_queue, - - .send_cmd = iwl_trans_pcie_send_cmd, - .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, - - .tx = iwl_trans_pcie_tx, - .reclaim = iwl_trans_pcie_reclaim, - - .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, - .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, - .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, - - .kick_nic = iwl_trans_pcie_kick_nic, - - .free = iwl_trans_pcie_free, - .stop_queue = iwl_trans_pcie_stop_queue, - - .dbgfs_register = iwl_trans_pcie_dbgfs_register, - - .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, - .check_stuck_queue = iwl_trans_pcie_check_stuck_queue, - - .suspend = iwl_trans_pcie_suspend, - .resume = iwl_trans_pcie_resume, -}; - diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h index 7a2daa886dfd..7993aa7ae668 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -63,235 +63,163 @@ #ifndef __iwl_trans_h__ #define __iwl_trans_h__ -#include -#include - -#include "iwl-shared.h" -#include "iwl-commands.h" - /*This file includes the declaration that are exported from the transport * layer */ struct iwl_priv; struct iwl_rxon_context; struct iwl_host_cmd; -struct iwl_shared; -struct iwl_device_cmd; /** * struct iwl_trans_ops - transport specific operations - * @alloc: allocates the meta data (not the queues themselves) - * @request_irq: requests IRQ - will be called before the FW load in probe flow * @start_device: allocates and inits all the resources for the transport * layer. * @prepare_card_hw: claim the ownership on the HW. Will be called during * probe. * @tx_start: starts and configures all the Tx fifo - usually done once the fw * is alive. - * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @stop_device:stops the whole device (embedded CPU put to reset) + * @rx_free: frees the rx memory + * @tx_free: frees the tx memory * @send_cmd:send a host command * @send_cmd_pdu:send a host command: flags can be CMD_* + * @get_tx_cmd: returns a pointer to a new Tx cmd for the upper layer use * @tx: send an skb - * @reclaim: free packet until ssn. Returns a list of freed packets. - * @tx_agg_alloc: allocate resources for a TX BA session - * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is + * @txq_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * ready and a successful ADDBA response has been received. - * @tx_agg_disable: de-configure a Tx queue to send AMPDUs + * @txq_agg_disable: de-configure a Tx queue to send AMPDUs * @kick_nic: remove the RESET from the embedded CPU and let it run + * @sync_irq: the upper layer will typically disable interrupt and call this + * handler. After this handler returns, it is guaranteed that all + * the ISR / tasklet etc... have finished running and the transport + * layer shall not pass any Rx. * @free: release all the ressource for the transport layer itself such as * irq, tasklet etc... - * @stop_queue: stop a specific queue - * @check_stuck_queue: check if a specific queue is stuck - * @wait_tx_queue_empty: wait until all tx queues are empty - * @dbgfs_register: add the dbgfs files under this directory. Files will be - * automatically deleted. - * @suspend: stop the device unless WoWLAN is configured - * @resume: resume activity of the device */ struct iwl_trans_ops { - struct iwl_trans *(*alloc)(struct iwl_shared *shrd); - int (*request_irq)(struct iwl_trans *iwl_trans); - int (*start_device)(struct iwl_trans *trans); - int (*prepare_card_hw)(struct iwl_trans *trans); - void (*stop_device)(struct iwl_trans *trans); - void (*tx_start)(struct iwl_trans *trans); + int (*start_device)(struct iwl_priv *priv); + int (*prepare_card_hw)(struct iwl_priv *priv); + void (*stop_device)(struct iwl_priv *priv); + void (*tx_start)(struct iwl_priv *priv); + void (*tx_free)(struct iwl_priv *priv); + void (*rx_free)(struct iwl_priv *priv); - void (*wake_any_queue)(struct iwl_trans *trans, u8 ctx); + int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); - int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); - - int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len, + int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, const void *data); - int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id); - void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid, - int txq_id, int ssn, u32 status, - struct sk_buff_head *skbs); - - int (*tx_agg_disable)(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, - int tid); - int (*tx_agg_alloc)(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, int tid, - u16 *ssn); - void (*tx_agg_setup)(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, int sta_id, int tid, - int frame_limit); + struct iwl_tx_cmd * (*get_tx_cmd)(struct iwl_priv *priv, int txq_id); + int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx); - void (*kick_nic)(struct iwl_trans *trans); + int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo); + void (*txq_agg_setup)(struct iwl_priv *priv, int sta_id, int tid, + int frame_limit); - void (*free)(struct iwl_trans *trans); + void (*kick_nic)(struct iwl_priv *priv); - void (*stop_queue)(struct iwl_trans *trans, int q); - - int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); - int (*check_stuck_queue)(struct iwl_trans *trans, int q); - int (*wait_tx_queue_empty)(struct iwl_trans *trans); - - int (*suspend)(struct iwl_trans *trans); - int (*resume)(struct iwl_trans *trans); + void (*sync_irq)(struct iwl_priv *priv); + void (*free)(struct iwl_priv *priv); }; -/** - * struct iwl_trans - transport common data - * @ops - pointer to iwl_trans_ops - * @shrd - pointer to iwl_shared which holds shared data from the upper layer - * @hcmd_lock: protects HCMD - */ struct iwl_trans { const struct iwl_trans_ops *ops; - struct iwl_shared *shrd; - spinlock_t hcmd_lock; - - /* pointer to trans specific struct */ - /*Ensure that this pointer will always be aligned to sizeof pointer */ - char trans_specific[0] __attribute__((__aligned__(sizeof(void *)))); + struct iwl_priv *priv; }; -static inline int iwl_trans_request_irq(struct iwl_trans *trans) +static inline int trans_start_device(struct iwl_trans *trans) { - return trans->ops->request_irq(trans); + return trans->ops->start_device(trans->priv); } -static inline int iwl_trans_start_device(struct iwl_trans *trans) +static inline int trans_prepare_card_hw(struct iwl_trans *trans) { - return trans->ops->start_device(trans); + return trans->ops->prepare_card_hw(trans->priv); } -static inline int iwl_trans_prepare_card_hw(struct iwl_trans *trans) +static inline void trans_stop_device(struct iwl_trans *trans) { - return trans->ops->prepare_card_hw(trans); + trans->ops->stop_device(trans->priv); } -static inline void iwl_trans_stop_device(struct iwl_trans *trans) +static inline void trans_tx_start(struct iwl_trans *trans) { - trans->ops->stop_device(trans); + trans->ops->tx_start(trans->priv); } -static inline void iwl_trans_tx_start(struct iwl_trans *trans) +static inline void trans_rx_free(struct iwl_trans *trans) { - trans->ops->tx_start(trans); + trans->ops->rx_free(trans->priv); } -static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, u8 ctx) +static inline void trans_tx_free(struct iwl_trans *trans) { - trans->ops->wake_any_queue(trans, ctx); + trans->ops->tx_free(trans->priv); } - -static inline int iwl_trans_send_cmd(struct iwl_trans *trans, +static inline int trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { - return trans->ops->send_cmd(trans, cmd); -} - -static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, - u32 flags, u16 len, const void *data) -{ - return trans->ops->send_cmd_pdu(trans, id, flags, len, data); + return trans->ops->send_cmd(trans->priv, cmd); } -static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, - struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) +static inline int trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags, + u16 len, const void *data) { - return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id); + return trans->ops->send_cmd_pdu(trans->priv, id, flags, len, data); } -static inline void iwl_trans_reclaim(struct iwl_trans *trans, int sta_id, - int tid, int txq_id, int ssn, u32 status, - struct sk_buff_head *skbs) +static inline struct iwl_tx_cmd *trans_get_tx_cmd(struct iwl_trans *trans, + int txq_id) { - trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, status, skbs); + return trans->ops->get_tx_cmd(trans->priv, txq_id); } -static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - int sta_id, int tid) +static inline int trans_tx(struct iwl_trans *trans, struct sk_buff *skb, + struct iwl_tx_cmd *tx_cmd, int txq_id, __le16 fc, bool ampdu, + struct iwl_rxon_context *ctx) { - return trans->ops->tx_agg_disable(trans, ctx, sta_id, tid); + return trans->ops->tx(trans->priv, skb, tx_cmd, txq_id, fc, ampdu, ctx); } -static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - int sta_id, int tid, u16 *ssn) +static inline int trans_txq_agg_disable(struct iwl_trans *trans, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) { - return trans->ops->tx_agg_alloc(trans, ctx, sta_id, tid, ssn); + return trans->ops->txq_agg_disable(trans->priv, txq_id, + ssn_idx, tx_fifo); } - -static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, - enum iwl_rxon_context_id ctx, - int sta_id, int tid, - int frame_limit) +static inline void trans_txq_agg_setup(struct iwl_trans *trans, int sta_id, + int tid, int frame_limit) { - trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit); + trans->ops->txq_agg_setup(trans->priv, sta_id, tid, frame_limit); } -static inline void iwl_trans_kick_nic(struct iwl_trans *trans) +static inline void trans_kick_nic(struct iwl_trans *trans) { - trans->ops->kick_nic(trans); + trans->ops->kick_nic(trans->priv); } -static inline void iwl_trans_free(struct iwl_trans *trans) +static inline void trans_sync_irq(struct iwl_trans *trans) { - trans->ops->free(trans); + trans->ops->sync_irq(trans->priv); } -static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q) +static inline void trans_free(struct iwl_trans *trans) { - trans->ops->stop_queue(trans, q); + trans->ops->free(trans->priv); } -static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) -{ - return trans->ops->wait_tx_queue_empty(trans); -} +int iwl_trans_register(struct iwl_trans *trans, struct iwl_priv *priv); -static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q) -{ - return trans->ops->check_stuck_queue(trans, q); -} -static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, - struct dentry *dir) -{ - return trans->ops->dbgfs_register(trans, dir); -} - -static inline int iwl_trans_suspend(struct iwl_trans *trans) -{ - return trans->ops->suspend(trans); -} - -static inline int iwl_trans_resume(struct iwl_trans *trans) -{ - return trans->ops->resume(trans); -} +/*TODO: this functions should NOT be exported from trans module - export it + * until the reclaim flow will be brought to the transport module too */ -/***************************************************** -* Transport layers implementations -******************************************************/ -extern const struct iwl_trans_ops trans_ops_pcie; +struct iwl_tx_queue; +void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl_tx_queue *txq); #endif /* __iwl_trans_h__ */ diff --git a/trunk/drivers/net/wireless/p54/p54spi.c b/trunk/drivers/net/wireless/p54/p54spi.c index f18df82eeb92..6d9204fef90b 100644 --- a/trunk/drivers/net/wireless/p54/p54spi.c +++ b/trunk/drivers/net/wireless/p54/p54spi.c @@ -41,6 +41,7 @@ #endif /* CONFIG_P54_SPI_DEFAULT_EEPROM */ MODULE_FIRMWARE("3826.arm"); +MODULE_ALIAS("stlc45xx"); /* * gpios should be handled in board files and provided via platform data, @@ -737,4 +738,3 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Lamparter "); MODULE_ALIAS("spi:cx3110x"); MODULE_ALIAS("spi:p54spi"); -MODULE_ALIAS("spi:stlc45xx"); diff --git a/trunk/drivers/net/wireless/p54/txrx.c b/trunk/drivers/net/wireless/p54/txrx.c index 2b97a89e7ff8..44a3bd4b0f43 100644 --- a/trunk/drivers/net/wireless/p54/txrx.c +++ b/trunk/drivers/net/wireless/p54/txrx.c @@ -19,7 +19,6 @@ #include #include #include -#include #include @@ -583,13 +582,10 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) if (chan) { struct survey_info *survey = &priv->survey[chan->hw_value]; survey->noise = clamp_t(s8, priv->noise, -128, 127); - survey->channel_time = priv->survey_raw.active; - survey->channel_time_tx = priv->survey_raw.tx; - survey->channel_time_busy = priv->survey_raw.tx + - priv->survey_raw.cca; - do_div(survey->channel_time, 1024); - do_div(survey->channel_time_tx, 1024); - do_div(survey->channel_time_busy, 1024); + survey->channel_time = priv->survey_raw.active / 1024; + survey->channel_time_tx = priv->survey_raw.tx / 1024; + survey->channel_time_busy = priv->survey_raw.cca / 1024 + + survey->channel_time_tx; } tmp = p54_find_and_unlink_skb(priv, hdr->req_id); diff --git a/trunk/drivers/net/wireless/wl12xx/acx.c b/trunk/drivers/net/wireless/wl12xx/acx.c index e047594794aa..7e33f1f4f3d4 100644 --- a/trunk/drivers/net/wireless/wl12xx/acx.c +++ b/trunk/drivers/net/wireless/wl12xx/acx.c @@ -46,7 +46,6 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl) goto out; } - wake_up->role_id = wl->role_id; wake_up->wake_up_event = wl->conf.conn.wake_up_event; wake_up->listen_interval = wl->conf.conn.listen_interval; @@ -102,7 +101,6 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) goto out; } - acx->role_id = wl->role_id; acx->current_tx_power = power * 10; ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); @@ -130,7 +128,6 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl) } /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ - feature->role_id = wl->role_id; feature->data_flow_options = 0; feature->options = 0; @@ -186,6 +183,34 @@ int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl) return ret; } +int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter) +{ + struct acx_rx_config *rx_config; + int ret; + + wl1271_debug(DEBUG_ACX, "acx rx config"); + + rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); + if (!rx_config) { + ret = -ENOMEM; + goto out; + } + + rx_config->config_options = cpu_to_le32(config); + rx_config->filter_options = cpu_to_le32(filter); + + ret = wl1271_cmd_configure(wl, ACX_RX_CFG, + rx_config, sizeof(*rx_config)); + if (ret < 0) { + wl1271_warning("failed to set rx config: %d", ret); + goto out; + } + +out: + kfree(rx_config); + return ret; +} + int wl1271_acx_pd_threshold(struct wl1271 *wl) { struct acx_packet_detection *pd; @@ -225,7 +250,6 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) goto out; } - slot->role_id = wl->role_id; slot->wone_index = STATION_WONE_INDEX; slot->slot_time = slot_time; @@ -255,7 +279,6 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, } /* MAC filtering */ - acx->role_id = wl->role_id; acx->enabled = enable; acx->num_groups = mc_list_len; memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); @@ -285,7 +308,6 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl) wl1271_debug(DEBUG_ACX, "acx service period timeout"); - rx_timeout->role_id = wl->role_id; rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout); rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout); @@ -322,7 +344,6 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) goto out; } - rts->role_id = wl->role_id; rts->threshold = cpu_to_le16((u16)rts_threshold); ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); @@ -382,7 +403,6 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) goto out; } - beacon_filter->role_id = wl->role_id; beacon_filter->enable = enable_filter; /* @@ -419,7 +439,6 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl) } /* configure default beacon pass-through rules */ - ie_table->role_id = wl->role_id; ie_table->num_ie = 0; for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) { struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]); @@ -481,7 +500,6 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) timeout = wl->conf.conn.bss_lose_timeout; } - acx->role_id = wl->role_id; acx->synch_fail_thold = cpu_to_le32(threshold); acx->bss_lose_timeout = cpu_to_le32(timeout); @@ -528,13 +546,43 @@ int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable) return ret; } -int wl12xx_acx_sg_cfg(struct wl1271 *wl) +int wl1271_acx_sta_sg_cfg(struct wl1271 *wl) +{ + struct acx_sta_bt_wlan_coex_param *param; + struct conf_sg_settings *c = &wl->conf.sg; + int i, ret; + + wl1271_debug(DEBUG_ACX, "acx sg sta cfg"); + + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) { + ret = -ENOMEM; + goto out; + } + + /* BT-WLAN coext parameters */ + for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++) + param->params[i] = cpu_to_le32(c->sta_params[i]); + param->param_idx = CONF_SG_PARAMS_ALL; + + ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); + if (ret < 0) { + wl1271_warning("failed to set sg config: %d", ret); + goto out; + } + +out: + kfree(param); + return ret; +} + +int wl1271_acx_ap_sg_cfg(struct wl1271 *wl) { - struct acx_bt_wlan_coex_param *param; + struct acx_ap_bt_wlan_coex_param *param; struct conf_sg_settings *c = &wl->conf.sg; int i, ret; - wl1271_debug(DEBUG_ACX, "acx sg cfg"); + wl1271_debug(DEBUG_ACX, "acx sg ap cfg"); param = kzalloc(sizeof(*param), GFP_KERNEL); if (!param) { @@ -543,8 +591,8 @@ int wl12xx_acx_sg_cfg(struct wl1271 *wl) } /* BT-WLAN coext parameters */ - for (i = 0; i < CONF_SG_PARAMS_MAX; i++) - param->params[i] = cpu_to_le32(c->params[i]); + for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++) + param->params[i] = cpu_to_le32(c->ap_params[i]); param->param_idx = CONF_SG_PARAMS_ALL; ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); @@ -599,7 +647,6 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) goto out; } - bb->role_id = wl->role_id; bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout); bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout); bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps; @@ -629,7 +676,6 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid) goto out; } - acx_aid->role_id = wl->role_id; acx_aid->aid = cpu_to_le16(aid); ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); @@ -685,7 +731,6 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) goto out; } - acx->role_id = wl->role_id; acx->preamble = preamble; ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); @@ -713,7 +758,6 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, goto out; } - acx->role_id = wl->role_id; acx->ctsprotect = ctsprotect; ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); @@ -745,8 +789,9 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) int wl1271_acx_sta_rate_policies(struct wl1271 *wl) { - struct acx_rate_policy *acx; + struct acx_sta_rate_policy *acx; struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf; + int idx = 0; int ret = 0; wl1271_debug(DEBUG_ACX, "acx rate policies"); @@ -758,30 +803,25 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl) goto out; } - wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x", - wl->basic_rate, wl->rate_set); - /* configure one basic rate class */ - acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE); - acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate); - acx->rate_policy.short_retry_limit = c->short_retry_limit; - acx->rate_policy.long_retry_limit = c->long_retry_limit; - acx->rate_policy.aflags = c->aflags; - - ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of rate policies failed: %d", ret); - goto out; - } + idx = ACX_TX_BASIC_RATE; + acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate); + acx->rate_class[idx].short_retry_limit = c->short_retry_limit; + acx->rate_class[idx].long_retry_limit = c->long_retry_limit; + acx->rate_class[idx].aflags = c->aflags; /* configure one AP supported rate class */ - acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE); - acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set); - acx->rate_policy.short_retry_limit = c->short_retry_limit; - acx->rate_policy.long_retry_limit = c->long_retry_limit; - acx->rate_policy.aflags = c->aflags; + idx = ACX_TX_AP_FULL_RATE; + acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); + acx->rate_class[idx].short_retry_limit = c->short_retry_limit; + acx->rate_class[idx].long_retry_limit = c->long_retry_limit; + acx->rate_class[idx].aflags = c->aflags; + acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); + wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x", + acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates, + acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates); ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); if (ret < 0) { @@ -797,7 +837,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl) int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, u8 idx) { - struct acx_rate_policy *acx; + struct acx_ap_rate_policy *acx; int ret = 0; wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x", @@ -843,7 +883,6 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, goto out; } - acx->role_id = wl->role_id; acx->ac = ac; acx->cw_min = cw_min; acx->cw_max = cpu_to_le16(cw_max); @@ -877,7 +916,6 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, goto out; } - acx->role_id = wl->role_id; acx->queue_id = queue_id; acx->channel_type = channel_type; acx->tsid = tsid; @@ -957,9 +995,52 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl) return ret; } -int wl12xx_acx_mem_cfg(struct wl1271 *wl) +int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) +{ + struct wl1271_acx_ap_config_memory *mem_conf; + struct conf_memory_settings *mem; + int ret; + + wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); + + mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); + if (!mem_conf) { + ret = -ENOMEM; + goto out; + } + + if (wl->chip.id == CHIP_ID_1283_PG20) + /* + * FIXME: The 128x AP FW does not yet support dynamic memory. + * Use the base memory configuration for 128x for now. This + * should be fine tuned in the future. + */ + mem = &wl->conf.mem_wl128x; + else + mem = &wl->conf.mem_wl127x; + + /* memory config */ + mem_conf->num_stations = mem->num_stations; + mem_conf->rx_mem_block_num = mem->rx_block_num; + mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; + mem_conf->num_ssid_profiles = mem->ssid_profiles; + mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); + + ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, + sizeof(*mem_conf)); + if (ret < 0) { + wl1271_warning("wl1271 mem config failed: %d", ret); + goto out; + } + +out: + kfree(mem_conf); + return ret; +} + +int wl1271_acx_sta_mem_cfg(struct wl1271 *wl) { - struct wl12xx_acx_config_memory *mem_conf; + struct wl1271_acx_sta_config_memory *mem_conf; struct conf_memory_settings *mem; int ret; @@ -1102,7 +1183,6 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) goto out; } - acx->role_id = wl->role_id; acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; acx->max_consecutive = wl->conf.conn.bet_max_consecutive; @@ -1130,7 +1210,6 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) goto out; } - acx->role_id = wl->role_id; acx->version = ACX_IPV4_VERSION; acx->enable = enable; @@ -1190,7 +1269,6 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) goto out; } - acx->role_id = wl->role_id; acx->enabled = enable; ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); @@ -1217,7 +1295,6 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) goto out; } - acx->role_id = wl->role_id; acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); acx->index = index; acx->tpl_validation = tpl_valid; @@ -1251,7 +1328,6 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, wl->last_rssi_event = -1; - acx->role_id = wl->role_id; acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; acx->type = WL1271_ACX_TRIG_TYPE_EDGE; @@ -1290,7 +1366,6 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) goto out; } - acx->role_id = wl->role_id; acx->rssi_beacon = c->avg_weight_rssi_beacon; acx->rssi_data = c->avg_weight_rssi_data; acx->snr_beacon = c->avg_weight_snr_beacon; @@ -1309,15 +1384,14 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, struct ieee80211_sta_ht_cap *ht_cap, - bool allow_ht_operation, u8 hlid) + bool allow_ht_operation) { struct wl1271_acx_ht_capabilities *acx; + u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; int ret = 0; u32 ht_capabilites = 0; - wl1271_debug(DEBUG_ACX, "acx ht capabilities setting " - "sta supp: %d sta cap: %d", ht_cap->ht_supported, - ht_cap->cap); + wl1271_debug(DEBUG_ACX, "acx ht capabilities setting"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) { @@ -1325,22 +1399,26 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, goto out; } - if (allow_ht_operation && ht_cap->ht_supported) { - /* no need to translate capabilities - use the spec values */ - ht_capabilites = ht_cap->cap; - - /* - * this bit is not employed by the spec but only by FW to - * indicate peer HT support - */ - ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION; + /* Allow HT Operation ? */ + if (allow_ht_operation) { + ht_capabilites = + WL1271_ACX_FW_CAP_HT_OPERATION; + if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD) + ht_capabilites |= + WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT; + if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) + ht_capabilites |= + WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS; + if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT) + ht_capabilites |= + WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION; /* get data from A-MPDU parameters field */ acx->ampdu_max_length = ht_cap->ampdu_factor; acx->ampdu_min_spacing = ht_cap->ampdu_density; } - acx->hlid = hlid; + memcpy(acx->mac_address, mac_address, ETH_ALEN); acx->ht_capabilites = cpu_to_le32(ht_capabilites); ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx)); @@ -1368,7 +1446,6 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, goto out; } - acx->role_id = wl->role_id; acx->ht_protection = (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); acx->rifs_mode = 0; @@ -1390,12 +1467,14 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, } /* Configure BA session initiator/receiver parameters setting in the FW. */ -int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) +int wl1271_acx_set_ba_session(struct wl1271 *wl, + enum ieee80211_back_parties direction, + u8 tid_index, u8 policy) { - struct wl1271_acx_ba_initiator_policy *acx; + struct wl1271_acx_ba_session_policy *acx; int ret; - wl1271_debug(DEBUG_ACX, "acx ba initiator policy"); + wl1271_debug(DEBUG_ACX, "acx ba session setting"); acx = kzalloc(sizeof(*acx), GFP_KERNEL); if (!acx) { @@ -1403,18 +1482,33 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) goto out; } - /* set for the current role */ - acx->role_id = wl->role_id; - acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap; - acx->win_size = wl->conf.ht.tx_ba_win_size; - acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; + /* ANY role */ + acx->role_id = 0xff; + acx->tid = tid_index; + acx->enable = policy; + acx->ba_direction = direction; + + switch (direction) { + case WLAN_BACK_INITIATOR: + acx->win_size = wl->conf.ht.tx_ba_win_size; + acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; + break; + case WLAN_BACK_RECIPIENT: + acx->win_size = RX_BA_WIN_SIZE; + acx->inactivity_timeout = 0; + break; + default: + wl1271_error("Incorrect acx command id=%x\n", direction); + ret = -EINVAL; + goto out; + } ret = wl1271_cmd_configure(wl, - ACX_BA_SESSION_INIT_POLICY, + ACX_BA_SESSION_POLICY_CFG, acx, sizeof(*acx)); if (ret < 0) { - wl1271_warning("acx ba initiator policy failed: %d", ret); + wl1271_warning("acx ba session setting failed: %d", ret); goto out; } @@ -1424,8 +1518,8 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) } /* setup BA session receiver setting in the FW. */ -int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, - u16 ssn, bool enable, u8 peer_hlid) +int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, + bool enable) { struct wl1271_acx_ba_receiver_setup *acx; int ret; @@ -1438,10 +1532,11 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, goto out; } - acx->hlid = peer_hlid; + /* Single link for now */ + acx->link_id = 1; acx->tid = tid_index; acx->enable = enable; - acx->win_size = wl->conf.ht.rx_ba_win_size; + acx->win_size = 0; acx->ssn = ssn; ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx, @@ -1511,7 +1606,6 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) if (!(conf_queues & BIT(i))) continue; - rx_streaming->role_id = wl->role_id; rx_streaming->tid = i; rx_streaming->enable = enable_queues & BIT(i); rx_streaming->period = wl->conf.rx_streaming.interval; @@ -1541,7 +1635,6 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) if (!acx) return -ENOMEM; - acx->role_id = wl->role_id; acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); @@ -1610,6 +1703,31 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr) return ret; } +int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable) +{ + struct acx_ap_beacon_filter *acx = NULL; + int ret; + + wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) + return -ENOMEM; + + acx->enable = enable ? 1 : 0; + + ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT, + acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx set ap beacon filter failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} + int wl1271_acx_fm_coex(struct wl1271 *wl) { struct wl1271_acx_fm_coex *acx; @@ -1649,45 +1767,3 @@ int wl1271_acx_fm_coex(struct wl1271 *wl) kfree(acx); return ret; } - -int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl) -{ - struct wl12xx_acx_set_rate_mgmt_params *acx = NULL; - struct conf_rate_policy_settings *conf = &wl->conf.rate; - int ret; - - wl1271_debug(DEBUG_ACX, "acx set rate mgmt params"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) - return -ENOMEM; - - acx->index = ACX_RATE_MGMT_ALL_PARAMS; - acx->rate_retry_score = cpu_to_le16(conf->rate_retry_score); - acx->per_add = cpu_to_le16(conf->per_add); - acx->per_th1 = cpu_to_le16(conf->per_th1); - acx->per_th2 = cpu_to_le16(conf->per_th2); - acx->max_per = cpu_to_le16(conf->max_per); - acx->inverse_curiosity_factor = conf->inverse_curiosity_factor; - acx->tx_fail_low_th = conf->tx_fail_low_th; - acx->tx_fail_high_th = conf->tx_fail_high_th; - acx->per_alpha_shift = conf->per_alpha_shift; - acx->per_add_shift = conf->per_add_shift; - acx->per_beta1_shift = conf->per_beta1_shift; - acx->per_beta2_shift = conf->per_beta2_shift; - acx->rate_check_up = conf->rate_check_up; - acx->rate_check_down = conf->rate_check_down; - memcpy(acx->rate_retry_policy, conf->rate_retry_policy, - sizeof(acx->rate_retry_policy)); - - ret = wl1271_cmd_configure(wl, ACX_SET_RATE_MGMT_PARAMS, - acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("acx set rate mgmt params failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} diff --git a/trunk/drivers/net/wireless/wl12xx/acx.h b/trunk/drivers/net/wireless/wl12xx/acx.h index 758c596f62f6..d2eb86eccc04 100644 --- a/trunk/drivers/net/wireless/wl12xx/acx.h +++ b/trunk/drivers/net/wireless/wl12xx/acx.h @@ -101,17 +101,6 @@ struct acx_error_counter { __le32 seq_num_miss; } __packed; -enum wl12xx_role { - WL1271_ROLE_STA = 0, - WL1271_ROLE_IBSS, - WL1271_ROLE_AP, - WL1271_ROLE_DEVICE, - WL1271_ROLE_P2P_CL, - WL1271_ROLE_P2P_GO, - - WL12XX_INVALID_ROLE_TYPE = 0xff -}; - enum wl1271_psm_mode { /* Active mode */ WL1271_PSM_CAM = 0, @@ -171,6 +160,94 @@ struct acx_rx_msdu_lifetime { __le32 lifetime; } __packed; +/* + * RX Config Options Table + * Bit Definition + * === ========== + * 31:14 Reserved + * 13 Copy RX Status - when set, write three receive status words + * to top of rx'd MPDUs. + * When cleared, do not write three status words (added rev 1.5) + * 12 Reserved + * 11 RX Complete upon FCS error - when set, give rx complete + * interrupt for FCS errors, after the rx filtering, e.g. unicast + * frames not to us with FCS error will not generate an interrupt. + * 10 SSID Filter Enable - When set, the WiLink discards all beacon, + * probe request, and probe response frames with an SSID that does + * not match the SSID specified by the host in the START/JOIN + * command. + * When clear, the WiLink receives frames with any SSID. + * 9 Broadcast Filter Enable - When set, the WiLink discards all + * broadcast frames. When clear, the WiLink receives all received + * broadcast frames. + * 8:6 Reserved + * 5 BSSID Filter Enable - When set, the WiLink discards any frames + * with a BSSID that does not match the BSSID specified by the + * host. + * When clear, the WiLink receives frames from any BSSID. + * 4 MAC Addr Filter - When set, the WiLink discards any frames + * with a destination address that does not match the MAC address + * of the adaptor. + * When clear, the WiLink receives frames destined to any MAC + * address. + * 3 Promiscuous - When set, the WiLink receives all valid frames + * (i.e., all frames that pass the FCS check). + * When clear, only frames that pass the other filters specified + * are received. + * 2 FCS - When set, the WiLink includes the FCS with the received + * frame. + * When cleared, the FCS is discarded. + * 1 PLCP header - When set, write all data from baseband to frame + * buffer including PHY header. + * 0 Reserved - Always equal to 0. + * + * RX Filter Options Table + * Bit Definition + * === ========== + * 31:12 Reserved - Always equal to 0. + * 11 Association - When set, the WiLink receives all association + * related frames (association request/response, reassocation + * request/response, and disassociation). When clear, these frames + * are discarded. + * 10 Auth/De auth - When set, the WiLink receives all authentication + * and de-authentication frames. When clear, these frames are + * discarded. + * 9 Beacon - When set, the WiLink receives all beacon frames. + * When clear, these frames are discarded. + * 8 Contention Free - When set, the WiLink receives all contention + * free frames. + * When clear, these frames are discarded. + * 7 Control - When set, the WiLink receives all control frames. + * When clear, these frames are discarded. + * 6 Data - When set, the WiLink receives all data frames. + * When clear, these frames are discarded. + * 5 FCS Error - When set, the WiLink receives frames that have FCS + * errors. + * When clear, these frames are discarded. + * 4 Management - When set, the WiLink receives all management + * frames. + * When clear, these frames are discarded. + * 3 Probe Request - When set, the WiLink receives all probe request + * frames. + * When clear, these frames are discarded. + * 2 Probe Response - When set, the WiLink receives all probe + * response frames. + * When clear, these frames are discarded. + * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK + * frames. + * When clear, these frames are discarded. + * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames + * that have reserved frame types and sub types as defined by the + * 802.11 specification. + * When clear, these frames are discarded. + */ +struct acx_rx_config { + struct acx_header header; + + __le32 config_options; + __le32 filter_options; +} __packed; + struct acx_packet_detection { struct acx_header header; @@ -190,10 +267,9 @@ enum acx_slot_type { struct acx_slot { struct acx_header header; - u8 role_id; u8 wone_index; /* Reserved */ u8 slot_time; - u8 reserved[5]; + u8 reserved[6]; } __packed; @@ -203,35 +279,29 @@ struct acx_slot { struct acx_dot11_grp_addr_tbl { struct acx_header header; - u8 role_id; u8 enabled; u8 num_groups; - u8 pad[1]; + u8 pad[2]; u8 mac_table[ADDRESS_GROUP_MAX_LEN]; } __packed; struct acx_rx_timeout { struct acx_header header; - u8 role_id; - u8 reserved; __le16 ps_poll_timeout; __le16 upsd_timeout; - u8 padding[2]; } __packed; struct acx_rts_threshold { struct acx_header header; - u8 role_id; - u8 reserved; __le16 threshold; + u8 pad[2]; } __packed; struct acx_beacon_filter_option { struct acx_header header; - u8 role_id; u8 enable; /* * The number of beacons without the unicast TIM @@ -241,7 +311,7 @@ struct acx_beacon_filter_option { * without the unicast TIM bit set are dropped. */ u8 max_num_beacons; - u8 pad[1]; + u8 pad[2]; } __packed; /* @@ -280,17 +350,14 @@ struct acx_beacon_filter_option { struct acx_beacon_filter_ie_table { struct acx_header header; - u8 role_id; u8 num_ie; - u8 pad[2]; + u8 pad[3]; u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; } __packed; struct acx_conn_monit_params { struct acx_header header; - u8 role_id; - u8 padding[3]; __le32 synch_fail_thold; /* number of beacons missed */ __le32 bss_lose_timeout; /* number of TU's from synch fail */ } __packed; @@ -302,14 +369,23 @@ struct acx_bt_wlan_coex { u8 pad[3]; } __packed; -struct acx_bt_wlan_coex_param { +struct acx_sta_bt_wlan_coex_param { + struct acx_header header; + + __le32 params[CONF_SG_STA_PARAMS_MAX]; + u8 param_idx; + u8 padding[3]; +} __packed; + +struct acx_ap_bt_wlan_coex_param { struct acx_header header; - __le32 params[CONF_SG_PARAMS_MAX]; + __le32 params[CONF_SG_AP_PARAMS_MAX]; u8 param_idx; u8 padding[3]; } __packed; + struct acx_dco_itrim_params { struct acx_header header; @@ -330,16 +406,15 @@ struct acx_energy_detection { struct acx_beacon_broadcast { struct acx_header header; - u8 role_id; - /* Enables receiving of broadcast packets in PS mode */ - u8 rx_broadcast_in_ps; - __le16 beacon_rx_timeout; __le16 broadcast_timeout; + /* Enables receiving of broadcast packets in PS mode */ + u8 rx_broadcast_in_ps; + /* Consecutive PS Poll failures before updating the host */ u8 ps_poll_threshold; - u8 pad[1]; + u8 pad[2]; } __packed; struct acx_event_mask { @@ -349,6 +424,35 @@ struct acx_event_mask { __le32 high_event_mask; /* Unused */ } __packed; +#define CFG_RX_FCS BIT(2) +#define CFG_RX_ALL_GOOD BIT(3) +#define CFG_UNI_FILTER_EN BIT(4) +#define CFG_BSSID_FILTER_EN BIT(5) +#define CFG_MC_FILTER_EN BIT(6) +#define CFG_MC_ADDR0_EN BIT(7) +#define CFG_MC_ADDR1_EN BIT(8) +#define CFG_BC_REJECT_EN BIT(9) +#define CFG_SSID_FILTER_EN BIT(10) +#define CFG_RX_INT_FCS_ERROR BIT(11) +#define CFG_RX_INT_ENCRYPTED BIT(12) +#define CFG_RX_WR_RX_STATUS BIT(13) +#define CFG_RX_FILTER_NULTI BIT(14) +#define CFG_RX_RESERVE BIT(15) +#define CFG_RX_TIMESTAMP_TSF BIT(16) + +#define CFG_RX_RSV_EN BIT(0) +#define CFG_RX_RCTS_ACK BIT(1) +#define CFG_RX_PRSP_EN BIT(2) +#define CFG_RX_PREQ_EN BIT(3) +#define CFG_RX_MGMT_EN BIT(4) +#define CFG_RX_FCS_ERROR BIT(5) +#define CFG_RX_DATA_EN BIT(6) +#define CFG_RX_CTL_EN BIT(7) +#define CFG_RX_CF_EN BIT(8) +#define CFG_RX_BCN_EN BIT(9) +#define CFG_RX_AUTH_EN BIT(10) +#define CFG_RX_ASSOC_EN BIT(11) + #define SCAN_PASSIVE BIT(0) #define SCAN_5GHZ_BAND BIT(1) #define SCAN_TRIGGERED BIT(2) @@ -361,8 +465,6 @@ struct acx_event_mask { struct acx_feature_config { struct acx_header header; - u8 role_id; - u8 padding[3]; __le32 options; __le32 data_flow_options; } __packed; @@ -370,18 +472,16 @@ struct acx_feature_config { struct acx_current_tx_power { struct acx_header header; - u8 role_id; u8 current_tx_power; - u8 padding[2]; + u8 padding[3]; } __packed; struct acx_wake_up_condition { struct acx_header header; - u8 role_id; u8 wake_up_event; /* Only one bit can be set */ u8 listen_interval; - u8 pad[1]; + u8 pad[2]; } __packed; struct acx_aid { @@ -390,9 +490,8 @@ struct acx_aid { /* * To be set when associated with an AP. */ - u8 role_id; - u8 reserved; __le16 aid; + u8 pad[2]; } __packed; enum acx_preamble_type { @@ -407,9 +506,8 @@ struct acx_preamble { * When set, the WiLink transmits the frames with a short preamble and * when cleared, the WiLink transmits the frames with a long preamble. */ - u8 role_id; u8 preamble; - u8 padding[2]; + u8 padding[3]; } __packed; enum acx_ctsprotect_type { @@ -419,9 +517,8 @@ enum acx_ctsprotect_type { struct acx_ctsprotect { struct acx_header header; - u8 role_id; u8 ctsprotect; - u8 padding[2]; + u8 padding[3]; } __packed; struct acx_tx_statistics { @@ -656,9 +753,18 @@ struct acx_rate_class { #define ACX_TX_BASIC_RATE 0 #define ACX_TX_AP_FULL_RATE 1 +#define ACX_TX_RATE_POLICY_CNT 2 +struct acx_sta_rate_policy { + struct acx_header header; + + __le32 rate_class_cnt; + struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES]; +} __packed; + + #define ACX_TX_AP_MODE_MGMT_RATE 4 #define ACX_TX_AP_MODE_BCST_RATE 5 -struct acx_rate_policy { +struct acx_ap_rate_policy { struct acx_header header; __le32 rate_policy_idx; @@ -667,23 +773,22 @@ struct acx_rate_policy { struct acx_ac_cfg { struct acx_header header; - u8 role_id; u8 ac; - u8 aifsn; u8 cw_min; __le16 cw_max; + u8 aifsn; + u8 reserved; __le16 tx_op_limit; } __packed; struct acx_tid_config { struct acx_header header; - u8 role_id; u8 queue_id; u8 channel_type; u8 tsid; u8 ps_scheme; u8 ack_policy; - u8 padding[2]; + u8 padding[3]; __le32 apsd_conf[2]; } __packed; @@ -699,7 +804,19 @@ struct acx_tx_config_options { __le16 tx_compl_threshold; /* number of packets */ } __packed; -struct wl12xx_acx_config_memory { +#define ACX_TX_DESCRIPTORS 32 + +struct wl1271_acx_ap_config_memory { + struct acx_header header; + + u8 rx_mem_block_num; + u8 tx_min_mem_block_num; + u8 num_stations; + u8 num_ssid_profiles; + __le32 total_tx_descriptors; +} __packed; + +struct wl1271_acx_sta_config_memory { struct acx_header header; u8 rx_mem_block_num; @@ -773,10 +890,9 @@ struct wl1271_acx_rx_config_opt { struct wl1271_acx_bet_enable { struct acx_header header; - u8 role_id; u8 enable; u8 max_consecutive; - u8 padding[1]; + u8 padding[2]; } __packed; #define ACX_IPV4_VERSION 4 @@ -789,10 +905,9 @@ struct wl1271_acx_bet_enable { struct wl1271_acx_arp_filter { struct acx_header header; - u8 role_id; u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */ u8 enable; /* bitmap of enabled ARP filtering features */ - u8 padding[1]; + u8 padding[2]; u8 address[16]; /* The configured device IP address - all ARP requests directed to this IP address will pass through. For IPv4, the first four bytes are @@ -810,9 +925,8 @@ struct wl1271_acx_pm_config { struct wl1271_acx_keep_alive_mode { struct acx_header header; - u8 role_id; u8 enabled; - u8 padding[2]; + u8 padding[3]; } __packed; enum { @@ -828,11 +942,11 @@ enum { struct wl1271_acx_keep_alive_config { struct acx_header header; - u8 role_id; + __le32 period; u8 index; u8 tpl_validation; u8 trigger; - __le32 period; + u8 padding; } __packed; #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) @@ -876,33 +990,26 @@ enum { struct wl1271_acx_rssi_snr_trigger { struct acx_header header; - u8 role_id; + __le16 threshold; + __le16 pacing; /* 0 - 60000 ms */ u8 metric; u8 type; u8 dir; - __le16 threshold; - __le16 pacing; /* 0 - 60000 ms */ u8 hysteresis; u8 index; u8 enable; - u8 padding[1]; + u8 padding[2]; }; struct wl1271_acx_rssi_snr_avg_weights { struct acx_header header; - u8 role_id; - u8 padding[3]; u8 rssi_beacon; u8 rssi_data; u8 snr_beacon; u8 snr_data; }; - -/* special capability bit (not employed by the 802.11n spec) */ -#define WL12XX_HT_CAP_HT_OPERATION BIT(16) - /* * ACX_PEER_HT_CAP * Configure HT capabilities - declare the capabilities of the peer @@ -911,11 +1018,28 @@ struct wl1271_acx_rssi_snr_avg_weights { struct wl1271_acx_ht_capabilities { struct acx_header header; - /* bitmask of capability bits supported by the peer */ + /* + * bit 0 - Allow HT Operation + * bit 1 - Allow Greenfield format in TX + * bit 2 - Allow Short GI in TX + * bit 3 - Allow L-SIG TXOP Protection in TX + * bit 4 - Allow HT Control fields in TX. + * Note, driver will still leave space for HT control in packets + * regardless of the value of this field. FW will be responsible + * to drop the HT field from any frame when this Bit set to 0. + * bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD. + * Exact policy setting for this feature is TBD. + * Note, this bit can only be set to 1 if bit 3 is set to 1. + */ __le32 ht_capabilites; - /* Indicates to which link these capabilities apply. */ - u8 hlid; + /* + * Indicates to which peer these capabilities apply. + * For infrastructure use ff:ff:ff:ff:ff:ff that indicates relevance + * for all peers. + * Only valid for IBSS/DLS operation. + */ + u8 mac_address[ETH_ALEN]; /* * This the maximum A-MPDU length supported by the AP. The FW may not @@ -925,10 +1049,17 @@ struct wl1271_acx_ht_capabilities { /* This is the minimal spacing required when sending A-MPDUs to the AP*/ u8 ampdu_min_spacing; - - u8 padding; } __packed; +/* HT Capabilites Fw Bit Mask Mapping */ +#define WL1271_ACX_FW_CAP_HT_OPERATION BIT(0) +#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT BIT(1) +#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS BIT(2) +#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION BIT(3) +#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS BIT(4) +#define WL1271_ACX_FW_CAP_RD_INITIATION BIT(5) + + /* * ACX_HT_BSS_OPERATION * Configure HT capabilities - AP rules for behavior in the BSS. @@ -936,8 +1067,6 @@ struct wl1271_acx_ht_capabilities { struct wl1271_acx_ht_information { struct acx_header header; - u8 role_id; - /* Values: 0 - RIFS not allowed, 1 - RIFS allowed */ u8 rifs_mode; @@ -959,51 +1088,60 @@ struct wl1271_acx_ht_information { */ u8 dual_cts_protection; - u8 padding[2]; + u8 padding[3]; } __packed; -#define RX_BA_MAX_SESSIONS 2 +#define RX_BA_WIN_SIZE 8 -struct wl1271_acx_ba_initiator_policy { +struct wl1271_acx_ba_session_policy { struct acx_header header; - - /* Specifies role Id, Range 0-7, 0xFF means ANY role. */ + /* + * Specifies role Id, Range 0-7, 0xFF means ANY role. + * Future use. For now this field is irrelevant + */ u8 role_id; - /* - * Per TID setting for allowing TX BA. Set a bit to 1 to allow - * TX BA sessions for the corresponding TID. + * Specifies Link Id, Range 0-31, 0xFF means ANY Link Id. + * Not applicable if Role Id is set to ANY. */ - u8 tid_bitmap; + u8 link_id; - /* Windows size in number of packets */ - u8 win_size; + u8 tid; - u8 padding1[1]; + u8 enable; + + /* Windows size in number of packets */ + u16 win_size; - /* As initiator inactivity timeout in time units(TU) of 1024us */ + /* + * As initiator inactivity timeout in time units(TU) of 1024us. + * As receiver reserved + */ u16 inactivity_timeout; - u8 padding[2]; + /* Initiator = 1/Receiver = 0 */ + u8 ba_direction; + + u8 padding[3]; } __packed; struct wl1271_acx_ba_receiver_setup { struct acx_header header; - /* Specifies link id, range 0-31 */ - u8 hlid; + /* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */ + u8 link_id; u8 tid; u8 enable; + u8 padding[1]; + /* Windows size in number of packets */ - u8 win_size; + u16 win_size; /* BA session starting sequence number. RANGE 0-FFF */ u16 ssn; - - u8 padding[2]; } __packed; struct wl1271_acx_fw_tsf_information { @@ -1020,7 +1158,6 @@ struct wl1271_acx_fw_tsf_information { struct wl1271_acx_ps_rx_streaming { struct acx_header header; - u8 role_id; u8 tid; u8 enable; @@ -1029,20 +1166,17 @@ struct wl1271_acx_ps_rx_streaming { /* timeout before first trigger (0-200 msec) */ u8 timeout; - u8 padding[3]; } __packed; struct wl1271_acx_ap_max_tx_retry { struct acx_header header; - u8 role_id; - u8 padding_1; - /* * the number of frames transmission failures before * issuing the aging event. */ __le16 max_tx_retry; + u8 padding_1[2]; } __packed; struct wl1271_acx_config_ps { @@ -1061,6 +1195,13 @@ struct wl1271_acx_inconnection_sta { u8 padding1[2]; } __packed; +struct acx_ap_beacon_filter { + struct acx_header header; + + u8 enable; + u8 pad[3]; +} __packed; + /* * ACX_FM_COEX_CFG * set the FM co-existence parameters. @@ -1120,30 +1261,6 @@ struct wl1271_acx_fm_coex { u8 swallow_clk_diff; } __packed; -#define ACX_RATE_MGMT_ALL_PARAMS 0xff -struct wl12xx_acx_set_rate_mgmt_params { - struct acx_header header; - - u8 index; /* 0xff to configure all params */ - u8 padding1; - __le16 rate_retry_score; - __le16 per_add; - __le16 per_th1; - __le16 per_th2; - __le16 max_per; - u8 inverse_curiosity_factor; - u8 tx_fail_low_th; - u8 tx_fail_high_th; - u8 per_alpha_shift; - u8 per_add_shift; - u8 per_beta1_shift; - u8 per_beta2_shift; - u8 rate_check_up; - u8 rate_check_down; - u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; - u8 padding2[2]; -} __packed; - enum { ACX_WAKE_UP_CONDITIONS = 0x0002, ACX_MEM_CFG = 0x0003, @@ -1151,7 +1268,10 @@ enum { ACX_AC_CFG = 0x0007, ACX_MEM_MAP = 0x0008, ACX_AID = 0x000A, + /* ACX_FW_REV is missing in the ref driver, but seems to work */ + ACX_FW_REV = 0x000D, ACX_MEDIUM_USAGE = 0x000F, + ACX_RX_CFG = 0x0010, ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ ACX_STATISTICS = 0x0013, /* Debug API */ ACX_PWR_CONSUMPTION_STATISTICS = 0x0014, @@ -1159,6 +1279,7 @@ enum { ACX_TID_CFG = 0x001A, ACX_PS_RX_STREAMING = 0x001B, ACX_BEACON_FILTER_OPT = 0x001F, + ACX_AP_BEACON_FILTER_OPT = 0x0020, ACX_NOISE_HIST = 0x0021, ACX_HDK_VERSION = 0x0022, /* ??? */ ACX_PD_THRESHOLD = 0x0023, @@ -1166,6 +1287,7 @@ enum { ACX_CCA_THRESHOLD = 0x0025, ACX_EVENT_MBOX_MASK = 0x0026, ACX_CONN_MONIT_PARAMS = 0x002D, + ACX_CONS_TX_FAILURE = 0x002F, ACX_BCN_DTIM_OPTIONS = 0x0031, ACX_SG_ENABLE = 0x0032, ACX_SG_CFG = 0x0033, @@ -1192,14 +1314,11 @@ enum { ACX_RSSI_SNR_WEIGHTS = 0x0052, ACX_KEEP_ALIVE_MODE = 0x0053, ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, - ACX_BA_SESSION_INIT_POLICY = 0x0055, + ACX_BA_SESSION_POLICY_CFG = 0x0055, ACX_BA_SESSION_RX_SETUP = 0x0056, ACX_PEER_HT_CAP = 0x0057, ACX_HT_BSS_OPERATION = 0x0058, ACX_COEX_ACTIVITY = 0x0059, - ACX_BURST_MODE = 0x005C, - ACX_SET_RATE_MGMT_PARAMS = 0x005D, - ACX_SET_RATE_ADAPT_PARAMS = 0x0060, ACX_SET_DCO_ITRIM_PARAMS = 0x0061, ACX_GEN_FW_CMD = 0x0070, ACX_HOST_IF_CFG_BITMAP = 0x0071, @@ -1223,6 +1342,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl); int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, size_t len); int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); +int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter); int wl1271_acx_pd_threshold(struct wl1271 *wl); int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, @@ -1234,7 +1354,8 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); int wl1271_acx_beacon_filter_table(struct wl1271 *wl); int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); -int wl12xx_acx_sg_cfg(struct wl1271 *wl); +int wl1271_acx_sta_sg_cfg(struct wl1271 *wl); +int wl1271_acx_ap_sg_cfg(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl); int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); int wl1271_acx_aid(struct wl1271 *wl, u16 aid); @@ -1253,7 +1374,8 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, u32 apsd_conf0, u32 apsd_conf1); int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); int wl1271_acx_tx_config_options(struct wl1271 *wl); -int wl12xx_acx_mem_cfg(struct wl1271 *wl); +int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); +int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl); int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); @@ -1268,18 +1390,20 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, struct ieee80211_sta_ht_cap *ht_cap, - bool allow_ht_operation, u8 hlid); + bool allow_ht_operation); int wl1271_acx_set_ht_information(struct wl1271 *wl, u16 ht_operation_mode); -int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl); -int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, - u16 ssn, bool enable, u8 peer_hlid); +int wl1271_acx_set_ba_session(struct wl1271 *wl, + enum ieee80211_back_parties direction, + u8 tid_index, u8 policy); +int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, + bool enable); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); +int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); int wl1271_acx_fm_coex(struct wl1271 *wl); -int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); #endif /* __WL1271_ACX_H__ */ diff --git a/trunk/drivers/net/wireless/wl12xx/boot.c b/trunk/drivers/net/wireless/wl12xx/boot.c index cc70422c0575..5ebc64d89407 100644 --- a/trunk/drivers/net/wireless/wl12xx/boot.c +++ b/trunk/drivers/net/wireless/wl12xx/boot.c @@ -107,6 +107,16 @@ static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl) unsigned int quirks = 0; unsigned int *fw_ver = wl->chip.fw_ver; + /* Only for wl127x */ + if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && + /* Check STA version */ + (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && + (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || + /* Check AP version */ + ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && + (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) + quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; + /* Only new station firmwares support routing fw logs to the host */ if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN)) @@ -494,18 +504,21 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) wl->event_mask = BSS_LOSE_EVENT_ID | SCAN_COMPLETE_EVENT_ID | PS_REPORT_EVENT_ID | + JOIN_EVENT_COMPLETE_ID | DISCONNECT_EVENT_COMPLETE_ID | RSSI_SNR_TRIGGER_0_EVENT_ID | PSPOLL_DELIVERY_FAILURE_EVENT_ID | SOFT_GEMINI_SENSE_EVENT_ID | PERIODIC_SCAN_REPORT_EVENT_ID | - PERIODIC_SCAN_COMPLETE_EVENT_ID | - DUMMY_PACKET_EVENT_ID | - PEER_REMOVE_COMPLETE_EVENT_ID | - BA_SESSION_RX_CONSTRAINT_EVENT_ID | - REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID | - INACTIVE_STA_EVENT_ID | - MAX_TX_RETRY_EVENT_ID; + PERIODIC_SCAN_COMPLETE_EVENT_ID; + + if (wl->bss_type == BSS_TYPE_AP_BSS) + wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | + INACTIVE_STA_EVENT_ID | + MAX_TX_RETRY_EVENT_ID; + else + wl->event_mask |= DUMMY_PACKET_EVENT_ID | + BA_SESSION_RX_CONSTRAINT_EVENT_ID; ret = wl1271_event_unmask(wl); if (ret < 0) { @@ -536,13 +549,13 @@ static void wl1271_boot_hw_version(struct wl1271 *wl) { u32 fuse; - if (wl->chip.id == CHIP_ID_1283_PG20) - fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); - else - fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); + fuse = wl1271_top_reg_read(wl, REG_FUSE_DATA_2_1); fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; wl->hw_pg_ver = (s8)fuse; + + if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3) + wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; } static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) @@ -683,8 +696,7 @@ static int wl127x_boot_clk(struct wl1271 *wl) u32 pause; u32 clk; - if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3) - wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; + wl1271_boot_hw_version(wl); if (wl->ref_clock == CONF_REF_CLK_19_2_E || wl->ref_clock == CONF_REF_CLK_38_4_E || @@ -738,8 +750,6 @@ int wl1271_load_firmware(struct wl1271 *wl) u32 tmp, clk; int selected_clock = -1; - wl1271_boot_hw_version(wl); - if (wl->chip.id == CHIP_ID_1283_PG20) { ret = wl128x_boot_clk(wl, &selected_clock); if (ret < 0) @@ -842,6 +852,9 @@ int wl1271_boot(struct wl1271 *wl) /* Enable firmware interrupts now */ wl1271_boot_enable_interrupts(wl); + /* set the wl1271 default filters */ + wl1271_set_default_filters(wl); + wl1271_event_mbox_config(wl); out: diff --git a/trunk/drivers/net/wireless/wl12xx/boot.h b/trunk/drivers/net/wireless/wl12xx/boot.h index 06dad9380fa7..e8f8255bbabe 100644 --- a/trunk/drivers/net/wireless/wl12xx/boot.h +++ b/trunk/drivers/net/wireless/wl12xx/boot.h @@ -55,8 +55,7 @@ struct wl1271_static_data { #define OCP_REG_CLK_POLARITY 0x0cb2 #define OCP_REG_CLK_PULL 0x0cb4 -#define WL127X_REG_FUSE_DATA_2_1 0x050a -#define WL128X_REG_FUSE_DATA_2_1 0x2152 +#define REG_FUSE_DATA_2_1 0x050a #define PG_VER_MASK 0x3c #define PG_VER_OFFSET 2 diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.c b/trunk/drivers/net/wireless/wl12xx/cmd.c index 817bc183bc83..97dd237a9580 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.c +++ b/trunk/drivers/net/wireless/wl12xx/cmd.c @@ -363,470 +363,63 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) return 0; } -int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id) +int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) { - struct wl12xx_cmd_role_enable *cmd; - int ret; - - wl1271_debug(DEBUG_CMD, "cmd role enable"); + struct wl1271_cmd_join *join; + int ret, i; + u8 *bssid; - if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID)) - return -EBUSY; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { + join = kzalloc(sizeof(*join), GFP_KERNEL); + if (!join) { ret = -ENOMEM; goto out; } - /* get role id */ - cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES); - if (cmd->role_id >= WL12XX_MAX_ROLES) { - ret = -EBUSY; - goto out_free; - } - - memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN); - cmd->role_type = role_type; - - ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd role enable"); - goto out_free; - } - - __set_bit(cmd->role_id, wl->roles_map); - *role_id = cmd->role_id; - -out_free: - kfree(cmd); - -out: - return ret; -} - -int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id) -{ - struct wl12xx_cmd_role_disable *cmd; - int ret; - - wl1271_debug(DEBUG_CMD, "cmd role disable"); - - if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID)) - return -ENOENT; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - cmd->role_id = *role_id; - - ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd role disable"); - goto out_free; - } - - __clear_bit(*role_id, wl->roles_map); - *role_id = WL12XX_INVALID_ROLE_ID; - -out_free: - kfree(cmd); - -out: - return ret; -} - -static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid) -{ - u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); - if (link >= WL12XX_MAX_LINKS) - return -EBUSY; - - __set_bit(link, wl->links_map); - *hlid = link; - return 0; -} - -static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) -{ - if (*hlid == WL12XX_INVALID_LINK_ID) - return; - - __clear_bit(*hlid, wl->links_map); - *hlid = WL12XX_INVALID_LINK_ID; -} - -static int wl12xx_get_new_session_id(struct wl1271 *wl) -{ - if (wl->session_counter >= SESSION_COUNTER_MAX) - wl->session_counter = 0; - - wl->session_counter++; + wl1271_debug(DEBUG_CMD, "cmd join"); - return wl->session_counter; -} - -int wl12xx_cmd_role_start_dev(struct wl1271 *wl) -{ - struct wl12xx_cmd_role_start *cmd; - int ret; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } + /* Reverse order BSSID */ + bssid = (u8 *) &join->bssid_lsb; + for (i = 0; i < ETH_ALEN; i++) + bssid[i] = wl->bssid[ETH_ALEN - i - 1]; - wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id); + join->rx_config_options = cpu_to_le32(wl->rx_config); + join->rx_filter_options = cpu_to_le32(wl->rx_filter); + join->bss_type = bss_type; + join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); + join->supported_rate_set = cpu_to_le32(wl->rate_set); - cmd->role_id = wl->dev_role_id; if (wl->band == IEEE80211_BAND_5GHZ) - cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wl->channel; - - if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wl->dev_hlid); - if (ret) - goto out_free; - } - cmd->device.hlid = wl->dev_hlid; - cmd->device.session = wl->session_counter; - - wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", - cmd->role_id, cmd->device.hlid, cmd->device.session); + join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; - ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd role enable"); - goto err_hlid; - } - - goto out_free; - -err_hlid: - /* clear links on error */ - __clear_bit(wl->dev_hlid, wl->links_map); - wl->dev_hlid = WL12XX_INVALID_LINK_ID; - - -out_free: - kfree(cmd); + join->beacon_interval = cpu_to_le16(wl->beacon_int); + join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; -out: - return ret; -} + join->channel = wl->channel; + join->ssid_len = wl->ssid_len; + memcpy(join->ssid, wl->ssid, wl->ssid_len); -int wl12xx_cmd_role_stop_dev(struct wl1271 *wl) -{ - struct wl12xx_cmd_role_stop *cmd; - int ret; + join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; - if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID)) - return -EINVAL; + wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x", + join->basic_rate_set, join->supported_rate_set); - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - wl1271_debug(DEBUG_CMD, "cmd role stop dev"); - - cmd->role_id = wl->dev_role_id; - cmd->disc_type = DISCONNECT_IMMEDIATE; - cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); - - ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); if (ret < 0) { - wl1271_error("failed to initiate cmd role stop"); + wl1271_error("failed to initiate cmd join"); goto out_free; } - ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); - if (ret < 0) { - wl1271_error("cmd role stop dev event completion error"); - goto out_free; - } - - wl12xx_free_link(wl, &wl->dev_hlid); - -out_free: - kfree(cmd); - -out: - return ret; -} - -int wl12xx_cmd_role_start_sta(struct wl1271 *wl) -{ - struct wl12xx_cmd_role_start *cmd; - int ret; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id); - - cmd->role_id = wl->role_id; - if (wl->band == IEEE80211_BAND_5GHZ) - cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wl->channel; - cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set); - cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int); - cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; - cmd->sta.ssid_len = wl->ssid_len; - memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len); - memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN); - cmd->sta.local_rates = cpu_to_le32(wl->rate_set); - - if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wl->sta_hlid); - if (ret) - goto out_free; - } - cmd->sta.hlid = wl->sta_hlid; - cmd->sta.session = wl12xx_get_new_session_id(wl); - cmd->sta.remote_rates = cpu_to_le32(wl->rate_set); - - wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " - "basic_rate_set: 0x%x, remote_rates: 0x%x", - wl->role_id, cmd->sta.hlid, cmd->sta.session, - wl->basic_rate_set, wl->rate_set); - - ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd role start sta"); - goto err_hlid; - } - - goto out_free; - -err_hlid: - /* clear links on error. */ - wl12xx_free_link(wl, &wl->sta_hlid); - -out_free: - kfree(cmd); - -out: - return ret; -} - -/* use this function to stop ibss as well */ -int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) -{ - struct wl12xx_cmd_role_stop *cmd; - int ret; - - if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID)) - return -EINVAL; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id); - - cmd->role_id = wl->role_id; - cmd->disc_type = DISCONNECT_IMMEDIATE; - cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); - - ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd role stop sta"); - goto out_free; - } - - wl12xx_free_link(wl, &wl->sta_hlid); - -out_free: - kfree(cmd); - -out: - return ret; -} - -int wl12xx_cmd_role_start_ap(struct wl1271 *wl) -{ - struct wl12xx_cmd_role_start *cmd; - struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; - int ret; - - wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); - - /* - * We currently do not support hidden SSID. The real SSID - * should be fetched from mac80211 first. - */ - if (wl->ssid_len == 0) { - wl1271_warning("Hidden SSID currently not supported for AP"); - ret = -EINVAL; - goto out; - } - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid); + ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); if (ret < 0) - goto out_free; - - ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid); - if (ret < 0) - goto out_free_global; - - cmd->role_id = wl->role_id; - cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); - cmd->ap.bss_index = WL1271_AP_BSS_INDEX; - cmd->ap.global_hlid = wl->ap_global_hlid; - cmd->ap.broadcast_hlid = wl->ap_bcast_hlid; - cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set); - cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); - cmd->ap.dtim_interval = bss_conf->dtim_period; - cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; - cmd->channel = wl->channel; - cmd->ap.ssid_len = wl->ssid_len; - cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; - memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); - cmd->ap.local_rates = cpu_to_le32(0xffffffff); - - switch (wl->band) { - case IEEE80211_BAND_2GHZ: - cmd->band = RADIO_BAND_2_4GHZ; - break; - case IEEE80211_BAND_5GHZ: - cmd->band = RADIO_BAND_5GHZ; - break; - default: - wl1271_warning("ap start - unknown band: %d", (int)wl->band); - cmd->band = RADIO_BAND_2_4GHZ; - break; - } - - ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd role start ap"); - goto out_free_bcast; - } - - goto out_free; - -out_free_bcast: - wl12xx_free_link(wl, &wl->ap_bcast_hlid); - -out_free_global: - wl12xx_free_link(wl, &wl->ap_global_hlid); - -out_free: - kfree(cmd); - -out: - return ret; -} - -int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) -{ - struct wl12xx_cmd_role_stop *cmd; - int ret; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id); - - cmd->role_id = wl->role_id; - - ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd role stop ap"); - goto out_free; - } - - wl12xx_free_link(wl, &wl->ap_bcast_hlid); - wl12xx_free_link(wl, &wl->ap_global_hlid); + wl1271_error("cmd join event completion error"); out_free: - kfree(cmd); + kfree(join); out: return ret; } -int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) -{ - struct wl12xx_cmd_role_start *cmd; - struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; - int ret; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id); - - cmd->role_id = wl->role_id; - if (wl->band == IEEE80211_BAND_5GHZ) - cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wl->channel; - cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set); - cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int); - cmd->ibss.dtim_interval = bss_conf->dtim_period; - cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; - cmd->ibss.ssid_len = wl->ssid_len; - memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len); - memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN); - cmd->sta.local_rates = cpu_to_le32(wl->rate_set); - - if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, &wl->sta_hlid); - if (ret) - goto out_free; - } - cmd->ibss.hlid = wl->sta_hlid; - cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set); - - wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " - "basic_rate_set: 0x%x, remote_rates: 0x%x", - wl->role_id, cmd->sta.hlid, cmd->sta.session, - wl->basic_rate_set, wl->rate_set); - - wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid); - - ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); - if (ret < 0) { - wl1271_error("failed to initiate cmd role enable"); - goto err_hlid; - } - - goto out_free; - -err_hlid: - /* clear links on error. */ - wl12xx_free_link(wl, &wl->sta_hlid); - -out_free: - kfree(cmd); - -out: - return ret; -} - - /** * send test command to firmware * @@ -974,7 +567,6 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) goto out; } - ps_params->role_id = wl->role_id; ps_params->ps_mode = ps_mode; ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, @@ -1221,9 +813,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) wl->basic_rate); } -int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) +int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id) { - struct wl1271_cmd_set_keys *cmd; + struct wl1271_cmd_set_sta_keys *cmd; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); @@ -1234,7 +826,36 @@ int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) goto out; } - cmd->hlid = hlid; + cmd->id = id; + cmd->key_action = cpu_to_le16(KEY_SET_ID); + cmd->key_type = KEY_WEP; + + ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_warning("cmd set_default_wep_key failed: %d", ret); + goto out; + } + +out: + kfree(cmd); + + return ret; +} + +int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id) +{ + struct wl1271_cmd_set_ap_keys *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->hlid = WL1271_AP_BROADCAST_HLID; cmd->key_id = id; cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; cmd->key_action = cpu_to_le16(KEY_SET_ID); @@ -1242,7 +863,7 @@ int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_warning("cmd set_default_wep_key failed: %d", ret); + wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret); goto out; } @@ -1256,27 +877,17 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16) { - struct wl1271_cmd_set_keys *cmd; + struct wl1271_cmd_set_sta_keys *cmd; int ret = 0; - /* hlid might have already been deleted */ - if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) - return 0; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } - cmd->hlid = wl->sta_hlid; - - if (key_type == KEY_WEP) - cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; - else if (is_broadcast_ether_addr(addr)) - cmd->lid_key_type = BROADCAST_LID_TYPE; - else - cmd->lid_key_type = UNICAST_LID_TYPE; + if (key_type != KEY_WEP) + memcpy(cmd->addr, addr, ETH_ALEN); cmd->key_action = cpu_to_le16(action); cmd->key_size = key_size; @@ -1285,7 +896,10 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); - cmd->key_id = id; + /* we have only one SSID profile */ + cmd->ssid_profile = 0; + + cmd->id = id; if (key_type == KEY_TKIP) { /* @@ -1316,15 +930,11 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, return ret; } -/* - * TODO: merge with sta/ibss into 1 set_key function. - * note there are slight diffs - */ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16) { - struct wl1271_cmd_set_keys *cmd; + struct wl1271_cmd_set_ap_keys *cmd; int ret = 0; u8 lid_type; @@ -1332,7 +942,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, if (!cmd) return -ENOMEM; - if (hlid == wl->ap_bcast_hlid) { + if (hlid == WL1271_AP_BROADCAST_HLID) { if (key_type == KEY_WEP) lid_type = WEP_DEFAULT_LID_TYPE; else @@ -1381,12 +991,12 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, return ret; } -int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid) +int wl1271_cmd_disconnect(struct wl1271 *wl) { - struct wl12xx_cmd_set_peer_state *cmd; + struct wl1271_cmd_disconnect *cmd; int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", hlid); + wl1271_debug(DEBUG_CMD, "cmd disconnect"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1394,15 +1004,21 @@ int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid) goto out; } - cmd->hlid = hlid; - cmd->state = WL1271_CMD_STA_STATE_CONNECTED; + cmd->rx_config_options = cpu_to_le32(wl->rx_config); + cmd->rx_filter_options = cpu_to_le32(wl->rx_filter); + /* disconnect reason is not used in immediate disconnections */ + cmd->type = DISCONNECT_IMMEDIATE; - ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to send set peer state command"); + wl1271_error("failed to send disconnect command"); goto out_free; } + ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); + if (ret < 0) + wl1271_error("cmd disconnect event completion error"); + out_free: kfree(cmd); @@ -1410,13 +1026,12 @@ int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid) return ret; } -int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) +int wl1271_cmd_set_sta_state(struct wl1271 *wl) { - struct wl12xx_cmd_add_peer *cmd; - int ret; - u32 sta_rates; + struct wl1271_cmd_set_sta_state *cmd; + int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid); + wl1271_debug(DEBUG_CMD, "cmd set sta state"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1424,27 +1039,11 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) goto out; } - /* currently we don't support UAPSD */ - cmd->sp_len = 0; - - memcpy(cmd->addr, sta->addr, ETH_ALEN); - cmd->bss_index = WL1271_AP_BSS_INDEX; - cmd->aid = sta->aid; - cmd->hlid = hlid; - cmd->wmm = sta->wme ? 1 : 0; - - sta_rates = sta->supp_rates[wl->band]; - if (sta->ht_cap.ht_supported) - sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; - - cmd->supported_rates = - cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates)); - - wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates); + cmd->state = WL1271_CMD_STA_STATE_CONNECTED; - ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to initiate cmd add peer"); + wl1271_error("failed to send set STA state command"); goto out_free; } @@ -1455,12 +1054,23 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) return ret; } -int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) +int wl1271_cmd_start_bss(struct wl1271 *wl) { - struct wl12xx_cmd_remove_peer *cmd; + struct wl1271_cmd_bss_start *cmd; + struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; int ret; - wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); + wl1271_debug(DEBUG_CMD, "cmd start bss"); + + /* + * FIXME: We currently do not support hidden SSID. The real SSID + * should be fetched from mac80211 first. + */ + if (wl->ssid_len == 0) { + wl1271_warning("Hidden SSID currently not supported for AP"); + ret = -EINVAL; + goto out; + } cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1468,24 +1078,40 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) goto out; } - cmd->hlid = hlid; - /* We never send a deauth, mac80211 is in charge of this */ - cmd->reason_opcode = 0; - cmd->send_deauth_flag = 0; + memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); + + cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); + cmd->bss_index = WL1271_AP_BSS_INDEX; + cmd->global_hlid = WL1271_AP_GLOBAL_HLID; + cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; + cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->beacon_interval = cpu_to_le16(wl->beacon_int); + cmd->dtim_interval = bss_conf->dtim_period; + cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP; + cmd->channel = wl->channel; + cmd->ssid_len = wl->ssid_len; + cmd->ssid_type = SSID_TYPE_PUBLIC; + memcpy(cmd->ssid, wl->ssid, wl->ssid_len); - ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0); + switch (wl->band) { + case IEEE80211_BAND_2GHZ: + cmd->band = RADIO_BAND_2_4GHZ; + break; + case IEEE80211_BAND_5GHZ: + cmd->band = RADIO_BAND_5GHZ; + break; + default: + wl1271_warning("bss start - unknown band: %d", (int)wl->band); + cmd->band = RADIO_BAND_2_4GHZ; + break; + } + + ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to initiate cmd remove peer"); + wl1271_error("failed to initiate cmd start bss"); goto out_free; } - /* - * We are ok with a timeout here. The event is sometimes not sent - * due to a firmware bug. - */ - wl1271_cmd_wait_for_event_or_timeout(wl, - PEER_REMOVE_COMPLETE_EVENT_ID); - out_free: kfree(cmd); @@ -1493,12 +1119,12 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) return ret; } -int wl12xx_cmd_config_fwlog(struct wl1271 *wl) +int wl1271_cmd_stop_bss(struct wl1271 *wl) { - struct wl12xx_cmd_config_fwlog *cmd; - int ret = 0; + struct wl1271_cmd_bss_start *cmd; + int ret; - wl1271_debug(DEBUG_CMD, "cmd config firmware logger"); + wl1271_debug(DEBUG_CMD, "cmd stop bss"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1506,15 +1132,11 @@ int wl12xx_cmd_config_fwlog(struct wl1271 *wl) goto out; } - cmd->logger_mode = wl->conf.fwlog.mode; - cmd->log_severity = wl->conf.fwlog.severity; - cmd->timestamp = wl->conf.fwlog.timestamp; - cmd->output = wl->conf.fwlog.output; - cmd->threshold = wl->conf.fwlog.threshold; + cmd->bss_index = WL1271_AP_BSS_INDEX; - ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to send config firmware logger command"); + wl1271_error("failed to initiate cmd stop bss"); goto out_free; } @@ -1525,12 +1147,12 @@ int wl12xx_cmd_config_fwlog(struct wl1271 *wl) return ret; } -int wl12xx_cmd_start_fwlog(struct wl1271 *wl) +int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) { - struct wl12xx_cmd_start_fwlog *cmd; - int ret = 0; + struct wl1271_cmd_add_sta *cmd; + int ret; - wl1271_debug(DEBUG_CMD, "cmd start firmware logger"); + wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1538,9 +1160,23 @@ int wl12xx_cmd_start_fwlog(struct wl1271 *wl) goto out; } - ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0); + /* currently we don't support UAPSD */ + cmd->sp_len = 0; + + memcpy(cmd->addr, sta->addr, ETH_ALEN); + cmd->bss_index = WL1271_AP_BSS_INDEX; + cmd->aid = sta->aid; + cmd->hlid = hlid; + cmd->wmm = sta->wme ? 1 : 0; + + cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, + sta->supp_rates[wl->band])); + + wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates); + + ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to send start firmware logger command"); + wl1271_error("failed to initiate cmd add sta"); goto out_free; } @@ -1551,12 +1187,12 @@ int wl12xx_cmd_start_fwlog(struct wl1271 *wl) return ret; } -int wl12xx_cmd_stop_fwlog(struct wl1271 *wl) +int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) { - struct wl12xx_cmd_stop_fwlog *cmd; - int ret = 0; + struct wl1271_cmd_remove_sta *cmd; + int ret; - wl1271_debug(DEBUG_CMD, "cmd stop firmware logger"); + wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1564,12 +1200,23 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl) goto out; } - ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0); + cmd->hlid = hlid; + /* We never send a deauth, mac80211 is in charge of this */ + cmd->reason_opcode = 0; + cmd->send_deauth_flag = 0; + + ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to send stop firmware logger command"); + wl1271_error("failed to initiate cmd remove sta"); goto out_free; } + /* + * We are ok with a timeout here. The event is sometimes not sent + * due to a firmware bug. + */ + wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID); + out_free: kfree(cmd); @@ -1577,15 +1224,12 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl) return ret; } -static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) +int wl12xx_cmd_config_fwlog(struct wl1271 *wl) { - struct wl12xx_cmd_roc *cmd; + struct wl12xx_cmd_config_fwlog *cmd; int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id); - - if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID)) - return -EINVAL; + wl1271_debug(DEBUG_CMD, "cmd config firmware logger"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { @@ -1593,25 +1237,15 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) goto out; } - cmd->role_id = role_id; - cmd->channel = wl->channel; - switch (wl->band) { - case IEEE80211_BAND_2GHZ: - cmd->band = RADIO_BAND_2_4GHZ; - break; - case IEEE80211_BAND_5GHZ: - cmd->band = RADIO_BAND_5GHZ; - break; - default: - wl1271_error("roc - unknown band: %d", (int)wl->band); - ret = -EINVAL; - goto out_free; - } - + cmd->logger_mode = wl->conf.fwlog.mode; + cmd->log_severity = wl->conf.fwlog.severity; + cmd->timestamp = wl->conf.fwlog.timestamp; + cmd->output = wl->conf.fwlog.output; + cmd->threshold = wl->conf.fwlog.threshold; - ret = wl1271_cmd_send(wl, CMD_REMAIN_ON_CHANNEL, cmd, sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to send ROC command"); + wl1271_error("failed to send config firmware logger command"); goto out_free; } @@ -1622,24 +1256,22 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) return ret; } -static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id) +int wl12xx_cmd_start_fwlog(struct wl1271 *wl) { - struct wl12xx_cmd_croc *cmd; + struct wl12xx_cmd_start_fwlog *cmd; int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd croc (%d)", role_id); + wl1271_debug(DEBUG_CMD, "cmd start firmware logger"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } - cmd->role_id = role_id; - ret = wl1271_cmd_send(wl, CMD_CANCEL_REMAIN_ON_CHANNEL, cmd, - sizeof(*cmd), 0); + ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("failed to send ROC command"); + wl1271_error("failed to send start firmware logger command"); goto out_free; } @@ -1650,41 +1282,28 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id) return ret; } -int wl12xx_roc(struct wl1271 *wl, u8 role_id) +int wl12xx_cmd_stop_fwlog(struct wl1271 *wl) { + struct wl12xx_cmd_stop_fwlog *cmd; int ret = 0; - if (WARN_ON(test_bit(role_id, wl->roc_map))) - return 0; + wl1271_debug(DEBUG_CMD, "cmd stop firmware logger"); - ret = wl12xx_cmd_roc(wl, role_id); - if (ret < 0) + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; goto out; + } - ret = wl1271_cmd_wait_for_event(wl, - REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID); + ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0); if (ret < 0) { - wl1271_error("cmd roc event completion error"); - goto out; + wl1271_error("failed to send stop firmware logger command"); + goto out_free; } - __set_bit(role_id, wl->roc_map); -out: - return ret; -} - -int wl12xx_croc(struct wl1271 *wl, u8 role_id) -{ - int ret = 0; - - if (WARN_ON(!test_bit(role_id, wl->roc_map))) - return 0; - - ret = wl12xx_cmd_croc(wl, role_id); - if (ret < 0) - goto out; +out_free: + kfree(cmd); - __clear_bit(role_id, wl->roc_map); out: return ret; } diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.h b/trunk/drivers/net/wireless/wl12xx/cmd.h index 22c2f373dd04..bba077ecd945 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.h +++ b/trunk/drivers/net/wireless/wl12xx/cmd.h @@ -36,15 +36,7 @@ int wl128x_cmd_general_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl); int wl128x_cmd_radio_parms(struct wl1271 *wl); int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); -int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id); -int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); -int wl12xx_cmd_role_start_dev(struct wl1271 *wl); -int wl12xx_cmd_role_stop_dev(struct wl1271 *wl); -int wl12xx_cmd_role_start_sta(struct wl1271 *wl); -int wl12xx_cmd_role_stop_sta(struct wl1271 *wl); -int wl12xx_cmd_role_start_ap(struct wl1271 *wl); -int wl12xx_cmd_role_stop_ap(struct wl1271 *wl); -int wl12xx_cmd_role_start_ibss(struct wl1271 *wl); +int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); @@ -64,18 +56,20 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); int wl1271_build_qos_null_data(struct wl1271 *wl); int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); -int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid); +int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id); +int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id); int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16); int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16); -int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid); -int wl12xx_roc(struct wl1271 *wl, u8 role_id); -int wl12xx_croc(struct wl1271 *wl, u8 role_id); -int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); -int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); +int wl1271_cmd_disconnect(struct wl1271 *wl); +int wl1271_cmd_set_sta_state(struct wl1271 *wl); +int wl1271_cmd_start_bss(struct wl1271 *wl); +int wl1271_cmd_stop_bss(struct wl1271 *wl); +int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); +int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid); int wl12xx_cmd_config_fwlog(struct wl1271 *wl); int wl12xx_cmd_start_fwlog(struct wl1271 *wl); int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); @@ -89,21 +83,25 @@ enum wl1271_commands { CMD_DISABLE_TX = 6, CMD_SCAN = 8, CMD_STOP_SCAN = 9, + CMD_START_JOIN = 11, CMD_SET_KEYS = 12, CMD_READ_MEMORY = 13, CMD_WRITE_MEMORY = 14, CMD_SET_TEMPLATE = 19, CMD_TEST = 23, CMD_NOISE_HIST = 28, - CMD_QUIET_ELEMENT_SET_STATE = 29, + CMD_LNA_CONTROL = 32, CMD_SET_BCN_MODE = 33, CMD_MEASUREMENT = 34, CMD_STOP_MEASUREMENT = 35, + CMD_DISCONNECT = 36, CMD_SET_PS_MODE = 37, CMD_CHANNEL_SWITCH = 38, CMD_STOP_CHANNEL_SWICTH = 39, CMD_AP_DISCOVERY = 40, CMD_STOP_AP_DISCOVERY = 41, + CMD_SPS_SCAN = 42, + CMD_STOP_SPS_SCAN = 43, CMD_HEALTH_CHECK = 45, CMD_DEBUG = 46, CMD_TRIGGER_SCAN_TO = 47, @@ -111,30 +109,16 @@ enum wl1271_commands { CMD_CONNECTION_SCAN_SSID_CFG = 49, CMD_START_PERIODIC_SCAN = 50, CMD_STOP_PERIODIC_SCAN = 51, - CMD_SET_PEER_STATE = 52, - CMD_REMAIN_ON_CHANNEL = 53, - CMD_CANCEL_REMAIN_ON_CHANNEL = 54, + CMD_SET_STA_STATE = 52, + CMD_CONFIG_FWLOGGER = 53, + CMD_START_FWLOGGER = 54, + CMD_STOP_FWLOGGER = 55, - CMD_CONFIG_FWLOGGER = 55, - CMD_START_FWLOGGER = 56, - CMD_STOP_FWLOGGER = 57, - - /* AP commands */ - CMD_ADD_PEER = 62, - CMD_REMOVE_PEER = 63, - - /* Role API */ - CMD_ROLE_ENABLE = 70, - CMD_ROLE_DISABLE = 71, - CMD_ROLE_START = 72, - CMD_ROLE_STOP = 73, - - /* WIFI Direct */ - CMD_WFD_START_DISCOVERY = 80, - CMD_WFD_STOP_DISCOVERY = 81, - CMD_WFD_ATTRIBUTE_CONFIG = 82, - - CMD_NOP = 100, + /* AP mode commands */ + CMD_BSS_START = 60, + CMD_BSS_STOP = 61, + CMD_ADD_STA = 62, + CMD_REMOVE_STA = 63, NUM_COMMANDS, MAX_COMMAND_ID = 0xFFFF, @@ -163,20 +147,21 @@ enum cmd_templ { CMD_TEMPL_CTS, /* * For CTS-to-self (FastCTS) mechanism * for BT/WLAN coexistence (SoftGemini). */ - CMD_TEMPL_AP_BEACON, - CMD_TEMPL_AP_PROBE_RESPONSE, CMD_TEMPL_ARP_RSP, - CMD_TEMPL_DEAUTH_AP, - CMD_TEMPL_TEMPORARY, CMD_TEMPL_LINK_MEASUREMENT_REPORT, + /* AP-mode specific */ + CMD_TEMPL_AP_BEACON = 13, + CMD_TEMPL_AP_PROBE_RESPONSE, + CMD_TEMPL_AP_ARP_RSP, + CMD_TEMPL_DEAUTH_AP, + CMD_TEMPL_MAX = 0xff }; /* unit ms */ #define WL1271_COMMAND_TIMEOUT 2000 -#define WL1271_CMD_TEMPL_DFLT_SIZE 252 -#define WL1271_CMD_TEMPL_MAX_SIZE 548 +#define WL1271_CMD_TEMPL_MAX_SIZE 252 #define WL1271_EVENT_TIMEOUT 750 struct wl1271_cmd_header { @@ -208,8 +193,6 @@ enum { CMD_STATUS_WRONG_NESTING = 19, CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/ CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ - CMD_STATUS_TEMPLATE_OOM = 23, - CMD_STATUS_NO_RX_BA_SESSION = 24, MAX_COMMAND_STATUS = 0xff }; @@ -227,114 +210,38 @@ enum { #define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1 #define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10 -struct wl12xx_cmd_role_enable { - struct wl1271_cmd_header header; - - u8 role_id; - u8 role_type; - u8 mac_address[ETH_ALEN]; -} __packed; - -struct wl12xx_cmd_role_disable { +struct wl1271_cmd_join { struct wl1271_cmd_header header; - u8 role_id; - u8 padding[3]; -} __packed; - -enum wl12xx_band { - WL12XX_BAND_2_4GHZ = 0, - WL12XX_BAND_5GHZ = 1, - WL12XX_BAND_JAPAN_4_9_GHZ = 2, - WL12XX_BAND_DEFAULT = WL12XX_BAND_2_4GHZ, - WL12XX_BAND_INVALID = 0x7E, - WL12XX_BAND_MAX_RADIO = 0x7F, -}; + __le32 bssid_lsb; + __le16 bssid_msb; + __le16 beacon_interval; /* in TBTTs */ + __le32 rx_config_options; + __le32 rx_filter_options; -struct wl12xx_cmd_role_start { - struct wl1271_cmd_header header; - - u8 role_id; - u8 band; + /* + * The target uses this field to determine the rate at + * which to transmit control frame responses (such as + * ACK or CTS frames). + */ + __le32 basic_rate_set; + __le32 supported_rate_set; + u8 dtim_interval; + /* + * bits 0-2: This bitwise field specifies the type + * of BSS to start or join (BSS_TYPE_*). + * bit 4: Band - The radio band in which to join + * or start. + * 0 - 2.4GHz band + * 1 - 5GHz band + * bits 3, 5-7: Reserved + */ + u8 bss_type; u8 channel; - u8 padding; - - union { - struct { - u8 hlid; - u8 session; - u8 padding_1[54]; - } __packed device; - /* sta & p2p_cli use the same struct */ - struct { - u8 bssid[ETH_ALEN]; - u8 hlid; /* data hlid */ - u8 session; - __le32 remote_rates; /* remote supported rates */ - - /* - * The target uses this field to determine the rate at - * which to transmit control frame responses (such as - * ACK or CTS frames). - */ - __le32 basic_rate_set; - __le32 local_rates; /* local supported rates */ - - u8 ssid_type; - u8 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - - __le16 beacon_interval; /* in TBTTs */ - } __packed sta; - struct { - u8 bssid[ETH_ALEN]; - u8 hlid; /* data hlid */ - u8 dtim_interval; - __le32 remote_rates; /* remote supported rates */ - - __le32 basic_rate_set; - __le32 local_rates; /* local supported rates */ - - u8 ssid_type; - u8 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - - __le16 beacon_interval; /* in TBTTs */ - - u8 padding_1[4]; - } __packed ibss; - /* ap & p2p_go use the same struct */ - struct { - __le16 aging_period; /* in secs */ - u8 beacon_expiry; /* in ms */ - u8 bss_index; - /* The host link id for the AP's global queue */ - u8 global_hlid; - /* The host link id for the AP's broadcast queue */ - u8 broadcast_hlid; - - __le16 beacon_interval; /* in TBTTs */ - - __le32 basic_rate_set; - __le32 local_rates; /* local supported rates */ - - u8 dtim_interval; - - u8 ssid_type; - u8 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - - u8 padding_1[5]; - } __packed ap; - }; -} __packed; - -struct wl12xx_cmd_role_stop { - struct wl1271_cmd_header header; - - u8 role_id; - u8 disc_type; /* only STA and P2P_CLI */ - __le16 reason; /* only STA and P2P_CLI */ + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ctrl; /* JOIN_CMD_CTRL_* */ + u8 reserved[3]; } __packed; struct cmd_enabledisable_path { @@ -380,9 +287,8 @@ enum wl1271_cmd_ps_mode { struct wl1271_cmd_ps_params { struct wl1271_cmd_header header; - u8 role_id; u8 ps_mode; /* STATION_* */ - u8 padding[2]; + u8 padding[3]; } __packed; /* HW encryption keys */ @@ -395,12 +301,6 @@ enum wl1271_cmd_key_action { MAX_KEY_ACTION = 0xffff, }; -enum wl1271_cmd_lid_key_type { - UNICAST_LID_TYPE = 0, - BROADCAST_LID_TYPE = 1, - WEP_DEFAULT_LID_TYPE = 2 -}; - enum wl1271_cmd_key_type { KEY_NONE = 0, KEY_WEP = 1, @@ -409,7 +309,44 @@ enum wl1271_cmd_key_type { KEY_GEM = 4, }; -struct wl1271_cmd_set_keys { +/* FIXME: Add description for key-types */ + +struct wl1271_cmd_set_sta_keys { + struct wl1271_cmd_header header; + + /* Ignored for default WEP key */ + u8 addr[ETH_ALEN]; + + /* key_action_e */ + __le16 key_action; + + __le16 reserved_1; + + /* key size in bytes */ + u8 key_size; + + /* key_type_e */ + u8 key_type; + u8 ssid_profile; + + /* + * TKIP, AES: frame's key id field. + * For WEP default key: key id; + */ + u8 id; + u8 reserved_2[6]; + u8 key[MAX_KEY_SIZE]; + __le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; + __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; +} __packed; + +enum wl1271_cmd_lid_key_type { + UNICAST_LID_TYPE = 0, + BROADCAST_LID_TYPE = 1, + WEP_DEFAULT_LID_TYPE = 2 +}; + +struct wl1271_cmd_set_ap_keys { struct wl1271_cmd_header header; /* @@ -559,39 +496,69 @@ enum wl1271_disconnect_type { DISCONNECT_DISASSOC }; +struct wl1271_cmd_disconnect { + struct wl1271_cmd_header header; + + __le32 rx_config_options; + __le32 rx_filter_options; + + __le16 reason; + u8 type; + + u8 padding; +} __packed; + #define WL1271_CMD_STA_STATE_CONNECTED 1 -struct wl12xx_cmd_set_peer_state { +struct wl1271_cmd_set_sta_state { struct wl1271_cmd_header header; - u8 hlid; u8 state; - u8 padding[2]; + u8 padding[3]; } __packed; -struct wl12xx_cmd_roc { - struct wl1271_cmd_header header; - - u8 role_id; - u8 channel; - u8 band; - u8 padding; +enum wl1271_ssid_type { + SSID_TYPE_PUBLIC = 0, + SSID_TYPE_HIDDEN = 1 }; -struct wl12xx_cmd_croc { +struct wl1271_cmd_bss_start { struct wl1271_cmd_header header; - u8 role_id; - u8 padding[3]; -}; + /* wl1271_ssid_type */ + u8 ssid_type; + u8 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 padding_1[2]; -enum wl12xx_ssid_type { - WL12XX_SSID_TYPE_PUBLIC = 0, - WL12XX_SSID_TYPE_HIDDEN = 1, - WL12XX_SSID_TYPE_ANY = 2, -}; + /* Basic rate set */ + __le32 basic_rate_set; + /* Aging period in seconds*/ + __le16 aging_period; + + /* + * This field specifies the time between target beacon + * transmission times (TBTTs), in time units (TUs). + * Valid values are 1 to 1024. + */ + __le16 beacon_interval; + u8 bssid[ETH_ALEN]; + u8 bss_index; + /* Radio band */ + u8 band; + u8 channel; + /* The host link id for the AP's global queue */ + u8 global_hlid; + /* The host link id for the AP's broadcast queue */ + u8 broadcast_hlid; + /* DTIM count */ + u8 dtim_interval; + /* Beacon expiry time in ms */ + u8 beacon_expiry; + u8 padding_2[3]; +} __packed; -struct wl12xx_cmd_add_peer { +struct wl1271_cmd_add_sta { struct wl1271_cmd_header header; u8 addr[ETH_ALEN]; @@ -605,7 +572,7 @@ struct wl12xx_cmd_add_peer { u8 padding1; } __packed; -struct wl12xx_cmd_remove_peer { +struct wl1271_cmd_remove_sta { struct wl1271_cmd_header header; u8 hlid; diff --git a/trunk/drivers/net/wireless/wl12xx/conf.h b/trunk/drivers/net/wireless/wl12xx/conf.h index 82f205c43342..6080e01d92c6 100644 --- a/trunk/drivers/net/wireless/wl12xx/conf.h +++ b/trunk/drivers/net/wireless/wl12xx/conf.h @@ -99,75 +99,40 @@ enum { enum { /* - * Configure the min and max time BT gains the antenna - * in WLAN / BT master basic rate + * PER threshold in PPM of the BT voice * - * Range: 0 - 255 (ms) + * Range: 0 - 10000000 */ - CONF_SG_ACL_BT_MASTER_MIN_BR = 0, - CONF_SG_ACL_BT_MASTER_MAX_BR, + CONF_SG_BT_PER_THRESHOLD = 0, /* - * Configure the min and max time BT gains the antenna - * in WLAN / BT slave basic rate + * Number of consequent RX_ACTIVE activities to override BT voice + * frames to ensure WLAN connection * - * Range: 0 - 255 (ms) - */ - CONF_SG_ACL_BT_SLAVE_MIN_BR, - CONF_SG_ACL_BT_SLAVE_MAX_BR, - - /* - * Configure the min and max time BT gains the antenna - * in WLAN / BT master EDR - * - * Range: 0 - 255 (ms) + * Range: 0 - 100 */ - CONF_SG_ACL_BT_MASTER_MIN_EDR, - CONF_SG_ACL_BT_MASTER_MAX_EDR, + CONF_SG_HV3_MAX_OVERRIDE, /* - * Configure the min and max time BT gains the antenna - * in WLAN / BT slave EDR + * Defines the PER threshold of the BT voice * - * Range: 0 - 255 (ms) + * Range: 0 - 65000 */ - CONF_SG_ACL_BT_SLAVE_MIN_EDR, - CONF_SG_ACL_BT_SLAVE_MAX_EDR, + CONF_SG_BT_NFS_SAMPLE_INTERVAL, /* - * The maximum time WLAN can gain the antenna - * in WLAN PSM / BT master/slave BR + * Defines the load ratio of BT * - * Range: 0 - 255 (ms) + * Range: 0 - 100 (%) */ - CONF_SG_ACL_WLAN_PS_MASTER_BR, - CONF_SG_ACL_WLAN_PS_SLAVE_BR, + CONF_SG_BT_LOAD_RATIO, /* - * The maximum time WLAN can gain the antenna - * in WLAN PSM / BT master/slave EDR + * Defines whether the SG will force WLAN host to enter/exit PSM * - * Range: 0 - 255 (ms) + * Range: 1 - SG can force, 0 - host handles PSM */ - CONF_SG_ACL_WLAN_PS_MASTER_EDR, - CONF_SG_ACL_WLAN_PS_SLAVE_EDR, - - /* TODO: explain these values */ - CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR, - CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR, - CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR, - CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR, - CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR, - CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR, - CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR, - CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR, - - CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR, - CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR, - CONF_SG_ACL_PASSIVE_SCAN_BT_BR, - CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR, - CONF_SG_ACL_PASSIVE_SCAN_BT_EDR, - CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR, + CONF_SG_AUTO_PS_MODE, /* * Compensation percentage of probe requests when scan initiated @@ -186,70 +151,102 @@ enum { CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3, /* - * Compensation percentage of WLAN active scan window if initiated - * during BT A2DP + * Defines antenna configuration (single/dual antenna) * - * Range: 0 - 1000 (%) + * Range: 0 - single antenna, 1 - dual antenna */ - CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, + CONF_SG_ANTENNA_CONFIGURATION, /* - * Compensation percentage of WLAN passive scan window if initiated - * during BT A2DP BR + * The threshold (percent) of max consequtive beacon misses before + * increasing priority of beacon reception. * - * Range: 0 - 1000 (%) + * Range: 0 - 100 (%) */ - CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR, + CONF_SG_BEACON_MISS_PERCENT, /* - * Compensation percentage of WLAN passive scan window if initiated - * during BT A2DP EDR + * The rate threshold below which receiving a data frame from the AP + * will increase the priority of the data frame above BT traffic. * - * Range: 0 - 1000 (%) + * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54 */ - CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR, + CONF_SG_RATE_ADAPT_THRESH, /* - * Compensation percentage of WLAN passive scan window if initiated - * during BT voice + * Not used currently. * - * Range: 0 - 1000 (%) + * Range: 0 */ - CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, + CONF_SG_RATE_ADAPT_SNR, - /* TODO: explain these values */ - CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN, - CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN, - CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN, + /* + * Configure the min and max time BT gains the antenna + * in WLAN PSM / BT master basic rate + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR, + CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR, /* - * Defines whether the SG will force WLAN host to enter/exit PSM + * The time after it expires no new WLAN trigger frame is trasmitted + * in WLAN PSM / BT master basic rate * - * Range: 1 - SG can force, 0 - host handles PSM + * Range: 0 - 255 (ms) */ - CONF_SG_STA_FORCE_PS_IN_BT_SCO, + CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR, /* - * Defines antenna configuration (single/dual antenna) + * Configure the min and max time BT gains the antenna + * in WLAN PSM / BT slave basic rate * - * Range: 0 - single antenna, 1 - dual antenna + * Range: 0 - 255 (ms) */ - CONF_SG_ANTENNA_CONFIGURATION, + CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR, + CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR, /* - * The threshold (percent) of max consecutive beacon misses before - * increasing priority of beacon reception. + * The time after it expires no new WLAN trigger frame is trasmitted + * in WLAN PSM / BT slave basic rate * - * Range: 0 - 100 (%) + * Range: 0 - 255 (ms) */ - CONF_SG_BEACON_MISS_PERCENT, + CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR, /* - * Protection time of the DHCP procedure. + * Configure the min and max time BT gains the antenna + * in WLAN PSM / BT master EDR * - * Range: 0 - 100000 (ms) + * Range: 0 - 255 (ms) */ - CONF_SG_DHCP_TIME, + CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR, + CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR, + + /* + * The time after it expires no new WLAN trigger frame is trasmitted + * in WLAN PSM / BT master EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR, + + /* + * Configure the min and max time BT gains the antenna + * in WLAN PSM / BT slave EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR, + CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR, + + /* + * The time after it expires no new WLAN trigger frame is trasmitted + * in WLAN PSM / BT slave EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR, /* * RX guard time before the beginning of a new BT voice frame during @@ -276,59 +273,166 @@ enum { */ CONF_SG_ADAPTIVE_RXT_TXT, - /* TODO: explain this value */ - CONF_SG_GENERAL_USAGE_BIT_MAP, + /* + * The used WLAN legacy service period during active BT ACL link + * + * Range: 0 - 255 (ms) + */ + CONF_SG_PS_POLL_TIMEOUT, /* - * Number of consecutive BT voice frames not interrupted by WLAN + * The used WLAN UPSD service period during active BT ACL link * - * Range: 0 - 100 + * Range: 0 - 255 (ms) */ - CONF_SG_HV3_MAX_SERVED, + CONF_SG_UPSD_TIMEOUT, /* - * The used WLAN legacy service period during active BT ACL link + * Configure the min and max time BT gains the antenna + * in WLAN Active / BT master EDR * * Range: 0 - 255 (ms) */ - CONF_SG_PS_POLL_TIMEOUT, + CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR, + CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR, /* - * The used WLAN UPSD service period during active BT ACL link + * The maximum time WLAN can gain the antenna for + * in WLAN Active / BT master EDR * * Range: 0 - 255 (ms) */ - CONF_SG_UPSD_TIMEOUT, + CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR, + + /* + * Configure the min and max time BT gains the antenna + * in WLAN Active / BT slave EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR, + CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR, + + /* + * The maximum time WLAN can gain the antenna for + * in WLAN Active / BT slave EDR + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR, + + /* + * Configure the min and max time BT gains the antenna + * in WLAN Active / BT basic rate + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR, + CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR, - CONF_SG_CONSECUTIVE_CTS_THRESHOLD, - CONF_SG_STA_RX_WINDOW_AFTER_DTIM, - CONF_SG_STA_CONNECTION_PROTECTION_TIME, + /* + * The maximum time WLAN can gain the antenna for + * in WLAN Active / BT basic rate + * + * Range: 0 - 255 (ms) + */ + CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR, + + /* + * Compensation percentage of WLAN passive scan window if initiated + * during BT voice + * + * Range: 0 - 1000 (%) + */ + CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3, - /* AP params */ - CONF_AP_BEACON_MISS_TX, - CONF_AP_RX_WINDOW_AFTER_BEACON, - CONF_AP_BEACON_WINDOW_INTERVAL, - CONF_AP_CONNECTION_PROTECTION_TIME, - CONF_AP_BT_ACL_VAL_BT_SERVE_TIME, - CONF_AP_BT_ACL_VAL_WL_SERVE_TIME, + /* + * Compensation percentage of WLAN passive scan window if initiated + * during BT A2DP + * + * Range: 0 - 1000 (%) + */ + CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP, + + /* + * Fixed time ensured for BT traffic to gain the antenna during WLAN + * passive scan. + * + * Range: 0 - 1000 ms + */ + CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME, + /* + * Fixed time ensured for WLAN traffic to gain the antenna during WLAN + * passive scan. + * + * Range: 0 - 1000 ms + */ + CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME, + + /* + * Number of consequent BT voice frames not interrupted by WLAN + * + * Range: 0 - 100 + */ + CONF_SG_HV3_MAX_SERVED, + + /* + * Protection time of the DHCP procedure. + * + * Range: 0 - 100000 (ms) + */ + CONF_SG_DHCP_TIME, + + /* + * Compensation percentage of WLAN active scan window if initiated + * during BT A2DP + * + * Range: 0 - 1000 (%) + */ + CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP, CONF_SG_TEMP_PARAM_1, CONF_SG_TEMP_PARAM_2, CONF_SG_TEMP_PARAM_3, CONF_SG_TEMP_PARAM_4, CONF_SG_TEMP_PARAM_5, + + /* + * AP beacon miss + * + * Range: 0 - 255 + */ + CONF_SG_AP_BEACON_MISS_TX, + + /* + * AP RX window length + * + * Range: 0 - 50 + */ + CONF_SG_RX_WINDOW_LENGTH, + + /* + * AP connection protection time + * + * Range: 0 - 5000 + */ + CONF_SG_AP_CONNECTION_PROTECTION_TIME, + CONF_SG_TEMP_PARAM_6, CONF_SG_TEMP_PARAM_7, CONF_SG_TEMP_PARAM_8, CONF_SG_TEMP_PARAM_9, CONF_SG_TEMP_PARAM_10, - CONF_SG_PARAMS_MAX, + CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1, + CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1, + CONF_SG_PARAMS_ALL = 0xff }; struct conf_sg_settings { - u32 params[CONF_SG_PARAMS_MAX]; + u32 sta_params[CONF_SG_STA_PARAMS_MAX]; + u32 ap_params[CONF_SG_AP_PARAMS_MAX]; u8 state; }; @@ -441,11 +545,6 @@ struct conf_rx_settings { CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ CONF_HW_BIT_RATE_54MBPS) -#define CONF_TX_MCS_RATES (CONF_HW_BIT_RATE_MCS_0 | \ - CONF_HW_BIT_RATE_MCS_1 | CONF_HW_BIT_RATE_MCS_2 | \ - CONF_HW_BIT_RATE_MCS_3 | CONF_HW_BIT_RATE_MCS_4 | \ - CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \ - CONF_HW_BIT_RATE_MCS_7) /* * Default rates for management traffic when operating in AP mode. This @@ -562,9 +661,6 @@ struct conf_tx_ac_category { #define CONF_TX_MAX_TID_COUNT 8 -/* Allow TX BA on all TIDs but 6,7. These are currently reserved in the FW */ -#define CONF_TX_BA_ENABLED_TID_BITMAP 0x3F - enum { CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/ CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/ @@ -817,7 +913,7 @@ struct conf_conn_settings { struct conf_bcn_filt_rule bcn_filt_ie[CONF_MAX_BCN_FILT_IE_COUNT]; /* - * The number of consecutive beacons to lose, before the firmware + * The number of consequtive beacons to lose, before the firmware * becomes out of synch. * * Range: u32 @@ -855,7 +951,7 @@ struct conf_conn_settings { u8 rx_broadcast_in_ps; /* - * Consecutive PS Poll failures before sending event to driver + * Consequtive PS Poll failures before sending event to driver * * Range: u8 */ @@ -1103,12 +1199,8 @@ struct conf_rf_settings { }; struct conf_ht_setting { - u8 rx_ba_win_size; - u8 tx_ba_win_size; + u16 tx_ba_win_size; u16 inactivity_timeout; - - /* bitmap of enabled TIDs for TX BA sessions */ - u8 tx_ba_tid_bitmap; }; struct conf_memory_settings { @@ -1217,25 +1309,6 @@ struct conf_fwlog { u8 threshold; }; -#define ACX_RATE_MGMT_NUM_OF_RATES 13 -struct conf_rate_policy_settings { - u16 rate_retry_score; - u16 per_add; - u16 per_th1; - u16 per_th2; - u16 max_per; - u8 inverse_curiosity_factor; - u8 tx_fail_low_th; - u8 tx_fail_high_th; - u8 per_alpha_shift; - u8 per_add_shift; - u8 per_beta1_shift; - u8 per_beta2_shift; - u8 rate_check_up; - u8 rate_check_down; - u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; -}; - struct conf_drv_settings { struct conf_sg_settings sg; struct conf_rx_settings rx; @@ -1253,7 +1326,6 @@ struct conf_drv_settings { struct conf_fm_coex fm_coex; struct conf_rx_streaming_settings rx_streaming; struct conf_fwlog fwlog; - struct conf_rate_policy_settings rate; u8 hci_io_ds; }; diff --git a/trunk/drivers/net/wireless/wl12xx/debugfs.c b/trunk/drivers/net/wireless/wl12xx/debugfs.c index d59354f53702..37934b5601cd 100644 --- a/trunk/drivers/net/wireless/wl12xx/debugfs.c +++ b/trunk/drivers/net/wireless/wl12xx/debugfs.c @@ -339,11 +339,10 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") DRIVER_STATE_PRINT_INT(tx_blocks_available); - DRIVER_STATE_PRINT_INT(tx_allocated_blocks); - DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]); - DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]); - DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]); - DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]); + DRIVER_STATE_PRINT_INT(tx_allocated_blocks[0]); + DRIVER_STATE_PRINT_INT(tx_allocated_blocks[1]); + DRIVER_STATE_PRINT_INT(tx_allocated_blocks[2]); + DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]); DRIVER_STATE_PRINT_INT(tx_frames_cnt); DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); DRIVER_STATE_PRINT_INT(tx_queue_count[0]); @@ -353,7 +352,10 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_packets_count); DRIVER_STATE_PRINT_INT(tx_results_count); DRIVER_STATE_PRINT_LHEX(flags); - DRIVER_STATE_PRINT_INT(tx_blocks_freed); + DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]); + DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); + DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); + DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); DRIVER_STATE_PRINT_INT(rx_counter); DRIVER_STATE_PRINT_INT(session_counter); @@ -367,6 +369,9 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(beacon_int); DRIVER_STATE_PRINT_INT(psm_entry_retry); DRIVER_STATE_PRINT_INT(ps_poll_failures); + DRIVER_STATE_PRINT_HEX(filters); + DRIVER_STATE_PRINT_HEX(rx_config); + DRIVER_STATE_PRINT_HEX(rx_filter); DRIVER_STATE_PRINT_INT(power_level); DRIVER_STATE_PRINT_INT(rssi_thold); DRIVER_STATE_PRINT_INT(last_rssi_event); diff --git a/trunk/drivers/net/wireless/wl12xx/event.c b/trunk/drivers/net/wireless/wl12xx/event.c index 0bd7b020a420..304aaa2ee011 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.c +++ b/trunk/drivers/net/wireless/wl12xx/event.c @@ -285,13 +285,13 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) { wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " - "ba_allowed = 0x%x", mbox->rx_ba_allowed); + "ba_allowed = 0x%x", mbox->ba_allowed); if (wl->vif) - wl1271_stop_ba_event(wl, mbox->rx_ba_allowed); + wl1271_stop_ba_event(wl, mbox->ba_allowed); } - if ((vector & DUMMY_PACKET_EVENT_ID)) { + if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) { wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); if (wl->vif) wl1271_tx_dummy_packet(wl); diff --git a/trunk/drivers/net/wireless/wl12xx/event.h b/trunk/drivers/net/wireless/wl12xx/event.h index 49c1a0ede5b1..e524ad6fe4e3 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.h +++ b/trunk/drivers/net/wireless/wl12xx/event.h @@ -49,27 +49,32 @@ enum { MEASUREMENT_START_EVENT_ID = BIT(8), MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), SCAN_COMPLETE_EVENT_ID = BIT(10), - WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11), + SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(11), AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), PS_REPORT_EVENT_ID = BIT(13), PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), DISCONNECT_EVENT_COMPLETE_ID = BIT(15), - /* BIT(16) is reserved */ + JOIN_EVENT_COMPLETE_ID = BIT(16), CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), BSS_LOSE_EVENT_ID = BIT(18), REGAINED_BSS_EVENT_ID = BIT(19), MAX_TX_RETRY_EVENT_ID = BIT(20), - DUMMY_PACKET_EVENT_ID = BIT(21), + /* STA: dummy paket for dynamic mem blocks */ + DUMMY_PACKET_EVENT_ID = BIT(21), + /* AP: STA remove complete */ + STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), - CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID = BIT(23), + /* STA: SG prediction */ + SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), + /* AP: Inactive STA */ + INACTIVE_STA_EVENT_ID = BIT(23), SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), - INACTIVE_STA_EVENT_ID = BIT(26), - PEER_REMOVE_COMPLETE_EVENT_ID = BIT(27), + DBG_EVENT_ID = BIT(26), + HEALTH_CHECK_REPLY_EVENT_ID = BIT(27), PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28), PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29), BA_SESSION_RX_CONSTRAINT_EVENT_ID = BIT(30), - REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID = BIT(31), EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, }; @@ -78,6 +83,15 @@ enum { EVENT_ENTER_POWER_SAVE_SUCCESS, }; +struct event_debug_report { + u8 debug_event_id; + u8 num_params; + __le16 pad; + __le32 report_1; + __le32 report_2; + __le32 report_3; +} __packed; + #define NUM_OF_RSSI_SNR_TRIGGERS 8 struct event_mailbox { @@ -86,45 +100,49 @@ struct event_mailbox { __le32 reserved_1; __le32 reserved_2; + u8 dbg_event_id; + u8 num_relevant_params; + __le16 reserved_3; + __le32 event_report_p1; + __le32 event_report_p2; + __le32 event_report_p3; + u8 number_of_scan_results; u8 scan_tag; - u8 completed_scan_status; - u8 reserved_3; + u8 reserved_4[2]; + __le32 compl_scheduled_scan_status; + __le16 scheduled_scan_attended_channels; u8 soft_gemini_sense_info; u8 soft_gemini_protective_info; s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; u8 channel_switch_status; u8 scheduled_scan_status; u8 ps_status; - /* tuned channel (roc) */ - u8 roc_channel; - __le16 hlid_removed_bitmap; + /* AP FW only */ + u8 hlid_removed; - /* bitmap of aged stations (by HLID) */ + /* a bitmap of hlids for stations that have been inactive too long */ __le16 sta_aging_status; - /* bitmap of stations (by HLID) which exceeded max tx retries */ + /* a bitmap of hlids for stations which didn't respond to TX */ __le16 sta_tx_retry_exceeded; - /* discovery completed results */ - u8 discovery_tag; - u8 number_of_preq_results; - u8 number_of_prsp_results; - u8 reserved_5; - - /* rx ba constraint */ - u8 role_id; /* 0xFF means any role. */ - u8 rx_ba_allowed; - u8 reserved_6[2]; - - u8 ps_poll_delivery_failure_role_ids; - u8 stopped_role_ids; - u8 started_role_ids; - u8 change_auto_mode_timeout; - - u8 reserved_7[12]; + /* + * Bitmap, Each bit set represents the Role ID for which this constraint + * is set. Range: 0 - FF, FF means ANY role + */ + u8 ba_role_id; + /* + * Bitmap, Each bit set represents the Link ID for which this constraint + * is set. Not applicable if ba_role_id is set to ANY role (FF). + * Range: 0 - FFFF, FFFF means ANY link in that role + */ + u8 ba_link_id; + u8 ba_allowed; + + u8 reserved_5[21]; } __packed; int wl1271_event_unmask(struct wl1271 *wl); diff --git a/trunk/drivers/net/wireless/wl12xx/init.c b/trunk/drivers/net/wireless/wl12xx/init.c index b13bebea95e0..c3e9a2e4410e 100644 --- a/trunk/drivers/net/wireless/wl12xx/init.c +++ b/trunk/drivers/net/wireless/wl12xx/init.c @@ -39,13 +39,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl) /* send empty templates for fw memory reservation */ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, - WL1271_CMD_TEMPL_DFLT_SIZE, + WL1271_CMD_TEMPL_MAX_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, - NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0, + NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -70,13 +70,15 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, - WL1271_CMD_TEMPL_DFLT_SIZE, + sizeof + (struct wl12xx_probe_resp_template), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, - WL1271_CMD_TEMPL_DFLT_SIZE, + sizeof + (struct wl12xx_beacon_template), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -90,7 +92,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl) for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, - WL1271_CMD_TEMPL_DFLT_SIZE, i, + WL1271_CMD_TEMPL_MAX_SIZE, i, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -189,13 +191,15 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl) * reserve memory for later. */ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, + sizeof + (struct wl12xx_probe_resp_template), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, + sizeof + (struct wl12xx_beacon_template), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -223,7 +227,7 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl) return 0; } -static int wl12xx_init_rx_config(struct wl1271 *wl) +static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) { int ret; @@ -231,6 +235,10 @@ static int wl12xx_init_rx_config(struct wl1271 *wl) if (ret < 0) return ret; + ret = wl1271_acx_rx_config(wl, config, filter); + if (ret < 0) + return ret; + return 0; } @@ -277,7 +285,10 @@ int wl1271_init_pta(struct wl1271 *wl) { int ret; - ret = wl12xx_acx_sg_cfg(wl); + if (wl->bss_type == BSS_TYPE_AP_BSS) + ret = wl1271_acx_ap_sg_cfg(wl); + else + ret = wl1271_acx_sta_sg_cfg(wl); if (ret < 0) return ret; @@ -381,7 +392,7 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl12xx_acx_mem_cfg(wl); + ret = wl1271_acx_sta_mem_cfg(wl); if (ret < 0) return ret; @@ -397,6 +408,12 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) { int ret, i; + ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key); + if (ret < 0) { + wl1271_warning("couldn't set default key"); + return ret; + } + /* disable all keep-alive templates */ for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_acx_keep_alive_config(wl, i, @@ -434,7 +451,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl12xx_acx_mem_cfg(wl); + ret = wl1271_acx_ap_mem_cfg(wl); if (ret < 0) return ret; @@ -466,7 +483,7 @@ int wl1271_ap_init_templates(struct wl1271 *wl) * when operating as AP we want to receive external beacons for * configuring ERP protection. */ - ret = wl1271_acx_beacon_filter_opt(wl, false); + ret = wl1271_acx_set_ap_beacon_filter(wl, false); if (ret < 0) return ret; @@ -515,9 +532,6 @@ int wl1271_init_ap_rates(struct wl1271 *wl) else supported_rates = CONF_TX_AP_ENABLED_RATES; - /* unconditionally enable HT rates */ - supported_rates |= CONF_TX_MCS_RATES; - /* configure unicast TX rate classes */ for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { rc.enabled_rates = supported_rates; @@ -532,24 +546,41 @@ int wl1271_init_ap_rates(struct wl1271 *wl) return 0; } +static void wl1271_check_ba_support(struct wl1271 *wl) +{ + /* validate FW cose ver x.x.x.50-60.x */ + if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) && + (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) { + wl->ba_support = true; + return; + } + + wl->ba_support = false; +} + static int wl1271_set_ba_policies(struct wl1271 *wl) { + u8 tid_index; + int ret = 0; + /* Reset the BA RX indicators */ wl->ba_rx_bitmap = 0; wl->ba_allowed = true; - wl->ba_rx_session_count = 0; - /* BA is supported in STA/AP modes */ - if (wl->bss_type != BSS_TYPE_AP_BSS && - wl->bss_type != BSS_TYPE_STA_BSS) { - wl->ba_support = false; - return 0; - } + /* validate that FW support BA */ + wl1271_check_ba_support(wl); - wl->ba_support = true; + if (wl->ba_support) + /* 802.11n initiator BA session setting */ + for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT; + ++tid_index) { + ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR, + tid_index, true); + if (ret < 0) + break; + } - /* 802.11n initiator BA session setting */ - return wl12xx_acx_set_ba_initiator_policy(wl); + return ret; } int wl1271_chip_specific_init(struct wl1271 *wl) @@ -619,7 +650,11 @@ int wl1271_hw_init(struct wl1271 *wl) return ret; /* RX config */ - ret = wl12xx_init_rx_config(wl); + ret = wl1271_init_rx_config(wl, + RX_CFG_PROMISCUOUS | RX_CFG_TSF, + RX_FILTER_OPTION_DEF); + /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, + RX_FILTER_OPTION_FILTER_ALL); */ if (ret < 0) goto out_free_memmap; @@ -698,10 +733,6 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; - ret = wl12xx_acx_set_rate_mgmt_params(wl); - if (ret < 0) - goto out_free_memmap; - /* Configure initiator BA sessions policies */ ret = wl1271_set_ba_policies(wl); if (ret < 0) diff --git a/trunk/drivers/net/wireless/wl12xx/io.h b/trunk/drivers/net/wireless/wl12xx/io.h index e839341dfafe..a2fe4f506ada 100644 --- a/trunk/drivers/net/wireless/wl12xx/io.h +++ b/trunk/drivers/net/wireless/wl12xx/io.h @@ -186,5 +186,6 @@ int wl1271_free_hw(struct wl1271 *wl); irqreturn_t wl1271_irq(int irq, void *data); bool wl1271_set_block_size(struct wl1271 *wl); int wl1271_tx_dummy_packet(struct wl1271 *wl); +void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters); #endif diff --git a/trunk/drivers/net/wireless/wl12xx/main.c b/trunk/drivers/net/wireless/wl12xx/main.c index 82f4408e89ad..3418299e17c8 100644 --- a/trunk/drivers/net/wireless/wl12xx/main.c +++ b/trunk/drivers/net/wireless/wl12xx/main.c @@ -52,67 +52,110 @@ static struct conf_drv_settings default_conf = { .sg = { - .params = { - [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10, - [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180, - [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10, - [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180, - [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10, - [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80, - [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10, - [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80, - [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8, - [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8, - [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20, - [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20, - [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20, - [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35, - [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16, - [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35, - [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32, - [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50, - [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28, - [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50, - [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10, - [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20, - [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75, - [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15, - [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27, - [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17, - /* active scan params */ - [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, - /* passive scan params */ - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800, - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200, - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, - /* passive scan in dual antenna params */ - [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0, - [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0, - [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0, - /* general params */ - [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1, - [CONF_SG_ANTENNA_CONFIGURATION] = 0, - [CONF_SG_BEACON_MISS_PERCENT] = 60, - [CONF_SG_DHCP_TIME] = 5000, - [CONF_SG_RXT] = 1200, - [CONF_SG_TXT] = 1000, - [CONF_SG_ADAPTIVE_RXT_TXT] = 1, - [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3, - [CONF_SG_HV3_MAX_SERVED] = 6, - [CONF_SG_PS_POLL_TIMEOUT] = 10, - [CONF_SG_UPSD_TIMEOUT] = 10, - [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2, - [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5, - [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30, - /* AP params */ - [CONF_AP_BEACON_MISS_TX] = 3, - [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10, - [CONF_AP_BEACON_WINDOW_INTERVAL] = 2, - [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, - [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, - [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, + .sta_params = { + [CONF_SG_BT_PER_THRESHOLD] = 7500, + [CONF_SG_HV3_MAX_OVERRIDE] = 0, + [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, + [CONF_SG_BT_LOAD_RATIO] = 200, + [CONF_SG_AUTO_PS_MODE] = 1, + [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, + [CONF_SG_ANTENNA_CONFIGURATION] = 0, + [CONF_SG_BEACON_MISS_PERCENT] = 60, + [CONF_SG_RATE_ADAPT_THRESH] = 12, + [CONF_SG_RATE_ADAPT_SNR] = 0, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30, + [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50, + /* Note: with UPSD, this should be 4 */ + [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20, + /* Note: with UPDS, this should be 15 */ + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, + /* Note: with UPDS, this should be 50 */ + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40, + /* Note: with UPDS, this should be 10 */ + [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20, + [CONF_SG_RXT] = 1200, + [CONF_SG_TXT] = 1000, + [CONF_SG_ADAPTIVE_RXT_TXT] = 1, + [CONF_SG_PS_POLL_TIMEOUT] = 10, + [CONF_SG_UPSD_TIMEOUT] = 10, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, + [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, + [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, + [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, + [CONF_SG_HV3_MAX_SERVED] = 6, + [CONF_SG_DHCP_TIME] = 5000, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, + }, + .ap_params = { + [CONF_SG_BT_PER_THRESHOLD] = 7500, + [CONF_SG_HV3_MAX_OVERRIDE] = 0, + [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, + [CONF_SG_BT_LOAD_RATIO] = 50, + [CONF_SG_AUTO_PS_MODE] = 1, + [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, + [CONF_SG_ANTENNA_CONFIGURATION] = 0, + [CONF_SG_BEACON_MISS_PERCENT] = 60, + [CONF_SG_RATE_ADAPT_THRESH] = 64, + [CONF_SG_RATE_ADAPT_SNR] = 1, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, + [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, + [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25, + [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25, + [CONF_SG_RXT] = 1200, + [CONF_SG_TXT] = 1000, + [CONF_SG_ADAPTIVE_RXT_TXT] = 1, + [CONF_SG_PS_POLL_TIMEOUT] = 10, + [CONF_SG_UPSD_TIMEOUT] = 10, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, + [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, + [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, + [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, + [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, + [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, + [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, + [CONF_SG_HV3_MAX_SERVED] = 6, + [CONF_SG_DHCP_TIME] = 5000, + [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, + [CONF_SG_TEMP_PARAM_1] = 0, + [CONF_SG_TEMP_PARAM_2] = 0, + [CONF_SG_TEMP_PARAM_3] = 0, + [CONF_SG_TEMP_PARAM_4] = 0, + [CONF_SG_TEMP_PARAM_5] = 0, + [CONF_SG_AP_BEACON_MISS_TX] = 3, + [CONF_SG_RX_WINDOW_LENGTH] = 6, + [CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50, + [CONF_SG_TEMP_PARAM_6] = 1, }, .state = CONF_SG_PROTECTIVE, }, @@ -286,10 +329,8 @@ static struct conf_drv_settings default_conf = { }, }, .ht = { - .rx_ba_win_size = 8, .tx_ba_win_size = 64, .inactivity_timeout = 10000, - .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, }, .mem_wl127x = { .num_stations = 1, @@ -338,27 +379,6 @@ static struct conf_drv_settings default_conf = { .threshold = 0, }, .hci_io_ds = HCI_IO_DS_6MA, - .rate = { - .rate_retry_score = 32000, - .per_add = 8192, - .per_th1 = 2048, - .per_th2 = 4096, - .max_per = 8100, - .inverse_curiosity_factor = 5, - .tx_fail_low_th = 4, - .tx_fail_high_th = 10, - .per_alpha_shift = 4, - .per_add_shift = 13, - .per_beta1_shift = 10, - .per_beta2_shift = 8, - .rate_check_up = 2, - .rate_check_down = 12, - .rate_retry_policy = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - }, - }, }; static char *fwlog_param; @@ -395,12 +415,10 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) return 0; - ret = wl12xx_cmd_set_peer_state(wl, wl->sta_hlid); + ret = wl1271_cmd_set_sta_state(wl); if (ret < 0) return ret; - wl12xx_croc(wl, wl->role_id); - wl1271_info("Association completed."); return 0; } @@ -700,7 +718,7 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; - ret = wl12xx_acx_mem_cfg(wl); + ret = wl1271_acx_sta_mem_cfg(wl); if (ret < 0) goto out_free_memmap; @@ -755,7 +773,7 @@ static int wl1271_plt_init(struct wl1271 *wl) return ret; } -static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) +static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks) { bool fw_ps; @@ -767,35 +785,21 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) /* * Wake up from high level PS if the STA is asleep with too little - * packets in FW or if the STA is awake. + * blocks in FW or if the STA is awake. */ - if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS) + if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS) wl1271_ps_link_end(wl, hlid); /* Start high-level PS if the STA is asleep with enough blocks in FW */ - else if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) + else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS) wl1271_ps_link_start(wl, hlid, true); } -bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) -{ - int id; - - /* global/broadcast "stations" are always active */ - if (hlid < WL1271_AP_STA_HLID_START) - return true; - - id = hlid - WL1271_AP_STA_HLID_START; - return test_bit(id, wl->ap_hlid_map); -} - -static void wl12xx_irq_update_links_status(struct wl1271 *wl, - struct wl12xx_fw_status *status) +static void wl1271_irq_update_links_status(struct wl1271 *wl, + struct wl1271_fw_ap_status *status) { u32 cur_fw_ps_map; - u8 hlid, cnt; - - /* TODO: also use link_fast_bitmap here */ + u8 hlid; cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); if (wl->ap_fw_ps_map != cur_fw_ps_map) { @@ -808,30 +812,45 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, } for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) { - if (!wl1271_is_active_sta(wl, hlid)) - continue; - - cnt = status->tx_lnk_free_pkts[hlid] - - wl->links[hlid].prev_freed_pkts; + u8 cnt = status->tx_lnk_free_blks[hlid] - + wl->links[hlid].prev_freed_blks; - wl->links[hlid].prev_freed_pkts = - status->tx_lnk_free_pkts[hlid]; - wl->links[hlid].allocated_pkts -= cnt; + wl->links[hlid].prev_freed_blks = + status->tx_lnk_free_blks[hlid]; + wl->links[hlid].allocated_blks -= cnt; - wl12xx_irq_ps_regulate_link(wl, hlid, - wl->links[hlid].allocated_pkts); + wl1271_irq_ps_regulate_link(wl, hlid, + wl->links[hlid].allocated_blks); } } -static void wl12xx_fw_status(struct wl1271 *wl, - struct wl12xx_fw_status *status) +static u32 wl1271_tx_allocated_blocks(struct wl1271 *wl) { + int i; + u32 total_alloc_blocks = 0; + + for (i = 0; i < NUM_TX_QUEUES; i++) + total_alloc_blocks += wl->tx_allocated_blocks[i]; + + return total_alloc_blocks; +} + +static void wl1271_fw_status(struct wl1271 *wl, + struct wl1271_fw_full_status *full_status) +{ + struct wl1271_fw_common_status *status = &full_status->common; struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; - int avail, freed_blocks; + u32 freed_blocks = 0, ac_freed_blocks; int i; - wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); + if (wl->bss_type == BSS_TYPE_AP_BSS) { + wl1271_raw_read(wl, FW_STATUS_ADDR, status, + sizeof(struct wl1271_fw_ap_status), false); + } else { + wl1271_raw_read(wl, FW_STATUS_ADDR, status, + sizeof(struct wl1271_fw_sta_status), false); + } wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", @@ -840,49 +859,42 @@ static void wl12xx_fw_status(struct wl1271 *wl, status->drv_rx_counter, status->tx_results_counter); + /* update number of available TX blocks */ for (i = 0; i < NUM_TX_QUEUES; i++) { - /* prevent wrap-around in freed-packets counter */ - wl->tx_allocated_pkts[i] -= - (status->tx_released_pkts[i] - - wl->tx_pkts_freed[i]) & 0xff; + ac_freed_blocks = le32_to_cpu(status->tx_released_blks[i]) - + wl->tx_blocks_freed[i]; + freed_blocks += ac_freed_blocks; - wl->tx_pkts_freed[i] = status->tx_released_pkts[i]; - } - - /* prevent wrap-around in total blocks counter */ - if (likely(wl->tx_blocks_freed <= - le32_to_cpu(status->total_released_blks))) - freed_blocks = le32_to_cpu(status->total_released_blks) - - wl->tx_blocks_freed; - else - freed_blocks = 0x100000000LL - wl->tx_blocks_freed + - le32_to_cpu(status->total_released_blks); + wl->tx_allocated_blocks[i] -= ac_freed_blocks; - wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks); - - wl->tx_allocated_blocks -= freed_blocks; + wl->tx_blocks_freed[i] = + le32_to_cpu(status->tx_released_blks[i]); + } - avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks; + if (wl->bss_type == BSS_TYPE_AP_BSS) { + /* Update num of allocated TX blocks per link and ps status */ + wl1271_irq_update_links_status(wl, &full_status->ap); + wl->tx_blocks_available += freed_blocks; + } else { + int avail = full_status->sta.tx_total - + wl1271_tx_allocated_blocks(wl); - /* - * The FW might change the total number of TX memblocks before - * we get a notification about blocks being released. Thus, the - * available blocks calculation might yield a temporary result - * which is lower than the actual available blocks. Keeping in - * mind that only blocks that were allocated can be moved from - * TX to RX, tx_blocks_available should never decrease here. - */ - wl->tx_blocks_available = max((int)wl->tx_blocks_available, - avail); + /* + * The FW might change the total number of TX memblocks before + * we get a notification about blocks being released. Thus, the + * available blocks calculation might yield a temporary result + * which is lower than the actual available blocks. Keeping in + * mind that only blocks that were allocated can be moved from + * TX to RX, tx_blocks_available should never decrease here. + */ + wl->tx_blocks_available = max((int)wl->tx_blocks_available, + avail); + } /* if more blocks are available now, tx work can be scheduled */ if (wl->tx_blocks_available > old_tx_blk_count) clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); - /* for AP update num of allocated TX blocks per link and ps status */ - if (wl->bss_type == BSS_TYPE_AP_BSS) - wl12xx_irq_update_links_status(wl, status); - /* update the host-chipset time offset */ getnstimeofday(&ts); wl->time_offset = (timespec_to_ns(&ts) >> 10) - @@ -955,8 +967,8 @@ irqreturn_t wl1271_irq(int irq, void *cookie) clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); smp_mb__after_clear_bit(); - wl12xx_fw_status(wl, wl->fw_status); - intr = le32_to_cpu(wl->fw_status->intr); + wl1271_fw_status(wl, wl->fw_status); + intr = le32_to_cpu(wl->fw_status->common.intr); intr &= WL1271_INTR_MASK; if (!intr) { done = true; @@ -975,7 +987,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) if (likely(intr & WL1271_ACX_INTR_DATA)) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); - wl12xx_rx(wl, wl->fw_status); + wl1271_rx(wl, &wl->fw_status->common); /* Check if any tx blocks were freed */ spin_lock_irqsave(&wl->wl_lock, flags); @@ -992,7 +1004,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) } /* check for tx results */ - if (wl->fw_status->tx_results_counter != + if (wl->fw_status->common.tx_results_counter != (wl->tx_results_count & 0xff)) wl1271_tx_complete(wl); @@ -1044,10 +1056,25 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) const char *fw_name; int ret; - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_FW_NAME; - else - fw_name = WL127X_FW_NAME; + switch (wl->bss_type) { + case BSS_TYPE_AP_BSS: + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_AP_FW_NAME; + else + fw_name = WL127X_AP_FW_NAME; + break; + case BSS_TYPE_IBSS: + case BSS_TYPE_STA_BSS: + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_FW_NAME; + else + fw_name = WL1271_FW_NAME; + break; + default: + wl1271_error("no compatible firmware for bss_type %d", + wl->bss_type); + return -EINVAL; + } wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); @@ -1076,6 +1103,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) } memcpy(wl->fw, fw->data, wl->fw_len); + wl->fw_bss_type = wl->bss_type; ret = 0; out: @@ -1166,8 +1194,8 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) wl12xx_cmd_stop_fwlog(wl); /* Read the first memory block address */ - wl12xx_fw_status(wl, wl->fw_status); - first_addr = le32_to_cpu(wl->fw_status->log_start_addr); + wl1271_fw_status(wl, wl->fw_status); + first_addr = __le32_to_cpu(wl->fw_status->sta.log_start_addr); if (!first_addr) goto out; @@ -1183,7 +1211,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) * of each memory block hold the hardware address of the next * one. The last memory block points to the first one. */ - addr = le32_to_cpup((__le32 *)block); + addr = __le32_to_cpup((__le32 *)block); if (!wl12xx_copy_fwlog(wl, block + sizeof(addr), WL12XX_HW_BLOCK_SIZE - sizeof(addr))) break; @@ -1346,7 +1374,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) goto out; } - if (wl->fw == NULL) { + /* Make sure the firmware type matches the BSS type */ + if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) { ret = wl1271_fetch_firmware(wl); if (ret < 0) goto out; @@ -1366,7 +1395,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) int wl1271_plt_start(struct wl1271 *wl) { int retries = WL1271_BOOT_RETRIES; - struct wiphy *wiphy = wl->hw->wiphy; int ret; mutex_lock(&wl->mutex); @@ -1400,11 +1428,6 @@ int wl1271_plt_start(struct wl1271 *wl) wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver_str); - /* update hw/fw version info in wiphy struct */ - wiphy->hw_version = wl->chip.id; - strncpy(wiphy->fw_version, wl->chip.fw_ver_str, - sizeof(wiphy->fw_version)); - goto out; irq_disable: @@ -1481,25 +1504,10 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) q = wl1271_tx_get_queue(mapping); if (wl->bss_type == BSS_TYPE_AP_BSS) - hlid = wl12xx_tx_get_hlid_ap(wl, skb); + hlid = wl1271_tx_get_hlid(skb); spin_lock_irqsave(&wl->wl_lock, flags); - /* queue the packet */ - if (wl->bss_type == BSS_TYPE_AP_BSS) { - if (!wl1271_is_active_sta(wl, hlid)) { - wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", - hlid, q); - dev_kfree_skb(skb); - goto out; - } - - wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); - skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); - } else { - skb_queue_tail(&wl->tx_queue[q], skb); - } - wl->tx_queue_count[q]++; /* @@ -1512,6 +1520,14 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) set_bit(q, &wl->stopped_queues_map); } + /* queue the packet */ + if (wl->bss_type == BSS_TYPE_AP_BSS) { + wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); + skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); + } else { + skb_queue_tail(&wl->tx_queue[q], skb); + } + /* * The chip specific setup must run before the first TX packet - * before that, the tx_work will not be initialized! @@ -1521,7 +1537,6 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) !test_bit(WL1271_FLAG_TX_PENDING, &wl->flags)) ieee80211_queue_work(wl->hw, &wl->tx_work); -out: spin_unlock_irqrestore(&wl->wl_lock, flags); } @@ -1658,7 +1673,7 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl) if (ret < 0) goto out_unlock; - ret = wl1271_acx_beacon_filter_opt(wl, true); + ret = wl1271_acx_set_ap_beacon_filter(wl, true); wl1271_ps_elp_sleep(wl); out_unlock: @@ -1696,7 +1711,7 @@ static void wl1271_configure_resume(struct wl1271 *wl) wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, wl->basic_rate, true); } else if (is_ap) { - wl1271_acx_beacon_filter_opt(wl, false); + wl1271_acx_set_ap_beacon_filter(wl, false); } wl1271_ps_elp_sleep(wl); @@ -1788,6 +1803,9 @@ static int wl1271_op_start(struct ieee80211_hw *hw) * * The MAC address is first known when the corresponding interface * is added. That is where we will initialize the hardware. + * + * In addition, we currently have different firmwares for AP and managed + * operation. We will know which to boot according to interface type. */ return 0; @@ -1798,24 +1816,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); } -static u8 wl12xx_get_role_type(struct wl1271 *wl) -{ - switch (wl->bss_type) { - case BSS_TYPE_AP_BSS: - return WL1271_ROLE_AP; - - case BSS_TYPE_STA_BSS: - return WL1271_ROLE_STA; - - case BSS_TYPE_IBSS: - return WL1271_ROLE_IBSS; - - default: - wl1271_error("invalid bss_type: %d", wl->bss_type); - } - return WL12XX_INVALID_ROLE_TYPE; -} - static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1823,7 +1823,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct wiphy *wiphy = hw->wiphy; int retries = WL1271_BOOT_RETRIES; int ret = 0; - u8 role_type; bool booted = false; wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", @@ -1864,11 +1863,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - role_type = wl12xx_get_role_type(wl); - if (role_type == WL12XX_INVALID_ROLE_TYPE) { - ret = -EINVAL; - goto out; - } memcpy(wl->mac_addr, vif->addr, ETH_ALEN); if (wl->state != WL1271_STATE_OFF) { @@ -1888,25 +1882,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto power_off; - if (wl->bss_type == BSS_TYPE_STA_BSS || - wl->bss_type == BSS_TYPE_IBSS) { - /* - * The device role is a special role used for - * rx and tx frames prior to association (as - * the STA role can get packets only from - * its associated bssid) - */ - ret = wl12xx_cmd_role_enable(wl, - WL1271_ROLE_DEVICE, - &wl->dev_role_id); - if (ret < 0) - goto irq_disable; - } - - ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id); - if (ret < 0) - goto irq_disable; - ret = wl1271_hw_init(wl); if (ret < 0) goto irq_disable; @@ -1971,7 +1946,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, static void __wl1271_op_remove_interface(struct wl1271 *wl, bool reset_tx_queues) { - int ret, i; + int i; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); @@ -1996,31 +1971,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, ieee80211_scan_completed(wl->hw, true); } - if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { - /* disable active roles */ - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto deinit; - - if (wl->bss_type == BSS_TYPE_STA_BSS) { - ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id); - if (ret < 0) - goto deinit; - } - - ret = wl12xx_cmd_role_disable(wl, &wl->role_id); - if (ret < 0) - goto deinit; - - wl1271_ps_elp_sleep(wl); - } -deinit: - /* clear all hlids (except system_hlid) */ - wl->sta_hlid = WL12XX_INVALID_LINK_ID; - wl->dev_hlid = WL12XX_INVALID_LINK_ID; - wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; - wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; - /* * this must be before the cancel_work calls below, so that the work * functions don't perform further work. @@ -2057,26 +2007,18 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; - wl->tx_allocated_blocks = 0; wl->tx_results_count = 0; wl->tx_packets_count = 0; wl->time_offset = 0; wl->session_counter = 0; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->vif = NULL; + wl->filters = 0; wl1271_free_ap_keys(wl); memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); wl->ap_fw_ps_map = 0; wl->ap_ps_map = 0; wl->sched_scanning = false; - wl->role_id = WL12XX_INVALID_ROLE_ID; - wl->dev_role_id = WL12XX_INVALID_ROLE_ID; - memset(wl->roles_map, 0, sizeof(wl->roles_map)); - memset(wl->links_map, 0, sizeof(wl->links_map)); - memset(wl->roc_map, 0, sizeof(wl->roc_map)); - - /* The system link is always allocated */ - __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); /* * this is performed after the cancel_work calls and the associated @@ -2085,11 +2027,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, */ wl->flags = 0; - wl->tx_blocks_freed = 0; - for (i = 0; i < NUM_TX_QUEUES; i++) { - wl->tx_pkts_freed[i] = 0; - wl->tx_allocated_pkts[i] = 0; + wl->tx_blocks_freed[i] = 0; + wl->tx_allocated_blocks[i] = 0; } wl1271_debugfs_reset(wl); @@ -2121,10 +2061,64 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, cancel_work_sync(&wl->recovery_work); } +void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) +{ + wl1271_set_default_filters(wl); + + /* combine requested filters with current filter config */ + filters = wl->filters | filters; + + wl1271_debug(DEBUG_FILTERS, "RX filters set: "); + + if (filters & FIF_PROMISC_IN_BSS) { + wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS"); + wl->rx_config &= ~CFG_UNI_FILTER_EN; + wl->rx_config |= CFG_BSSID_FILTER_EN; + } + if (filters & FIF_BCN_PRBRESP_PROMISC) { + wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC"); + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + wl->rx_config &= ~CFG_SSID_FILTER_EN; + } + if (filters & FIF_OTHER_BSS) { + wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS"); + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + } + if (filters & FIF_CONTROL) { + wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL"); + wl->rx_filter |= CFG_RX_CTL_EN; + } + if (filters & FIF_FCSFAIL) { + wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL"); + wl->rx_filter |= CFG_RX_FCS_ERROR; + } +} + +static int wl1271_dummy_join(struct wl1271 *wl) +{ + int ret = 0; + /* we need to use a dummy BSSID for now */ + static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, + 0xad, 0xbe, 0xef }; + + memcpy(wl->bssid, dummy_bssid, ETH_ALEN); + + /* pass through frames from all BSS */ + wl1271_configure_filters(wl, FIF_OTHER_BSS); + + ret = wl1271_cmd_join(wl, wl->set_bss_type); + if (ret < 0) + goto out; + + set_bit(WL1271_FLAG_JOINED, &wl->flags); + +out: + return ret; +} + static int wl1271_join(struct wl1271 *wl, bool set_assoc) { int ret; - bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); /* * One of the side effects of the JOIN command is that is clears @@ -2141,13 +2135,12 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) if (set_assoc) set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); - if (is_ibss) - ret = wl12xx_cmd_role_start_ibss(wl); - else - ret = wl12xx_cmd_role_start_sta(wl); + ret = wl1271_cmd_join(wl, wl->set_bss_type); if (ret < 0) goto out; + set_bit(WL1271_FLAG_JOINED, &wl->flags); + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) goto out; @@ -2183,16 +2176,20 @@ static int wl1271_unjoin(struct wl1271 *wl) int ret; /* to stop listening to a channel, we disconnect */ - ret = wl12xx_cmd_role_stop_sta(wl); + ret = wl1271_cmd_disconnect(wl); if (ret < 0) goto out; + clear_bit(WL1271_FLAG_JOINED, &wl->flags); memset(wl->bssid, 0, ETH_ALEN); /* reset TX security counters on a clean disconnect */ wl->tx_security_last_seq_lsb = 0; wl->tx_security_seq = 0; + /* stop filtering packets based on bssid */ + wl1271_configure_filters(wl, FIF_OTHER_BSS); + out: return ret; } @@ -2205,29 +2202,13 @@ static void wl1271_set_band_rate(struct wl1271 *wl) wl->basic_rate_set = wl->conf.tx.basic_rate_5; } -static bool wl12xx_is_roc(struct wl1271 *wl) -{ - u8 role_id; - - role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES); - if (role_id >= WL12XX_MAX_ROLES) - return false; - - return true; -} - static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) { int ret; if (idle) { - /* no need to croc if we weren't busy (e.g. during boot) */ - if (wl12xx_is_roc(wl)) { - ret = wl12xx_croc(wl, wl->dev_role_id); - if (ret < 0) - goto out; - - ret = wl12xx_cmd_role_stop_dev(wl); + if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { + ret = wl1271_unjoin(wl); if (ret < 0) goto out; } @@ -2242,17 +2223,18 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) goto out; set_bit(WL1271_FLAG_IDLE, &wl->flags); } else { + /* increment the session counter */ + wl->session_counter++; + if (wl->session_counter >= SESSION_COUNTER_MAX) + wl->session_counter = 0; + /* The current firmware only supports sched_scan in idle */ if (wl->sched_scanning) { wl1271_scan_sched_scan_stop(wl); ieee80211_sched_scan_stopped(wl->hw); } - ret = wl12xx_cmd_role_start_dev(wl); - if (ret < 0) - goto out; - - ret = wl12xx_roc(wl, wl->dev_role_id); + ret = wl1271_dummy_join(wl); if (ret < 0) goto out; clear_bit(WL1271_FLAG_IDLE, &wl->flags); @@ -2332,34 +2314,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_warning("rate policy for channel " "failed %d", ret); - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { - if (wl12xx_is_roc(wl)) { - /* roaming */ - ret = wl12xx_croc(wl, wl->dev_role_id); - if (ret < 0) - goto out_sleep; - } + if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { ret = wl1271_join(wl, false); if (ret < 0) wl1271_warning("cmd join on channel " "failed %d", ret); - } else { - /* - * change the ROC channel. do it only if we are - * not idle. otherwise, CROC will be called - * anyway. - */ - if (wl12xx_is_roc(wl) && - !(conf->flags & IEEE80211_CONF_IDLE)) { - ret = wl12xx_croc(wl, wl->dev_role_id); - if (ret < 0) - goto out_sleep; - - ret = wl12xx_roc(wl, wl->dev_role_id); - if (ret < 0) - wl1271_warning("roc failed %d", - ret); - } } } } @@ -2499,11 +2458,18 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, goto out_sleep; } - /* - * the fw doesn't provide an api to configure the filters. instead, - * the filters configuration is based on the active roles / ROC - * state. - */ + /* determine, whether supported filter values have changed */ + if (changed == 0) + goto out_sleep; + + /* configure filters */ + wl->filters = *total; + wl1271_configure_filters(wl, 0); + + /* apply configured filters */ + ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); + if (ret < 0) + goto out_sleep; out_sleep: wl1271_ps_elp_sleep(wl); @@ -2575,19 +2541,14 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) bool wep_key_added = false; for (i = 0; i < MAX_NUM_KEYS; i++) { - u8 hlid; if (wl->recorded_ap_keys[i] == NULL) break; key = wl->recorded_ap_keys[i]; - hlid = key->hlid; - if (hlid == WL12XX_INVALID_LINK_ID) - hlid = wl->ap_bcast_hlid; - ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE, key->id, key->key_type, key->key_size, key->key, - hlid, key->tx_seq_32, + key->hlid, key->tx_seq_32, key->tx_seq_16); if (ret < 0) goto out; @@ -2597,8 +2558,7 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) } if (wep_key_added) { - ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key, - wl->ap_bcast_hlid); + ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key); if (ret < 0) goto out; } @@ -2623,7 +2583,7 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, wl_sta = (struct wl1271_station *)sta->drv_priv; hlid = wl_sta->hlid; } else { - hlid = wl->ap_bcast_hlid; + hlid = WL1271_AP_BROADCAST_HLID; } if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { @@ -2667,11 +2627,6 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr)) return 0; - /* don't remove key if hlid was already deleted */ - if (action == KEY_REMOVE && - wl->sta_hlid == WL12XX_INVALID_LINK_ID) - return 0; - ret = wl1271_cmd_set_sta_key(wl, action, id, key_type, key_size, key, addr, tx_seq_32, @@ -2681,9 +2636,8 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, /* the default WEP key needs to be configured at least once */ if (key_type == KEY_WEP) { - ret = wl12xx_cmd_set_default_wep_key(wl, - wl->default_key, - wl->sta_hlid); + ret = wl1271_cmd_set_sta_default_wep_key(wl, + wl->default_key); if (ret < 0) return ret; } @@ -2825,20 +2779,10 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, if (ret < 0) goto out; - /* cancel ROC before scanning */ - if (wl12xx_is_roc(wl)) { - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { - /* don't allow scanning right now */ - ret = -EBUSY; - goto out_sleep; - } - wl12xx_croc(wl, wl->dev_role_id); - wl12xx_cmd_role_stop_dev(wl); - } - ret = wl1271_scan(hw->priv, ssid, len, req); -out_sleep: + wl1271_ps_elp_sleep(wl); + out: mutex_unlock(&wl->mutex); @@ -3150,20 +3094,20 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if ((changed & BSS_CHANGED_BEACON_ENABLED)) { if (bss_conf->enable_beacon) { if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { - ret = wl12xx_cmd_role_start_ap(wl); + ret = wl1271_cmd_start_bss(wl); if (ret < 0) goto out; + set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); + wl1271_debug(DEBUG_AP, "started AP"); + ret = wl1271_ap_init_hwenc(wl); if (ret < 0) goto out; - - set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); - wl1271_debug(DEBUG_AP, "started AP"); } } else { if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { - ret = wl12xx_cmd_role_stop_ap(wl); + ret = wl1271_cmd_stop_bss(wl); if (ret < 0) goto out; @@ -3176,18 +3120,6 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); if (ret < 0) goto out; - - /* Handle HT information change */ - if ((changed & BSS_CHANGED_HT) && - (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_information(wl, - bss_conf->ht_operation_mode); - if (ret < 0) { - wl1271_warning("Set ht information failed %d", ret); - goto out; - } - } - out: return; } @@ -3200,7 +3132,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, { bool do_join = false, set_assoc = false; bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); - bool ibss_joined = false; u32 sta_rate_set = 0; int ret; struct ieee80211_sta *sta; @@ -3214,28 +3145,14 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, goto out; } - if (changed & BSS_CHANGED_IBSS) { - if (bss_conf->ibss_joined) { - set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags); - ibss_joined = true; - } else { - if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED, - &wl->flags)) { - wl1271_unjoin(wl); - wl12xx_cmd_role_start_dev(wl); - wl12xx_roc(wl, wl->dev_role_id); - } - } - } - - if ((changed & BSS_CHANGED_BEACON_INT) && ibss_joined) + if ((changed & BSS_CHANGED_BEACON_INT) && is_ibss) do_join = true; /* Need to update the SSID (for filtering etc) */ - if ((changed & BSS_CHANGED_BEACON) && ibss_joined) + if ((changed & BSS_CHANGED_BEACON) && is_ibss) do_join = true; - if ((changed & BSS_CHANGED_BEACON_ENABLED) && ibss_joined) { + if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) { wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", bss_conf->enable_beacon ? "enabled" : "disabled"); @@ -3275,17 +3192,17 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (ret < 0) goto out; + /* filter out all packets not from this BSSID */ + wl1271_configure_filters(wl, 0); + /* Need to update the BSSID (for filtering etc) */ do_join = true; } } - if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { - rcu_read_lock(); - sta = ieee80211_find_sta(vif, bss_conf->bssid); - if (!sta) - goto sta_not_found; - + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (sta) { /* save the supp_rates of the ap */ sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band]; if (sta->ht_cap.ht_supported) @@ -3293,9 +3210,38 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); sta_ht_cap = sta->ht_cap; sta_exists = true; + } + rcu_read_unlock(); -sta_not_found: - rcu_read_unlock(); + if (sta_exists) { + /* handle new association with HT and HT information change */ + if ((changed & BSS_CHANGED_HT) && + (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { + ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, + true); + if (ret < 0) { + wl1271_warning("Set ht cap true failed %d", + ret); + goto out; + } + ret = wl1271_acx_set_ht_information(wl, + bss_conf->ht_operation_mode); + if (ret < 0) { + wl1271_warning("Set ht information failed %d", + ret); + goto out; + } + } + /* handle new association without HT and disassociation */ + else if (changed & BSS_CHANGED_ASSOC) { + ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, + false); + if (ret < 0) { + wl1271_warning("Set ht cap false failed %d", + ret); + goto out; + } + } } if ((changed & BSS_CHANGED_ASSOC)) { @@ -3363,9 +3309,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, bool was_assoc = !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); - bool was_ifup = - !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT, - &wl->flags); + clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); wl->aid = 0; /* free probe-request template */ @@ -3392,32 +3336,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, /* restore the bssid filter and go to dummy bssid */ if (was_assoc) { - u32 conf_flags = wl->hw->conf.flags; - /* - * we might have to disable roc, if there was - * no IF_OPER_UP notification. - */ - if (!was_ifup) { - ret = wl12xx_croc(wl, wl->role_id); - if (ret < 0) - goto out; - } - /* - * (we also need to disable roc in case of - * roaming on the same channel. until we will - * have a better flow...) - */ - if (test_bit(wl->dev_role_id, wl->roc_map)) { - ret = wl12xx_croc(wl, wl->dev_role_id); - if (ret < 0) - goto out; - } - wl1271_unjoin(wl); - if (!(conf_flags & IEEE80211_CONF_IDLE)) { - wl12xx_cmd_role_start_dev(wl); - wl12xx_roc(wl, wl->dev_role_id); - } + wl1271_dummy_join(wl); } } } @@ -3478,68 +3398,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, wl1271_warning("cmd join failed %d", ret); goto out; } - - /* ROC until connected (after EAPOL exchange) */ - if (!is_ibss) { - ret = wl12xx_roc(wl, wl->role_id); - if (ret < 0) - goto out; - - wl1271_check_operstate(wl, - ieee80211_get_operstate(vif)); - } - /* - * stop device role if started (we might already be in - * STA role). TODO: make it better. - */ - if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) { - ret = wl12xx_croc(wl, wl->dev_role_id); - if (ret < 0) - goto out; - - ret = wl12xx_cmd_role_stop_dev(wl); - if (ret < 0) - goto out; - } - } - - /* Handle new association with HT. Do this after join. */ - if (sta_exists) { - if ((changed & BSS_CHANGED_HT) && - (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_capabilities(wl, - &sta_ht_cap, - true, - wl->sta_hlid); - if (ret < 0) { - wl1271_warning("Set ht cap true failed %d", - ret); - goto out; - } - } - /* handle new association without HT and disassociation */ - else if (changed & BSS_CHANGED_ASSOC) { - ret = wl1271_acx_set_ht_capabilities(wl, - &sta_ht_cap, - false, - wl->sta_hlid); - if (ret < 0) { - wl1271_warning("Set ht cap false failed %d", - ret); - goto out; - } - } - } - - /* Handle HT information change. Done after join. */ - if ((changed & BSS_CHANGED_HT) && - (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_information(wl, - bss_conf->ht_operation_mode); - if (ret < 0) { - wl1271_warning("Set ht information failed %d", ret); - goto out; - } + wl1271_check_operstate(wl, ieee80211_get_operstate(vif)); } out: @@ -3709,7 +3568,7 @@ static int wl1271_allocate_sta(struct wl1271 *wl, } wl_sta = (struct wl1271_station *)sta->drv_priv; - set_bit(id, wl->ap_hlid_map); + __set_bit(id, wl->ap_hlid_map); wl_sta->hlid = WL1271_AP_STA_HLID_START + id; *hlid = wl_sta->hlid; memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); @@ -3723,14 +3582,19 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) return; - clear_bit(id, wl->ap_hlid_map); + __clear_bit(id, wl->ap_hlid_map); memset(wl->links[hlid].addr, 0, ETH_ALEN); - wl->links[hlid].ba_bitmap = 0; wl1271_tx_reset_link_queues(wl, hlid); __clear_bit(hlid, &wl->ap_ps_map); __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); } +bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) +{ + int id = hlid - WL1271_AP_STA_HLID_START; + return test_bit(id, wl->ap_hlid_map); +} + static int wl1271_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -3757,15 +3621,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, if (ret < 0) goto out_free_sta; - ret = wl12xx_cmd_add_peer(wl, sta, hlid); - if (ret < 0) - goto out_sleep; - - ret = wl12xx_cmd_set_peer_state(wl, hlid); - if (ret < 0) - goto out_sleep; - - ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid); + ret = wl1271_cmd_add_sta(wl, sta, hlid); if (ret < 0) goto out_sleep; @@ -3808,7 +3664,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, if (ret < 0) goto out; - ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid); + ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid); if (ret < 0) goto out_sleep; @@ -3830,14 +3686,6 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, { struct wl1271 *wl = hw->priv; int ret; - u8 hlid, *ba_bitmap; - - wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action, - tid); - - /* sanity check - the fields in FW are only 8bits wide */ - if (WARN_ON(tid > 0xFF)) - return -ENOTSUPP; mutex_lock(&wl->mutex); @@ -3846,20 +3694,6 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, goto out; } - if (wl->bss_type == BSS_TYPE_STA_BSS) { - hlid = wl->sta_hlid; - ba_bitmap = &wl->ba_rx_bitmap; - } else if (wl->bss_type == BSS_TYPE_AP_BSS) { - struct wl1271_station *wl_sta; - - wl_sta = (struct wl1271_station *)sta->drv_priv; - hlid = wl_sta->hlid; - ba_bitmap = &wl->links[hlid].ba_bitmap; - } else { - ret = -EINVAL; - goto out; - } - ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; @@ -3869,46 +3703,20 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if (!wl->ba_support || !wl->ba_allowed) { + if ((wl->ba_support) && (wl->ba_allowed)) { + ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn, + true); + if (!ret) + wl->ba_rx_bitmap |= BIT(tid); + } else { ret = -ENOTSUPP; - break; - } - - if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) { - ret = -EBUSY; - wl1271_error("exceeded max RX BA sessions"); - break; - } - - if (*ba_bitmap & BIT(tid)) { - ret = -EINVAL; - wl1271_error("cannot enable RX BA session on active " - "tid: %d", tid); - break; - } - - ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true, - hlid); - if (!ret) { - *ba_bitmap |= BIT(tid); - wl->ba_rx_session_count++; } break; case IEEE80211_AMPDU_RX_STOP: - if (!(*ba_bitmap & BIT(tid))) { - ret = -EINVAL; - wl1271_error("no active RX BA session on tid: %d", - tid); - break; - } - - ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false, - hlid); - if (!ret) { - *ba_bitmap &= ~BIT(tid); - wl->ba_rx_session_count--; - } + ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false); + if (!ret) + wl->ba_rx_bitmap &= ~BIT(tid); break; /* @@ -4318,7 +4126,7 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, return len; } -static DEVICE_ATTR(hw_pg_ver, S_IRUGO, +static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR, wl1271_sysfs_show_hw_pg_ver, NULL); static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj, @@ -4480,7 +4288,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) * should be the maximum length possible for a template, without * the IEEE80211 header of the template */ - wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - + wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - sizeof(struct ieee80211_header); /* make sure all our channels fit in the scanned_ch bitmask */ @@ -4579,6 +4387,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->beacon_int = WL1271_DEFAULT_BEACON_INT; wl->default_key = 0; wl->rx_counter = 0; + wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG; + wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER; wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; @@ -4591,6 +4401,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->hw_pg_ver = -1; wl->bss_type = MAX_BSS_TYPE; wl->set_bss_type = MAX_BSS_TYPE; + wl->fw_bss_type = MAX_BSS_TYPE; wl->last_tx_hlid = 0; wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; @@ -4599,22 +4410,12 @@ struct ieee80211_hw *wl1271_alloc_hw(void) wl->sched_scanning = false; wl->tx_security_seq = 0; wl->tx_security_last_seq_lsb = 0; - wl->role_id = WL12XX_INVALID_ROLE_ID; - wl->system_hlid = WL12XX_SYSTEM_HLID; - wl->sta_hlid = WL12XX_INVALID_LINK_ID; - wl->dev_role_id = WL12XX_INVALID_ROLE_ID; - wl->dev_hlid = WL12XX_INVALID_LINK_ID; - wl->session_counter = 0; - wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; - wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; + setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, (unsigned long) wl); wl->fwlog_size = 0; init_waitqueue_head(&wl->fwlog_waitq); - /* The system link is always allocated */ - __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); - memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; @@ -4721,10 +4522,6 @@ int wl1271_free_hw(struct wl1271 *wl) mutex_unlock(&wl->mutex); device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr); - - device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); - - device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); platform_device_unregister(wl->plat_dev); free_page((unsigned long)wl->fwlog); dev_kfree_skb(wl->dummy_packet); diff --git a/trunk/drivers/net/wireless/wl12xx/ps.c b/trunk/drivers/net/wireless/wl12xx/ps.c index 4b720b1b9f65..3548377ab9c2 100644 --- a/trunk/drivers/net/wireless/wl12xx/ps.c +++ b/trunk/drivers/net/wireless/wl12xx/ps.c @@ -226,8 +226,8 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) if (test_bit(hlid, &wl->ap_ps_map)) return; - wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d " - "clean_queues %d", hlid, wl->links[hlid].allocated_pkts, + wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d " + "clean_queues %d", hlid, wl->links[hlid].allocated_blks, clean_queues); rcu_read_lock(); diff --git a/trunk/drivers/net/wireless/wl12xx/reg.h b/trunk/drivers/net/wireless/wl12xx/reg.h index 3f570f397586..440a4ee9cb42 100644 --- a/trunk/drivers/net/wireless/wl12xx/reg.h +++ b/trunk/drivers/net/wireless/wl12xx/reg.h @@ -296,6 +296,81 @@ ===============================================*/ #define REG_EVENT_MAILBOX_PTR (SCR_PAD1) + +/* Misc */ + +#define REG_ENABLE_TX_RX (ENABLE) +/* + * Rx configuration (filter) information element + * --------------------------------------------- + */ +#define REG_RX_CONFIG (RX_CFG) +#define REG_RX_FILTER (RX_FILTER_CFG) + + +#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002 + +/* promiscuous - receives all valid frames */ +#define RX_CFG_PROMISCUOUS 0x0008 + +/* receives frames from any BSSID */ +#define RX_CFG_BSSID 0x0020 + +/* receives frames destined to any MAC address */ +#define RX_CFG_MAC 0x0010 + +#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010 +#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000 +#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020 +#define RX_CFG_ENABLE_ANY_BSSID 0x0000 + +/* discards all broadcast frames */ +#define RX_CFG_DISABLE_BCAST 0x0200 + +#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400 +#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800 +#define RX_CFG_COPY_RX_STATUS 0x2000 +#define RX_CFG_TSF 0x10000 + +#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ + RX_CFG_ENABLE_ONLY_MY_BSSID) + +#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ + | RX_CFG_ENABLE_ANY_BSSID) + +#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ + RX_CFG_ENABLE_ANY_BSSID) + +#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ + | RX_CFG_ENABLE_ONLY_MY_BSSID) + +#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \ + | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \ + | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF) + +#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC) + +#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \ + RX_CFG_ENABLE_ONLY_MY_DEST_MAC) + +#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \ + RX_CFG_ENABLE_ONLY_MY_DEST_MAC) + +#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ + | CFG_RX_CTL_EN | CFG_RX_BCN_EN\ + | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) + +#define RX_FILTER_OPTION_FILTER_ALL 0 + +#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\ + | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN) + +#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ + | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\ + | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\ + | CFG_RX_PRSP_EN) + + /*=============================================== EEPROM Read/Write Request 32bit RW ------------------------------------------ diff --git a/trunk/drivers/net/wireless/wl12xx/rx.c b/trunk/drivers/net/wireless/wl12xx/rx.c index 78d8410da1f4..0450fb49dbb1 100644 --- a/trunk/drivers/net/wireless/wl12xx/rx.c +++ b/trunk/drivers/net/wireless/wl12xx/rx.c @@ -30,28 +30,20 @@ #include "rx.h" #include "io.h" -static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, +static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status, u32 drv_rx_counter) { return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & RX_MEM_BLOCK_MASK; } -static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status, +static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status, u32 drv_rx_counter) { return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; } -static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status, - u32 drv_rx_counter) -{ - /* Convert the value to bool */ - return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & - RX_BUF_UNALIGNED_PAYLOAD); -} - static void wl1271_rx_status(struct wl1271 *wl, struct wl1271_rx_descriptor *desc, struct ieee80211_rx_status *status, @@ -97,8 +89,7 @@ static void wl1271_rx_status(struct wl1271 *wl, } } -static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, - bool unaligned) +static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) { struct wl1271_rx_descriptor *desc; struct sk_buff *skb; @@ -106,7 +97,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, u8 *buf; u8 beacon = 0; u8 is_data = 0; - u8 reserved = unaligned ? NET_IP_ALIGN : 0; /* * In PLT mode we seem to get frames and mac80211 warns about them, @@ -141,25 +131,17 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, return -EINVAL; } - /* skb length not included rx descriptor */ - skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL); + skb = __dev_alloc_skb(length, GFP_KERNEL); if (!skb) { wl1271_error("Couldn't allocate RX frame"); return -ENOMEM; } - /* reserve the unaligned payload(if any) */ - skb_reserve(skb, reserved); + buf = skb_put(skb, length); + memcpy(buf, data, length); - buf = skb_put(skb, length - sizeof(*desc)); - - /* - * Copy packets from aggregation buffer to the skbs without rx - * descriptor and with packet payload aligned care. In case of unaligned - * packets copy the packets in offset of 2 bytes guarantee IP header - * payload aligned to 4 bytes. - */ - memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); + /* now we pull the descriptor out of the buffer */ + skb_pull(skb, sizeof(*desc)); hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_beacon(hdr->frame_control)) @@ -181,7 +163,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, return is_data; } -void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) +void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) { struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; u32 buf_size; @@ -193,13 +175,12 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) u32 pkt_offset; bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); bool had_data = false; - bool unaligned = false; while (drv_rx_counter != fw_rx_counter) { buf_size = 0; rx_counter = drv_rx_counter; while (rx_counter != fw_rx_counter) { - pkt_length = wl12xx_rx_get_buf_size(status, rx_counter); + pkt_length = wl1271_rx_get_buf_size(status, rx_counter); if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE) break; buf_size += pkt_length; @@ -218,7 +199,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) * For aggregated packets, only the first memory block * should be retrieved. The FW takes care of the rest. */ - mem_block = wl12xx_rx_get_mem_block(status, + mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); wl->rx_mem_pool_addr.addr = (mem_block << 8) + @@ -239,12 +220,8 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) /* Split data into separate packets */ pkt_offset = 0; while (pkt_offset < buf_size) { - pkt_length = wl12xx_rx_get_buf_size(status, + pkt_length = wl1271_rx_get_buf_size(status, drv_rx_counter); - - unaligned = wl12xx_rx_get_unaligned(status, - drv_rx_counter); - /* * the handle data call can only fail in memory-outage * conditions, in that case the received frame will just @@ -252,7 +229,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) */ if (wl1271_rx_handle_data(wl, wl->aggr_buf + pkt_offset, - pkt_length, unaligned) == 1) + pkt_length) == 1) had_data = true; wl->rx_counter++; @@ -283,3 +260,14 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) jiffies + msecs_to_jiffies(timeout)); } } + +void wl1271_set_default_filters(struct wl1271 *wl) +{ + if (wl->bss_type == BSS_TYPE_AP_BSS) { + wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG; + wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER; + } else { + wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG; + wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER; + } +} diff --git a/trunk/drivers/net/wireless/wl12xx/rx.h b/trunk/drivers/net/wireless/wl12xx/rx.h index 86ba6b1d0cdc..c88e3fa1d603 100644 --- a/trunk/drivers/net/wireless/wl12xx/rx.h +++ b/trunk/drivers/net/wireless/wl12xx/rx.h @@ -86,18 +86,16 @@ * Bits 3-5 - process_id tag (AP mode FW) * Bits 6-7 - reserved */ -#define WL1271_RX_DESC_STATUS_MASK 0x03 +#define WL1271_RX_DESC_STATUS_MASK 0x07 #define WL1271_RX_DESC_SUCCESS 0x00 #define WL1271_RX_DESC_DECRYPT_FAIL 0x01 #define WL1271_RX_DESC_MIC_FAIL 0x02 #define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03 -#define RX_MEM_BLOCK_MASK 0xFF -#define RX_BUF_SIZE_MASK 0xFFF00 -#define RX_BUF_SIZE_SHIFT_DIV 6 -/* If set, the start of IP payload is not 4 bytes aligned */ -#define RX_BUF_UNALIGNED_PAYLOAD BIT(20) +#define RX_MEM_BLOCK_MASK 0xFF +#define RX_BUF_SIZE_MASK 0xFFF00 +#define RX_BUF_SIZE_SHIFT_DIV 6 enum { WL12XX_RX_CLASS_UNKNOWN, @@ -121,12 +119,16 @@ struct wl1271_rx_descriptor { u8 snr; __le32 timestamp; u8 packet_class; - u8 hlid; + union { + u8 process_id; /* STA FW */ + u8 hlid; /* AP FW */ + } __packed; u8 pad_len; u8 reserved; } __packed; -void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status); +void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); +void wl1271_set_default_filters(struct wl1271 *wl); #endif diff --git a/trunk/drivers/net/wireless/wl12xx/scan.c b/trunk/drivers/net/wireless/wl12xx/scan.c index 7229eaa89018..edfe01c321ca 100644 --- a/trunk/drivers/net/wireless/wl12xx/scan.c +++ b/trunk/drivers/net/wireless/wl12xx/scan.c @@ -33,8 +33,6 @@ void wl1271_scan_complete_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; - int ret; - bool is_sta, is_ibss; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, scan_complete_work); @@ -52,34 +50,21 @@ void wl1271_scan_complete_work(struct work_struct *work) wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; + ieee80211_scan_completed(wl->hw, false); - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - + /* restore hardware connection monitoring template */ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { - /* restore hardware connection monitoring template */ - wl1271_cmd_build_ap_probe_req(wl, wl->probereq); - } - - /* return to ROC if needed */ - is_sta = (wl->bss_type == BSS_TYPE_STA_BSS); - is_ibss = (wl->bss_type == BSS_TYPE_IBSS); - if ((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || - (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) { - /* restore remain on channel */ - wl12xx_cmd_role_start_dev(wl); - wl12xx_roc(wl, wl->dev_role_id); + if (wl1271_ps_elp_wakeup(wl) == 0) { + wl1271_cmd_build_ap_probe_req(wl, wl->probereq); + wl1271_ps_elp_sleep(wl); + } } - wl1271_ps_elp_sleep(wl); if (wl->scan.failed) { wl1271_info("Scan completed due to error."); wl12xx_queue_recovery_work(wl); } - ieee80211_scan_completed(wl->hw, false); - out: mutex_unlock(&wl->mutex); @@ -171,11 +156,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, if (passive || wl->scan.req->n_ssids == 0) scan_options |= WL1271_SCAN_OPT_PASSIVE; - if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { - ret = -EINVAL; - goto out; - } - cmd->params.role_id = wl->role_id; cmd->params.scan_options = cpu_to_le16(scan_options); cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, @@ -187,6 +167,10 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, } cmd->params.tx_rate = cpu_to_le32(basic_rate); + cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); + cmd->params.rx_filter_options = + cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); + cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.tid_trigger = 0; @@ -202,8 +186,6 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); } - memcpy(cmd->addr, wl->mac_addr, ETH_ALEN); - ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, wl->scan.req->ie, wl->scan.req->ie_len, band); diff --git a/trunk/drivers/net/wireless/wl12xx/scan.h b/trunk/drivers/net/wireless/wl12xx/scan.h index 92115156522f..0b2a2987439d 100644 --- a/trunk/drivers/net/wireless/wl12xx/scan.h +++ b/trunk/drivers/net/wireless/wl12xx/scan.h @@ -46,10 +46,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl); #define WL1271_SCAN_CURRENT_TX_PWR 0 #define WL1271_SCAN_OPT_ACTIVE 0 #define WL1271_SCAN_OPT_PASSIVE 1 -#define WL1271_SCAN_OPT_TRIGGERED_SCAN 2 #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 -/* scan even if we fail to enter psm */ -#define WL1271_SCAN_OPT_FORCE 8 #define WL1271_SCAN_BAND_2_4_GHZ 0 #define WL1271_SCAN_BAND_5_GHZ 1 @@ -65,27 +62,27 @@ enum { }; struct basic_scan_params { + __le32 rx_config_options; + __le32 rx_filter_options; /* Scan option flags (WL1271_SCAN_OPT_*) */ __le16 scan_options; - u8 role_id; /* Number of scan channels in the list (maximum 30) */ u8 n_ch; /* This field indicates the number of probe requests to send per channel for an active scan */ u8 n_probe_reqs; - u8 tid_trigger; - u8 ssid_len; - u8 use_ssid_list; - /* Rate bit field for sending the probes */ __le32 tx_rate; - + u8 tid_trigger; + u8 ssid_len; + /* in order to align */ + u8 padding1[2]; u8 ssid[IEEE80211_MAX_SSID_LEN]; /* Band to scan */ u8 band; - + u8 use_ssid_list; u8 scan_tag; - u8 padding2[2]; + u8 padding2; } __packed; struct basic_scan_channel_params { @@ -108,10 +105,6 @@ struct wl1271_cmd_scan { struct basic_scan_params params; struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; - - /* src mac address */ - u8 addr[ETH_ALEN]; - u8 padding[2]; } __packed; struct wl1271_cmd_trigger_scan_to { @@ -191,7 +184,7 @@ struct wl1271_cmd_sched_scan_config { } __packed; -#define SCHED_SCAN_MAX_SSIDS 16 +#define SCHED_SCAN_MAX_SSIDS 8 enum { SCAN_SSID_TYPE_PUBLIC = 0, diff --git a/trunk/drivers/net/wireless/wl12xx/sdio.c b/trunk/drivers/net/wireless/wl12xx/sdio.c index ac2e5661397c..5cf18c2c23f0 100644 --- a/trunk/drivers/net/wireless/wl12xx/sdio.c +++ b/trunk/drivers/net/wireless/wl12xx/sdio.c @@ -412,5 +412,7 @@ module_exit(wl1271_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); -MODULE_FIRMWARE(WL127X_FW_NAME); +MODULE_FIRMWARE(WL1271_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); +MODULE_FIRMWARE(WL127X_AP_FW_NAME); +MODULE_FIRMWARE(WL128X_AP_FW_NAME); diff --git a/trunk/drivers/net/wireless/wl12xx/sdio_test.c b/trunk/drivers/net/wireless/wl12xx/sdio_test.c index c3610492852e..f28915392877 100644 --- a/trunk/drivers/net/wireless/wl12xx/sdio_test.c +++ b/trunk/drivers/net/wireless/wl12xx/sdio_test.c @@ -193,7 +193,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) ret = request_firmware(&fw, WL128X_FW_NAME, wl1271_wl_to_dev(wl)); else - ret = request_firmware(&fw, WL127X_FW_NAME, + ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { diff --git a/trunk/drivers/net/wireless/wl12xx/spi.c b/trunk/drivers/net/wireless/wl12xx/spi.c index 0f9718677860..e0b3736d7e19 100644 --- a/trunk/drivers/net/wireless/wl12xx/spi.c +++ b/trunk/drivers/net/wireless/wl12xx/spi.c @@ -486,6 +486,8 @@ module_exit(wl1271_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); -MODULE_FIRMWARE(WL127X_FW_NAME); +MODULE_FIRMWARE(WL1271_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); +MODULE_FIRMWARE(WL127X_AP_FW_NAME); +MODULE_FIRMWARE(WL128X_AP_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/trunk/drivers/net/wireless/wl12xx/tx.c b/trunk/drivers/net/wireless/wl12xx/tx.c index 0f1578577b1a..48fde96ce0d4 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.c +++ b/trunk/drivers/net/wireless/wl12xx/tx.c @@ -37,10 +37,9 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id) bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); if (is_ap) - ret = wl12xx_cmd_set_default_wep_key(wl, id, - wl->ap_bcast_hlid); + ret = wl1271_cmd_set_ap_default_wep_key(wl, id); else - ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid); + ret = wl1271_cmd_set_sta_default_wep_key(wl, id); if (ret < 0) return ret; @@ -78,7 +77,6 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, struct sk_buff *skb) { struct ieee80211_hdr *hdr; - int ret; hdr = (struct ieee80211_hdr *)(skb->data + sizeof(struct wl1271_tx_hw_descr)); @@ -92,19 +90,9 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, if (!ieee80211_is_auth(hdr->frame_control)) return 0; - if (wl->dev_hlid != WL12XX_INVALID_LINK_ID) - goto out; + wl1271_configure_filters(wl, FIF_OTHER_BSS); - wl1271_debug(DEBUG_CMD, "starting device role for roaming"); - ret = wl12xx_cmd_role_start_dev(wl); - if (ret < 0) - goto out; - - ret = wl12xx_roc(wl, wl->dev_role_id); - if (ret < 0) - goto out; -out: - return 0; + return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); } static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, @@ -126,29 +114,24 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) { bool fw_ps; - u8 tx_pkts; + u8 tx_blks; /* only regulate station links */ if (hlid < WL1271_AP_STA_HLID_START) return; fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); - tx_pkts = wl->links[hlid].allocated_pkts; + tx_blks = wl->links[hlid].allocated_blks; /* * if in FW PS and there is enough data in FW we can put the link * into high-level PS and clean out its TX queues. */ - if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) + if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS) wl1271_ps_link_start(wl, hlid, true); } -static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) -{ - return wl->dummy_packet == skb; -} - -u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) +u8 wl1271_tx_get_hlid(struct sk_buff *skb) { struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb); @@ -161,32 +144,14 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) } else { struct ieee80211_hdr *hdr; - if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) - return wl->system_hlid; - hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_mgmt(hdr->frame_control)) - return wl->ap_global_hlid; + return WL1271_AP_GLOBAL_HLID; else - return wl->ap_bcast_hlid; + return WL1271_AP_BROADCAST_HLID; } } -static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) -{ - if (wl12xx_is_dummy_packet(wl, skb)) - return wl->system_hlid; - - if (wl->bss_type == BSS_TYPE_AP_BSS) - return wl12xx_tx_get_hlid_ap(wl, skb); - - if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || - test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) - return wl->sta_hlid; - else - return wl->dev_hlid; -} - static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, unsigned int packet_length) { @@ -204,9 +169,12 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, u32 len; u32 total_blocks; int id, ret = -EBUSY, ac; + u32 spare_blocks; - /* we use 1 spare block */ - u32 spare_blocks = 1; + if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) + spare_blocks = 2; + else + spare_blocks = 1; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; @@ -238,14 +206,12 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, desc->id = id; wl->tx_blocks_available -= total_blocks; - wl->tx_allocated_blocks += total_blocks; ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); - wl->tx_allocated_pkts[ac]++; + wl->tx_allocated_blocks[ac] += total_blocks; - if (wl->bss_type == BSS_TYPE_AP_BSS && - hlid >= WL1271_AP_STA_HLID_START) - wl->links[hlid].allocated_pkts++; + if (wl->bss_type == BSS_TYPE_AP_BSS) + wl->links[hlid].allocated_blks += total_blocks; ret = 0; @@ -259,6 +225,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, return ret; } +static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) +{ + return wl->dummy_packet == skb; +} + static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, u32 extra, struct ieee80211_tx_info *control, u8 hlid) @@ -309,9 +280,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; } - desc->hlid = hlid; - if (wl->bss_type != BSS_TYPE_AP_BSS) { + desc->aid = hlid; + /* if the packets are destined for AP (have a STA entry) send them with AP rate policies, otherwise use default basic rates */ @@ -320,12 +291,18 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, else rate_idx = ACX_TX_BASIC_RATE; } else { - if (hlid == wl->ap_global_hlid) + desc->hlid = hlid; + switch (hlid) { + case WL1271_AP_GLOBAL_HLID: rate_idx = ACX_TX_AP_MODE_MGMT_RATE; - else if (hlid == wl->ap_bcast_hlid) + break; + case WL1271_AP_BROADCAST_HLID: rate_idx = ACX_TX_AP_MODE_BCST_RATE; - else + break; + default: rate_idx = ac; + break; + } } tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; @@ -399,11 +376,10 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, } } - hlid = wl1271_tx_get_hlid(wl, skb); - if (hlid == WL12XX_INVALID_LINK_ID) { - wl1271_error("invalid hlid. dropping skb 0x%p", skb); - return -EINVAL; - } + if (wl->bss_type == BSS_TYPE_AP_BSS) + hlid = wl1271_tx_get_hlid(skb); + else + hlid = TX_HW_DEFAULT_AID; ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid); if (ret < 0) @@ -486,24 +462,20 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl) static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, struct sk_buff_head *queues) { - int i, q = -1, ac; - u32 min_pkts = 0xffffffff; + int i, q = -1; + u32 min_blks = 0xffffffff; /* * Find a non-empty ac where: * 1. There are packets to transmit * 2. The FW has the least allocated blocks - * - * We prioritize the ACs according to VO>VI>BE>BK */ - for (i = 0; i < NUM_TX_QUEUES; i++) { - ac = wl1271_tx_get_queue(i); - if (!skb_queue_empty(&queues[ac]) && - (wl->tx_allocated_pkts[ac] < min_pkts)) { - q = ac; - min_pkts = wl->tx_allocated_pkts[q]; + for (i = 0; i < NUM_TX_QUEUES; i++) + if (!skb_queue_empty(&queues[i]) && + (wl->tx_allocated_blocks[i] < min_blks)) { + q = i; + min_blks = wl->tx_allocated_blocks[q]; } - } if (q == -1) return NULL; @@ -607,7 +579,7 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) if (wl12xx_is_dummy_packet(wl, skb)) { set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); } else if (wl->bss_type == BSS_TYPE_AP_BSS) { - u8 hlid = wl1271_tx_get_hlid(wl, skb); + u8 hlid = wl1271_tx_get_hlid(skb); skb_queue_head(&wl->links[hlid].tx_queue[q], skb); /* make sure we dequeue the same packet next time */ @@ -854,14 +826,10 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) total[i] = 0; while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) { wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb); - - if (!wl12xx_is_dummy_packet(wl, skb)) { - info = IEEE80211_SKB_CB(skb); - info->status.rates[0].idx = -1; - info->status.rates[0].count = 0; - ieee80211_tx_status_ni(wl->hw, skb); - } - + info = IEEE80211_SKB_CB(skb); + info->status.rates[0].idx = -1; + info->status.rates[0].count = 0; + ieee80211_tx_status_ni(wl->hw, skb); total[i]++; } } @@ -885,8 +853,8 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) if (wl->bss_type == BSS_TYPE_AP_BSS) { for (i = 0; i < AP_MAX_LINKS; i++) { wl1271_tx_reset_link_queues(wl, i); - wl->links[i].allocated_pkts = 0; - wl->links[i].prev_freed_pkts = 0; + wl->links[i].allocated_blks = 0; + wl->links[i].prev_freed_blks = 0; } wl->last_tx_hlid = 0; diff --git a/trunk/drivers/net/wireless/wl12xx/tx.h b/trunk/drivers/net/wireless/wl12xx/tx.h index 7da35c0e411b..5d719b5a3d1d 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.h +++ b/trunk/drivers/net/wireless/wl12xx/tx.h @@ -29,6 +29,9 @@ #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 #define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000 +/* The chipset reference driver states, that the "aid" value 1 + * is for infra-BSS, but is still always used */ +#define TX_HW_DEFAULT_AID 1 #define TX_HW_ATTR_SAVE_RETRIES BIT(0) #define TX_HW_ATTR_HEADER_PAD BIT(1) @@ -113,8 +116,12 @@ struct wl1271_tx_hw_descr { u8 id; /* The packet TID value (as User-Priority) */ u8 tid; - /* host link ID (HLID) */ - u8 hlid; + union { + /* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */ + u8 aid; + /* AP - host link ID (HLID) */ + u8 hlid; + } __packed; u8 reserved; } __packed; @@ -126,8 +133,7 @@ enum wl1271_tx_hw_res_status { TX_TIMEOUT = 4, TX_KEY_NOT_FOUND = 5, TX_PEER_NOT_FOUND = 6, - TX_SESSION_MISMATCH = 7, - TX_LINK_NOT_VALID = 8, + TX_SESSION_MISMATCH = 7 }; struct wl1271_tx_hw_res_descr { @@ -210,7 +216,7 @@ void wl1271_tx_flush(struct wl1271 *wl); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); u32 wl1271_tx_min_rate_get(struct wl1271 *wl); -u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb); +u8 wl1271_tx_get_hlid(struct sk_buff *skb); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_handle_tx_low_watermark(struct wl1271 *wl); diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/wl12xx/wl12xx.h index 61a7c2163ea2..0bc29356ebe4 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx.h @@ -112,8 +112,28 @@ extern u32 wl12xx_debug_level; true); \ } while (0) -#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" -#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" +#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN | \ + CFG_BSSID_FILTER_EN | \ + CFG_MC_FILTER_EN) + +#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \ + CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ + CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ + CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) + +#define WL1271_DEFAULT_AP_RX_CONFIG 0 + +#define WL1271_DEFAULT_AP_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \ + CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ + CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \ + CFG_RX_ASSOC_EN) + + + +#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin" +#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin" +#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin" +#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin" /* * wl127x and wl128x are using the same NVS file name. However, the @@ -137,34 +157,25 @@ extern u32 wl12xx_debug_level; #define WL1271_DEFAULT_BEACON_INT 100 #define WL1271_DEFAULT_DTIM_PERIOD 1 -#define WL12XX_MAX_ROLES 4 -#define WL12XX_MAX_LINKS 8 -#define WL12XX_INVALID_ROLE_ID 0xff -#define WL12XX_INVALID_LINK_ID 0xff - -/* Defined by FW as 0. Will not be freed or allocated. */ -#define WL12XX_SYSTEM_HLID 0 - -/* - * TODO: we currently don't support multirole. remove - * this constant from the code when we do. - */ -#define WL1271_AP_STA_HLID_START 3 +#define WL1271_AP_GLOBAL_HLID 0 +#define WL1271_AP_BROADCAST_HLID 1 +#define WL1271_AP_STA_HLID_START 2 /* - * When in AP-mode, we allow (at least) this number of packets + * When in AP-mode, we allow (at least) this number of mem-blocks * to be transmitted to FW for a STA in PS-mode. Only when packets are * present in the FW buffers it will wake the sleeping STA. We want to put * enough packets for the driver to transmit all of its buffered data before - * the STA goes to sleep again. But we don't want to take too much memory + * the STA goes to sleep again. But we don't want to take too much mem-blocks * as it might hurt the throughput of active STAs. + * The number of blocks (18) is enough for 2 large packets. */ -#define WL1271_PS_STA_MAX_PACKETS 2 +#define WL1271_PS_STA_MAX_BLOCKS (2 * 9) #define WL1271_AP_BSS_INDEX 0 #define WL1271_AP_DEF_BEACON_EXP 20 -#define ACX_TX_DESCRIPTORS 16 +#define ACX_TX_DESCRIPTORS 32 #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) @@ -236,22 +247,26 @@ struct wl1271_stats { #define AP_MAX_STATIONS 5 -/* Broadcast and Global links + system link + links to stations */ -/* - * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all - * the places that use this. - */ -#define AP_MAX_LINKS (AP_MAX_STATIONS + 3) +/* Broadcast and Global links + links to stations */ +#define AP_MAX_LINKS (AP_MAX_STATIONS + 2) -/* FW status registers */ -struct wl12xx_fw_status { +/* FW status registers common for AP/STA */ +struct wl1271_fw_common_status { __le32 intr; u8 fw_rx_counter; u8 drv_rx_counter; u8 reserved; u8 tx_results_counter; __le32 rx_pkt_descs[NUM_RX_PKT_DESC]; + __le32 tx_released_blks[NUM_TX_QUEUES]; __le32 fw_localtime; +} __packed; + +/* FW status registers for AP */ +struct wl1271_fw_ap_status { + struct wl1271_fw_common_status common; + + /* Next fields valid only in AP FW */ /* * A bitmap (where each bit represents a single HLID) @@ -259,30 +274,30 @@ struct wl12xx_fw_status { */ __le32 link_ps_bitmap; - /* - * A bitmap (where each bit represents a single HLID) to indicate - * if the station is in Fast mode - */ - __le32 link_fast_bitmap; - - /* Cumulative counter of total released mem blocks since FW-reset */ - __le32 total_released_blks; - - /* Size (in Memory Blocks) of TX pool */ - __le32 tx_total; - - /* Cumulative counter of released packets per AC */ - u8 tx_released_pkts[NUM_TX_QUEUES]; + /* Number of freed MBs per HLID */ + u8 tx_lnk_free_blks[AP_MAX_LINKS]; + u8 padding_1[1]; +} __packed; - /* Cumulative counter of freed packets per HLID */ - u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS]; +/* FW status registers for STA */ +struct wl1271_fw_sta_status { + struct wl1271_fw_common_status common; - /* Cumulative counter of released Voice memory blocks */ - u8 tx_voice_released_blks; - u8 padding_1[7]; + u8 tx_total; + u8 reserved1; + __le16 reserved2; __le32 log_start_addr; } __packed; +struct wl1271_fw_full_status { + union { + struct wl1271_fw_common_status common; + struct wl1271_fw_sta_status sta; + struct wl1271_fw_ap_status ap; + }; +} __packed; + + struct wl1271_rx_mem_pool_addr { u32 addr; u32 addr_extra; @@ -327,7 +342,7 @@ struct wl1271_ap_key { enum wl12xx_flags { WL1271_FLAG_STA_ASSOCIATED, - WL1271_FLAG_IBSS_JOINED, + WL1271_FLAG_JOINED, WL1271_FLAG_GPIO_POWER, WL1271_FLAG_TX_QUEUE_STOPPED, WL1271_FLAG_TX_PENDING, @@ -354,14 +369,11 @@ struct wl1271_link { /* AP-mode - TX queue per AC in link */ struct sk_buff_head tx_queue[NUM_TX_QUEUES]; - /* accounting for allocated / freed packets in FW */ - u8 allocated_pkts; - u8 prev_freed_pkts; + /* accounting for allocated / available TX blocks in FW */ + u8 allocated_blks; + u8 prev_freed_blks; u8 addr[ETH_ALEN]; - - /* bitmap of TIDs where RX BA sessions are active for this link */ - u8 ba_bitmap; }; struct wl1271 { @@ -393,6 +405,7 @@ struct wl1271 { u8 *fw; size_t fw_len; + u8 fw_bss_type; void *nvs; size_t nvs_len; @@ -405,30 +418,15 @@ struct wl1271 { u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 ssid_len; int channel; - u8 role_id; - u8 dev_role_id; - u8 system_hlid; - u8 sta_hlid; - u8 dev_hlid; - u8 ap_global_hlid; - u8 ap_bcast_hlid; - - unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; - unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; - unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; struct wl1271_acx_mem_map *target_mem_map; /* Accounting for allocated / available TX blocks on HW */ - u32 tx_blocks_freed; + u32 tx_blocks_freed[NUM_TX_QUEUES]; u32 tx_blocks_available; - u32 tx_allocated_blocks; + u32 tx_allocated_blocks[NUM_TX_QUEUES]; u32 tx_results_count; - /* Accounting for allocated / available Tx packets in HW */ - u32 tx_pkts_freed[NUM_TX_QUEUES]; - u32 tx_allocated_pkts[NUM_TX_QUEUES]; - /* Transmitted TX packets counter for chipset interface */ u32 tx_packets_count; @@ -537,6 +535,10 @@ struct wl1271 { struct work_struct rx_streaming_disable_work; struct timer_list rx_streaming_timer; + unsigned int filters; + unsigned int rx_config; + unsigned int rx_filter; + struct completion *elp_compl; struct completion *ps_compl; struct delayed_work elp_work; @@ -560,7 +562,7 @@ struct wl1271 { u32 buffer_cmd; u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; - struct wl12xx_fw_status *fw_status; + struct wl1271_fw_full_status *fw_status; struct wl1271_tx_hw_res_if *tx_res_if; struct ieee80211_vif *vif; @@ -620,9 +622,6 @@ struct wl1271 { /* Platform limitations */ unsigned int platform_quirks; - - /* number of currently active RX BA sessions */ - int ba_rx_session_count; }; struct wl1271_station { @@ -660,6 +659,12 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); /* Each RX/TX transaction requires an end-of-transaction transfer */ #define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) +/* + * Older firmwares use 2 spare TX blocks + * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47) + */ +#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1) + /* WL128X requires aggregated packets to be aligned to the SDIO block size */ #define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h b/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h index f7971d3b0898..f334ea081722 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -105,6 +105,18 @@ struct wl12xx_ie_country { /* Templates */ +struct wl12xx_beacon_template { + struct ieee80211_header header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; + struct wl12xx_ie_ds_params ds_params; + struct wl12xx_ie_country country; +} __packed; + struct wl12xx_null_data_template { struct ieee80211_header header; } __packed; @@ -134,6 +146,19 @@ struct wl12xx_arp_rsp_template { __be32 target_ip; } __packed; + +struct wl12xx_probe_resp_template { + struct ieee80211_header header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; + struct wl12xx_ie_ds_params ds_params; + struct wl12xx_ie_country country; +} __packed; + struct wl12xx_disconn_template { struct ieee80211_header header; __le16 disconn_reason; diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index eb2659aefd97..88112ca59c8e 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -1792,7 +1792,6 @@ struct wiphy_wowlan_support { * @debugfsdir: debugfs directory used for this wiphy, will be renamed * automatically on wiphy renames * @dev: (virtual) struct device for this wiphy - * @registered: helps synchronize suspend/resume with wiphy unregister * @wext: wireless extension handlers * @priv: driver private data (sized according to wiphy_new() parameter) * @interface_modes: bitmask of interfaces types valid for this wiphy, diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index 267ed45ef6a2..186e02f7cc32 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -195,12 +195,20 @@ static ssize_t uapsd_queues_write(struct file *file, size_t count, loff_t *ppos) { struct ieee80211_local *local = file->private_data; - u8 val; + unsigned long val; + char buf[10]; + size_t len; int ret; - ret = kstrtou8_from_user(user_buf, count, 0, &val); + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + ret = strict_strtoul(buf, 0, &val); + if (ret) - return ret; + return -EINVAL; if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) return -ERANGE; diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c index f97d17cb073c..7fde32159fdc 100644 --- a/trunk/net/mac80211/mesh_pathtbl.c +++ b/trunk/net/mac80211/mesh_pathtbl.c @@ -307,14 +307,14 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, while (num_skbs--) { skb = __skb_dequeue(&failq); - if (copy) { + if (copy) cp_skb = skb_copy(skb, GFP_ATOMIC); - if (cp_skb) - __skb_queue_tail(&failq, cp_skb); - } prepare_for_gate(skb, gate_mpath->dst, gate_mpath); __skb_queue_tail(&gateq, skb); + + if (copy && cp_skb) + __skb_queue_tail(&failq, cp_skb); } spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags);