drivers/net: enic: Adding support for Cisco Low Latency NIC
authorNeel Patel <neepatel@cisco.com>
Fri, 16 Aug 2013 22:47:39 +0000 (15:47 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 20 Aug 2013 20:41:01 +0000 (13:41 -0700)
This patch,
    - Adds new firmware commands for the new Cisco Low Latency NIC
      (aka. USNIC).

Signed-off-by: Neel Patel <neepatel@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cisco/enic/enic.h
drivers/net/ethernet/cisco/enic/enic_res.h
drivers/net/ethernet/cisco/enic/vnic_devcmd.h
drivers/net/ethernet/cisco/enic/vnic_rq.c
drivers/net/ethernet/cisco/enic/vnic_rq.h
drivers/net/ethernet/cisco/enic/vnic_wq.c
drivers/net/ethernet/cisco/enic/vnic_wq.h

index 2e37c63981c1127ca86fce5cbbd92fd9926838e9..75e842d6cfe72eb1cf2f41d62231670679319a6e 100644 (file)
@@ -33,7 +33,7 @@
 #define DRV_NAME               "enic"
 #define DRV_DESCRIPTION                "Cisco VIC Ethernet NIC Driver"
 #define DRV_VERSION            "2.1.1.39"
-#define DRV_COPYRIGHT          "Copyright 2008-2011 Cisco Systems, Inc"
+#define DRV_COPYRIGHT          "Copyright 2008-2013 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX          6
 
index 25be2734c3feba3cf0d3fa631f64da360248fa80..69f60afd6577ec2d7c5c41540f81fbc59b7049a6 100644 (file)
@@ -47,6 +47,9 @@ static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
        int offload_mode, int cq_entry, int sop, int eop, int loopback)
 {
        struct wq_enet_desc *desc = vnic_wq_next_desc(wq);
+       u8 desc_skip_cnt = 1;
+       u8 compressed_send = 0;
+       u64 wrid = 0;
 
        wq_enet_desc_enc(desc,
                (u64)dma_addr | VNIC_PADDR_TARGET,
@@ -59,7 +62,8 @@ static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
                (u16)vlan_tag,
                (u8)loopback);
 
-       vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop);
+       vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop, desc_skip_cnt,
+                       (u8)cq_entry, compressed_send, wrid);
 }
 
 static inline void enic_queue_wq_desc_cont(struct vnic_wq *wq,
@@ -120,6 +124,7 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq,
        dma_addr_t dma_addr, unsigned int len)
 {
        struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
+       u64 wrid = 0;
        u8 type = os_buf_index ?
                RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP;
 
@@ -127,7 +132,7 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq,
                (u64)dma_addr | VNIC_PADDR_TARGET,
                type, (u16)len);
 
-       vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len);
+       vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len, wrid);
 }
 
 struct enic;
index 23d555255cf8ed99ef3c949ceeb0c3b42822ff9b..b9a0d78fd6391698a15a169cf206ec27b098b2c0 100644 (file)
@@ -281,11 +281,25 @@ enum vnic_devcmd_cmd {
         *              0 if no VIF-CONFIG-INFO TLV was ever received. */
        CMD_CONFIG_INFO_GET     = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44),
 
+       /* INT13 API: (u64)a0=paddr to vnic_int13_params struct
+        *            (u32)a1=INT13_CMD_xxx
+        */
+       CMD_INT13_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 45),
+
+       /* Set default vlan:
+        * in: (u16)a0=new default vlan
+        *     (u16)a1=zero for overriding vlan with param a0,
+        *                     non-zero for resetting vlan to the default
+        * out: (u16)a0=old default vlan
+        */
+       CMD_SET_DEFAULT_VLAN = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 46),
+
        /* init_prov_info2:
         * Variant of CMD_INIT_PROV_INFO, where it will not try to enable
         * the vnic until CMD_ENABLE2 is issued.
         *     (u64)a0=paddr of vnic_devcmd_provinfo
-        *     (u32)a1=sizeof provision info */
+        *     (u32)a1=sizeof provision info
+        */
        CMD_INIT_PROV_INFO2  = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 47),
 
        /* enable2:
@@ -339,16 +353,57 @@ enum vnic_devcmd_cmd {
        CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
 
        /*
-        * cmd_set_mac_addr
-        *      set mac address
+        * Set the predefined mac address as default
         * in:
         *   (u48)a0 = mac addr
-        *
         */
        CMD_SET_MAC_ADDR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 55),
+
+       /* Update the provisioning info of the given VIF
+        *     (u64)a0=paddr of vnic_devcmd_provinfo
+        *     (u32)a1=sizeof provision info
+        */
+       CMD_PROV_INFO_UPDATE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 56),
+
+       /* Add a filter.
+        * in: (u64) a0= filter address
+        *     (u32) a1= size of filter
+        * out: (u32) a0=filter identifier
+        */
+       CMD_ADD_FILTER = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 58),
+
+       /* Delete a filter.
+        * in: (u32) a0=filter identifier
+        */
+       CMD_DEL_FILTER = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 59),
+
+       /* Enable a Queue Pair in User space NIC
+        * in: (u32) a0=Queue Pair number
+        *     (u32) a1= command
+        */
+       CMD_QP_ENABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 60),
+
+       /* Disable a Queue Pair in User space NIC
+        * in: (u32) a0=Queue Pair number
+        *     (u32) a1= command
+        */
+       CMD_QP_DISABLE = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 61),
+
+       /* Stats dump Queue Pair in User space NIC
+        * in: (u32) a0=Queue Pair number
+        *     (u64) a1=host buffer addr for status dump
+        *     (u32) a2=length of the buffer
+        */
+       CMD_QP_STATS_DUMP = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 62),
+
+       /* Clear stats for Queue Pair in User space NIC
+        * in: (u32) a0=Queue Pair number
+        */
+       CMD_QP_STATS_CLEAR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 63),
 };
 
 /* CMD_ENABLE2 flags */
+#define CMD_ENABLE2_STANDBY 0x0
 #define CMD_ENABLE2_ACTIVE  0x1
 
 /* flags for CMD_OPEN */
@@ -364,6 +419,9 @@ enum vnic_devcmd_cmd {
 #define CMD_PFILTER_PROMISCUOUS                0x08
 #define CMD_PFILTER_ALL_MULTICAST      0x10
 
+/* Commands for CMD_QP_ENABLE/CM_QP_DISABLE */
+#define CMD_QP_RQWQ                     0x0
+
 /* rewrite modes for CMD_IG_VLAN_REWRITE_MODE */
 #define IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK              0
 #define IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN         1
@@ -390,6 +448,7 @@ enum vnic_devcmd_error {
        ERR_EMAXRES = 10,
        ERR_ENOTSUPPORTED = 11,
        ERR_EINPROGRESS = 12,
+       ERR_MAX
 };
 
 /*
@@ -435,6 +494,115 @@ struct vnic_devcmd_provinfo {
        u8 data[0];
 };
 
+/* These are used in flags field of different filters to denote
+ * valid fields used.
+ */
+#define FILTER_FIELD_VALID(fld) (1 << (fld - 1))
+
+#define FILTER_FIELDS_USNIC ( \
+                       FILTER_FIELD_VALID(1) | \
+                       FILTER_FIELD_VALID(2) | \
+                       FILTER_FIELD_VALID(3) | \
+                       FILTER_FIELD_VALID(4))
+
+#define FILTER_FIELDS_IPV4_5TUPLE ( \
+                       FILTER_FIELD_VALID(1) | \
+                       FILTER_FIELD_VALID(2) | \
+                       FILTER_FIELD_VALID(3) | \
+                       FILTER_FIELD_VALID(4) | \
+                       FILTER_FIELD_VALID(5))
+
+#define FILTER_FIELDS_MAC_VLAN ( \
+                       FILTER_FIELD_VALID(1) | \
+                       FILTER_FIELD_VALID(2))
+
+#define FILTER_FIELD_USNIC_VLAN    FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_USNIC_ETHTYPE FILTER_FIELD_VALID(2)
+#define FILTER_FIELD_USNIC_PROTO   FILTER_FIELD_VALID(3)
+#define FILTER_FIELD_USNIC_ID      FILTER_FIELD_VALID(4)
+
+struct filter_usnic_id {
+       u32 flags;
+       u16 vlan;
+       u16 ethtype;
+       u8 proto_version;
+       u32 usnic_id;
+} __packed;
+
+#define FILTER_FIELD_5TUP_PROTO  FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_5TUP_SRC_AD FILTER_FIELD_VALID(2)
+#define FILTER_FIELD_5TUP_DST_AD FILTER_FIELD_VALID(3)
+#define FILTER_FIELD_5TUP_SRC_PT FILTER_FIELD_VALID(4)
+#define FILTER_FIELD_5TUP_DST_PT FILTER_FIELD_VALID(5)
+
+/* Enums for the protocol field. */
+enum protocol_e {
+       PROTO_UDP = 0,
+       PROTO_TCP = 1,
+};
+
+struct filter_ipv4_5tuple {
+       u32 flags;
+       u32 protocol;
+       u32 src_addr;
+       u32 dst_addr;
+       u16 src_port;
+       u16 dst_port;
+} __packed;
+
+#define FILTER_FIELD_VMQ_VLAN   FILTER_FIELD_VALID(1)
+#define FILTER_FIELD_VMQ_MAC    FILTER_FIELD_VALID(2)
+
+struct filter_mac_vlan {
+       u32 flags;
+       u16 vlan;
+       u8 mac_addr[6];
+} __packed;
+
+/* Specifies the filter_action type. */
+enum {
+       FILTER_ACTION_RQ_STEERING = 0,
+       FILTER_ACTION_MAX
+};
+
+struct filter_action {
+       u32 type;
+       union {
+               u32 rq_idx;
+       } u;
+} __packed;
+
+/* Specifies the filter type. */
+enum filter_type {
+       FILTER_USNIC_ID = 0,
+       FILTER_IPV4_5TUPLE = 1,
+       FILTER_MAC_VLAN = 2,
+       FILTER_MAX
+};
+
+struct filter {
+       u32 type;
+       union {
+               struct filter_usnic_id usnic;
+               struct filter_ipv4_5tuple ipv4;
+               struct filter_mac_vlan mac_vlan;
+       } u;
+} __packed;
+
+enum {
+       CLSF_TLV_FILTER = 0,
+       CLSF_TLV_ACTION = 1,
+};
+
+/* Maximum size of buffer to CMD_ADD_FILTER */
+#define FILTER_MAX_BUF_SIZE 100
+
+struct filter_tlv {
+       u_int32_t type;
+       u_int32_t length;
+       u_int32_t val[0];
+};
+
 /*
  * Writing cmd register causes STAT_BUSY to get set in status register.
  * When cmd completes, STAT_BUSY will be cleared.
index 7e1488fc8ab28bc3ab6c5f6565e9cf61c70f62d9..36a2ed606c911f21355360fad81eb39b18162c59 100644 (file)
 static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
 {
        struct vnic_rq_buf *buf;
-       struct vnic_dev *vdev;
        unsigned int i, j, count = rq->ring.desc_count;
        unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count);
 
-       vdev = rq->vdev;
-
        for (i = 0; i < blks; i++) {
                rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC);
                if (!rq->bufs[i])
@@ -141,7 +138,7 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
        unsigned int error_interrupt_enable,
        unsigned int error_interrupt_offset)
 {
-       u32 fetch_index;
+       u32 fetch_index = 0;
 
        /* Use current fetch_index as the ring starting point */
        fetch_index = ioread32(&rq->ctrl->fetch_index);
index 2056586f4d4b02641ec9609e3858b3c0368822ff..ee7bc95af278c691acebb358341a9885017863f3 100644 (file)
@@ -72,6 +72,7 @@ struct vnic_rq_buf {
        unsigned int len;
        unsigned int index;
        void *desc;
+       uint64_t wr_id;
 };
 
 struct vnic_rq {
@@ -110,7 +111,8 @@ static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)
 
 static inline void vnic_rq_post(struct vnic_rq *rq,
        void *os_buf, unsigned int os_buf_index,
-       dma_addr_t dma_addr, unsigned int len)
+       dma_addr_t dma_addr, unsigned int len,
+       uint64_t wrid)
 {
        struct vnic_rq_buf *buf = rq->to_use;
 
@@ -118,6 +120,7 @@ static inline void vnic_rq_post(struct vnic_rq *rq,
        buf->os_buf_index = os_buf_index;
        buf->dma_addr = dma_addr;
        buf->len = len;
+       buf->wr_id = wrid;
 
        buf = buf->next;
        rq->to_use = buf;
index 5e0d7a2be9bc4a95c32864ba7fc25d14b0b5f3c9..3e6b8d54dafcbac2e7c628b850378b89cb8ab7fe 100644 (file)
 static int vnic_wq_alloc_bufs(struct vnic_wq *wq)
 {
        struct vnic_wq_buf *buf;
-       struct vnic_dev *vdev;
        unsigned int i, j, count = wq->ring.desc_count;
        unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count);
 
-       vdev = wq->vdev;
-
        for (i = 0; i < blks; i++) {
                wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC);
                if (!wq->bufs[i])
index 7dd937ac11c23e51fefdedf7ce72f70d7f2b76e9..2c6c70804a39edb475d4c97e1f3e617aad387ed4 100644 (file)
@@ -58,6 +58,10 @@ struct vnic_wq_buf {
        unsigned int index;
        int sop;
        void *desc;
+       uint64_t wr_id; /* Cookie */
+       uint8_t cq_entry; /* Gets completion event from hw */
+       uint8_t desc_skip_cnt; /* Num descs to occupy */
+       uint8_t compressed_send; /* Both hdr and payload in one desc */
 };
 
 /* Break the vnic_wq_buf allocations into blocks of 32/64 entries */
@@ -102,14 +106,20 @@ static inline void *vnic_wq_next_desc(struct vnic_wq *wq)
 
 static inline void vnic_wq_post(struct vnic_wq *wq,
        void *os_buf, dma_addr_t dma_addr,
-       unsigned int len, int sop, int eop)
+       unsigned int len, int sop, int eop,
+       uint8_t desc_skip_cnt, uint8_t cq_entry,
+       uint8_t compressed_send, uint64_t wrid)
 {
        struct vnic_wq_buf *buf = wq->to_use;
 
        buf->sop = sop;
+       buf->cq_entry = cq_entry;
+       buf->compressed_send = compressed_send;
+       buf->desc_skip_cnt = desc_skip_cnt;
        buf->os_buf = eop ? os_buf : NULL;
        buf->dma_addr = dma_addr;
        buf->len = len;
+       buf->wr_id = wrid;
 
        buf = buf->next;
        if (eop) {
@@ -123,7 +133,7 @@ static inline void vnic_wq_post(struct vnic_wq *wq,
        }
        wq->to_use = buf;
 
-       wq->ring.desc_avail--;
+       wq->ring.desc_avail -= desc_skip_cnt;
 }
 
 static inline void vnic_wq_service(struct vnic_wq *wq,