Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[deliverable/linux.git] / drivers / net / ethernet / hisilicon / hns / hns_enet.c
index 3f77ff77abbc4594f8aeb0ccc40c6691fc122fac..687204b780b02143486031971e7fe8b6af165f29 100644 (file)
@@ -48,7 +48,6 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv,
        struct iphdr *iphdr;
        struct ipv6hdr *ipv6hdr;
        struct sk_buff *skb;
-       int skb_tmp_len;
        __be16 protocol;
        u8 bn_pid = 0;
        u8 rrcfv = 0;
@@ -66,10 +65,14 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv,
        desc->addr = cpu_to_le64(dma);
        desc->tx.send_size = cpu_to_le16((u16)size);
 
-       /*config bd buffer end */
+       /* config bd buffer end */
        hnae_set_bit(rrcfv, HNSV2_TXD_VLD_B, 1);
        hnae_set_field(bn_pid, HNSV2_TXD_BUFNUM_M, 0, buf_num - 1);
 
+       /* fill port_id in the tx bd for sending management pkts */
+       hnae_set_field(bn_pid, HNSV2_TXD_PORTID_M,
+                      HNSV2_TXD_PORTID_S, ring->q->handle->dport_id);
+
        if (type == DESC_TYPE_SKB) {
                skb = (struct sk_buff *)priv;
 
@@ -90,13 +93,13 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv,
                                hnae_set_bit(rrcfv, HNSV2_TXD_L4CS_B, 1);
 
                                /* check for tcp/udp header */
-                               if (iphdr->protocol == IPPROTO_TCP) {
+                               if (iphdr->protocol == IPPROTO_TCP &&
+                                   skb_is_gso(skb)) {
                                        hnae_set_bit(tvsvsn,
                                                     HNSV2_TXD_TSE_B, 1);
-                                       skb_tmp_len = SKB_TMP_LEN(skb);
                                        l4_len = tcp_hdrlen(skb);
-                                       mss = mtu - skb_tmp_len - ETH_FCS_LEN;
-                                       paylen = skb->len - skb_tmp_len;
+                                       mss = skb_shinfo(skb)->gso_size;
+                                       paylen = skb->len - SKB_TMP_LEN(skb);
                                }
                        } else if (skb->protocol == htons(ETH_P_IPV6)) {
                                hnae_set_bit(tvsvsn, HNSV2_TXD_IPV6_B, 1);
@@ -104,13 +107,13 @@ static void fill_v2_desc(struct hnae_ring *ring, void *priv,
                                hnae_set_bit(rrcfv, HNSV2_TXD_L4CS_B, 1);
 
                                /* check for tcp/udp header */
-                               if (ipv6hdr->nexthdr == IPPROTO_TCP) {
+                               if (ipv6hdr->nexthdr == IPPROTO_TCP &&
+                                   skb_is_gso(skb) && skb_is_gso_v6(skb)) {
                                        hnae_set_bit(tvsvsn,
                                                     HNSV2_TXD_TSE_B, 1);
-                                       skb_tmp_len = SKB_TMP_LEN(skb);
                                        l4_len = tcp_hdrlen(skb);
-                                       mss = mtu - skb_tmp_len - ETH_FCS_LEN;
-                                       paylen = skb->len - skb_tmp_len;
+                                       mss = skb_shinfo(skb)->gso_size;
+                                       paylen = skb->len - SKB_TMP_LEN(skb);
                                }
                        }
                        desc->tx.ip_offset = ip_offset;
@@ -564,6 +567,7 @@ static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data,
        struct sk_buff *skb;
        struct hnae_desc *desc;
        struct hnae_desc_cb *desc_cb;
+       struct ethhdr *eh;
        unsigned char *va;
        int bnum, length, i;
        int pull_len;
@@ -670,6 +674,14 @@ out_bnum_err:
                return -EFAULT;
        }
 
+       /* filter out multicast pkt with the same src mac as this port */
+       eh = eth_hdr(skb);
+       if (unlikely(is_multicast_ether_addr(eh->h_dest) &&
+                    ether_addr_equal(ndev->dev_addr, eh->h_source))) {
+               dev_kfree_skb_any(skb);
+               return -EFAULT;
+       }
+
        ring->stats.rx_pkts++;
        ring->stats.rx_bytes += skb->len;
 
@@ -901,10 +913,7 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data,
 static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data)
 {
        struct hnae_ring *ring = ring_data->ring;
-       int head = ring->next_to_clean;
-
-       /* for hardware bug fixed */
-       head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
+       int head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
 
        if (head != ring->next_to_clean) {
                ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
@@ -947,8 +956,8 @@ static int hns_nic_common_poll(struct napi_struct *napi, int budget)
                napi_complete(napi);
                ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
                        ring_data->ring, 0);
-
-               ring_data->fini_process(ring_data);
+               if (ring_data->fini_process)
+                       ring_data->fini_process(ring_data);
                return 0;
        }
 
@@ -1711,6 +1720,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv)
 {
        struct hnae_handle *h = priv->ae_handle;
        struct hns_nic_ring_data *rd;
+       bool is_ver1 = AE_IS_VER1(priv->enet_ver);
        int i;
 
        if (h->q_num > NIC_MAX_Q_PER_VF) {
@@ -1728,7 +1738,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv)
                rd->queue_index = i;
                rd->ring = &h->qs[i]->tx_ring;
                rd->poll_one = hns_nic_tx_poll_one;
-               rd->fini_process = hns_nic_tx_fini_pro;
+               rd->fini_process = is_ver1 ? hns_nic_tx_fini_pro : NULL;
 
                netif_napi_add(priv->netdev, &rd->napi,
                               hns_nic_common_poll, NIC_TX_CLEAN_MAX_NUM);
@@ -1740,7 +1750,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv)
                rd->ring = &h->qs[i - h->q_num]->rx_ring;
                rd->poll_one = hns_nic_rx_poll_one;
                rd->ex_process = hns_nic_rx_up_pro;
-               rd->fini_process = hns_nic_rx_fini_pro;
+               rd->fini_process = is_ver1 ? hns_nic_rx_fini_pro : NULL;
 
                netif_napi_add(priv->netdev, &rd->napi,
                               hns_nic_common_poll, NIC_RX_CLEAN_MAX_NUM);
@@ -1804,7 +1814,7 @@ static int hns_nic_try_get_ae(struct net_device *ndev)
        h = hnae_get_handle(&priv->netdev->dev,
                            priv->ae_node, priv->port_id, NULL);
        if (IS_ERR_OR_NULL(h)) {
-               ret = PTR_ERR(h);
+               ret = -ENODEV;
                dev_dbg(priv->dev, "has not handle, register notifier!\n");
                goto out;
        }
This page took 0.044707 seconds and 5 git commands to generate.