bna: Implement FW Download for New HW
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / brocade / bna / bnad.c
index 32df3a8bf59338265c288ff1eab4af63d5ee89b4..320f11c76e149e66244b04b940032a21eea75897 100644 (file)
@@ -137,39 +137,20 @@ bnad_free_all_txbufs(struct bnad *bnad,
        struct bnad_unmap_q *unmap_q = tcb->unmap_q;
        struct bnad_skb_unmap *unmap_array;
        struct sk_buff          *skb = NULL;
-       int                     i;
+       int                     q;
 
        unmap_array = unmap_q->unmap_array;
 
-       unmap_cons = 0;
-       while (unmap_cons < unmap_q->q_depth) {
-               skb = unmap_array[unmap_cons].skb;
-               if (!skb) {
-                       unmap_cons++;
+       for (q = 0; q < unmap_q->q_depth; q++) {
+               skb = unmap_array[q].skb;
+               if (!skb)
                        continue;
-               }
-               unmap_array[unmap_cons].skb = NULL;
-
-               dma_unmap_single(&bnad->pcidev->dev,
-                                dma_unmap_addr(&unmap_array[unmap_cons],
-                                               dma_addr), skb_headlen(skb),
-                                               DMA_TO_DEVICE);
 
-               dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
-               if (++unmap_cons >= unmap_q->q_depth)
-                       break;
+               unmap_cons = q;
+               unmap_cons = bnad_pci_unmap_skb(&bnad->pcidev->dev, unmap_array,
+                               unmap_cons, unmap_q->q_depth, skb,
+                               skb_shinfo(skb)->nr_frags);
 
-               for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-                       dma_unmap_page(&bnad->pcidev->dev,
-                                      dma_unmap_addr(&unmap_array[unmap_cons],
-                                                     dma_addr),
-                                      skb_shinfo(skb)->frags[i].size,
-                                      DMA_TO_DEVICE);
-                       dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
-                                          0);
-                       if (++unmap_cons >= unmap_q->q_depth)
-                               break;
-               }
                dev_kfree_skb_any(skb);
        }
 }
@@ -393,6 +374,7 @@ bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
                                                rcb->rxq->buffer_size);
                if (unlikely(!skb)) {
                        BNAD_UPDATE_CTR(bnad, rxbuf_alloc_failed);
+                       rcb->rxq->rxbuf_alloc_failed++;
                        goto finishing;
                }
                unmap_array[unmap_prod].skb = skb;
@@ -585,10 +567,11 @@ bnad_msix_mbox_handler(int irq, void *data)
        unsigned long flags;
        struct bnad *bnad = (struct bnad *)data;
 
-       if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
-               return IRQ_HANDLED;
-
        spin_lock_irqsave(&bnad->bna_lock, flags);
+       if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))) {
+               spin_unlock_irqrestore(&bnad->bna_lock, flags);
+               return IRQ_HANDLED;
+       }
 
        bna_intr_status_get(&bnad->bna, intr_status);
 
@@ -611,15 +594,18 @@ bnad_isr(int irq, void *data)
        struct bnad_rx_ctrl *rx_ctrl;
        struct bna_tcb *tcb = NULL;
 
-       if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags)))
+       spin_lock_irqsave(&bnad->bna_lock, flags);
+       if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))) {
+               spin_unlock_irqrestore(&bnad->bna_lock, flags);
                return IRQ_NONE;
+       }
 
        bna_intr_status_get(&bnad->bna, intr_status);
 
-       if (unlikely(!intr_status))
+       if (unlikely(!intr_status)) {
+               spin_unlock_irqrestore(&bnad->bna_lock, flags);
                return IRQ_NONE;
-
-       spin_lock_irqsave(&bnad->bna_lock, flags);
+       }
 
        if (BNA_IS_MBOX_ERR_INTR(&bnad->bna, intr_status))
                bna_mbox_handler(&bnad->bna, intr_status);
@@ -1744,7 +1730,14 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
        struct bna_intr_info *intr_info =
                        &res_info[BNA_TX_RES_INTR_T_TXCMPL].res_u.intr_info;
        struct bna_tx_config *tx_config = &bnad->tx_config[tx_id];
-       struct bna_tx_event_cbfn tx_cbfn;
+       static const struct bna_tx_event_cbfn tx_cbfn = {
+               .tcb_setup_cbfn = bnad_cb_tcb_setup,
+               .tcb_destroy_cbfn = bnad_cb_tcb_destroy,
+               .tx_stall_cbfn = bnad_cb_tx_stall,
+               .tx_resume_cbfn = bnad_cb_tx_resume,
+               .tx_cleanup_cbfn = bnad_cb_tx_cleanup,
+       };
+
        struct bna_tx *tx;
        unsigned long flags;
 
@@ -1756,13 +1749,6 @@ bnad_setup_tx(struct bnad *bnad, u32 tx_id)
        tx_config->tx_type = BNA_TX_T_REGULAR;
        tx_config->coalescing_timeo = bnad->tx_coalescing_timeo;
 
-       /* Initialize the tx event handlers */
-       tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup;
-       tx_cbfn.tcb_destroy_cbfn = bnad_cb_tcb_destroy;
-       tx_cbfn.tx_stall_cbfn = bnad_cb_tx_stall;
-       tx_cbfn.tx_resume_cbfn = bnad_cb_tx_resume;
-       tx_cbfn.tx_cleanup_cbfn = bnad_cb_tx_cleanup;
-
        /* Get BNA's resource requirement for one tx object */
        spin_lock_irqsave(&bnad->bna_lock, flags);
        bna_tx_res_req(bnad->num_txq_per_tx,
@@ -1889,9 +1875,10 @@ bnad_cleanup_rx(struct bnad *bnad, u32 rx_id)
 
        spin_lock_irqsave(&bnad->bna_lock, flags);
        bna_rx_destroy(rx_info->rx);
-       spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        rx_info->rx = NULL;
+       rx_info->rx_id = 0;
+       spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        bnad_rx_res_free(bnad, res_info);
 }
@@ -1906,7 +1893,14 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
        struct bna_intr_info *intr_info =
                        &res_info[BNA_RX_RES_T_INTR].res_u.intr_info;
        struct bna_rx_config *rx_config = &bnad->rx_config[rx_id];
-       struct bna_rx_event_cbfn rx_cbfn;
+       static const struct bna_rx_event_cbfn rx_cbfn = {
+               .rcb_setup_cbfn = bnad_cb_rcb_setup,
+               .rcb_destroy_cbfn = bnad_cb_rcb_destroy,
+               .ccb_setup_cbfn = bnad_cb_ccb_setup,
+               .ccb_destroy_cbfn = bnad_cb_ccb_destroy,
+               .rx_cleanup_cbfn = bnad_cb_rx_cleanup,
+               .rx_post_cbfn = bnad_cb_rx_post,
+       };
        struct bna_rx *rx;
        unsigned long flags;
 
@@ -1915,14 +1909,6 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
        /* Initialize the Rx object configuration */
        bnad_init_rx_config(bnad, rx_config);
 
-       /* Initialize the Rx event handlers */
-       rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
-       rx_cbfn.rcb_destroy_cbfn = bnad_cb_rcb_destroy;
-       rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
-       rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
-       rx_cbfn.rx_cleanup_cbfn = bnad_cb_rx_cleanup;
-       rx_cbfn.rx_post_cbfn = bnad_cb_rx_post;
-
        /* Get BNA's resource requirement for one Rx object */
        spin_lock_irqsave(&bnad->bna_lock, flags);
        bna_rx_res_req(rx_config, res_info);
@@ -1946,10 +1932,13 @@ bnad_setup_rx(struct bnad *bnad, u32 rx_id)
        spin_lock_irqsave(&bnad->bna_lock, flags);
        rx = bna_rx_create(&bnad->bna, bnad, rx_config, &rx_cbfn, res_info,
                        rx_info);
-       spin_unlock_irqrestore(&bnad->bna_lock, flags);
-       if (!rx)
+       if (!rx) {
+               err = -ENOMEM;
+               spin_unlock_irqrestore(&bnad->bna_lock, flags);
                goto err_return;
+       }
        rx_info->rx = rx;
+       spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
        /*
         * Init NAPI, so that state is set to NAPI_STATE_SCHED,
@@ -2023,7 +2012,7 @@ bnad_rx_coalescing_timeo_set(struct bnad *bnad)
 /*
  * Called with bnad->bna_lock held
  */
-static int
+int
 bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
 {
        int ret;
@@ -2043,7 +2032,7 @@ bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr)
 }
 
 /* Should be called with conf_lock held */
-static int
+int
 bnad_enable_default_bcast(struct bnad *bnad)
 {
        struct bnad_rx_info *rx_info = &bnad->rx_info[0];
@@ -2069,7 +2058,7 @@ bnad_enable_default_bcast(struct bnad *bnad)
 }
 
 /* Called with mutex_lock(&bnad->conf_mutex) held */
-static void
+void
 bnad_restore_vlans(struct bnad *bnad, u32 rx_id)
 {
        u16 vid;
@@ -2764,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 = dma_map_page(&bnad->pcidev->dev, frag->page,
-                                       frag->page_offset, size, DMA_TO_DEVICE);
+               dma_addr = skb_frag_dma_map(&bnad->pcidev->dev, frag,
+                                           0, 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);
@@ -2822,7 +2811,7 @@ bnad_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
        return stats;
 }
 
-static void
+void
 bnad_set_rx_mode(struct net_device *netdev)
 {
        struct bnad *bnad = netdev_priv(netdev);
@@ -3206,7 +3195,7 @@ static int __devinit
 bnad_pci_probe(struct pci_dev *pdev,
                const struct pci_device_id *pcidev_id)
 {
-       bool    using_dac = false;
+       bool    using_dac;
        int     err;
        struct bnad *bnad;
        struct bna *bna;
@@ -3329,6 +3318,11 @@ bnad_pci_probe(struct pci_dev *pdev,
                        bna_num_rxp_set(bna, BNAD_NUM_RXP + 1))
                        err = -EIO;
        }
+       spin_unlock_irqrestore(&bnad->bna_lock, flags);
+       if (err)
+               goto disable_ioceth;
+
+       spin_lock_irqsave(&bnad->bna_lock, flags);
        bna_mod_res_req(&bnad->bna, &bnad->mod_res_info[0]);
        spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
@@ -3365,6 +3359,7 @@ probe_success:
        return 0;
 
 probe_uninit:
+       mutex_lock(&bnad->conf_mutex);
        bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX);
 disable_ioceth:
        bnad_ioceth_disable(bnad);
@@ -3482,3 +3477,4 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Brocade 10G PCIe Ethernet driver");
 MODULE_VERSION(BNAD_VERSION);
 MODULE_FIRMWARE(CNA_FW_FILE_CT);
+MODULE_FIRMWARE(CNA_FW_FILE_CT2);