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 ð_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