svn commit: r299444 - head/sys/dev/vnic
Adrian Chadd
adrian.chadd at gmail.com
Wed May 11 15:22:59 UTC 2016
ooo! do you have any plans to integrate it into the kernel RSS options?
-a
On 11 May 2016 at 06:22, Zbigniew Bodek <zbb at freebsd.org> wrote:
> Author: zbb
> Date: Wed May 11 13:22:13 2016
> New Revision: 299444
> URL: https://svnweb.freebsd.org/changeset/base/299444
>
> Log:
> Add HW RSS support to VNIC driver
>
> Based on v1.0 driver provided by Cavium under BSD license.
> Support in-hardware RSS to distribute IP, UDP and TCP traffic
> among available RX Queues and hence multiple CPUs.
>
> Reviewed by: wma
> Obtained from: Semihalf
> Sponsored by: Cavium
> Differential Revision: https://reviews.freebsd.org/D6230
>
> Modified:
> head/sys/dev/vnic/nic.h
> head/sys/dev/vnic/nic_main.c
> head/sys/dev/vnic/nicvf_main.c
> head/sys/dev/vnic/nicvf_queues.c
>
> Modified: head/sys/dev/vnic/nic.h
> ==============================================================================
> --- head/sys/dev/vnic/nic.h Wed May 11 13:20:29 2016 (r299443)
> +++ head/sys/dev/vnic/nic.h Wed May 11 13:22:13 2016 (r299444)
> @@ -176,6 +176,24 @@ struct msix_entry {
> #define NIC_MAX_RSS_IDR_TBL_SIZE (1 << NIC_MAX_RSS_HASH_BITS)
> #define RSS_HASH_KEY_SIZE 5 /* 320 bit key */
>
> +struct nicvf_rss_info {
> + boolean_t enable;
> +#define RSS_L2_EXTENDED_HASH_ENA (1UL << 0)
> +#define RSS_IP_HASH_ENA (1UL << 1)
> +#define RSS_TCP_HASH_ENA (1UL << 2)
> +#define RSS_TCP_SYN_DIS (1UL << 3)
> +#define RSS_UDP_HASH_ENA (1UL << 4)
> +#define RSS_L4_EXTENDED_HASH_ENA (1UL << 5)
> +#define RSS_ROCE_ENA (1UL << 6)
> +#define RSS_L3_BI_DIRECTION_ENA (1UL << 7)
> +#define RSS_L4_BI_DIRECTION_ENA (1UL << 8)
> + uint64_t cfg;
> + uint8_t hash_bits;
> + uint16_t rss_size;
> + uint8_t ind_tbl[NIC_MAX_RSS_IDR_TBL_SIZE];
> + uint64_t key[RSS_HASH_KEY_SIZE];
> +};
> +
> enum rx_stats_reg_offset {
> RX_OCTS = 0x0,
> RX_UCAST = 0x1,
> @@ -285,6 +303,7 @@ struct nicvf {
> boolean_t tns_mode:1;
> boolean_t sqs_mode:1;
> bool loopback_supported:1;
> + struct nicvf_rss_info rss_info;
> uint16_t mtu;
> struct queue_set *qs;
> uint8_t rx_queues;
>
> Modified: head/sys/dev/vnic/nic_main.c
> ==============================================================================
> --- head/sys/dev/vnic/nic_main.c Wed May 11 13:20:29 2016 (r299443)
> +++ head/sys/dev/vnic/nic_main.c Wed May 11 13:22:13 2016 (r299444)
> @@ -103,6 +103,7 @@ struct nicpf {
> uint8_t duplex[MAX_LMAC];
> uint32_t speed[MAX_LMAC];
> uint16_t cpi_base[MAX_NUM_VFS_SUPPORTED];
> + uint16_t rssi_base[MAX_NUM_VFS_SUPPORTED];
> uint16_t rss_ind_tbl_size;
>
> /* MSI-X */
> @@ -744,6 +745,58 @@ nic_config_cpi(struct nicpf *nic, struct
> rssi = ((cpi - cpi_base) & 0x38) >> 3;
> }
> nic->cpi_base[cfg->vf_id] = cpi_base;
> + nic->rssi_base[cfg->vf_id] = rssi_base;
> +}
> +
> +/* Responsds to VF with its RSS indirection table size */
> +static void
> +nic_send_rss_size(struct nicpf *nic, int vf)
> +{
> + union nic_mbx mbx = {};
> + uint64_t *msg;
> +
> + msg = (uint64_t *)&mbx;
> +
> + mbx.rss_size.msg = NIC_MBOX_MSG_RSS_SIZE;
> + mbx.rss_size.ind_tbl_size = nic->rss_ind_tbl_size;
> + nic_send_msg_to_vf(nic, vf, &mbx);
> +}
> +
> +/*
> + * Receive side scaling configuration
> + * configure:
> + * - RSS index
> + * - indir table i.e hash::RQ mapping
> + * - no of hash bits to consider
> + */
> +static void
> +nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
> +{
> + uint8_t qset, idx;
> + uint64_t cpi_cfg, cpi_base, rssi_base, rssi;
> + uint64_t idx_addr;
> +
> + idx = 0;
> + rssi_base = nic->rssi_base[cfg->vf_id] + cfg->tbl_offset;
> +
> + rssi = rssi_base;
> + qset = cfg->vf_id;
> +
> + for (; rssi < (rssi_base + cfg->tbl_len); rssi++) {
> + nic_reg_write(nic, NIC_PF_RSSI_0_4097_RQ | (rssi << 3),
> + (qset << 3) | (cfg->ind_tbl[idx] & 0x7));
> + idx++;
> + }
> +
> + cpi_base = nic->cpi_base[cfg->vf_id];
> + if (pass1_silicon(nic->dev))
> + idx_addr = NIC_PF_CPI_0_2047_CFG;
> + else
> + idx_addr = NIC_PF_MPI_0_2047_CFG;
> + cpi_cfg = nic_reg_read(nic, idx_addr | (cpi_base << 3));
> + cpi_cfg &= ~(0xFUL << 20);
> + cpi_cfg |= (cfg->hash_bits << 20);
> + nic_reg_write(nic, idx_addr | (cpi_base << 3), cpi_cfg);
> }
>
> /*
> @@ -896,6 +949,13 @@ nic_handle_mbx_intr(struct nicpf *nic, i
> case NIC_MBOX_MSG_CPI_CFG:
> nic_config_cpi(nic, &mbx.cpi_cfg);
> break;
> + case NIC_MBOX_MSG_RSS_SIZE:
> + nic_send_rss_size(nic, vf);
> + goto unlock;
> + case NIC_MBOX_MSG_RSS_CFG:
> + case NIC_MBOX_MSG_RSS_CFG_CONT: /* fall through */
> + nic_config_rss(nic, &mbx.rss_cfg);
> + break;
> case NIC_MBOX_MSG_CFG_DONE:
> /* Last message of VF config msg sequence */
> nic->vf_info[vf].vf_enabled = TRUE;
>
> Modified: head/sys/dev/vnic/nicvf_main.c
> ==============================================================================
> --- head/sys/dev/vnic/nicvf_main.c Wed May 11 13:20:29 2016 (r299443)
> +++ head/sys/dev/vnic/nicvf_main.c Wed May 11 13:22:13 2016 (r299444)
> @@ -140,6 +140,7 @@ static int nicvf_allocate_net_interrupts
> static void nicvf_release_all_interrupts(struct nicvf *);
> static int nicvf_hw_set_mac_addr(struct nicvf *, uint8_t *);
> static void nicvf_config_cpi(struct nicvf *);
> +static int nicvf_rss_init(struct nicvf *);
> static int nicvf_init_resources(struct nicvf *);
>
> static int nicvf_setup_ifnet(struct nicvf *);
> @@ -245,6 +246,9 @@ nicvf_attach(device_t dev)
> nic->cpi_alg = CPI_ALG_NONE;
> NICVF_CORE_LOCK(nic);
> nicvf_config_cpi(nic);
> + /* Configure receive side scaling */
> + if (nic->qs->rq_cnt > 1)
> + nicvf_rss_init(nic);
> NICVF_CORE_UNLOCK(nic);
>
> err = nicvf_setup_ifnet(nic);
> @@ -940,6 +944,10 @@ nicvf_handle_mbx_intr(struct nicvf *nic)
> case NIC_MBOX_MSG_NACK:
> nic->pf_nacked = TRUE;
> break;
> + case NIC_MBOX_MSG_RSS_SIZE:
> + nic->rss_info.rss_size = mbx.rss_size.ind_tbl_size;
> + nic->pf_acked = TRUE;
> + break;
> case NIC_MBOX_MSG_BGX_STATS:
> nicvf_read_bgx_stats(nic, &mbx.bgx_stats);
> nic->pf_acked = TRUE;
> @@ -990,6 +998,100 @@ nicvf_config_cpi(struct nicvf *nic)
> nicvf_send_msg_to_pf(nic, &mbx);
> }
>
> +static void
> +nicvf_get_rss_size(struct nicvf *nic)
> +{
> + union nic_mbx mbx = {};
> +
> + mbx.rss_size.msg = NIC_MBOX_MSG_RSS_SIZE;
> + mbx.rss_size.vf_id = nic->vf_id;
> + nicvf_send_msg_to_pf(nic, &mbx);
> +}
> +
> +static void
> +nicvf_config_rss(struct nicvf *nic)
> +{
> + union nic_mbx mbx = {};
> + struct nicvf_rss_info *rss;
> + int ind_tbl_len;
> + int i, nextq;
> +
> + rss = &nic->rss_info;
> + ind_tbl_len = rss->rss_size;
> + nextq = 0;
> +
> + mbx.rss_cfg.vf_id = nic->vf_id;
> + mbx.rss_cfg.hash_bits = rss->hash_bits;
> + while (ind_tbl_len != 0) {
> + mbx.rss_cfg.tbl_offset = nextq;
> + mbx.rss_cfg.tbl_len = MIN(ind_tbl_len,
> + RSS_IND_TBL_LEN_PER_MBX_MSG);
> + mbx.rss_cfg.msg = mbx.rss_cfg.tbl_offset ?
> + NIC_MBOX_MSG_RSS_CFG_CONT : NIC_MBOX_MSG_RSS_CFG;
> +
> + for (i = 0; i < mbx.rss_cfg.tbl_len; i++)
> + mbx.rss_cfg.ind_tbl[i] = rss->ind_tbl[nextq++];
> +
> + nicvf_send_msg_to_pf(nic, &mbx);
> +
> + ind_tbl_len -= mbx.rss_cfg.tbl_len;
> + }
> +}
> +
> +static void
> +nicvf_set_rss_key(struct nicvf *nic)
> +{
> + struct nicvf_rss_info *rss;
> + uint64_t key_addr;
> + int idx;
> +
> + rss = &nic->rss_info;
> + key_addr = NIC_VNIC_RSS_KEY_0_4;
> +
> + for (idx = 0; idx < RSS_HASH_KEY_SIZE; idx++) {
> + nicvf_reg_write(nic, key_addr, rss->key[idx]);
> + key_addr += sizeof(uint64_t);
> + }
> +}
> +
> +static int
> +nicvf_rss_init(struct nicvf *nic)
> +{
> + struct nicvf_rss_info *rss;
> + int idx;
> +
> + nicvf_get_rss_size(nic);
> +
> + rss = &nic->rss_info;
> + if (nic->cpi_alg != CPI_ALG_NONE) {
> + rss->enable = FALSE;
> + rss->hash_bits = 0;
> + return (ENXIO);
> + }
> +
> + rss->enable = TRUE;
> +
> + /* Using the HW reset value for now */
> + rss->key[0] = 0xFEED0BADFEED0BADUL;
> + rss->key[1] = 0xFEED0BADFEED0BADUL;
> + rss->key[2] = 0xFEED0BADFEED0BADUL;
> + rss->key[3] = 0xFEED0BADFEED0BADUL;
> + rss->key[4] = 0xFEED0BADFEED0BADUL;
> +
> + nicvf_set_rss_key(nic);
> +
> + rss->cfg = RSS_IP_HASH_ENA | RSS_TCP_HASH_ENA | RSS_UDP_HASH_ENA;
> + nicvf_reg_write(nic, NIC_VNIC_RSS_CFG, rss->cfg);
> +
> + rss->hash_bits = fls(rss->rss_size) - 1;
> + for (idx = 0; idx < rss->rss_size; idx++)
> + rss->ind_tbl[idx] = idx % nic->rx_queues;
> +
> + nicvf_config_rss(nic);
> +
> + return (0);
> +}
> +
> static int
> nicvf_init_resources(struct nicvf *nic)
> {
>
> Modified: head/sys/dev/vnic/nicvf_queues.c
> ==============================================================================
> --- head/sys/dev/vnic/nicvf_queues.c Wed May 11 13:20:29 2016 (r299443)
> +++ head/sys/dev/vnic/nicvf_queues.c Wed May 11 13:22:13 2016 (r299444)
> @@ -1611,8 +1611,7 @@ nicvf_set_qset_resources(struct nicvf *n
>
> /* Set count of each queue */
> qs->rbdr_cnt = RBDR_CNT;
> - /* With no RSS we stay with single RQ */
> - qs->rq_cnt = 1;
> + qs->rq_cnt = RCV_QUEUE_CNT;
>
> qs->sq_cnt = SND_QUEUE_CNT;
> qs->cq_cnt = CMP_QUEUE_CNT;
>
More information about the svn-src-all
mailing list