]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drivers: net: xgene: Add support for RSS
authorIyappan Subramanian <isubramanian@apm.com>
Wed, 17 Feb 2016 23:00:40 +0000 (15:00 -0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Feb 2016 03:08:34 +0000 (22:08 -0500)
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Khuong Dinh <kdinh@apm.com>
Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
Tested-by: Toan Le <toanle@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
drivers/net/ethernet/apm/xgene/xgene_enet_cle.h

index ff24ca9647edad85266397002b06f1a8fef0fba5..c00749727e6ad9bba6373a77892404dc668e156b 100644 (file)
 
 #include "xgene_enet_main.h"
 
+/* interfaces to convert structures to HW recognized bit formats */
+static void xgene_cle_sband_to_hw(u8 frag, enum xgene_cle_prot_version ver,
+                                 enum xgene_cle_prot_type type, u32 len,
+                                 u32 *reg)
+{
+       *reg =  SET_VAL(SB_IPFRAG, frag) |
+               SET_VAL(SB_IPPROT, type) |
+               SET_VAL(SB_IPVER, ver) |
+               SET_VAL(SB_HDRLEN, len);
+}
+
+static void xgene_cle_idt_to_hw(u32 dstqid, u32 fpsel,
+                               u32 nfpsel, u32 *idt_reg)
+{
+       *idt_reg =  SET_VAL(IDT_DSTQID, dstqid) |
+                   SET_VAL(IDT_FPSEL, fpsel) |
+                   SET_VAL(IDT_NFPSEL, nfpsel);
+}
+
 static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
                                  struct xgene_cle_dbptr *dbptr, u32 *buf)
 {
@@ -257,29 +276,372 @@ static void xgene_cle_setup_def_dbptr(struct xgene_enet_pdata *pdata,
        }
 }
 
+static int xgene_cle_set_rss_sband(struct xgene_enet_cle *cle)
+{
+       u32 idx = CLE_PKTRAM_SIZE / sizeof(u32);
+       u32 mac_hdr_len = ETH_HLEN;
+       u32 sband, reg = 0;
+       u32 ipv4_ihl = 5;
+       u32 hdr_len;
+       int ret;
+
+       /* Sideband: IPV4/TCP packets */
+       hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
+       xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_TCP, hdr_len, &reg);
+       sband = reg;
+
+       /* Sideband: IPv4/UDP packets */
+       hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
+       xgene_cle_sband_to_hw(1, XGENE_CLE_IPV4, XGENE_CLE_UDP, hdr_len, &reg);
+       sband |= (reg << 16);
+
+       ret = xgene_cle_dram_wr(cle, &sband, 1, idx, PKT_RAM, CLE_CMD_WR);
+       if (ret)
+               return ret;
+
+       /* Sideband: IPv4/RAW packets */
+       hdr_len = (mac_hdr_len << 5) | ipv4_ihl;
+       xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER,
+                             hdr_len, &reg);
+       sband = reg;
+
+       /* Sideband: Ethernet II/RAW packets */
+       hdr_len = (mac_hdr_len << 5);
+       xgene_cle_sband_to_hw(0, XGENE_CLE_IPV4, XGENE_CLE_OTHER,
+                             hdr_len, &reg);
+       sband |= (reg << 16);
+
+       ret = xgene_cle_dram_wr(cle, &sband, 1, idx + 1, PKT_RAM, CLE_CMD_WR);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int xgene_cle_set_rss_skeys(struct xgene_enet_cle *cle)
+{
+       u32 secret_key_ipv4[4];  /* 16 Bytes*/
+       int ret = 0;
+
+       get_random_bytes(secret_key_ipv4, 16);
+       ret = xgene_cle_dram_wr(cle, secret_key_ipv4, 4, 0,
+                               RSS_IPV4_HASH_SKEY, CLE_CMD_WR);
+       return ret;
+}
+
+static int xgene_cle_set_rss_idt(struct xgene_enet_pdata *pdata)
+{
+       u32 fpsel, dstqid, nfpsel, idt_reg;
+       int i, ret = 0;
+       u16 pool_id;
+
+       for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) {
+               pool_id = pdata->rx_ring->buf_pool->id;
+               fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+               dstqid = xgene_enet_dst_ring_num(pdata->rx_ring);
+               nfpsel = 0;
+               idt_reg = 0;
+
+               xgene_cle_idt_to_hw(dstqid, fpsel, nfpsel, &idt_reg);
+               ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i,
+                                       RSS_IDT, CLE_CMD_WR);
+               if (ret)
+                       return ret;
+       }
+
+       ret = xgene_cle_set_rss_skeys(&pdata->cle);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int xgene_cle_setup_rss(struct xgene_enet_pdata *pdata)
+{
+       struct xgene_enet_cle *cle = &pdata->cle;
+       void __iomem *base = cle->base;
+       u32 offset, val = 0;
+       int i, ret = 0;
+
+       offset = CLE_PORT_OFFSET;
+       for (i = 0; i < cle->parsers; i++) {
+               if (cle->active_parser != PARSER_ALL)
+                       offset = cle->active_parser * CLE_PORT_OFFSET;
+               else
+                       offset = i * CLE_PORT_OFFSET;
+
+               /* enable RSS */
+               val = (RSS_IPV4_12B << 1) | 0x1;
+               writel(val, base + RSS_CTRL0 + offset);
+       }
+
+       /* setup sideband data */
+       ret = xgene_cle_set_rss_sband(cle);
+       if (ret)
+               return ret;
+
+       /* setup indirection table */
+       ret = xgene_cle_set_rss_idt(pdata);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 {
        struct xgene_enet_cle *enet_cle = &pdata->cle;
        struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
+       struct xgene_cle_ptree_branch *br;
        u32 def_qid, def_fpsel, pool_id;
        struct xgene_cle_ptree *ptree;
        struct xgene_cle_ptree_kn kn;
+       int ret;
        struct xgene_cle_ptree_ewdn ptree_dn[] = {
                {
                        /* PKT_TYPE_NODE */
                        .node_type = EWDN,
                        .last_node = 0,
-                       .hdr_len_store = 0,
+                       .hdr_len_store = 1,
                        .hdr_extn = NO_BYTE,
                        .byte_store = NO_BYTE,
                        .search_byte_store = NO_BYTE,
                        .result_pointer = DB_RES_DROP,
-                       .num_branches = 1,
+                       .num_branches = 2,
                        .branch = {
                                {
-                                       /* Allow all packet type */
+                                       /* IPV4 */
                                        .valid = 0,
-                                       .next_packet_pointer = 0,
+                                       .next_packet_pointer = 22,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = PKT_PROT_NODE,
+                                       .next_branch = 0,
+                                       .data = 0x8,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       .valid = 0,
+                                       .next_packet_pointer = 262,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = LAST_NODE,
+                                       .next_branch = 0,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               }
+                       },
+               },
+               {
+                       /* PKT_PROT_NODE */
+                       .node_type = EWDN,
+                       .last_node = 0,
+                       .hdr_len_store = 1,
+                       .hdr_extn = NO_BYTE,
+                       .byte_store = NO_BYTE,
+                       .search_byte_store = NO_BYTE,
+                       .result_pointer = DB_RES_DROP,
+                       .num_branches = 3,
+                       .branch = {
+                               {
+                                       /* TCP */
+                                       .valid = 1,
+                                       .next_packet_pointer = 26,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_TCP_NODE,
+                                       .next_branch = 0,
+                                       .data = 0x0600,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* UDP */
+                                       .valid = 1,
+                                       .next_packet_pointer = 26,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_UDP_NODE,
+                                       .next_branch = 0,
+                                       .data = 0x1100,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       .valid = 0,
+                                       .next_packet_pointer = 260,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = LAST_NODE,
+                                       .next_branch = 0,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               }
+                       }
+               },
+               {
+                       /* RSS_IPV4_TCP_NODE */
+                       .node_type = EWDN,
+                       .last_node = 0,
+                       .hdr_len_store = 1,
+                       .hdr_extn = NO_BYTE,
+                       .byte_store = NO_BYTE,
+                       .search_byte_store = BOTH_BYTES,
+                       .result_pointer = DB_RES_DROP,
+                       .num_branches = 6,
+                       .branch = {
+                               {
+                                       /* SRC IPV4 B01 */
+                                       .valid = 0,
+                                       .next_packet_pointer = 28,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_TCP_NODE,
+                                       .next_branch = 1,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* SRC IPV4 B23 */
+                                       .valid = 0,
+                                       .next_packet_pointer = 30,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_TCP_NODE,
+                                       .next_branch = 2,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* DST IPV4 B01 */
+                                       .valid = 0,
+                                       .next_packet_pointer = 32,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_TCP_NODE,
+                                       .next_branch = 3,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* DST IPV4 B23 */
+                                       .valid = 0,
+                                       .next_packet_pointer = 34,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_TCP_NODE,
+                                       .next_branch = 4,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* TCP SRC Port */
+                                       .valid = 0,
+                                       .next_packet_pointer = 36,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_TCP_NODE,
+                                       .next_branch = 5,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* TCP DST Port */
+                                       .valid = 0,
+                                       .next_packet_pointer = 256,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = LAST_NODE,
+                                       .next_branch = 0,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               }
+                       }
+               },
+               {
+                       /* RSS_IPV4_UDP_NODE */
+                       .node_type = EWDN,
+                       .last_node = 0,
+                       .hdr_len_store = 1,
+                       .hdr_extn = NO_BYTE,
+                       .byte_store = NO_BYTE,
+                       .search_byte_store = BOTH_BYTES,
+                       .result_pointer = DB_RES_DROP,
+                       .num_branches = 6,
+                       .branch = {
+                               {
+                                       /* SRC IPV4 B01 */
+                                       .valid = 0,
+                                       .next_packet_pointer = 28,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_UDP_NODE,
+                                       .next_branch = 1,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* SRC IPV4 B23 */
+                                       .valid = 0,
+                                       .next_packet_pointer = 30,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_UDP_NODE,
+                                       .next_branch = 2,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* DST IPV4 B01 */
+                                       .valid = 0,
+                                       .next_packet_pointer = 32,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_UDP_NODE,
+                                       .next_branch = 3,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* DST IPV4 B23 */
+                                       .valid = 0,
+                                       .next_packet_pointer = 34,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_UDP_NODE,
+                                       .next_branch = 4,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* TCP SRC Port */
+                                       .valid = 0,
+                                       .next_packet_pointer = 36,
+                                       .jump_bw = JMP_FW,
+                                       .jump_rel = JMP_ABS,
+                                       .operation = EQT,
+                                       .next_node = RSS_IPV4_UDP_NODE,
+                                       .next_branch = 5,
+                                       .data = 0x0,
+                                       .mask = 0xffff
+                               },
+                               {
+                                       /* TCP DST Port */
+                                       .valid = 0,
+                                       .next_packet_pointer = 256,
                                        .jump_bw = JMP_FW,
                                        .jump_rel = JMP_ABS,
                                        .operation = EQT,
@@ -294,7 +656,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
                        /* LAST NODE */
                        .node_type = EWDN,
                        .last_node = 1,
-                       .hdr_len_store = 0,
+                       .hdr_len_store = 1,
                        .hdr_extn = NO_BYTE,
                        .byte_store = NO_BYTE,
                        .search_byte_store = NO_BYTE,
@@ -318,6 +680,20 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 
        ptree = &enet_cle->ptree;
        ptree->start_pkt = 12; /* Ethertype */
+       if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+               ret = xgene_cle_setup_rss(pdata);
+               if (ret) {
+                       netdev_err(pdata->ndev, "RSS initialization failed\n");
+                       return ret;
+               }
+       } else {
+               br = &ptree_dn[PKT_PROT_NODE].branch[0];
+               br->valid = 0;
+               br->next_packet_pointer = 260;
+               br->next_node = LAST_NODE;
+               br->data = 0x0000;
+               br->mask = 0xffff;
+       }
 
        def_qid = xgene_enet_dst_ring_num(pdata->rx_ring);
        pool_id = pdata->rx_ring->buf_pool->id;
index 1db2fd769602698d6d2d72b6f9334ca4b943838c..29a17abdd828174cb3f5e4fad10458c0df26efca 100644 (file)
@@ -34,6 +34,7 @@
 #define SPPTR0                 0x0104
 #define DFCLSRESDBPTR0         0x0108
 #define DFCLSRESDB00           0x010c
+#define RSS_CTRL0              0x0000013c
 
 #define CLE_CMD_TO             10      /* ms */
 #define CLE_PKTRAM_SIZE                256     /* bytes */
@@ -98,6 +99,9 @@
 
 enum xgene_cle_ptree_nodes {
        PKT_TYPE_NODE,
+       PKT_PROT_NODE,
+       RSS_IPV4_TCP_NODE,
+       RSS_IPV4_UDP_NODE,
        LAST_NODE,
        MAX_NODES
 };
@@ -137,6 +141,8 @@ enum xgene_cle_parser {
 #define XGENE_CLE_DRAM(type)   (((type) & 0xf) << 28)
 enum xgene_cle_dram_type {
        PKT_RAM,
+       RSS_IDT,
+       RSS_IPV4_HASH_SKEY,
        PTREE_RAM = 0xc,
        AVL_RAM,
        DB_RAM
@@ -150,6 +156,22 @@ enum xgene_cle_cmd_type {
        CLE_CMD_AVL_SRCH = 32
 };
 
+enum xgene_cle_ipv4_rss_hashtype {
+       RSS_IPV4_8B,
+       RSS_IPV4_12B,
+};
+
+enum xgene_cle_prot_type {
+       XGENE_CLE_TCP,
+       XGENE_CLE_UDP,
+       XGENE_CLE_ESP,
+       XGENE_CLE_OTHER
+};
+
+enum xgene_cle_prot_version {
+       XGENE_CLE_IPV4,
+};
+
 enum xgene_cle_ptree_dbptrs {
        DB_RES_DROP,
        DB_RES_DEF,
@@ -157,6 +179,25 @@ enum xgene_cle_ptree_dbptrs {
        DB_MAX_PTRS
 };
 
+/* RSS sideband signal info */
+#define SB_IPFRAG_POS  0
+#define SB_IPFRAG_LEN  1
+#define SB_IPPROT_POS  1
+#define SB_IPPROT_LEN  2
+#define SB_IPVER_POS   3
+#define SB_IPVER_LEN   1
+#define SB_HDRLEN_POS  4
+#define SB_HDRLEN_LEN  12
+
+/* RSS indirection table */
+#define XGENE_CLE_IDT_ENTRIES  128
+#define IDT_DSTQID_POS         0
+#define IDT_DSTQID_LEN         12
+#define IDT_FPSEL_POS          12
+#define IDT_FPSEL_LEN          4
+#define IDT_NFPSEL_POS         16
+#define IDT_NFPSEL_LEN         4
+
 struct xgene_cle_ptree_branch {
        bool valid;
        u16 next_packet_pointer;