Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / chelsio / cxgb4 / sge.c
index e0cfce88890fb17f48a92615feafc6a030299f85..0d2eddab04efbf7b2a0e1054ea46848273c97933 100644 (file)
@@ -592,8 +592,10 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n,
        unsigned int cred = q->avail;
        __be64 *d = &q->desc[q->pidx];
        struct rx_sw_desc *sd = &q->sdesc[q->pidx];
+       int node;
 
        gfp |= __GFP_NOWARN;
+       node = dev_to_node(adap->pdev_dev);
 
        if (s->fl_pg_order == 0)
                goto alloc_small_pages;
@@ -602,7 +604,7 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n,
         * Prefer large buffers
         */
        while (n) {
-               pg = __dev_alloc_pages(gfp, s->fl_pg_order);
+               pg = alloc_pages_node(node, gfp | __GFP_COMP, s->fl_pg_order);
                if (unlikely(!pg)) {
                        q->large_alloc_failed++;
                        break;       /* fall back to single pages */
@@ -632,7 +634,7 @@ static unsigned int refill_fl(struct adapter *adap, struct sge_fl *q, int n,
 
 alloc_small_pages:
        while (n--) {
-               pg = __dev_alloc_page(gfp);
+               pg = alloc_pages_node(node, gfp, 0);
                if (unlikely(!pg)) {
                        q->alloc_failed++;
                        break;
@@ -728,6 +730,22 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
  */
 static inline unsigned int sgl_len(unsigned int n)
 {
+       /* A Direct Scatter Gather List uses 32-bit lengths and 64-bit PCI DMA
+        * addresses.  The DSGL Work Request starts off with a 32-bit DSGL
+        * ULPTX header, then Length0, then Address0, then, for 1 <= i <= N,
+        * repeated sequences of { Length[i], Length[i+1], Address[i],
+        * Address[i+1] } (this ensures that all addresses are on 64-bit
+        * boundaries).  If N is even, then Length[N+1] should be set to 0 and
+        * Address[N+1] is omitted.
+        *
+        * The following calculation incorporates all of the above.  It's
+        * somewhat hard to follow but, briefly: the "+2" accounts for the
+        * first two flits which include the DSGL header, Length0 and
+        * Address0; the "(3*(n-1))/2" covers the main body of list entries (3
+        * flits for every pair of the remaining N) +1 if (n-1) is odd; and
+        * finally the "+((n-1)&1)" adds the one remaining flit needed if
+        * (n-1) is odd ...
+        */
        n--;
        return (3 * n) / 2 + (n & 1) + 2;
 }
@@ -775,12 +793,30 @@ static inline unsigned int calc_tx_flits(const struct sk_buff *skb)
        unsigned int flits;
        int hdrlen = is_eth_imm(skb);
 
+       /* If the skb is small enough, we can pump it out as a work request
+        * with only immediate data.  In that case we just have to have the
+        * TX Packet header plus the skb data in the Work Request.
+        */
+
        if (hdrlen)
                return DIV_ROUND_UP(skb->len + hdrlen, sizeof(__be64));
 
+       /* Otherwise, we're going to have to construct a Scatter gather list
+        * of the skb body and fragments.  We also include the flits necessary
+        * for the TX Packet Work Request and CPL.  We always have a firmware
+        * Write Header (incorporated as part of the cpl_tx_pkt_lso and
+        * cpl_tx_pkt structures), followed by either a TX Packet Write CPL
+        * message or, if we're doing a Large Send Offload, an LSO CPL message
+        * with an embedded TX Packet Write CPL message.
+        */
        flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 4;
        if (skb_shinfo(skb)->gso_size)
-               flits += 2;
+               flits += (sizeof(struct fw_eth_tx_pkt_wr) +
+                         sizeof(struct cpl_tx_pkt_lso_core) +
+                         sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
+       else
+               flits += (sizeof(struct fw_eth_tx_pkt_wr) +
+                         sizeof(struct cpl_tx_pkt_core)) / sizeof(__be64);
        return flits;
 }
 
@@ -2202,7 +2238,8 @@ static irqreturn_t t4_intr_msi(int irq, void *cookie)
 {
        struct adapter *adap = cookie;
 
-       t4_slow_intr_handler(adap);
+       if (adap->flags & MASTER_PF)
+               t4_slow_intr_handler(adap);
        process_intrq(adap);
        return IRQ_HANDLED;
 }
@@ -2217,7 +2254,8 @@ static irqreturn_t t4_intr_intx(int irq, void *cookie)
        struct adapter *adap = cookie;
 
        t4_write_reg(adap, MYPF_REG(PCIE_PF_CLI_A), 0);
-       if (t4_slow_intr_handler(adap) | process_intrq(adap))
+       if (((adap->flags & MASTER_PF) && t4_slow_intr_handler(adap)) |
+           process_intrq(adap))
                return IRQ_HANDLED;
        return IRQ_NONE;             /* probably shared interrupt */
 }