8139cp: Fix TSO/scatter-gather descriptor setup
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / realtek / 8139cp.c
index d79e33b3c1913ae41caa046860fc74fb2d4c8698..75a8cee6b1d676a9aae85d8966a66300c7f511e9 100644 (file)
@@ -786,10 +786,11 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                wmb();
 
                cp->tx_skb[entry] = skb;
-               entry = NEXT_TX(entry);
+               netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
+                         entry, skb->len);
        } else {
                struct cp_desc *txd;
-               u32 first_len, first_eor;
+               u32 first_len, first_eor, ctrl;
                dma_addr_t first_mapping;
                int frag, first_entry = entry;
                const struct iphdr *ip = ip_hdr(skb);
@@ -805,14 +806,14 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                        goto out_dma_error;
 
                cp->tx_skb[entry] = skb;
-               entry = NEXT_TX(entry);
 
                for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
                        const skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
                        u32 len;
-                       u32 ctrl;
                        dma_addr_t mapping;
 
+                       entry = NEXT_TX(entry);
+
                        len = skb_frag_size(this_frag);
                        mapping = dma_map_single(&cp->pdev->dev,
                                                 skb_frag_address(this_frag),
@@ -848,9 +849,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 
                        txd->opts1 = cpu_to_le32(ctrl);
                        wmb();
-
                        cp->tx_skb[entry] = skb;
-                       entry = NEXT_TX(entry);
                }
 
                txd = &cp->tx_ring[first_entry];
@@ -858,27 +857,27 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                txd->addr = cpu_to_le64(first_mapping);
                wmb();
 
-               if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               ctrl = first_eor | first_len | FirstFrag | DescOwn;
+               if (mss)
+                       ctrl |= LargeSend | ((mss & MSSMask) << MSSShift);
+               else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                        if (ip->protocol == IPPROTO_TCP)
-                               txd->opts1 = cpu_to_le32(first_eor | first_len |
-                                                        FirstFrag | DescOwn |
-                                                        IPCS | TCPCS);
+                               ctrl |= IPCS | TCPCS;
                        else if (ip->protocol == IPPROTO_UDP)
-                               txd->opts1 = cpu_to_le32(first_eor | first_len |
-                                                        FirstFrag | DescOwn |
-                                                        IPCS | UDPCS);
+                               ctrl |= IPCS | UDPCS;
                        else
                                BUG();
-               } else
-                       txd->opts1 = cpu_to_le32(first_eor | first_len |
-                                                FirstFrag | DescOwn);
+               }
+
+               txd->opts1 = cpu_to_le32(ctrl);
                wmb();
+
+               netif_dbg(cp, tx_queued, cp->dev, "tx queued, slots %d-%d, skblen %d\n",
+                         first_entry, entry, skb->len);
        }
-       cp->tx_head = entry;
+       cp->tx_head = NEXT_TX(entry);
 
        netdev_sent_queue(dev, skb->len);
-       netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
-                 entry, skb->len);
        if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
                netif_stop_queue(dev);
 
@@ -1151,7 +1150,7 @@ static void cp_clean_rings (struct cp_private *cp)
                        desc = cp->rx_ring + i;
                        dma_unmap_single(&cp->pdev->dev,le64_to_cpu(desc->addr),
                                         cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-                       dev_kfree_skb(cp->rx_skb[i]);
+                       dev_kfree_skb_any(cp->rx_skb[i]);
                }
        }
 
@@ -1164,7 +1163,7 @@ static void cp_clean_rings (struct cp_private *cp)
                                         le32_to_cpu(desc->opts1) & 0xffff,
                                         PCI_DMA_TODEVICE);
                        if (le32_to_cpu(desc->opts1) & LastFrag)
-                               dev_kfree_skb(skb);
+                               dev_kfree_skb_any(skb);
                        cp->dev->stats.tx_dropped++;
                }
        }
@@ -1261,9 +1260,11 @@ static void cp_tx_timeout(struct net_device *dev)
        cp_clean_rings(cp);
        rc = cp_init_rings(cp);
        cp_start_hw(cp);
-       cp_enable_irq(cp);
+       __cp_set_rx_mode(dev);
+       cpw16_f(IntrMask, cp_norx_intr_mask);
 
        netif_wake_queue(dev);
+       napi_schedule_irqoff(&cp->napi);
 
        spin_unlock_irqrestore(&cp->lock, flags);
 }