drivers/net: enic: Adding support for Cisco Low Latency NIC

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>
This commit is contained in:
Neel Patel 2013-08-16 15:47:39 -07:00 committed by David S. Miller
parent 89d5e23210
commit 92e2b46962
7 changed files with 197 additions and 17 deletions

View File

@ -33,7 +33,7 @@
#define DRV_NAME "enic" #define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
#define DRV_VERSION "2.1.1.39" #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 #define ENIC_BARS_MAX 6

View 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) int offload_mode, int cq_entry, int sop, int eop, int loopback)
{ {
struct wq_enet_desc *desc = vnic_wq_next_desc(wq); 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, wq_enet_desc_enc(desc,
(u64)dma_addr | VNIC_PADDR_TARGET, (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, (u16)vlan_tag,
(u8)loopback); (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, 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) dma_addr_t dma_addr, unsigned int len)
{ {
struct rq_enet_desc *desc = vnic_rq_next_desc(rq); struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
u64 wrid = 0;
u8 type = os_buf_index ? u8 type = os_buf_index ?
RQ_ENET_TYPE_NOT_SOP : RQ_ENET_TYPE_ONLY_SOP; 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, (u64)dma_addr | VNIC_PADDR_TARGET,
type, (u16)len); 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; struct enic;

View File

@ -281,11 +281,25 @@ enum vnic_devcmd_cmd {
* 0 if no VIF-CONFIG-INFO TLV was ever received. */ * 0 if no VIF-CONFIG-INFO TLV was ever received. */
CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44), 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: /* init_prov_info2:
* Variant of CMD_INIT_PROV_INFO, where it will not try to enable * Variant of CMD_INIT_PROV_INFO, where it will not try to enable
* the vnic until CMD_ENABLE2 is issued. * the vnic until CMD_ENABLE2 is issued.
* (u64)a0=paddr of vnic_devcmd_provinfo * (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), CMD_INIT_PROV_INFO2 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 47),
/* enable2: /* enable2:
@ -339,16 +353,57 @@ enum vnic_devcmd_cmd {
CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50), CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50),
/* /*
* cmd_set_mac_addr * Set the predefined mac address as default
* set mac address
* in: * in:
* (u48)a0 = mac addr * (u48)a0 = mac addr
*
*/ */
CMD_SET_MAC_ADDR = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 55), 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 */ /* CMD_ENABLE2 flags */
#define CMD_ENABLE2_STANDBY 0x0
#define CMD_ENABLE2_ACTIVE 0x1 #define CMD_ENABLE2_ACTIVE 0x1
/* flags for CMD_OPEN */ /* flags for CMD_OPEN */
@ -364,6 +419,9 @@ enum vnic_devcmd_cmd {
#define CMD_PFILTER_PROMISCUOUS 0x08 #define CMD_PFILTER_PROMISCUOUS 0x08
#define CMD_PFILTER_ALL_MULTICAST 0x10 #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 */ /* rewrite modes for CMD_IG_VLAN_REWRITE_MODE */
#define IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK 0 #define IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK 0
#define IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN 1 #define IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN 1
@ -390,6 +448,7 @@ enum vnic_devcmd_error {
ERR_EMAXRES = 10, ERR_EMAXRES = 10,
ERR_ENOTSUPPORTED = 11, ERR_ENOTSUPPORTED = 11,
ERR_EINPROGRESS = 12, ERR_EINPROGRESS = 12,
ERR_MAX
}; };
/* /*
@ -435,6 +494,115 @@ struct vnic_devcmd_provinfo {
u8 data[0]; 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. * Writing cmd register causes STAT_BUSY to get set in status register.
* When cmd completes, STAT_BUSY will be cleared. * When cmd completes, STAT_BUSY will be cleared.

View File

@ -30,12 +30,9 @@
static int vnic_rq_alloc_bufs(struct vnic_rq *rq) static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
{ {
struct vnic_rq_buf *buf; struct vnic_rq_buf *buf;
struct vnic_dev *vdev;
unsigned int i, j, count = rq->ring.desc_count; unsigned int i, j, count = rq->ring.desc_count;
unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count); unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count);
vdev = rq->vdev;
for (i = 0; i < blks; i++) { for (i = 0; i < blks; i++) {
rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC); rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ(count), GFP_ATOMIC);
if (!rq->bufs[i]) 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_enable,
unsigned int error_interrupt_offset) unsigned int error_interrupt_offset)
{ {
u32 fetch_index; u32 fetch_index = 0;
/* Use current fetch_index as the ring starting point */ /* Use current fetch_index as the ring starting point */
fetch_index = ioread32(&rq->ctrl->fetch_index); fetch_index = ioread32(&rq->ctrl->fetch_index);

View File

@ -72,6 +72,7 @@ struct vnic_rq_buf {
unsigned int len; unsigned int len;
unsigned int index; unsigned int index;
void *desc; void *desc;
uint64_t wr_id;
}; };
struct vnic_rq { 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, static inline void vnic_rq_post(struct vnic_rq *rq,
void *os_buf, unsigned int os_buf_index, 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; 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->os_buf_index = os_buf_index;
buf->dma_addr = dma_addr; buf->dma_addr = dma_addr;
buf->len = len; buf->len = len;
buf->wr_id = wrid;
buf = buf->next; buf = buf->next;
rq->to_use = buf; rq->to_use = buf;

View File

@ -30,12 +30,9 @@
static int vnic_wq_alloc_bufs(struct vnic_wq *wq) static int vnic_wq_alloc_bufs(struct vnic_wq *wq)
{ {
struct vnic_wq_buf *buf; struct vnic_wq_buf *buf;
struct vnic_dev *vdev;
unsigned int i, j, count = wq->ring.desc_count; unsigned int i, j, count = wq->ring.desc_count;
unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count); unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count);
vdev = wq->vdev;
for (i = 0; i < blks; i++) { for (i = 0; i < blks; i++) {
wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC); wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ(count), GFP_ATOMIC);
if (!wq->bufs[i]) if (!wq->bufs[i])

View File

@ -58,6 +58,10 @@ struct vnic_wq_buf {
unsigned int index; unsigned int index;
int sop; int sop;
void *desc; 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 */ /* 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, static inline void vnic_wq_post(struct vnic_wq *wq,
void *os_buf, dma_addr_t dma_addr, 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; struct vnic_wq_buf *buf = wq->to_use;
buf->sop = sop; 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->os_buf = eop ? os_buf : NULL;
buf->dma_addr = dma_addr; buf->dma_addr = dma_addr;
buf->len = len; buf->len = len;
buf->wr_id = wrid;
buf = buf->next; buf = buf->next;
if (eop) { if (eop) {
@ -123,7 +133,7 @@ static inline void vnic_wq_post(struct vnic_wq *wq,
} }
wq->to_use = buf; 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, static inline void vnic_wq_service(struct vnic_wq *wq,