diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 353814b9d9da5c5831550cb6f7824ab91f5e34b9..777aa54417cf2a2712dff7d6ba908bc719dafff9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -564,6 +564,8 @@ struct hnae_handle { u32 coal_ring_idx; u32 eport_id; u32 dport_id; /* v2 tx bd should fill the dport_id */ + u32 *rss_key; + u32 *rss_indir_table; bool coal_adapt_en; enum hnae_port_type port_type; enum hnae_media_type media_type; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 350e5d136c26403a7c0f2834fcacea2cb5cd6b39..cadfe42ad5a17c09ad6467de81888f68959bad72 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -80,6 +80,7 @@ static struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, struct hnae_handle *ae_handle; struct ring_pair_cb *ring_pair_cb; struct hnae_vf_cb *vf_cb; + struct hns_ppe_cb *ppe_cb; dsaf_dev = hns_ae_get_dsaf_dev(dev); @@ -128,12 +129,16 @@ static struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, vf_cb->port_index = port_id; vf_cb->mac_cb = dsaf_dev->mac_cb[port_id]; + ppe_cb = hns_get_ppe_cb(ae_handle); + ae_handle->phy_if = vf_cb->mac_cb->phy_if; ae_handle->phy_dev = vf_cb->mac_cb->phy_dev; ae_handle->if_support = vf_cb->mac_cb->if_support; ae_handle->port_type = vf_cb->mac_cb->mac_type; ae_handle->media_type = vf_cb->mac_cb->media_type; ae_handle->dport_id = port_id; + ae_handle->rss_key = ppe_cb->rss_key; + ae_handle->rss_indir_table = ppe_cb->rss_indir_table; return ae_handle; vf_id_err: diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 1c70f9aa0aa766e6da6433e8f29bf2e50c3b4791..3734cfb7559612bcd043d3686fad2ef4c030e171 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -37,6 +37,8 @@ #define SKB_TMP_LEN(SKB) \ (((SKB)->transport_header - (SKB)->mac_header) + tcp_hdrlen(SKB)) +#define INVALID_TX_RING 0xffff + static void fill_v2_desc_hw(struct hnae_ring *ring, void *priv, int size, int send_sz, dma_addr_t dma, int frag_end, int buf_num, enum hns_desc_type type, int mtu) @@ -1958,6 +1960,61 @@ static void hns_nic_get_stats64(struct net_device *ndev, stats->tx_compressed = ndev->stats.tx_compressed; } +static u32 hns_calc_tx_rss(u32 sip, u32 dip, u32 sport, u32 dport, u32 *rss_key) +{ + u32 rss = 0; + int i; + u32 port; + + port = (sport << 16) | dport; + + for (i = 0; i < 32; i++) + if (sip & (1 << (31 - i))) + rss ^= (rss_key[9] << i) | + (u32)((u64)rss_key[8] >> (32 - i)); + + for (i = 0; i < 32; i++) + if (dip & (1 << (31 - i))) + rss ^= (rss_key[8] << i) | + (u32)((u64)rss_key[7] >> (32 - i)); + + for (i = 0; i < 32; i++) + if (port & (1 << (31 - i))) + rss ^= (rss_key[7] << i) | + (u32)((u64)rss_key[6] >> (32 - i)); + + return rss; +} + +/* if tcp or udp, then calc tx ring index */ +static u16 hns_calc_tx_ring_idx(struct hns_nic_priv *priv, + struct sk_buff *skb) +{ + struct hnae_handle *handle; + struct iphdr *iphdr; + struct tcphdr *tcphdr; + u32 rss; + int protocol; + u16 ring = INVALID_TX_RING; + + if (skb->protocol == htons(ETH_P_IP)) { + iphdr = ip_hdr(skb); + protocol = iphdr->protocol; + if (protocol == IPPROTO_TCP) { + /* because tcp and udp dest and src port is same */ + tcphdr = tcp_hdr(skb); + handle = priv->ae_handle; + rss = hns_calc_tx_rss(ntohl(iphdr->daddr), + ntohl(iphdr->saddr), + ntohs(tcphdr->dest), + ntohs(tcphdr->source), + handle->rss_key); + ring = handle->rss_indir_table[rss & 0xff] & 0xf; + } + } + + return ring; +} static u16 hns_nic_select_queue(struct net_device *ndev, struct sk_buff *skb, struct net_device *sb_dev, @@ -1965,11 +2022,16 @@ hns_nic_select_queue(struct net_device *ndev, struct sk_buff *skb, { struct ethhdr *eth_hdr = (struct ethhdr *)skb->data; struct hns_nic_priv *priv = netdev_priv(ndev); + u16 ring; /* fix hardware broadcast/multicast packets queue loopback */ if (!AE_IS_VER1(priv->enet_ver) && is_multicast_ether_addr(eth_hdr->h_dest)) return 0; + + ring = hns_calc_tx_ring_idx(priv, skb); + if (ring != INVALID_TX_RING) + return ring; else return fallback(ndev, skb, NULL); }