enic: add support for set/get rss hash key
[cascardo/linux.git] / drivers / net / ethernet / cisco / enic / enic_main.c
index 73cf165..868d0f6 100644 (file)
@@ -283,12 +283,10 @@ static irqreturn_t enic_isr_legacy(int irq, void *data)
                return IRQ_HANDLED;
        }
 
-       if (ENIC_TEST_INTR(pba, io_intr)) {
-               if (napi_schedule_prep(&enic->napi[0]))
-                       __napi_schedule(&enic->napi[0]);
-       } else {
+       if (ENIC_TEST_INTR(pba, io_intr))
+               napi_schedule_irqoff(&enic->napi[0]);
+       else
                vnic_intr_unmask(&enic->intr[io_intr]);
-       }
 
        return IRQ_HANDLED;
 }
@@ -313,7 +311,7 @@ static irqreturn_t enic_isr_msi(int irq, void *data)
         * writes).
         */
 
-       napi_schedule(&enic->napi[0]);
+       napi_schedule_irqoff(&enic->napi[0]);
 
        return IRQ_HANDLED;
 }
@@ -322,7 +320,7 @@ static irqreturn_t enic_isr_msix(int irq, void *data)
 {
        struct napi_struct *napi = data;
 
-       napi_schedule(napi);
+       napi_schedule_irqoff(napi);
 
        return IRQ_HANDLED;
 }
@@ -531,8 +529,8 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
 {
        struct enic *enic = netdev_priv(netdev);
        struct vnic_wq *wq;
-       unsigned long flags;
        unsigned int txq_map;
+       struct netdev_queue *txq;
 
        if (skb->len <= 0) {
                dev_kfree_skb_any(skb);
@@ -541,6 +539,7 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
 
        txq_map = skb_get_queue_mapping(skb) % enic->wq_count;
        wq = &enic->wq[txq_map];
+       txq = netdev_get_tx_queue(netdev, txq_map);
 
        /* Non-TSO sends must fit within ENIC_NON_TSO_MAX_DESC descs,
         * which is very likely.  In the off chance it's going to take
@@ -554,23 +553,25 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
-       spin_lock_irqsave(&enic->wq_lock[txq_map], flags);
+       spin_lock(&enic->wq_lock[txq_map]);
 
        if (vnic_wq_desc_avail(wq) <
            skb_shinfo(skb)->nr_frags + ENIC_DESC_MAX_SPLITS) {
-               netif_tx_stop_queue(netdev_get_tx_queue(netdev, txq_map));
+               netif_tx_stop_queue(txq);
                /* This is a hard error, log it */
                netdev_err(netdev, "BUG! Tx ring full when queue awake!\n");
-               spin_unlock_irqrestore(&enic->wq_lock[txq_map], flags);
+               spin_unlock(&enic->wq_lock[txq_map]);
                return NETDEV_TX_BUSY;
        }
 
        enic_queue_wq_skb(enic, wq, skb);
 
        if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)
-               netif_tx_stop_queue(netdev_get_tx_queue(netdev, txq_map));
+               netif_tx_stop_queue(txq);
+       if (!skb->xmit_more || netif_xmit_stopped(txq))
+               vnic_wq_doorbell(wq);
 
-       spin_unlock_irqrestore(&enic->wq_lock[txq_map], flags);
+       spin_unlock(&enic->wq_lock[txq_map]);
 
        return NETDEV_TX_OK;
 }
@@ -1312,9 +1313,10 @@ static int enic_poll_msix_wq(struct napi_struct *napi, int budget)
        if (!wq_work_done) {
                napi_complete(napi);
                vnic_intr_unmask(&enic->intr[intr]);
+               return 0;
        }
 
-       return 0;
+       return budget;
 }
 
 static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
@@ -1886,25 +1888,23 @@ static int enic_dev_hang_reset(struct enic *enic)
        return err;
 }
 
-static int enic_set_rsskey(struct enic *enic)
+int __enic_set_rsskey(struct enic *enic)
 {
+       union vnic_rss_key *rss_key_buf_va;
        dma_addr_t rss_key_buf_pa;
-       union vnic_rss_key *rss_key_buf_va = NULL;
-       union vnic_rss_key rss_key = {
-               .key[0].b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101},
-               .key[1].b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101},
-               .key[2].b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115},
-               .key[3].b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108},
-       };
-       int err;
+       int i, kidx, bidx, err;
 
-       rss_key_buf_va = pci_alloc_consistent(enic->pdev,
-               sizeof(union vnic_rss_key), &rss_key_buf_pa);
+       rss_key_buf_va = pci_zalloc_consistent(enic->pdev,
+                                              sizeof(union vnic_rss_key),
+                                              &rss_key_buf_pa);
        if (!rss_key_buf_va)
                return -ENOMEM;
 
-       memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key));
-
+       for (i = 0; i < ENIC_RSS_LEN; i++) {
+               kidx = i / ENIC_RSS_BYTES_PER_KEY;
+               bidx = i % ENIC_RSS_BYTES_PER_KEY;
+               rss_key_buf_va->key[kidx].b[bidx] = enic->rss_key[i];
+       }
        spin_lock_bh(&enic->devcmd_lock);
        err = enic_set_rss_key(enic,
                rss_key_buf_pa,
@@ -1917,6 +1917,13 @@ static int enic_set_rsskey(struct enic *enic)
        return err;
 }
 
+static int enic_set_rsskey(struct enic *enic)
+{
+       netdev_rss_key_fill(enic->rss_key, ENIC_RSS_LEN);
+
+       return __enic_set_rsskey(enic);
+}
+
 static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
 {
        dma_addr_t rss_cpu_buf_pa;