xref: /dpdk/drivers/net/enic/enic_main.c (revision c44d9f01adf3477a80ac93746ffcb16fcf86a27b)
172f3de30SBruce Richardson /*
272f3de30SBruce Richardson  * Copyright 2008-2014 Cisco Systems, Inc.  All rights reserved.
372f3de30SBruce Richardson  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
472f3de30SBruce Richardson  *
572f3de30SBruce Richardson  * Copyright (c) 2014, Cisco Systems, Inc.
672f3de30SBruce Richardson  * All rights reserved.
772f3de30SBruce Richardson  *
872f3de30SBruce Richardson  * Redistribution and use in source and binary forms, with or without
972f3de30SBruce Richardson  * modification, are permitted provided that the following conditions
1072f3de30SBruce Richardson  * are met:
1172f3de30SBruce Richardson  *
1272f3de30SBruce Richardson  * 1. Redistributions of source code must retain the above copyright
1372f3de30SBruce Richardson  * notice, this list of conditions and the following disclaimer.
1472f3de30SBruce Richardson  *
1572f3de30SBruce Richardson  * 2. Redistributions in binary form must reproduce the above copyright
1672f3de30SBruce Richardson  * notice, this list of conditions and the following disclaimer in
1772f3de30SBruce Richardson  * the documentation and/or other materials provided with the
1872f3de30SBruce Richardson  * distribution.
1972f3de30SBruce Richardson  *
2072f3de30SBruce Richardson  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2172f3de30SBruce Richardson  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2272f3de30SBruce Richardson  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2372f3de30SBruce Richardson  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2472f3de30SBruce Richardson  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2572f3de30SBruce Richardson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2672f3de30SBruce Richardson  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2772f3de30SBruce Richardson  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2872f3de30SBruce Richardson  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2972f3de30SBruce Richardson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3072f3de30SBruce Richardson  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3172f3de30SBruce Richardson  * POSSIBILITY OF SUCH DAMAGE.
3272f3de30SBruce Richardson  *
3372f3de30SBruce Richardson  */
3472f3de30SBruce Richardson 
3572f3de30SBruce Richardson #include <stdio.h>
3672f3de30SBruce Richardson 
3772f3de30SBruce Richardson #include <sys/stat.h>
3872f3de30SBruce Richardson #include <sys/mman.h>
3972f3de30SBruce Richardson #include <fcntl.h>
4072f3de30SBruce Richardson #include <libgen.h>
4172f3de30SBruce Richardson 
4272f3de30SBruce Richardson #include <rte_pci.h>
4372f3de30SBruce Richardson #include <rte_memzone.h>
4472f3de30SBruce Richardson #include <rte_malloc.h>
4572f3de30SBruce Richardson #include <rte_mbuf.h>
4672f3de30SBruce Richardson #include <rte_string_fns.h>
4772f3de30SBruce Richardson #include <rte_ethdev.h>
4872f3de30SBruce Richardson 
4972f3de30SBruce Richardson #include "enic_compat.h"
5072f3de30SBruce Richardson #include "enic.h"
5172f3de30SBruce Richardson #include "wq_enet_desc.h"
5272f3de30SBruce Richardson #include "rq_enet_desc.h"
5372f3de30SBruce Richardson #include "cq_enet_desc.h"
5472f3de30SBruce Richardson #include "vnic_enet.h"
5572f3de30SBruce Richardson #include "vnic_dev.h"
5672f3de30SBruce Richardson #include "vnic_wq.h"
5772f3de30SBruce Richardson #include "vnic_rq.h"
5872f3de30SBruce Richardson #include "vnic_cq.h"
5972f3de30SBruce Richardson #include "vnic_intr.h"
6072f3de30SBruce Richardson #include "vnic_nic.h"
61d739ba4cSJohn Daley #include "enic_vnic_wq.h"
6272f3de30SBruce Richardson 
6372f3de30SBruce Richardson static inline int enic_is_sriov_vf(struct enic *enic)
6472f3de30SBruce Richardson {
6572f3de30SBruce Richardson 	return enic->pdev->id.device_id == PCI_DEVICE_ID_CISCO_VIC_ENET_VF;
6672f3de30SBruce Richardson }
6772f3de30SBruce Richardson 
6872f3de30SBruce Richardson static int is_zero_addr(uint8_t *addr)
6972f3de30SBruce Richardson {
7072f3de30SBruce Richardson 	return !(addr[0] |  addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
7172f3de30SBruce Richardson }
7272f3de30SBruce Richardson 
7372f3de30SBruce Richardson static int is_mcast_addr(uint8_t *addr)
7472f3de30SBruce Richardson {
7572f3de30SBruce Richardson 	return addr[0] & 1;
7672f3de30SBruce Richardson }
7772f3de30SBruce Richardson 
7872f3de30SBruce Richardson static int is_eth_addr_valid(uint8_t *addr)
7972f3de30SBruce Richardson {
8072f3de30SBruce Richardson 	return !is_mcast_addr(addr) && !is_zero_addr(addr);
8172f3de30SBruce Richardson }
8272f3de30SBruce Richardson 
83947d860cSJohn Daley static void
84947d860cSJohn Daley enic_rxmbuf_queue_release(struct enic *enic, struct vnic_rq *rq)
8572f3de30SBruce Richardson {
86947d860cSJohn Daley 	uint16_t i;
8772f3de30SBruce Richardson 
88947d860cSJohn Daley 	if (!rq || !rq->mbuf_ring) {
89947d860cSJohn Daley 		dev_debug(enic, "Pointer to rq or mbuf_ring is NULL");
90947d860cSJohn Daley 		return;
9172f3de30SBruce Richardson 	}
9272f3de30SBruce Richardson 
93947d860cSJohn Daley 	for (i = 0; i < enic->config.rq_desc_count; i++) {
94947d860cSJohn Daley 		if (rq->mbuf_ring[i]) {
95947d860cSJohn Daley 			rte_pktmbuf_free_seg(rq->mbuf_ring[i]);
96947d860cSJohn Daley 			rq->mbuf_ring[i] = NULL;
97947d860cSJohn Daley 		}
98947d860cSJohn Daley 	}
99947d860cSJohn Daley }
100947d860cSJohn Daley 
101947d860cSJohn Daley 
10272f3de30SBruce Richardson void enic_set_hdr_split_size(struct enic *enic, u16 split_hdr_size)
10372f3de30SBruce Richardson {
10472f3de30SBruce Richardson 	vnic_set_hdr_split_size(enic->vdev, split_hdr_size);
10572f3de30SBruce Richardson }
10672f3de30SBruce Richardson 
10772f3de30SBruce Richardson static void enic_free_wq_buf(__rte_unused struct vnic_wq *wq, struct vnic_wq_buf *buf)
10872f3de30SBruce Richardson {
10972f3de30SBruce Richardson 	struct rte_mbuf *mbuf = (struct rte_mbuf *)buf->os_buf;
11072f3de30SBruce Richardson 
11172f3de30SBruce Richardson 	rte_mempool_put(mbuf->pool, mbuf);
11272f3de30SBruce Richardson 	buf->os_buf = NULL;
11372f3de30SBruce Richardson }
11472f3de30SBruce Richardson 
11572f3de30SBruce Richardson static void enic_wq_free_buf(struct vnic_wq *wq,
11672f3de30SBruce Richardson 	__rte_unused struct cq_desc *cq_desc,
11772f3de30SBruce Richardson 	struct vnic_wq_buf *buf,
11872f3de30SBruce Richardson 	__rte_unused void *opaque)
11972f3de30SBruce Richardson {
12072f3de30SBruce Richardson 	enic_free_wq_buf(wq, buf);
12172f3de30SBruce Richardson }
12272f3de30SBruce Richardson 
12372f3de30SBruce Richardson static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
12472f3de30SBruce Richardson 	__rte_unused u8 type, u16 q_number, u16 completed_index, void *opaque)
12572f3de30SBruce Richardson {
12672f3de30SBruce Richardson 	struct enic *enic = vnic_dev_priv(vdev);
12772f3de30SBruce Richardson 
12872f3de30SBruce Richardson 	vnic_wq_service(&enic->wq[q_number], cq_desc,
12972f3de30SBruce Richardson 		completed_index, enic_wq_free_buf,
13072f3de30SBruce Richardson 		opaque);
13172f3de30SBruce Richardson 
13272f3de30SBruce Richardson 	return 0;
13372f3de30SBruce Richardson }
13472f3de30SBruce Richardson 
13572f3de30SBruce Richardson static void enic_log_q_error(struct enic *enic)
13672f3de30SBruce Richardson {
13772f3de30SBruce Richardson 	unsigned int i;
13872f3de30SBruce Richardson 	u32 error_status;
13972f3de30SBruce Richardson 
14072f3de30SBruce Richardson 	for (i = 0; i < enic->wq_count; i++) {
14172f3de30SBruce Richardson 		error_status = vnic_wq_error_status(&enic->wq[i]);
14272f3de30SBruce Richardson 		if (error_status)
14372f3de30SBruce Richardson 			dev_err(enic, "WQ[%d] error_status %d\n", i,
14472f3de30SBruce Richardson 				error_status);
14572f3de30SBruce Richardson 	}
14672f3de30SBruce Richardson 
14772f3de30SBruce Richardson 	for (i = 0; i < enic->rq_count; i++) {
14872f3de30SBruce Richardson 		error_status = vnic_rq_error_status(&enic->rq[i]);
14972f3de30SBruce Richardson 		if (error_status)
15072f3de30SBruce Richardson 			dev_err(enic, "RQ[%d] error_status %d\n", i,
15172f3de30SBruce Richardson 				error_status);
15272f3de30SBruce Richardson 	}
15372f3de30SBruce Richardson }
15472f3de30SBruce Richardson 
15572f3de30SBruce Richardson unsigned int enic_cleanup_wq(struct enic *enic, struct vnic_wq *wq)
15672f3de30SBruce Richardson {
15772f3de30SBruce Richardson 	unsigned int cq = enic_cq_wq(enic, wq->index);
15872f3de30SBruce Richardson 
15972f3de30SBruce Richardson 	/* Return the work done */
16072f3de30SBruce Richardson 	return vnic_cq_service(&enic->cq[cq],
16172f3de30SBruce Richardson 		-1 /*wq_work_to_do*/, enic_wq_service, NULL);
16272f3de30SBruce Richardson }
16372f3de30SBruce Richardson 
164d739ba4cSJohn Daley void enic_post_wq_index(struct vnic_wq *wq)
165d739ba4cSJohn Daley {
166d739ba4cSJohn Daley 	enic_vnic_post_wq_index(wq);
167d739ba4cSJohn Daley }
16872f3de30SBruce Richardson 
169d739ba4cSJohn Daley void enic_send_pkt(struct enic *enic, struct vnic_wq *wq,
17072f3de30SBruce Richardson 		   struct rte_mbuf *tx_pkt, unsigned short len,
171d739ba4cSJohn Daley 		   uint8_t sop, uint8_t eop, uint8_t cq_entry,
17272f3de30SBruce Richardson 		   uint16_t ol_flags, uint16_t vlan_tag)
17372f3de30SBruce Richardson {
17472f3de30SBruce Richardson 	struct wq_enet_desc *desc = vnic_wq_next_desc(wq);
17572f3de30SBruce Richardson 	uint16_t mss = 0;
17672f3de30SBruce Richardson 	uint8_t vlan_tag_insert = 0;
17772f3de30SBruce Richardson 	uint64_t bus_addr = (dma_addr_t)
17839ab35a3SYoann Desmouceaux 	    (tx_pkt->buf_physaddr + tx_pkt->data_off);
17972f3de30SBruce Richardson 
18072f3de30SBruce Richardson 	if (sop) {
18172f3de30SBruce Richardson 		if (ol_flags & PKT_TX_VLAN_PKT)
18272f3de30SBruce Richardson 			vlan_tag_insert = 1;
18372f3de30SBruce Richardson 
18472f3de30SBruce Richardson 		if (enic->hw_ip_checksum) {
18572f3de30SBruce Richardson 			if (ol_flags & PKT_TX_IP_CKSUM)
18672f3de30SBruce Richardson 				mss |= ENIC_CALC_IP_CKSUM;
18772f3de30SBruce Richardson 
18872f3de30SBruce Richardson 			if (ol_flags & PKT_TX_TCP_UDP_CKSUM)
18972f3de30SBruce Richardson 				mss |= ENIC_CALC_TCP_UDP_CKSUM;
19072f3de30SBruce Richardson 		}
19172f3de30SBruce Richardson 	}
19272f3de30SBruce Richardson 
19372f3de30SBruce Richardson 	wq_enet_desc_enc(desc,
19472f3de30SBruce Richardson 		bus_addr,
19572f3de30SBruce Richardson 		len,
19672f3de30SBruce Richardson 		mss,
19772f3de30SBruce Richardson 		0 /* header_length */,
19872f3de30SBruce Richardson 		0 /* offload_mode WQ_ENET_OFFLOAD_MODE_CSUM */,
19972f3de30SBruce Richardson 		eop,
20072f3de30SBruce Richardson 		cq_entry,
20172f3de30SBruce Richardson 		0 /* fcoe_encap */,
20272f3de30SBruce Richardson 		vlan_tag_insert,
20372f3de30SBruce Richardson 		vlan_tag,
20472f3de30SBruce Richardson 		0 /* loopback */);
20572f3de30SBruce Richardson 
206d739ba4cSJohn Daley 	enic_vnic_post_wq(wq, (void *)tx_pkt, bus_addr, len,
207d739ba4cSJohn Daley 			  sop,
20872f3de30SBruce Richardson 			  1 /*desc_skip_cnt*/,
20972f3de30SBruce Richardson 			  cq_entry,
21072f3de30SBruce Richardson 			  0 /*compressed send*/,
21172f3de30SBruce Richardson 			  0 /*wrid*/);
21272f3de30SBruce Richardson }
21372f3de30SBruce Richardson 
21465b5434dSJohn Daley static void enic_clear_soft_stats(struct enic *enic)
21565b5434dSJohn Daley {
21665b5434dSJohn Daley 	struct enic_soft_stats *soft_stats = &enic->soft_stats;
21765b5434dSJohn Daley 	rte_atomic64_clear(&soft_stats->rx_nombuf);
218*c44d9f01SJohn Daley 	rte_atomic64_clear(&soft_stats->rx_packet_errors);
21965b5434dSJohn Daley }
22065b5434dSJohn Daley 
22165b5434dSJohn Daley static void enic_init_soft_stats(struct enic *enic)
22265b5434dSJohn Daley {
22365b5434dSJohn Daley 	struct enic_soft_stats *soft_stats = &enic->soft_stats;
22465b5434dSJohn Daley 	rte_atomic64_init(&soft_stats->rx_nombuf);
225*c44d9f01SJohn Daley 	rte_atomic64_init(&soft_stats->rx_packet_errors);
22665b5434dSJohn Daley 	enic_clear_soft_stats(enic);
22765b5434dSJohn Daley }
22865b5434dSJohn Daley 
22972f3de30SBruce Richardson void enic_dev_stats_clear(struct enic *enic)
23072f3de30SBruce Richardson {
23172f3de30SBruce Richardson 	if (vnic_dev_stats_clear(enic->vdev))
23272f3de30SBruce Richardson 		dev_err(enic, "Error in clearing stats\n");
23365b5434dSJohn Daley 	enic_clear_soft_stats(enic);
23472f3de30SBruce Richardson }
23572f3de30SBruce Richardson 
23672f3de30SBruce Richardson void enic_dev_stats_get(struct enic *enic, struct rte_eth_stats *r_stats)
23772f3de30SBruce Richardson {
23872f3de30SBruce Richardson 	struct vnic_stats *stats;
239*c44d9f01SJohn Daley 	struct enic_soft_stats *soft_stats = &enic->soft_stats;
240*c44d9f01SJohn Daley 	int64_t rx_truncated;
241*c44d9f01SJohn Daley 	uint64_t rx_packet_errors;
24272f3de30SBruce Richardson 
24372f3de30SBruce Richardson 	if (vnic_dev_stats_dump(enic->vdev, &stats)) {
24472f3de30SBruce Richardson 		dev_err(enic, "Error in getting stats\n");
24572f3de30SBruce Richardson 		return;
24672f3de30SBruce Richardson 	}
24772f3de30SBruce Richardson 
248*c44d9f01SJohn Daley 	/* The number of truncated packets can only be calculated by
249*c44d9f01SJohn Daley 	 * subtracting a hardware counter from error packets received by
250*c44d9f01SJohn Daley 	 * the driver. Note: this causes transient inaccuracies in the
251*c44d9f01SJohn Daley 	 * ipackets count. Also, the length of truncated packets are
252*c44d9f01SJohn Daley 	 * counted in ibytes even though truncated packets are dropped
253*c44d9f01SJohn Daley 	 * which can make ibytes be slightly higher than it should be.
254*c44d9f01SJohn Daley 	 */
255*c44d9f01SJohn Daley 	rx_packet_errors = rte_atomic64_read(&soft_stats->rx_packet_errors);
256*c44d9f01SJohn Daley 	rx_truncated = rx_packet_errors - stats->rx.rx_errors;
257*c44d9f01SJohn Daley 
258*c44d9f01SJohn Daley 	r_stats->ipackets = stats->rx.rx_frames_ok - rx_truncated;
25972f3de30SBruce Richardson 	r_stats->opackets = stats->tx.tx_frames_ok;
26072f3de30SBruce Richardson 
26172f3de30SBruce Richardson 	r_stats->ibytes = stats->rx.rx_bytes_ok;
26272f3de30SBruce Richardson 	r_stats->obytes = stats->tx.tx_bytes_ok;
26372f3de30SBruce Richardson 
26465b5434dSJohn Daley 	r_stats->ierrors = stats->rx.rx_errors + stats->rx.rx_drop;
26572f3de30SBruce Richardson 	r_stats->oerrors = stats->tx.tx_errors;
26672f3de30SBruce Richardson 
267*c44d9f01SJohn Daley 	r_stats->imissed = stats->rx.rx_no_bufs + rx_truncated;
2687182d3e7SJohn Daley 
26965b5434dSJohn Daley 	r_stats->rx_nombuf = rte_atomic64_read(&soft_stats->rx_nombuf);
27072f3de30SBruce Richardson }
27172f3de30SBruce Richardson 
27272f3de30SBruce Richardson void enic_del_mac_address(struct enic *enic)
27372f3de30SBruce Richardson {
27472f3de30SBruce Richardson 	if (vnic_dev_del_addr(enic->vdev, enic->mac_addr))
27572f3de30SBruce Richardson 		dev_err(enic, "del mac addr failed\n");
27672f3de30SBruce Richardson }
27772f3de30SBruce Richardson 
27872f3de30SBruce Richardson void enic_set_mac_address(struct enic *enic, uint8_t *mac_addr)
27972f3de30SBruce Richardson {
28072f3de30SBruce Richardson 	int err;
28172f3de30SBruce Richardson 
28272f3de30SBruce Richardson 	if (!is_eth_addr_valid(mac_addr)) {
28372f3de30SBruce Richardson 		dev_err(enic, "invalid mac address\n");
28472f3de30SBruce Richardson 		return;
28572f3de30SBruce Richardson 	}
28672f3de30SBruce Richardson 
28772f3de30SBruce Richardson 	err = vnic_dev_del_addr(enic->vdev, mac_addr);
28872f3de30SBruce Richardson 	if (err) {
28972f3de30SBruce Richardson 		dev_err(enic, "del mac addr failed\n");
29072f3de30SBruce Richardson 		return;
29172f3de30SBruce Richardson 	}
29272f3de30SBruce Richardson 
29372f3de30SBruce Richardson 	ether_addr_copy((struct ether_addr *)mac_addr,
29472f3de30SBruce Richardson 		(struct ether_addr *)enic->mac_addr);
29572f3de30SBruce Richardson 
29672f3de30SBruce Richardson 	err = vnic_dev_add_addr(enic->vdev, mac_addr);
29772f3de30SBruce Richardson 	if (err) {
29872f3de30SBruce Richardson 		dev_err(enic, "add mac addr failed\n");
29972f3de30SBruce Richardson 		return;
30072f3de30SBruce Richardson 	}
30172f3de30SBruce Richardson }
30272f3de30SBruce Richardson 
30372f3de30SBruce Richardson static void
304947d860cSJohn Daley enic_free_rq_buf(struct rte_mbuf **mbuf)
30572f3de30SBruce Richardson {
306947d860cSJohn Daley 	if (*mbuf == NULL)
30772f3de30SBruce Richardson 		return;
30872f3de30SBruce Richardson 
309947d860cSJohn Daley 	rte_pktmbuf_free(*mbuf);
310947d860cSJohn Daley 	mbuf = NULL;
31172f3de30SBruce Richardson }
31272f3de30SBruce Richardson 
31372f3de30SBruce Richardson void enic_init_vnic_resources(struct enic *enic)
31472f3de30SBruce Richardson {
31572f3de30SBruce Richardson 	unsigned int error_interrupt_enable = 1;
31672f3de30SBruce Richardson 	unsigned int error_interrupt_offset = 0;
31772f3de30SBruce Richardson 	unsigned int index = 0;
31872f3de30SBruce Richardson 
31972f3de30SBruce Richardson 	for (index = 0; index < enic->rq_count; index++) {
32072f3de30SBruce Richardson 		vnic_rq_init(&enic->rq[index],
32172f3de30SBruce Richardson 			enic_cq_rq(enic, index),
32272f3de30SBruce Richardson 			error_interrupt_enable,
32372f3de30SBruce Richardson 			error_interrupt_offset);
32472f3de30SBruce Richardson 	}
32572f3de30SBruce Richardson 
32672f3de30SBruce Richardson 	for (index = 0; index < enic->wq_count; index++) {
32772f3de30SBruce Richardson 		vnic_wq_init(&enic->wq[index],
32872f3de30SBruce Richardson 			enic_cq_wq(enic, index),
32972f3de30SBruce Richardson 			error_interrupt_enable,
33072f3de30SBruce Richardson 			error_interrupt_offset);
33172f3de30SBruce Richardson 	}
33272f3de30SBruce Richardson 
33372f3de30SBruce Richardson 	vnic_dev_stats_clear(enic->vdev);
33472f3de30SBruce Richardson 
33572f3de30SBruce Richardson 	for (index = 0; index < enic->cq_count; index++) {
33672f3de30SBruce Richardson 		vnic_cq_init(&enic->cq[index],
33772f3de30SBruce Richardson 			0 /* flow_control_enable */,
33872f3de30SBruce Richardson 			1 /* color_enable */,
33972f3de30SBruce Richardson 			0 /* cq_head */,
34072f3de30SBruce Richardson 			0 /* cq_tail */,
34172f3de30SBruce Richardson 			1 /* cq_tail_color */,
34272f3de30SBruce Richardson 			0 /* interrupt_enable */,
34372f3de30SBruce Richardson 			1 /* cq_entry_enable */,
34472f3de30SBruce Richardson 			0 /* cq_message_enable */,
34572f3de30SBruce Richardson 			0 /* interrupt offset */,
34672f3de30SBruce Richardson 			0 /* cq_message_addr */);
34772f3de30SBruce Richardson 	}
34872f3de30SBruce Richardson 
34972f3de30SBruce Richardson 	vnic_intr_init(&enic->intr,
35072f3de30SBruce Richardson 		enic->config.intr_timer_usec,
35172f3de30SBruce Richardson 		enic->config.intr_timer_type,
35272f3de30SBruce Richardson 		/*mask_on_assertion*/1);
35372f3de30SBruce Richardson }
35472f3de30SBruce Richardson 
35572f3de30SBruce Richardson 
356947d860cSJohn Daley static int
357947d860cSJohn Daley enic_alloc_rx_queue_mbufs(struct enic *enic, struct vnic_rq *rq)
35872f3de30SBruce Richardson {
359947d860cSJohn Daley 	struct rte_mbuf *mb;
360947d860cSJohn Daley 	struct rq_enet_desc *rqd = rq->ring.descs;
361947d860cSJohn Daley 	unsigned i;
36272f3de30SBruce Richardson 	dma_addr_t dma_addr;
36372f3de30SBruce Richardson 
364bba57df3SNelson Escobar 	dev_debug(enic, "queue %u, allocating %u rx queue mbufs\n", rq->index,
365947d860cSJohn Daley 		  rq->ring.desc_count);
366947d860cSJohn Daley 
367947d860cSJohn Daley 	for (i = 0; i < rq->ring.desc_count; i++, rqd++) {
368fbfd9955SOlivier Matz 		mb = rte_mbuf_raw_alloc(rq->mp);
369947d860cSJohn Daley 		if (mb == NULL) {
370bba57df3SNelson Escobar 			dev_err(enic, "RX mbuf alloc failed queue_id=%u\n",
371947d860cSJohn Daley 			(unsigned)rq->index);
372947d860cSJohn Daley 			return -ENOMEM;
37372f3de30SBruce Richardson 		}
37472f3de30SBruce Richardson 
3754a3259d6SJohn Daley 		dma_addr = (dma_addr_t)(mb->buf_physaddr
3764a3259d6SJohn Daley 			   + RTE_PKTMBUF_HEADROOM);
377947d860cSJohn Daley 
378947d860cSJohn Daley 		rq_enet_desc_enc(rqd, dma_addr, RQ_ENET_TYPE_ONLY_SOP,
3794a3259d6SJohn Daley 				 mb->buf_len - RTE_PKTMBUF_HEADROOM);
380947d860cSJohn Daley 		rq->mbuf_ring[i] = mb;
38172f3de30SBruce Richardson 	}
38272f3de30SBruce Richardson 
383947d860cSJohn Daley 	/* make sure all prior writes are complete before doing the PIO write */
384947d860cSJohn Daley 	rte_rmb();
38572f3de30SBruce Richardson 
386947d860cSJohn Daley 	/* Post all but the last 2 cache lines' worth of descriptors */
387947d860cSJohn Daley 	rq->posted_index = rq->ring.desc_count - (2 * RTE_CACHE_LINE_SIZE
388947d860cSJohn Daley 			/ sizeof(struct rq_enet_desc));
389947d860cSJohn Daley 	rq->rx_nb_hold = 0;
39072f3de30SBruce Richardson 
391947d860cSJohn Daley 	dev_debug(enic, "port=%u, qidx=%u, Write %u posted idx, %u sw held\n",
392947d860cSJohn Daley 		enic->port_id, rq->index, rq->posted_index, rq->rx_nb_hold);
393947d860cSJohn Daley 	iowrite32(rq->posted_index, &rq->ctrl->posted_index);
394947d860cSJohn Daley 	rte_rmb();
39572f3de30SBruce Richardson 
39672f3de30SBruce Richardson 	return 0;
39772f3de30SBruce Richardson 
39872f3de30SBruce Richardson }
39972f3de30SBruce Richardson 
40072f3de30SBruce Richardson static void *
40172f3de30SBruce Richardson enic_alloc_consistent(__rte_unused void *priv, size_t size,
40272f3de30SBruce Richardson 	dma_addr_t *dma_handle, u8 *name)
40372f3de30SBruce Richardson {
40472f3de30SBruce Richardson 	void *vaddr;
40572f3de30SBruce Richardson 	const struct rte_memzone *rz;
40672f3de30SBruce Richardson 	*dma_handle = 0;
40772f3de30SBruce Richardson 
40872f3de30SBruce Richardson 	rz = rte_memzone_reserve_aligned((const char *)name,
4097a0b8b7cSDavid Marchand 					 size, SOCKET_ID_ANY, 0, ENIC_ALIGN);
41072f3de30SBruce Richardson 	if (!rz) {
411bba57df3SNelson Escobar 		pr_err("%s : Failed to allocate memory requested for %s\n",
41272f3de30SBruce Richardson 			__func__, name);
41372f3de30SBruce Richardson 		return NULL;
41472f3de30SBruce Richardson 	}
41572f3de30SBruce Richardson 
41672f3de30SBruce Richardson 	vaddr = rz->addr;
41772f3de30SBruce Richardson 	*dma_handle = (dma_addr_t)rz->phys_addr;
41872f3de30SBruce Richardson 
41972f3de30SBruce Richardson 	return vaddr;
42072f3de30SBruce Richardson }
42172f3de30SBruce Richardson 
42272f3de30SBruce Richardson static void
42372f3de30SBruce Richardson enic_free_consistent(__rte_unused struct rte_pci_device *hwdev,
42472f3de30SBruce Richardson 	__rte_unused size_t size,
42572f3de30SBruce Richardson 	__rte_unused void *vaddr,
42672f3de30SBruce Richardson 	__rte_unused dma_addr_t dma_handle)
42772f3de30SBruce Richardson {
42872f3de30SBruce Richardson 	/* Nothing to be done */
42972f3de30SBruce Richardson }
43072f3de30SBruce Richardson 
43172f3de30SBruce Richardson static void
43272f3de30SBruce Richardson enic_intr_handler(__rte_unused struct rte_intr_handle *handle,
43372f3de30SBruce Richardson 	void *arg)
43472f3de30SBruce Richardson {
43572f3de30SBruce Richardson 	struct enic *enic = pmd_priv((struct rte_eth_dev *)arg);
43672f3de30SBruce Richardson 
43772f3de30SBruce Richardson 	vnic_intr_return_all_credits(&enic->intr);
43872f3de30SBruce Richardson 
43972f3de30SBruce Richardson 	enic_log_q_error(enic);
44072f3de30SBruce Richardson }
44172f3de30SBruce Richardson 
44272f3de30SBruce Richardson int enic_enable(struct enic *enic)
44372f3de30SBruce Richardson {
44472f3de30SBruce Richardson 	unsigned int index;
445947d860cSJohn Daley 	int err;
44672f3de30SBruce Richardson 	struct rte_eth_dev *eth_dev = enic->rte_dev;
44772f3de30SBruce Richardson 
44872f3de30SBruce Richardson 	eth_dev->data->dev_link.link_speed = vnic_dev_port_speed(enic->vdev);
44972f3de30SBruce Richardson 	eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
45072f3de30SBruce Richardson 	vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */
45172f3de30SBruce Richardson 
45272f3de30SBruce Richardson 	if (enic_clsf_init(enic))
45372f3de30SBruce Richardson 		dev_warning(enic, "Init of hash table for clsf failed."\
45472f3de30SBruce Richardson 			"Flow director feature will not work\n");
45572f3de30SBruce Richardson 
45672f3de30SBruce Richardson 	for (index = 0; index < enic->rq_count; index++) {
457947d860cSJohn Daley 		err = enic_alloc_rx_queue_mbufs(enic, &enic->rq[index]);
458947d860cSJohn Daley 		if (err) {
459947d860cSJohn Daley 			dev_err(enic, "Failed to alloc RX queue mbufs\n");
460947d860cSJohn Daley 			return err;
46172f3de30SBruce Richardson 		}
46272f3de30SBruce Richardson 	}
46372f3de30SBruce Richardson 
46472f3de30SBruce Richardson 	for (index = 0; index < enic->wq_count; index++)
46572f3de30SBruce Richardson 		vnic_wq_enable(&enic->wq[index]);
46672f3de30SBruce Richardson 	for (index = 0; index < enic->rq_count; index++)
46772f3de30SBruce Richardson 		vnic_rq_enable(&enic->rq[index]);
46872f3de30SBruce Richardson 
46972f3de30SBruce Richardson 	vnic_dev_enable_wait(enic->vdev);
47072f3de30SBruce Richardson 
47172f3de30SBruce Richardson 	/* Register and enable error interrupt */
47272f3de30SBruce Richardson 	rte_intr_callback_register(&(enic->pdev->intr_handle),
47372f3de30SBruce Richardson 		enic_intr_handler, (void *)enic->rte_dev);
47472f3de30SBruce Richardson 
47572f3de30SBruce Richardson 	rte_intr_enable(&(enic->pdev->intr_handle));
47672f3de30SBruce Richardson 	vnic_intr_unmask(&enic->intr);
47772f3de30SBruce Richardson 
47872f3de30SBruce Richardson 	return 0;
47972f3de30SBruce Richardson }
48072f3de30SBruce Richardson 
48172f3de30SBruce Richardson int enic_alloc_intr_resources(struct enic *enic)
48272f3de30SBruce Richardson {
48372f3de30SBruce Richardson 	int err;
48472f3de30SBruce Richardson 
48572f3de30SBruce Richardson 	dev_info(enic, "vNIC resources used:  "\
48672f3de30SBruce Richardson 		"wq %d rq %d cq %d intr %d\n",
48772f3de30SBruce Richardson 		enic->wq_count, enic->rq_count,
48872f3de30SBruce Richardson 		enic->cq_count, enic->intr_count);
48972f3de30SBruce Richardson 
49072f3de30SBruce Richardson 	err = vnic_intr_alloc(enic->vdev, &enic->intr, 0);
49172f3de30SBruce Richardson 	if (err)
49272f3de30SBruce Richardson 		enic_free_vnic_resources(enic);
49372f3de30SBruce Richardson 
49472f3de30SBruce Richardson 	return err;
49572f3de30SBruce Richardson }
49672f3de30SBruce Richardson 
49772f3de30SBruce Richardson void enic_free_rq(void *rxq)
49872f3de30SBruce Richardson {
49972f3de30SBruce Richardson 	struct vnic_rq *rq = (struct vnic_rq *)rxq;
50072f3de30SBruce Richardson 	struct enic *enic = vnic_dev_priv(rq->vdev);
50172f3de30SBruce Richardson 
502947d860cSJohn Daley 	enic_rxmbuf_queue_release(enic, rq);
503947d860cSJohn Daley 	rte_free(rq->mbuf_ring);
504947d860cSJohn Daley 	rq->mbuf_ring = NULL;
50572f3de30SBruce Richardson 	vnic_rq_free(rq);
50672f3de30SBruce Richardson 	vnic_cq_free(&enic->cq[rq->index]);
50772f3de30SBruce Richardson }
50872f3de30SBruce Richardson 
50972f3de30SBruce Richardson void enic_start_wq(struct enic *enic, uint16_t queue_idx)
51072f3de30SBruce Richardson {
51172f3de30SBruce Richardson 	vnic_wq_enable(&enic->wq[queue_idx]);
51272f3de30SBruce Richardson }
51372f3de30SBruce Richardson 
51472f3de30SBruce Richardson int enic_stop_wq(struct enic *enic, uint16_t queue_idx)
51572f3de30SBruce Richardson {
51672f3de30SBruce Richardson 	return vnic_wq_disable(&enic->wq[queue_idx]);
51772f3de30SBruce Richardson }
51872f3de30SBruce Richardson 
51972f3de30SBruce Richardson void enic_start_rq(struct enic *enic, uint16_t queue_idx)
52072f3de30SBruce Richardson {
52172f3de30SBruce Richardson 	vnic_rq_enable(&enic->rq[queue_idx]);
52272f3de30SBruce Richardson }
52372f3de30SBruce Richardson 
52472f3de30SBruce Richardson int enic_stop_rq(struct enic *enic, uint16_t queue_idx)
52572f3de30SBruce Richardson {
52672f3de30SBruce Richardson 	return vnic_rq_disable(&enic->rq[queue_idx]);
52772f3de30SBruce Richardson }
52872f3de30SBruce Richardson 
52972f3de30SBruce Richardson int enic_alloc_rq(struct enic *enic, uint16_t queue_idx,
53072f3de30SBruce Richardson 	unsigned int socket_id, struct rte_mempool *mp,
53172f3de30SBruce Richardson 	uint16_t nb_desc)
53272f3de30SBruce Richardson {
533947d860cSJohn Daley 	int rc;
53472f3de30SBruce Richardson 	struct vnic_rq *rq = &enic->rq[queue_idx];
53572f3de30SBruce Richardson 
53672f3de30SBruce Richardson 	rq->socket_id = socket_id;
53772f3de30SBruce Richardson 	rq->mp = mp;
53872f3de30SBruce Richardson 
53972f3de30SBruce Richardson 	if (nb_desc) {
54072f3de30SBruce Richardson 		if (nb_desc > enic->config.rq_desc_count) {
54172f3de30SBruce Richardson 			dev_warning(enic,
54272f3de30SBruce Richardson 				"RQ %d - number of rx desc in cmd line (%d)"\
54372f3de30SBruce Richardson 				"is greater than that in the UCSM/CIMC adapter"\
54472f3de30SBruce Richardson 				"policy.  Applying the value in the adapter "\
54572f3de30SBruce Richardson 				"policy (%d).\n",
54672f3de30SBruce Richardson 				queue_idx, nb_desc, enic->config.rq_desc_count);
54765ca78fdSNelson Escobar 			nb_desc = enic->config.rq_desc_count;
54872f3de30SBruce Richardson 		}
54965ca78fdSNelson Escobar 		dev_info(enic, "RX Queues - effective number of descs:%d\n",
55065ca78fdSNelson Escobar 			 nb_desc);
55172f3de30SBruce Richardson 	}
55272f3de30SBruce Richardson 
55372f3de30SBruce Richardson 	/* Allocate queue resources */
554947d860cSJohn Daley 	rc = vnic_rq_alloc(enic->vdev, rq, queue_idx,
55565ca78fdSNelson Escobar 		nb_desc, sizeof(struct rq_enet_desc));
556947d860cSJohn Daley 	if (rc) {
55772f3de30SBruce Richardson 		dev_err(enic, "error in allocation of rq\n");
558947d860cSJohn Daley 		goto err_exit;
55972f3de30SBruce Richardson 	}
56072f3de30SBruce Richardson 
561947d860cSJohn Daley 	rc = vnic_cq_alloc(enic->vdev, &enic->cq[queue_idx], queue_idx,
56265ca78fdSNelson Escobar 		socket_id, nb_desc,
56372f3de30SBruce Richardson 		sizeof(struct cq_enet_rq_desc));
564947d860cSJohn Daley 	if (rc) {
56572f3de30SBruce Richardson 		dev_err(enic, "error in allocation of cq for rq\n");
566947d860cSJohn Daley 		goto err_free_rq_exit;
56772f3de30SBruce Richardson 	}
56872f3de30SBruce Richardson 
569947d860cSJohn Daley 	/* Allocate the mbuf ring */
570947d860cSJohn Daley 	rq->mbuf_ring = (struct rte_mbuf **)rte_zmalloc_socket("rq->mbuf_ring",
57165ca78fdSNelson Escobar 			sizeof(struct rte_mbuf *) * nb_desc,
572947d860cSJohn Daley 			RTE_CACHE_LINE_SIZE, rq->socket_id);
573947d860cSJohn Daley 
574947d860cSJohn Daley 	if (rq->mbuf_ring != NULL)
575947d860cSJohn Daley 		return 0;
576947d860cSJohn Daley 
577947d860cSJohn Daley 	/* cleanup on error */
578947d860cSJohn Daley 	vnic_cq_free(&enic->cq[queue_idx]);
579947d860cSJohn Daley err_free_rq_exit:
580947d860cSJohn Daley 	vnic_rq_free(rq);
581947d860cSJohn Daley err_exit:
582947d860cSJohn Daley 	return -ENOMEM;
58372f3de30SBruce Richardson }
58472f3de30SBruce Richardson 
58572f3de30SBruce Richardson void enic_free_wq(void *txq)
58672f3de30SBruce Richardson {
58772f3de30SBruce Richardson 	struct vnic_wq *wq = (struct vnic_wq *)txq;
58872f3de30SBruce Richardson 	struct enic *enic = vnic_dev_priv(wq->vdev);
58972f3de30SBruce Richardson 
59072f3de30SBruce Richardson 	vnic_wq_free(wq);
59172f3de30SBruce Richardson 	vnic_cq_free(&enic->cq[enic->rq_count + wq->index]);
59272f3de30SBruce Richardson }
59372f3de30SBruce Richardson 
59472f3de30SBruce Richardson int enic_alloc_wq(struct enic *enic, uint16_t queue_idx,
59572f3de30SBruce Richardson 	unsigned int socket_id, uint16_t nb_desc)
59672f3de30SBruce Richardson {
59772f3de30SBruce Richardson 	int err;
59872f3de30SBruce Richardson 	struct vnic_wq *wq = &enic->wq[queue_idx];
59972f3de30SBruce Richardson 	unsigned int cq_index = enic_cq_wq(enic, queue_idx);
60072f3de30SBruce Richardson 
60172f3de30SBruce Richardson 	wq->socket_id = socket_id;
60272f3de30SBruce Richardson 	if (nb_desc) {
60372f3de30SBruce Richardson 		if (nb_desc > enic->config.wq_desc_count) {
60472f3de30SBruce Richardson 			dev_warning(enic,
60572f3de30SBruce Richardson 				"WQ %d - number of tx desc in cmd line (%d)"\
60672f3de30SBruce Richardson 				"is greater than that in the UCSM/CIMC adapter"\
60772f3de30SBruce Richardson 				"policy.  Applying the value in the adapter "\
60872f3de30SBruce Richardson 				"policy (%d)\n",
60972f3de30SBruce Richardson 				queue_idx, nb_desc, enic->config.wq_desc_count);
61072f3de30SBruce Richardson 		} else if (nb_desc != enic->config.wq_desc_count) {
61172f3de30SBruce Richardson 			enic->config.wq_desc_count = nb_desc;
61272f3de30SBruce Richardson 			dev_info(enic,
61372f3de30SBruce Richardson 				"TX Queues - effective number of descs:%d\n",
61472f3de30SBruce Richardson 				nb_desc);
61572f3de30SBruce Richardson 		}
61672f3de30SBruce Richardson 	}
61772f3de30SBruce Richardson 
61872f3de30SBruce Richardson 	/* Allocate queue resources */
61972f3de30SBruce Richardson 	err = vnic_wq_alloc(enic->vdev, &enic->wq[queue_idx], queue_idx,
62072f3de30SBruce Richardson 		enic->config.wq_desc_count,
62172f3de30SBruce Richardson 		sizeof(struct wq_enet_desc));
62272f3de30SBruce Richardson 	if (err) {
62372f3de30SBruce Richardson 		dev_err(enic, "error in allocation of wq\n");
62472f3de30SBruce Richardson 		return err;
62572f3de30SBruce Richardson 	}
62672f3de30SBruce Richardson 
62772f3de30SBruce Richardson 	err = vnic_cq_alloc(enic->vdev, &enic->cq[cq_index], cq_index,
62872f3de30SBruce Richardson 		socket_id, enic->config.wq_desc_count,
62972f3de30SBruce Richardson 		sizeof(struct cq_enet_wq_desc));
63072f3de30SBruce Richardson 	if (err) {
63172f3de30SBruce Richardson 		vnic_wq_free(wq);
63272f3de30SBruce Richardson 		dev_err(enic, "error in allocation of cq for wq\n");
63372f3de30SBruce Richardson 	}
63472f3de30SBruce Richardson 
63572f3de30SBruce Richardson 	return err;
63672f3de30SBruce Richardson }
63772f3de30SBruce Richardson 
63872f3de30SBruce Richardson int enic_disable(struct enic *enic)
63972f3de30SBruce Richardson {
64072f3de30SBruce Richardson 	unsigned int i;
64172f3de30SBruce Richardson 	int err;
64272f3de30SBruce Richardson 
64372f3de30SBruce Richardson 	vnic_intr_mask(&enic->intr);
64472f3de30SBruce Richardson 	(void)vnic_intr_masked(&enic->intr); /* flush write */
64572f3de30SBruce Richardson 
64672f3de30SBruce Richardson 	vnic_dev_disable(enic->vdev);
64772f3de30SBruce Richardson 
64872f3de30SBruce Richardson 	enic_clsf_destroy(enic);
64972f3de30SBruce Richardson 
65072f3de30SBruce Richardson 	if (!enic_is_sriov_vf(enic))
65172f3de30SBruce Richardson 		vnic_dev_del_addr(enic->vdev, enic->mac_addr);
65272f3de30SBruce Richardson 
65372f3de30SBruce Richardson 	for (i = 0; i < enic->wq_count; i++) {
65472f3de30SBruce Richardson 		err = vnic_wq_disable(&enic->wq[i]);
65572f3de30SBruce Richardson 		if (err)
65672f3de30SBruce Richardson 			return err;
65772f3de30SBruce Richardson 	}
65872f3de30SBruce Richardson 	for (i = 0; i < enic->rq_count; i++) {
65972f3de30SBruce Richardson 		err = vnic_rq_disable(&enic->rq[i]);
66072f3de30SBruce Richardson 		if (err)
66172f3de30SBruce Richardson 			return err;
66272f3de30SBruce Richardson 	}
66372f3de30SBruce Richardson 
66472f3de30SBruce Richardson 	vnic_dev_set_reset_flag(enic->vdev, 1);
66572f3de30SBruce Richardson 	vnic_dev_notify_unset(enic->vdev);
66672f3de30SBruce Richardson 
66772f3de30SBruce Richardson 	for (i = 0; i < enic->wq_count; i++)
66872f3de30SBruce Richardson 		vnic_wq_clean(&enic->wq[i], enic_free_wq_buf);
669947d860cSJohn Daley 
67072f3de30SBruce Richardson 	for (i = 0; i < enic->rq_count; i++)
67172f3de30SBruce Richardson 		vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
67272f3de30SBruce Richardson 	for (i = 0; i < enic->cq_count; i++)
67372f3de30SBruce Richardson 		vnic_cq_clean(&enic->cq[i]);
67472f3de30SBruce Richardson 	vnic_intr_clean(&enic->intr);
67572f3de30SBruce Richardson 
67672f3de30SBruce Richardson 	return 0;
67772f3de30SBruce Richardson }
67872f3de30SBruce Richardson 
67972f3de30SBruce Richardson static int enic_dev_wait(struct vnic_dev *vdev,
68072f3de30SBruce Richardson 	int (*start)(struct vnic_dev *, int),
68172f3de30SBruce Richardson 	int (*finished)(struct vnic_dev *, int *),
68272f3de30SBruce Richardson 	int arg)
68372f3de30SBruce Richardson {
68472f3de30SBruce Richardson 	int done;
68572f3de30SBruce Richardson 	int err;
68672f3de30SBruce Richardson 	int i;
68772f3de30SBruce Richardson 
68872f3de30SBruce Richardson 	err = start(vdev, arg);
68972f3de30SBruce Richardson 	if (err)
69072f3de30SBruce Richardson 		return err;
69172f3de30SBruce Richardson 
69272f3de30SBruce Richardson 	/* Wait for func to complete...2 seconds max */
69372f3de30SBruce Richardson 	for (i = 0; i < 2000; i++) {
69472f3de30SBruce Richardson 		err = finished(vdev, &done);
69572f3de30SBruce Richardson 		if (err)
69672f3de30SBruce Richardson 			return err;
69772f3de30SBruce Richardson 		if (done)
69872f3de30SBruce Richardson 			return 0;
69972f3de30SBruce Richardson 		usleep(1000);
70072f3de30SBruce Richardson 	}
70172f3de30SBruce Richardson 	return -ETIMEDOUT;
70272f3de30SBruce Richardson }
70372f3de30SBruce Richardson 
70472f3de30SBruce Richardson static int enic_dev_open(struct enic *enic)
70572f3de30SBruce Richardson {
70672f3de30SBruce Richardson 	int err;
70772f3de30SBruce Richardson 
70872f3de30SBruce Richardson 	err = enic_dev_wait(enic->vdev, vnic_dev_open,
70972f3de30SBruce Richardson 		vnic_dev_open_done, 0);
71072f3de30SBruce Richardson 	if (err)
71172f3de30SBruce Richardson 		dev_err(enic_get_dev(enic),
71272f3de30SBruce Richardson 			"vNIC device open failed, err %d\n", err);
71372f3de30SBruce Richardson 
71472f3de30SBruce Richardson 	return err;
71572f3de30SBruce Richardson }
71672f3de30SBruce Richardson 
71772f3de30SBruce Richardson static int enic_set_rsskey(struct enic *enic)
71872f3de30SBruce Richardson {
71972f3de30SBruce Richardson 	dma_addr_t rss_key_buf_pa;
72072f3de30SBruce Richardson 	union vnic_rss_key *rss_key_buf_va = NULL;
72172f3de30SBruce Richardson 	static union vnic_rss_key rss_key = {
72272f3de30SBruce Richardson 		.key = {
72372f3de30SBruce Richardson 			[0] = {.b = {85, 67, 83, 97, 119, 101, 115, 111, 109, 101}},
72472f3de30SBruce Richardson 			[1] = {.b = {80, 65, 76, 79, 117, 110, 105, 113, 117, 101}},
72572f3de30SBruce Richardson 			[2] = {.b = {76, 73, 78, 85, 88, 114, 111, 99, 107, 115}},
72672f3de30SBruce Richardson 			[3] = {.b = {69, 78, 73, 67, 105, 115, 99, 111, 111, 108}},
72772f3de30SBruce Richardson 		}
72872f3de30SBruce Richardson 	};
72972f3de30SBruce Richardson 	int err;
73072f3de30SBruce Richardson 	u8 name[NAME_MAX];
73172f3de30SBruce Richardson 
73272f3de30SBruce Richardson 	snprintf((char *)name, NAME_MAX, "rss_key-%s", enic->bdf_name);
73372f3de30SBruce Richardson 	rss_key_buf_va = enic_alloc_consistent(enic, sizeof(union vnic_rss_key),
73472f3de30SBruce Richardson 		&rss_key_buf_pa, name);
73572f3de30SBruce Richardson 	if (!rss_key_buf_va)
73672f3de30SBruce Richardson 		return -ENOMEM;
73772f3de30SBruce Richardson 
73872f3de30SBruce Richardson 	rte_memcpy(rss_key_buf_va, &rss_key, sizeof(union vnic_rss_key));
73972f3de30SBruce Richardson 
74072f3de30SBruce Richardson 	err = enic_set_rss_key(enic,
74172f3de30SBruce Richardson 		rss_key_buf_pa,
74272f3de30SBruce Richardson 		sizeof(union vnic_rss_key));
74372f3de30SBruce Richardson 
74472f3de30SBruce Richardson 	enic_free_consistent(enic->pdev, sizeof(union vnic_rss_key),
74572f3de30SBruce Richardson 		rss_key_buf_va, rss_key_buf_pa);
74672f3de30SBruce Richardson 
74772f3de30SBruce Richardson 	return err;
74872f3de30SBruce Richardson }
74972f3de30SBruce Richardson 
75072f3de30SBruce Richardson static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
75172f3de30SBruce Richardson {
75272f3de30SBruce Richardson 	dma_addr_t rss_cpu_buf_pa;
75372f3de30SBruce Richardson 	union vnic_rss_cpu *rss_cpu_buf_va = NULL;
75472f3de30SBruce Richardson 	int i;
75572f3de30SBruce Richardson 	int err;
75672f3de30SBruce Richardson 	u8 name[NAME_MAX];
75772f3de30SBruce Richardson 
75872f3de30SBruce Richardson 	snprintf((char *)name, NAME_MAX, "rss_cpu-%s", enic->bdf_name);
75972f3de30SBruce Richardson 	rss_cpu_buf_va = enic_alloc_consistent(enic, sizeof(union vnic_rss_cpu),
76072f3de30SBruce Richardson 		&rss_cpu_buf_pa, name);
76172f3de30SBruce Richardson 	if (!rss_cpu_buf_va)
76272f3de30SBruce Richardson 		return -ENOMEM;
76372f3de30SBruce Richardson 
76472f3de30SBruce Richardson 	for (i = 0; i < (1 << rss_hash_bits); i++)
76572f3de30SBruce Richardson 		(*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count;
76672f3de30SBruce Richardson 
76772f3de30SBruce Richardson 	err = enic_set_rss_cpu(enic,
76872f3de30SBruce Richardson 		rss_cpu_buf_pa,
76972f3de30SBruce Richardson 		sizeof(union vnic_rss_cpu));
77072f3de30SBruce Richardson 
77172f3de30SBruce Richardson 	enic_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu),
77272f3de30SBruce Richardson 		rss_cpu_buf_va, rss_cpu_buf_pa);
77372f3de30SBruce Richardson 
77472f3de30SBruce Richardson 	return err;
77572f3de30SBruce Richardson }
77672f3de30SBruce Richardson 
77772f3de30SBruce Richardson static int enic_set_niccfg(struct enic *enic, u8 rss_default_cpu,
77872f3de30SBruce Richardson 	u8 rss_hash_type, u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable)
77972f3de30SBruce Richardson {
78072f3de30SBruce Richardson 	const u8 tso_ipid_split_en = 0;
78172f3de30SBruce Richardson 	int err;
78272f3de30SBruce Richardson 
78372f3de30SBruce Richardson 	/* Enable VLAN tag stripping */
78472f3de30SBruce Richardson 
78572f3de30SBruce Richardson 	err = enic_set_nic_cfg(enic,
78672f3de30SBruce Richardson 		rss_default_cpu, rss_hash_type,
78772f3de30SBruce Richardson 		rss_hash_bits, rss_base_cpu,
78872f3de30SBruce Richardson 		rss_enable, tso_ipid_split_en,
78972f3de30SBruce Richardson 		enic->ig_vlan_strip_en);
79072f3de30SBruce Richardson 
79172f3de30SBruce Richardson 	return err;
79272f3de30SBruce Richardson }
79372f3de30SBruce Richardson 
79472f3de30SBruce Richardson int enic_set_rss_nic_cfg(struct enic *enic)
79572f3de30SBruce Richardson {
79672f3de30SBruce Richardson 	const u8 rss_default_cpu = 0;
79772f3de30SBruce Richardson 	const u8 rss_hash_type = NIC_CFG_RSS_HASH_TYPE_IPV4 |
79872f3de30SBruce Richardson 	    NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 |
79972f3de30SBruce Richardson 	    NIC_CFG_RSS_HASH_TYPE_IPV6 |
80072f3de30SBruce Richardson 	    NIC_CFG_RSS_HASH_TYPE_TCP_IPV6;
80172f3de30SBruce Richardson 	const u8 rss_hash_bits = 7;
80272f3de30SBruce Richardson 	const u8 rss_base_cpu = 0;
80372f3de30SBruce Richardson 	u8 rss_enable = ENIC_SETTING(enic, RSS) && (enic->rq_count > 1);
80472f3de30SBruce Richardson 
80572f3de30SBruce Richardson 	if (rss_enable) {
80672f3de30SBruce Richardson 		if (!enic_set_rsskey(enic)) {
80772f3de30SBruce Richardson 			if (enic_set_rsscpu(enic, rss_hash_bits)) {
80872f3de30SBruce Richardson 				rss_enable = 0;
80972f3de30SBruce Richardson 				dev_warning(enic, "RSS disabled, "\
81072f3de30SBruce Richardson 					"Failed to set RSS cpu indirection table.");
81172f3de30SBruce Richardson 			}
81272f3de30SBruce Richardson 		} else {
81372f3de30SBruce Richardson 			rss_enable = 0;
81472f3de30SBruce Richardson 			dev_warning(enic,
81572f3de30SBruce Richardson 				"RSS disabled, Failed to set RSS key.\n");
81672f3de30SBruce Richardson 		}
81772f3de30SBruce Richardson 	}
81872f3de30SBruce Richardson 
81972f3de30SBruce Richardson 	return enic_set_niccfg(enic, rss_default_cpu, rss_hash_type,
82072f3de30SBruce Richardson 		rss_hash_bits, rss_base_cpu, rss_enable);
82172f3de30SBruce Richardson }
82272f3de30SBruce Richardson 
82372f3de30SBruce Richardson int enic_setup_finish(struct enic *enic)
82472f3de30SBruce Richardson {
82572f3de30SBruce Richardson 	int ret;
82672f3de30SBruce Richardson 
82765b5434dSJohn Daley 	enic_init_soft_stats(enic);
82865b5434dSJohn Daley 
82972f3de30SBruce Richardson 	ret = enic_set_rss_nic_cfg(enic);
83072f3de30SBruce Richardson 	if (ret) {
83172f3de30SBruce Richardson 		dev_err(enic, "Failed to config nic, aborting.\n");
83272f3de30SBruce Richardson 		return -1;
83372f3de30SBruce Richardson 	}
83472f3de30SBruce Richardson 
83572f3de30SBruce Richardson 	vnic_dev_add_addr(enic->vdev, enic->mac_addr);
83672f3de30SBruce Richardson 
83772f3de30SBruce Richardson 	/* Default conf */
83872f3de30SBruce Richardson 	vnic_dev_packet_filter(enic->vdev,
83972f3de30SBruce Richardson 		1 /* directed  */,
84072f3de30SBruce Richardson 		1 /* multicast */,
84172f3de30SBruce Richardson 		1 /* broadcast */,
84272f3de30SBruce Richardson 		0 /* promisc   */,
84372f3de30SBruce Richardson 		1 /* allmulti  */);
84472f3de30SBruce Richardson 
84572f3de30SBruce Richardson 	enic->promisc = 0;
84672f3de30SBruce Richardson 	enic->allmulti = 1;
84772f3de30SBruce Richardson 
84872f3de30SBruce Richardson 	return 0;
84972f3de30SBruce Richardson }
85072f3de30SBruce Richardson 
85172f3de30SBruce Richardson void enic_add_packet_filter(struct enic *enic)
85272f3de30SBruce Richardson {
85372f3de30SBruce Richardson 	/* Args -> directed, multicast, broadcast, promisc, allmulti */
85472f3de30SBruce Richardson 	vnic_dev_packet_filter(enic->vdev, 1, 1, 1,
85572f3de30SBruce Richardson 		enic->promisc, enic->allmulti);
85672f3de30SBruce Richardson }
85772f3de30SBruce Richardson 
85872f3de30SBruce Richardson int enic_get_link_status(struct enic *enic)
85972f3de30SBruce Richardson {
86072f3de30SBruce Richardson 	return vnic_dev_link_status(enic->vdev);
86172f3de30SBruce Richardson }
86272f3de30SBruce Richardson 
86372f3de30SBruce Richardson static void enic_dev_deinit(struct enic *enic)
86472f3de30SBruce Richardson {
86572f3de30SBruce Richardson 	struct rte_eth_dev *eth_dev = enic->rte_dev;
86672f3de30SBruce Richardson 
86772f3de30SBruce Richardson 	rte_free(eth_dev->data->mac_addrs);
86872f3de30SBruce Richardson }
86972f3de30SBruce Richardson 
87072f3de30SBruce Richardson 
87172f3de30SBruce Richardson int enic_set_vnic_res(struct enic *enic)
87272f3de30SBruce Richardson {
87372f3de30SBruce Richardson 	struct rte_eth_dev *eth_dev = enic->rte_dev;
87472f3de30SBruce Richardson 
87572f3de30SBruce Richardson 	if ((enic->rq_count < eth_dev->data->nb_rx_queues) ||
87672f3de30SBruce Richardson 		(enic->wq_count < eth_dev->data->nb_tx_queues)) {
87772f3de30SBruce Richardson 		dev_err(dev, "Not enough resources configured, aborting\n");
87872f3de30SBruce Richardson 		return -1;
87972f3de30SBruce Richardson 	}
88072f3de30SBruce Richardson 
88172f3de30SBruce Richardson 	enic->rq_count = eth_dev->data->nb_rx_queues;
88272f3de30SBruce Richardson 	enic->wq_count = eth_dev->data->nb_tx_queues;
88372f3de30SBruce Richardson 	if (enic->cq_count < (enic->rq_count + enic->wq_count)) {
88472f3de30SBruce Richardson 		dev_err(dev, "Not enough resources configured, aborting\n");
88572f3de30SBruce Richardson 		return -1;
88672f3de30SBruce Richardson 	}
88772f3de30SBruce Richardson 
88872f3de30SBruce Richardson 	enic->cq_count = enic->rq_count + enic->wq_count;
88972f3de30SBruce Richardson 	return 0;
89072f3de30SBruce Richardson }
89172f3de30SBruce Richardson 
89272f3de30SBruce Richardson static int enic_dev_init(struct enic *enic)
89372f3de30SBruce Richardson {
89472f3de30SBruce Richardson 	int err;
89572f3de30SBruce Richardson 	struct rte_eth_dev *eth_dev = enic->rte_dev;
89672f3de30SBruce Richardson 
89772f3de30SBruce Richardson 	vnic_dev_intr_coal_timer_info_default(enic->vdev);
89872f3de30SBruce Richardson 
89972f3de30SBruce Richardson 	/* Get vNIC configuration
90072f3de30SBruce Richardson 	*/
90172f3de30SBruce Richardson 	err = enic_get_vnic_config(enic);
90272f3de30SBruce Richardson 	if (err) {
90372f3de30SBruce Richardson 		dev_err(dev, "Get vNIC configuration failed, aborting\n");
90472f3de30SBruce Richardson 		return err;
90572f3de30SBruce Richardson 	}
90672f3de30SBruce Richardson 
90772f3de30SBruce Richardson 	eth_dev->data->mac_addrs = rte_zmalloc("enic_mac_addr", ETH_ALEN, 0);
90872f3de30SBruce Richardson 	if (!eth_dev->data->mac_addrs) {
90972f3de30SBruce Richardson 		dev_err(enic, "mac addr storage alloc failed, aborting.\n");
91072f3de30SBruce Richardson 		return -1;
91172f3de30SBruce Richardson 	}
91272f3de30SBruce Richardson 	ether_addr_copy((struct ether_addr *) enic->mac_addr,
91372f3de30SBruce Richardson 		&eth_dev->data->mac_addrs[0]);
91472f3de30SBruce Richardson 
91572f3de30SBruce Richardson 
91672f3de30SBruce Richardson 	/* Get available resource counts
91772f3de30SBruce Richardson 	*/
91872f3de30SBruce Richardson 	enic_get_res_counts(enic);
91972f3de30SBruce Richardson 
92072f3de30SBruce Richardson 	vnic_dev_set_reset_flag(enic->vdev, 0);
92172f3de30SBruce Richardson 
92272f3de30SBruce Richardson 	return 0;
92372f3de30SBruce Richardson 
92472f3de30SBruce Richardson }
92572f3de30SBruce Richardson 
92672f3de30SBruce Richardson int enic_probe(struct enic *enic)
92772f3de30SBruce Richardson {
92872f3de30SBruce Richardson 	struct rte_pci_device *pdev = enic->pdev;
92972f3de30SBruce Richardson 	int err = -1;
93072f3de30SBruce Richardson 
93172f3de30SBruce Richardson 	dev_debug(enic, " Initializing ENIC PMD version %s\n", DRV_VERSION);
93272f3de30SBruce Richardson 
93372f3de30SBruce Richardson 	enic->bar0.vaddr = (void *)pdev->mem_resource[0].addr;
93472f3de30SBruce Richardson 	enic->bar0.len = pdev->mem_resource[0].len;
93572f3de30SBruce Richardson 
93672f3de30SBruce Richardson 	/* Register vNIC device */
93772f3de30SBruce Richardson 	enic->vdev = vnic_dev_register(NULL, enic, enic->pdev, &enic->bar0, 1);
93872f3de30SBruce Richardson 	if (!enic->vdev) {
93972f3de30SBruce Richardson 		dev_err(enic, "vNIC registration failed, aborting\n");
94072f3de30SBruce Richardson 		goto err_out;
94172f3de30SBruce Richardson 	}
94272f3de30SBruce Richardson 
94372f3de30SBruce Richardson 	vnic_register_cbacks(enic->vdev,
94472f3de30SBruce Richardson 		enic_alloc_consistent,
94572f3de30SBruce Richardson 		enic_free_consistent);
94672f3de30SBruce Richardson 
94772f3de30SBruce Richardson 	/* Issue device open to get device in known state */
94872f3de30SBruce Richardson 	err = enic_dev_open(enic);
94972f3de30SBruce Richardson 	if (err) {
95072f3de30SBruce Richardson 		dev_err(enic, "vNIC dev open failed, aborting\n");
95172f3de30SBruce Richardson 		goto err_out_unregister;
95272f3de30SBruce Richardson 	}
95372f3de30SBruce Richardson 
95472f3de30SBruce Richardson 	/* Set ingress vlan rewrite mode before vnic initialization */
95572f3de30SBruce Richardson 	err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
956947d860cSJohn Daley 		IG_VLAN_REWRITE_MODE_PASS_THRU);
95772f3de30SBruce Richardson 	if (err) {
95872f3de30SBruce Richardson 		dev_err(enic,
95972f3de30SBruce Richardson 			"Failed to set ingress vlan rewrite mode, aborting.\n");
96072f3de30SBruce Richardson 		goto err_out_dev_close;
96172f3de30SBruce Richardson 	}
96272f3de30SBruce Richardson 
96372f3de30SBruce Richardson 	/* Issue device init to initialize the vnic-to-switch link.
96472f3de30SBruce Richardson 	 * We'll start with carrier off and wait for link UP
96572f3de30SBruce Richardson 	 * notification later to turn on carrier.  We don't need
96672f3de30SBruce Richardson 	 * to wait here for the vnic-to-switch link initialization
96772f3de30SBruce Richardson 	 * to complete; link UP notification is the indication that
96872f3de30SBruce Richardson 	 * the process is complete.
96972f3de30SBruce Richardson 	 */
97072f3de30SBruce Richardson 
97172f3de30SBruce Richardson 	err = vnic_dev_init(enic->vdev, 0);
97272f3de30SBruce Richardson 	if (err) {
97372f3de30SBruce Richardson 		dev_err(enic, "vNIC dev init failed, aborting\n");
97472f3de30SBruce Richardson 		goto err_out_dev_close;
97572f3de30SBruce Richardson 	}
97672f3de30SBruce Richardson 
97772f3de30SBruce Richardson 	err = enic_dev_init(enic);
97872f3de30SBruce Richardson 	if (err) {
97972f3de30SBruce Richardson 		dev_err(enic, "Device initialization failed, aborting\n");
98072f3de30SBruce Richardson 		goto err_out_dev_close;
98172f3de30SBruce Richardson 	}
98272f3de30SBruce Richardson 
98372f3de30SBruce Richardson 	return 0;
98472f3de30SBruce Richardson 
98572f3de30SBruce Richardson err_out_dev_close:
98672f3de30SBruce Richardson 	vnic_dev_close(enic->vdev);
98772f3de30SBruce Richardson err_out_unregister:
98872f3de30SBruce Richardson 	vnic_dev_unregister(enic->vdev);
98972f3de30SBruce Richardson err_out:
99072f3de30SBruce Richardson 	return err;
99172f3de30SBruce Richardson }
99272f3de30SBruce Richardson 
99372f3de30SBruce Richardson void enic_remove(struct enic *enic)
99472f3de30SBruce Richardson {
99572f3de30SBruce Richardson 	enic_dev_deinit(enic);
99672f3de30SBruce Richardson 	vnic_dev_close(enic->vdev);
99772f3de30SBruce Richardson 	vnic_dev_unregister(enic->vdev);
99872f3de30SBruce Richardson }
999