Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / iwlegacy / 4965-mac.c
index c3fbf6717564a3295ea2a87ecdc669e80d2e9d89..6affa7e8f017e830c9ac96a403182aa4bb215e8e 100644 (file)
@@ -319,6 +319,7 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
        struct list_head *element;
        struct il_rx_buf *rxb;
        struct page *page;
+       dma_addr_t page_dma;
        unsigned long flags;
        gfp_t gfp_mask = priority;
 
@@ -356,33 +357,35 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
                        return;
                }
 
+               /* Get physical address of the RB */
+               page_dma =
+                   pci_map_page(il->pci_dev, page, 0,
+                                PAGE_SIZE << il->hw_params.rx_page_order,
+                                PCI_DMA_FROMDEVICE);
+               if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) {
+                       __free_pages(page, il->hw_params.rx_page_order);
+                       break;
+               }
+
                spin_lock_irqsave(&rxq->lock, flags);
 
                if (list_empty(&rxq->rx_used)) {
                        spin_unlock_irqrestore(&rxq->lock, flags);
+                       pci_unmap_page(il->pci_dev, page_dma,
+                                      PAGE_SIZE << il->hw_params.rx_page_order,
+                                      PCI_DMA_FROMDEVICE);
                        __free_pages(page, il->hw_params.rx_page_order);
                        return;
                }
+
                element = rxq->rx_used.next;
                rxb = list_entry(element, struct il_rx_buf, list);
                list_del(element);
 
-               spin_unlock_irqrestore(&rxq->lock, flags);
-
                BUG_ON(rxb->page);
-               rxb->page = page;
-               /* Get physical address of the RB */
-               rxb->page_dma =
-                   pci_map_page(il->pci_dev, page, 0,
-                                PAGE_SIZE << il->hw_params.rx_page_order,
-                                PCI_DMA_FROMDEVICE);
-               /* dma address must be no more than 36 bits */
-               BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
-               /* and also 256 byte aligned! */
-               BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
-
-               spin_lock_irqsave(&rxq->lock, flags);
 
+               rxb->page = page;
+               rxb->page_dma = page_dma;
                list_add_tail(&rxb->list, &rxq->rx_free);
                rxq->free_count++;
                il->alloc_rxb_page++;
@@ -609,7 +612,7 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
 
 /* Called for N_RX (legacy ABG frames), or
  * N_RX_MPDU (HT high-throughput N frames). */
-void
+static void
 il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
 {
        struct ieee80211_hdr *header;
@@ -725,17 +728,28 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
        if (rate_n_flags & RATE_MCS_SGI_MSK)
                rx_status.flag |= RX_FLAG_SHORT_GI;
 
+       if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) {
+               /* We know which subframes of an A-MPDU belong
+                * together since we get a single PHY response
+                * from the firmware for all of them.
+                */
+
+               rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
+               rx_status.ampdu_reference = il->_4965.ampdu_ref;
+       }
+
        il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb,
                                       &rx_status);
 }
 
 /* Cache phy data (Rx signal strength, etc) for HT frame (N_RX_PHY).
  * This will be used later in il_hdl_rx() for N_RX_MPDU. */
-void
+static void
 il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
 {
        struct il_rx_pkt *pkt = rxb_addr(rxb);
        il->_4965.last_phy_res_valid = true;
+       il->_4965.ampdu_ref++;
        memcpy(&il->_4965.last_phy_res, pkt->u.raw,
               sizeof(struct il_rx_phy_res));
 }
@@ -1236,7 +1250,7 @@ il4965_dump_fh(struct il_priv *il, char **buf, bool display)
        return 0;
 }
 
-void
+static void
 il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb)
 {
        struct il_rx_pkt *pkt = rxb_addr(rxb);
@@ -1343,7 +1357,7 @@ il4965_accumulative_stats(struct il_priv *il, __le32 * stats)
 }
 #endif
 
-void
+static void
 il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
 {
        const int recalib_seconds = 60;
@@ -1385,7 +1399,7 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb)
                il4965_temperature_calib(il);
 }
 
-void
+static void
 il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb)
 {
        struct il_rx_pkt *pkt = rxb_addr(rxb);
@@ -1779,8 +1793,7 @@ il4965_tx_skb(struct il_priv *il,
        memcpy(tx_cmd->hdr, hdr, hdr_len);
 
        /* Total # bytes to be transmitted */
-       len = (u16) skb->len;
-       tx_cmd->len = cpu_to_le16(len);
+       tx_cmd->len = cpu_to_le16((u16) skb->len);
 
        if (info->control.hw_key)
                il4965_tx_cmd_build_hwcrypto(il, info, tx_cmd, skb, sta_id);
@@ -1790,7 +1803,6 @@ il4965_tx_skb(struct il_priv *il,
 
        il4965_tx_cmd_build_rate(il, tx_cmd, info, sta, fc);
 
-       il_update_stats(il, true, fc, len);
        /*
         * Use the first empty entry in this queue's command buffer array
         * to contain the Tx command and MAC header concatenated together
@@ -1812,18 +1824,8 @@ il4965_tx_skb(struct il_priv *il,
        txcmd_phys =
            pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen,
                           PCI_DMA_BIDIRECTIONAL);
-       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-       dma_unmap_len_set(out_meta, len, firstlen);
-       /* Add buffer containing Tx command and MAC(!) header to TFD's
-        * first entry */
-       il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0);
-
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
-               txq->need_update = 1;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
+       if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys)))
+               goto drop_unlock;
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
         * if any (802.11 null frames have no payload). */
@@ -1832,8 +1834,24 @@ il4965_tx_skb(struct il_priv *il,
                phys_addr =
                    pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen,
                                   PCI_DMA_TODEVICE);
+               if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr)))
+                       goto drop_unlock;
+       }
+
+       /* Add buffer containing Tx command and MAC(!) header to TFD's
+        * first entry */
+       il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0);
+       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+       dma_unmap_len_set(out_meta, len, firstlen);
+       if (secondlen)
                il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen,
                                               0, 0);
+
+       if (!ieee80211_has_morefrags(hdr->frame_control)) {
+               txq->need_update = 1;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
        }
 
        scratch_phys =
@@ -1846,6 +1864,8 @@ il4965_tx_skb(struct il_priv *il,
        tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
        tx_cmd->dram_msb_ptr = il_get_dma_hi_addr(scratch_phys);
 
+       il_update_stats(il, true, fc, skb->len);
+
        D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
        D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
        il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd, sizeof(*tx_cmd));
@@ -1901,8 +1921,8 @@ drop_unlock:
 static inline int
 il4965_alloc_dma_ptr(struct il_priv *il, struct il_dma_ptr *ptr, size_t size)
 {
-       ptr->addr =
-           dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma, GFP_KERNEL);
+       ptr->addr = dma_alloc_coherent(&il->pci_dev->dev, size, &ptr->dma,
+                                      GFP_KERNEL);
        if (!ptr->addr)
                return -ENOMEM;
        ptr->size = size;
@@ -2030,7 +2050,7 @@ il4965_txq_ctx_reset(struct il_priv *il)
                il_tx_queue_reset(il, txq_id);
 }
 
-void
+static void
 il4965_txq_ctx_unmap(struct il_priv *il)
 {
        int txq_id;
@@ -2238,7 +2258,7 @@ il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif,
 
        spin_lock_irqsave(&il->sta_lock, flags);
        tid_data = &il->stations[sta_id].tid[tid];
-       *ssn = SEQ_TO_SN(tid_data->seq_number);
+       *ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
        tid_data->agg.txq_id = txq_id;
        il_set_swq_id(&il->txq[txq_id], il4965_get_ac_from_tid(tid), txq_id);
        spin_unlock_irqrestore(&il->sta_lock, flags);
@@ -2388,7 +2408,7 @@ il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id)
                /* 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);
+                       u16 ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
                        int tx_fifo = il4965_get_fifo_from_tid(tid);
                        D_HT("HW queue empty: continue DELBA flow\n");
                        il4965_txq_agg_disable(il, txq_id, ssn, tx_fifo);
@@ -2607,7 +2627,8 @@ il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr)
 static inline u32
 il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp)
 {
-       return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
+       return le32_to_cpup(&tx_resp->u.status +
+                           tx_resp->frame_count) & IEEE80211_MAX_SN;
 }
 
 static inline u32
@@ -2697,15 +2718,15 @@ il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg,
                        hdr = (struct ieee80211_hdr *) skb->data;
 
                        sc = le16_to_cpu(hdr->seq_ctrl);
-                       if (idx != (SEQ_TO_SN(sc) & 0xff)) {
+                       if (idx != (IEEE80211_SEQ_TO_SN(sc) & 0xff)) {
                                IL_ERR("BUG_ON idx doesn't match seq control"
                                       " idx=%d, seq_idx=%d, seq=%d\n", idx,
-                                      SEQ_TO_SN(sc), hdr->seq_ctrl);
+                                      IEEE80211_SEQ_TO_SN(sc), hdr->seq_ctrl);
                                return -1;
                        }
 
                        D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx,
-                                  SEQ_TO_SN(sc));
+                                  IEEE80211_SEQ_TO_SN(sc));
 
                        sh = idx - start;
                        if (sh > 64) {
@@ -2875,7 +2896,7 @@ il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags,
  * Handles block-acknowledge notification from device, which reports success
  * of frames sent via aggregation.
  */
-void
+static void
 il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb)
 {
        struct il_rx_pkt *pkt = rxb_addr(rxb);
@@ -4281,8 +4302,16 @@ il4965_rx_handle(struct il_priv *il)
                            pci_map_page(il->pci_dev, rxb->page, 0,
                                         PAGE_SIZE << il->hw_params.
                                         rx_page_order, PCI_DMA_FROMDEVICE);
-                       list_add_tail(&rxb->list, &rxq->rx_free);
-                       rxq->free_count++;
+
+                       if (unlikely(pci_dma_mapping_error(il->pci_dev,
+                                                          rxb->page_dma))) {
+                               __il_free_pages(il, rxb->page);
+                               rxb->page = NULL;
+                               list_add_tail(&rxb->list, &rxq->rx_used);
+                       } else {
+                               list_add_tail(&rxb->list, &rxq->rx_free);
+                               rxq->free_count++;
+                       }
                } else
                        list_add_tail(&rxb->list, &rxq->rx_used);
 
@@ -5711,9 +5740,9 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
        /* Tell mac80211 our characteristics */
        hw->flags =
            IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
-           IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT |
-           IEEE80211_HW_REPORTS_TX_ACK_STATUS;
-
+           IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT |
+           IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS |
+           IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
        if (il->cfg->sku & IL_SKU_N)
                hw->flags |=
                    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
@@ -5968,7 +5997,9 @@ il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                D_HT("start Tx\n");
                ret = il4965_tx_agg_start(il, vif, sta, tid, ssn);
                break;
-       case IEEE80211_AMPDU_TX_STOP:
+       case IEEE80211_AMPDU_TX_STOP_CONT:
+       case IEEE80211_AMPDU_TX_STOP_FLUSH:
+       case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
                D_HT("stop Tx\n");
                ret = il4965_tx_agg_stop(il, vif, sta, tid);
                if (test_bit(S_EXIT_PENDING, &il->status))
@@ -6286,7 +6317,7 @@ il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq,
               scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
 }
 
-const struct ieee80211_ops il4965_mac_ops = {
+static const struct ieee80211_ops il4965_mac_ops = {
        .tx = il4965_mac_tx,
        .start = il4965_mac_start,
        .stop = il4965_mac_stop,
@@ -6306,6 +6337,7 @@ const struct ieee80211_ops il4965_mac_ops = {
        .sta_remove = il_mac_sta_remove,
        .channel_switch = il4965_mac_channel_switch,
        .tx_last_beacon = il_mac_tx_last_beacon,
+       .flush = il_mac_flush,
 };
 
 static int
@@ -6553,6 +6585,7 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        il4965_prepare_card_hw(il);
        if (!il->hw_ready) {
                IL_WARN("Failed, HW not ready\n");
+               err = -EIO;
                goto out_iounmap;
        }
 
@@ -6569,9 +6602,6 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto out_free_eeprom;
 
-       if (err)
-               goto out_free_eeprom;
-
        /* extract MAC Address */
        il4965_eeprom_get_mac(il, il->addresses[0].addr);
        D_INFO("MAC address: %pM\n", il->addresses[0].addr);