From owner-svn-src-all@freebsd.org Wed May 11 13:22:15 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 81570B36E26; Wed, 11 May 2016 13:22:15 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4507D1A4D; Wed, 11 May 2016 13:22:15 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4BDMEJh070574; Wed, 11 May 2016 13:22:14 GMT (envelope-from zbb@FreeBSD.org) Received: (from zbb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4BDMEsp070569; Wed, 11 May 2016 13:22:14 GMT (envelope-from zbb@FreeBSD.org) Message-Id: <201605111322.u4BDMEsp070569@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: zbb set sender to zbb@FreeBSD.org using -f From: Zbigniew Bodek Date: Wed, 11 May 2016 13:22:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r299444 - head/sys/dev/vnic X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 May 2016 13:22:15 -0000 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;