1669c8de6SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2669c8de6SAlfredo Cardigliano * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. 3669c8de6SAlfredo Cardigliano */ 4669c8de6SAlfredo Cardigliano 5669c8de6SAlfredo Cardigliano #include <rte_malloc.h> 6669c8de6SAlfredo Cardigliano #include <rte_ethdev_driver.h> 7669c8de6SAlfredo Cardigliano 8669c8de6SAlfredo Cardigliano #include "ionic.h" 9669c8de6SAlfredo Cardigliano #include "ionic_logs.h" 10669c8de6SAlfredo Cardigliano #include "ionic_lif.h" 11669c8de6SAlfredo Cardigliano #include "ionic_ethdev.h" 12669c8de6SAlfredo Cardigliano 1301a6c311SAlfredo Cardigliano int 1401a6c311SAlfredo Cardigliano ionic_qcq_enable(struct ionic_qcq *qcq) 1501a6c311SAlfredo Cardigliano { 1601a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 1701a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 1801a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 1901a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 2001a6c311SAlfredo Cardigliano .pending_work = true, 2101a6c311SAlfredo Cardigliano .cmd.q_control = { 2201a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 2301a6c311SAlfredo Cardigliano .lif_index = lif->index, 2401a6c311SAlfredo Cardigliano .type = q->type, 2501a6c311SAlfredo Cardigliano .index = q->index, 2601a6c311SAlfredo Cardigliano .oper = IONIC_Q_ENABLE, 2701a6c311SAlfredo Cardigliano }, 2801a6c311SAlfredo Cardigliano }; 2901a6c311SAlfredo Cardigliano 3001a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) { 3101a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 3201a6c311SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 3301a6c311SAlfredo Cardigliano } 3401a6c311SAlfredo Cardigliano 3501a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 3601a6c311SAlfredo Cardigliano } 3701a6c311SAlfredo Cardigliano 3801a6c311SAlfredo Cardigliano int 3901a6c311SAlfredo Cardigliano ionic_qcq_disable(struct ionic_qcq *qcq) 4001a6c311SAlfredo Cardigliano { 4101a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 4201a6c311SAlfredo Cardigliano struct ionic_lif *lif = q->lif; 4301a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 4401a6c311SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 4501a6c311SAlfredo Cardigliano .pending_work = true, 4601a6c311SAlfredo Cardigliano .cmd.q_control = { 4701a6c311SAlfredo Cardigliano .opcode = IONIC_CMD_Q_CONTROL, 4801a6c311SAlfredo Cardigliano .lif_index = lif->index, 4901a6c311SAlfredo Cardigliano .type = q->type, 5001a6c311SAlfredo Cardigliano .index = q->index, 5101a6c311SAlfredo Cardigliano .oper = IONIC_Q_DISABLE, 5201a6c311SAlfredo Cardigliano }, 5301a6c311SAlfredo Cardigliano }; 5401a6c311SAlfredo Cardigliano 5501a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) { 5601a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 5701a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 5801a6c311SAlfredo Cardigliano } 5901a6c311SAlfredo Cardigliano 6001a6c311SAlfredo Cardigliano return ionic_adminq_post_wait(lif, &ctx); 6101a6c311SAlfredo Cardigliano } 6201a6c311SAlfredo Cardigliano 6301a6c311SAlfredo Cardigliano int 6401a6c311SAlfredo Cardigliano ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr) 6501a6c311SAlfredo Cardigliano { 6601a6c311SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 6701a6c311SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 6801a6c311SAlfredo Cardigliano unsigned long index; 6901a6c311SAlfredo Cardigliano 7001a6c311SAlfredo Cardigliano /* 7101a6c311SAlfredo Cardigliano * Note: interrupt handler is called for index = 0 only 7201a6c311SAlfredo Cardigliano * (we use interrupts for the notifyq only anyway, 7301a6c311SAlfredo Cardigliano * which hash index = 0) 7401a6c311SAlfredo Cardigliano */ 7501a6c311SAlfredo Cardigliano 7601a6c311SAlfredo Cardigliano for (index = 0; index < adapter->nintrs; index++) 7701a6c311SAlfredo Cardigliano if (!adapter->intrs[index]) 7801a6c311SAlfredo Cardigliano break; 7901a6c311SAlfredo Cardigliano 8001a6c311SAlfredo Cardigliano if (index == adapter->nintrs) 8101a6c311SAlfredo Cardigliano return -ENOSPC; 8201a6c311SAlfredo Cardigliano 8301a6c311SAlfredo Cardigliano adapter->intrs[index] = true; 8401a6c311SAlfredo Cardigliano 8501a6c311SAlfredo Cardigliano ionic_intr_init(idev, intr, index); 8601a6c311SAlfredo Cardigliano 8701a6c311SAlfredo Cardigliano return 0; 8801a6c311SAlfredo Cardigliano } 8901a6c311SAlfredo Cardigliano 9001a6c311SAlfredo Cardigliano void 9101a6c311SAlfredo Cardigliano ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr) 9201a6c311SAlfredo Cardigliano { 9301a6c311SAlfredo Cardigliano if (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED) 9401a6c311SAlfredo Cardigliano lif->adapter->intrs[intr->index] = false; 9501a6c311SAlfredo Cardigliano } 9601a6c311SAlfredo Cardigliano 9701a6c311SAlfredo Cardigliano static int 9801a6c311SAlfredo Cardigliano ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type, 9901a6c311SAlfredo Cardigliano uint32_t index, 10001a6c311SAlfredo Cardigliano const char *base, uint32_t flags, 10101a6c311SAlfredo Cardigliano uint32_t num_descs, 10201a6c311SAlfredo Cardigliano uint32_t desc_size, 10301a6c311SAlfredo Cardigliano uint32_t cq_desc_size, 10401a6c311SAlfredo Cardigliano uint32_t sg_desc_size, 10501a6c311SAlfredo Cardigliano uint32_t pid, struct ionic_qcq **qcq) 10601a6c311SAlfredo Cardigliano { 10701a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 10801a6c311SAlfredo Cardigliano struct ionic_qcq *new; 10901a6c311SAlfredo Cardigliano uint32_t q_size, cq_size, sg_size, total_size; 11001a6c311SAlfredo Cardigliano void *q_base, *cq_base, *sg_base; 11101a6c311SAlfredo Cardigliano rte_iova_t q_base_pa = 0; 11201a6c311SAlfredo Cardigliano rte_iova_t cq_base_pa = 0; 11301a6c311SAlfredo Cardigliano rte_iova_t sg_base_pa = 0; 11401a6c311SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 11501a6c311SAlfredo Cardigliano int err; 11601a6c311SAlfredo Cardigliano 11701a6c311SAlfredo Cardigliano *qcq = NULL; 11801a6c311SAlfredo Cardigliano 11901a6c311SAlfredo Cardigliano q_size = num_descs * desc_size; 12001a6c311SAlfredo Cardigliano cq_size = num_descs * cq_desc_size; 12101a6c311SAlfredo Cardigliano sg_size = num_descs * sg_desc_size; 12201a6c311SAlfredo Cardigliano 12301a6c311SAlfredo Cardigliano total_size = RTE_ALIGN(q_size, PAGE_SIZE) + 12401a6c311SAlfredo Cardigliano RTE_ALIGN(cq_size, PAGE_SIZE); 12501a6c311SAlfredo Cardigliano /* 12601a6c311SAlfredo Cardigliano * Note: aligning q_size/cq_size is not enough due to cq_base address 12701a6c311SAlfredo Cardigliano * aligning as q_base could be not aligned to the page. 12801a6c311SAlfredo Cardigliano * Adding PAGE_SIZE. 12901a6c311SAlfredo Cardigliano */ 13001a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 13101a6c311SAlfredo Cardigliano 13201a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 13301a6c311SAlfredo Cardigliano total_size += RTE_ALIGN(sg_size, PAGE_SIZE); 13401a6c311SAlfredo Cardigliano total_size += PAGE_SIZE; 13501a6c311SAlfredo Cardigliano } 13601a6c311SAlfredo Cardigliano 13701a6c311SAlfredo Cardigliano new = rte_zmalloc("ionic", sizeof(*new), 0); 13801a6c311SAlfredo Cardigliano if (!new) { 13901a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue structure"); 14001a6c311SAlfredo Cardigliano return -ENOMEM; 14101a6c311SAlfredo Cardigliano } 14201a6c311SAlfredo Cardigliano 14301a6c311SAlfredo Cardigliano new->lif = lif; 14401a6c311SAlfredo Cardigliano new->flags = flags; 14501a6c311SAlfredo Cardigliano 14601a6c311SAlfredo Cardigliano new->q.info = rte_zmalloc("ionic", sizeof(*new->q.info) * num_descs, 0); 14701a6c311SAlfredo Cardigliano if (!new->q.info) { 14801a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate queue info"); 14901a6c311SAlfredo Cardigliano return -ENOMEM; 15001a6c311SAlfredo Cardigliano } 15101a6c311SAlfredo Cardigliano 15201a6c311SAlfredo Cardigliano new->q.type = type; 15301a6c311SAlfredo Cardigliano 15401a6c311SAlfredo Cardigliano err = ionic_q_init(lif, idev, &new->q, index, num_descs, 15501a6c311SAlfredo Cardigliano desc_size, sg_desc_size, pid); 15601a6c311SAlfredo Cardigliano if (err) { 15701a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Queue initialization failed"); 15801a6c311SAlfredo Cardigliano return err; 15901a6c311SAlfredo Cardigliano } 16001a6c311SAlfredo Cardigliano 16101a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_INTR) { 16201a6c311SAlfredo Cardigliano err = ionic_intr_alloc(lif, &new->intr); 16301a6c311SAlfredo Cardigliano if (err) 16401a6c311SAlfredo Cardigliano return err; 16501a6c311SAlfredo Cardigliano 16601a6c311SAlfredo Cardigliano ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index, 16701a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 16801a6c311SAlfredo Cardigliano } else { 16901a6c311SAlfredo Cardigliano new->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED; 17001a6c311SAlfredo Cardigliano } 17101a6c311SAlfredo Cardigliano 17201a6c311SAlfredo Cardigliano err = ionic_cq_init(lif, &new->cq, &new->intr, 17301a6c311SAlfredo Cardigliano num_descs, cq_desc_size); 17401a6c311SAlfredo Cardigliano if (err) { 17501a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Completion queue initialization failed"); 17601a6c311SAlfredo Cardigliano goto err_out_free_intr; 17701a6c311SAlfredo Cardigliano } 17801a6c311SAlfredo Cardigliano 17901a6c311SAlfredo Cardigliano new->base_z = rte_eth_dma_zone_reserve(lif->eth_dev, 18001a6c311SAlfredo Cardigliano base /* name */, index /* queue_idx */, 18101a6c311SAlfredo Cardigliano total_size, IONIC_ALIGN, socket_id); 18201a6c311SAlfredo Cardigliano 18301a6c311SAlfredo Cardigliano if (!new->base_z) { 18401a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve queue DMA memory"); 18501a6c311SAlfredo Cardigliano err = -ENOMEM; 18601a6c311SAlfredo Cardigliano goto err_out_free_intr; 18701a6c311SAlfredo Cardigliano } 18801a6c311SAlfredo Cardigliano 18901a6c311SAlfredo Cardigliano new->base = new->base_z->addr; 19001a6c311SAlfredo Cardigliano new->base_pa = new->base_z->iova; 19101a6c311SAlfredo Cardigliano new->total_size = total_size; 19201a6c311SAlfredo Cardigliano 19301a6c311SAlfredo Cardigliano q_base = new->base; 19401a6c311SAlfredo Cardigliano q_base_pa = new->base_pa; 19501a6c311SAlfredo Cardigliano 19601a6c311SAlfredo Cardigliano cq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE); 19701a6c311SAlfredo Cardigliano cq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE); 19801a6c311SAlfredo Cardigliano 19901a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_SG) { 20001a6c311SAlfredo Cardigliano sg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size, 20101a6c311SAlfredo Cardigliano PAGE_SIZE); 20201a6c311SAlfredo Cardigliano sg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE); 20301a6c311SAlfredo Cardigliano ionic_q_sg_map(&new->q, sg_base, sg_base_pa); 20401a6c311SAlfredo Cardigliano } 20501a6c311SAlfredo Cardigliano 20601a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Q-Base-PA = %ju CQ-Base-PA = %ju " 20701a6c311SAlfredo Cardigliano "SG-base-PA = %ju", 20801a6c311SAlfredo Cardigliano q_base_pa, cq_base_pa, sg_base_pa); 20901a6c311SAlfredo Cardigliano 21001a6c311SAlfredo Cardigliano ionic_q_map(&new->q, q_base, q_base_pa); 21101a6c311SAlfredo Cardigliano ionic_cq_map(&new->cq, cq_base, cq_base_pa); 21201a6c311SAlfredo Cardigliano ionic_cq_bind(&new->cq, &new->q); 21301a6c311SAlfredo Cardigliano 21401a6c311SAlfredo Cardigliano *qcq = new; 21501a6c311SAlfredo Cardigliano 21601a6c311SAlfredo Cardigliano return 0; 21701a6c311SAlfredo Cardigliano 21801a6c311SAlfredo Cardigliano err_out_free_intr: 21901a6c311SAlfredo Cardigliano if (flags & IONIC_QCQ_F_INTR) 22001a6c311SAlfredo Cardigliano ionic_intr_free(lif, &new->intr); 22101a6c311SAlfredo Cardigliano 22201a6c311SAlfredo Cardigliano return err; 22301a6c311SAlfredo Cardigliano } 22401a6c311SAlfredo Cardigliano 22501a6c311SAlfredo Cardigliano void 22601a6c311SAlfredo Cardigliano ionic_qcq_free(struct ionic_qcq *qcq) 22701a6c311SAlfredo Cardigliano { 22801a6c311SAlfredo Cardigliano if (qcq->base_z) { 22901a6c311SAlfredo Cardigliano qcq->base = NULL; 23001a6c311SAlfredo Cardigliano qcq->base_pa = 0; 23101a6c311SAlfredo Cardigliano rte_memzone_free(qcq->base_z); 23201a6c311SAlfredo Cardigliano qcq->base_z = NULL; 23301a6c311SAlfredo Cardigliano } 23401a6c311SAlfredo Cardigliano 23501a6c311SAlfredo Cardigliano if (qcq->q.info) { 23601a6c311SAlfredo Cardigliano rte_free(qcq->q.info); 23701a6c311SAlfredo Cardigliano qcq->q.info = NULL; 23801a6c311SAlfredo Cardigliano } 23901a6c311SAlfredo Cardigliano 24001a6c311SAlfredo Cardigliano rte_free(qcq); 24101a6c311SAlfredo Cardigliano } 24201a6c311SAlfredo Cardigliano 24301a6c311SAlfredo Cardigliano static int 24401a6c311SAlfredo Cardigliano ionic_admin_qcq_alloc(struct ionic_lif *lif) 24501a6c311SAlfredo Cardigliano { 24601a6c311SAlfredo Cardigliano uint32_t flags; 24701a6c311SAlfredo Cardigliano int err = -ENOMEM; 24801a6c311SAlfredo Cardigliano 24901a6c311SAlfredo Cardigliano flags = 0; 25001a6c311SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags, 25101a6c311SAlfredo Cardigliano IONIC_ADMINQ_LENGTH, 25201a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_cmd), 25301a6c311SAlfredo Cardigliano sizeof(struct ionic_admin_comp), 25401a6c311SAlfredo Cardigliano 0, 25501a6c311SAlfredo Cardigliano lif->kern_pid, &lif->adminqcq); 256*27b942c8SAlfredo Cardigliano if (err) 257*27b942c8SAlfredo Cardigliano return err; 25801a6c311SAlfredo Cardigliano 259*27b942c8SAlfredo Cardigliano return 0; 260*27b942c8SAlfredo Cardigliano } 261*27b942c8SAlfredo Cardigliano 262*27b942c8SAlfredo Cardigliano static int 263*27b942c8SAlfredo Cardigliano ionic_notify_qcq_alloc(struct ionic_lif *lif) 264*27b942c8SAlfredo Cardigliano { 265*27b942c8SAlfredo Cardigliano uint32_t flags; 266*27b942c8SAlfredo Cardigliano int err = -ENOMEM; 267*27b942c8SAlfredo Cardigliano 268*27b942c8SAlfredo Cardigliano flags = IONIC_QCQ_F_NOTIFYQ | IONIC_QCQ_F_INTR; 269*27b942c8SAlfredo Cardigliano 270*27b942c8SAlfredo Cardigliano err = ionic_qcq_alloc(lif, IONIC_QTYPE_NOTIFYQ, 0, "notify", 271*27b942c8SAlfredo Cardigliano flags, 272*27b942c8SAlfredo Cardigliano IONIC_NOTIFYQ_LENGTH, 273*27b942c8SAlfredo Cardigliano sizeof(struct ionic_notifyq_cmd), 274*27b942c8SAlfredo Cardigliano sizeof(union ionic_notifyq_comp), 275*27b942c8SAlfredo Cardigliano 0, 276*27b942c8SAlfredo Cardigliano lif->kern_pid, &lif->notifyqcq); 27701a6c311SAlfredo Cardigliano if (err) 27801a6c311SAlfredo Cardigliano return err; 27901a6c311SAlfredo Cardigliano 28001a6c311SAlfredo Cardigliano return 0; 28101a6c311SAlfredo Cardigliano } 28201a6c311SAlfredo Cardigliano 283c67719e1SAlfredo Cardigliano static void * 284c67719e1SAlfredo Cardigliano ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num) 285c67719e1SAlfredo Cardigliano { 286c67719e1SAlfredo Cardigliano char *vaddr = adapter->bars[IONIC_PCI_BAR_DBELL].vaddr; 287c67719e1SAlfredo Cardigliano 288c67719e1SAlfredo Cardigliano if (adapter->num_bars <= IONIC_PCI_BAR_DBELL) 289c67719e1SAlfredo Cardigliano return NULL; 290c67719e1SAlfredo Cardigliano 291c67719e1SAlfredo Cardigliano return (void *)&vaddr[page_num << PAGE_SHIFT]; 292c67719e1SAlfredo Cardigliano } 293c67719e1SAlfredo Cardigliano 294669c8de6SAlfredo Cardigliano int 295669c8de6SAlfredo Cardigliano ionic_lif_alloc(struct ionic_lif *lif) 296669c8de6SAlfredo Cardigliano { 297c67719e1SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 298669c8de6SAlfredo Cardigliano uint32_t socket_id = rte_socket_id(); 299c67719e1SAlfredo Cardigliano int dbpage_num; 30001a6c311SAlfredo Cardigliano int err; 301669c8de6SAlfredo Cardigliano 302669c8de6SAlfredo Cardigliano snprintf(lif->name, sizeof(lif->name), "lif%u", lif->index); 303669c8de6SAlfredo Cardigliano 304669c8de6SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 305669c8de6SAlfredo Cardigliano 30601a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_lock); 30701a6c311SAlfredo Cardigliano rte_spinlock_init(&lif->adminq_service_lock); 30801a6c311SAlfredo Cardigliano 309c67719e1SAlfredo Cardigliano lif->kern_pid = 0; 310c67719e1SAlfredo Cardigliano 311c67719e1SAlfredo Cardigliano dbpage_num = ionic_db_page_num(lif, 0); 312c67719e1SAlfredo Cardigliano 313c67719e1SAlfredo Cardigliano lif->kern_dbpage = ionic_bus_map_dbpage(adapter, dbpage_num); 314c67719e1SAlfredo Cardigliano if (!lif->kern_dbpage) { 315c67719e1SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot map dbpage, aborting"); 316c67719e1SAlfredo Cardigliano return -ENOMEM; 317c67719e1SAlfredo Cardigliano } 318c67719e1SAlfredo Cardigliano 319*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Notify Queue"); 320*27b942c8SAlfredo Cardigliano 321*27b942c8SAlfredo Cardigliano err = ionic_notify_qcq_alloc(lif); 322*27b942c8SAlfredo Cardigliano 323*27b942c8SAlfredo Cardigliano if (err) { 324*27b942c8SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate notify queue"); 325*27b942c8SAlfredo Cardigliano return err; 326*27b942c8SAlfredo Cardigliano } 327*27b942c8SAlfredo Cardigliano 328*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 329*27b942c8SAlfredo Cardigliano 33001a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Admin Queue"); 33101a6c311SAlfredo Cardigliano 33201a6c311SAlfredo Cardigliano err = ionic_admin_qcq_alloc(lif); 33301a6c311SAlfredo Cardigliano if (err) { 33401a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate admin queue"); 33501a6c311SAlfredo Cardigliano return err; 33601a6c311SAlfredo Cardigliano } 33701a6c311SAlfredo Cardigliano 33801a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Allocating Lif Info"); 33901a6c311SAlfredo Cardigliano 340669c8de6SAlfredo Cardigliano lif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE); 341669c8de6SAlfredo Cardigliano 342669c8de6SAlfredo Cardigliano lif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev, 343669c8de6SAlfredo Cardigliano "lif_info", 0 /* queue_idx*/, 344669c8de6SAlfredo Cardigliano lif->info_sz, IONIC_ALIGN, socket_id); 345669c8de6SAlfredo Cardigliano if (!lif->info_z) { 346669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot allocate lif info memory"); 347669c8de6SAlfredo Cardigliano return -ENOMEM; 348669c8de6SAlfredo Cardigliano } 349669c8de6SAlfredo Cardigliano 350669c8de6SAlfredo Cardigliano lif->info = lif->info_z->addr; 351669c8de6SAlfredo Cardigliano lif->info_pa = lif->info_z->iova; 352669c8de6SAlfredo Cardigliano 353669c8de6SAlfredo Cardigliano return 0; 354669c8de6SAlfredo Cardigliano } 355669c8de6SAlfredo Cardigliano 356669c8de6SAlfredo Cardigliano void 357669c8de6SAlfredo Cardigliano ionic_lif_free(struct ionic_lif *lif) 358669c8de6SAlfredo Cardigliano { 359*27b942c8SAlfredo Cardigliano if (lif->notifyqcq) { 360*27b942c8SAlfredo Cardigliano ionic_qcq_free(lif->notifyqcq); 361*27b942c8SAlfredo Cardigliano lif->notifyqcq = NULL; 362*27b942c8SAlfredo Cardigliano } 363*27b942c8SAlfredo Cardigliano 36401a6c311SAlfredo Cardigliano if (lif->adminqcq) { 36501a6c311SAlfredo Cardigliano ionic_qcq_free(lif->adminqcq); 36601a6c311SAlfredo Cardigliano lif->adminqcq = NULL; 36701a6c311SAlfredo Cardigliano } 36801a6c311SAlfredo Cardigliano 369669c8de6SAlfredo Cardigliano if (lif->info) { 370669c8de6SAlfredo Cardigliano rte_memzone_free(lif->info_z); 371669c8de6SAlfredo Cardigliano lif->info = NULL; 372669c8de6SAlfredo Cardigliano } 373669c8de6SAlfredo Cardigliano } 374669c8de6SAlfredo Cardigliano 37501a6c311SAlfredo Cardigliano static void 37601a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq) 37701a6c311SAlfredo Cardigliano { 37801a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 37901a6c311SAlfredo Cardigliano 38001a6c311SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) 38101a6c311SAlfredo Cardigliano return; 38201a6c311SAlfredo Cardigliano 38301a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 38401a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 38501a6c311SAlfredo Cardigliano IONIC_INTR_MASK_SET); 38601a6c311SAlfredo Cardigliano 38701a6c311SAlfredo Cardigliano qcq->flags &= ~IONIC_QCQ_F_INITED; 38801a6c311SAlfredo Cardigliano } 38901a6c311SAlfredo Cardigliano 39001a6c311SAlfredo Cardigliano bool 39101a6c311SAlfredo Cardigliano ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index, 39201a6c311SAlfredo Cardigliano void *cb_arg __rte_unused) 39301a6c311SAlfredo Cardigliano { 39401a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc_base = cq->base; 39501a6c311SAlfredo Cardigliano struct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index]; 39601a6c311SAlfredo Cardigliano 39701a6c311SAlfredo Cardigliano if (!color_match(cq_desc->color, cq->done_color)) 39801a6c311SAlfredo Cardigliano return false; 39901a6c311SAlfredo Cardigliano 40001a6c311SAlfredo Cardigliano ionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL); 40101a6c311SAlfredo Cardigliano 40201a6c311SAlfredo Cardigliano return true; 40301a6c311SAlfredo Cardigliano } 40401a6c311SAlfredo Cardigliano 40501a6c311SAlfredo Cardigliano /* This acts like ionic_napi */ 40601a6c311SAlfredo Cardigliano int 40701a6c311SAlfredo Cardigliano ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb, 40801a6c311SAlfredo Cardigliano void *cb_arg) 40901a6c311SAlfredo Cardigliano { 41001a6c311SAlfredo Cardigliano struct ionic_cq *cq = &qcq->cq; 41101a6c311SAlfredo Cardigliano uint32_t work_done; 41201a6c311SAlfredo Cardigliano 41301a6c311SAlfredo Cardigliano work_done = ionic_cq_service(cq, budget, cb, cb_arg); 41401a6c311SAlfredo Cardigliano 41501a6c311SAlfredo Cardigliano return work_done; 41601a6c311SAlfredo Cardigliano } 41701a6c311SAlfredo Cardigliano 418*27b942c8SAlfredo Cardigliano static void 419*27b942c8SAlfredo Cardigliano ionic_link_status_check(struct ionic_lif *lif) 420*27b942c8SAlfredo Cardigliano { 421*27b942c8SAlfredo Cardigliano struct ionic_adapter *adapter = lif->adapter; 422*27b942c8SAlfredo Cardigliano bool link_up; 423*27b942c8SAlfredo Cardigliano 424*27b942c8SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_LINK_CHECK_NEEDED; 425*27b942c8SAlfredo Cardigliano 426*27b942c8SAlfredo Cardigliano if (!lif->info) 427*27b942c8SAlfredo Cardigliano return; 428*27b942c8SAlfredo Cardigliano 429*27b942c8SAlfredo Cardigliano link_up = (lif->info->status.link_status == IONIC_PORT_OPER_STATUS_UP); 430*27b942c8SAlfredo Cardigliano 431*27b942c8SAlfredo Cardigliano if ((link_up && adapter->link_up) || 432*27b942c8SAlfredo Cardigliano (!link_up && !adapter->link_up)) 433*27b942c8SAlfredo Cardigliano return; 434*27b942c8SAlfredo Cardigliano 435*27b942c8SAlfredo Cardigliano if (link_up) { 436*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link up - %d Gbps", 437*27b942c8SAlfredo Cardigliano lif->info->status.link_speed); 438*27b942c8SAlfredo Cardigliano adapter->link_speed = lif->info->status.link_speed; 439*27b942c8SAlfredo Cardigliano } else { 440*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Link down"); 441*27b942c8SAlfredo Cardigliano } 442*27b942c8SAlfredo Cardigliano 443*27b942c8SAlfredo Cardigliano adapter->link_up = link_up; 444*27b942c8SAlfredo Cardigliano } 445*27b942c8SAlfredo Cardigliano 446*27b942c8SAlfredo Cardigliano static bool 447*27b942c8SAlfredo Cardigliano ionic_notifyq_cb(struct ionic_cq *cq, uint32_t cq_desc_index, void *cb_arg) 448*27b942c8SAlfredo Cardigliano { 449*27b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc_base = cq->base; 450*27b942c8SAlfredo Cardigliano union ionic_notifyq_comp *cq_desc = &cq_desc_base[cq_desc_index]; 451*27b942c8SAlfredo Cardigliano struct ionic_lif *lif = cb_arg; 452*27b942c8SAlfredo Cardigliano 453*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq callback eid = %jd ecode = %d", 454*27b942c8SAlfredo Cardigliano cq_desc->event.eid, cq_desc->event.ecode); 455*27b942c8SAlfredo Cardigliano 456*27b942c8SAlfredo Cardigliano /* Have we run out of new completions to process? */ 457*27b942c8SAlfredo Cardigliano if (!(cq_desc->event.eid > lif->last_eid)) 458*27b942c8SAlfredo Cardigliano return false; 459*27b942c8SAlfredo Cardigliano 460*27b942c8SAlfredo Cardigliano lif->last_eid = cq_desc->event.eid; 461*27b942c8SAlfredo Cardigliano 462*27b942c8SAlfredo Cardigliano switch (cq_desc->event.ecode) { 463*27b942c8SAlfredo Cardigliano case IONIC_EVENT_LINK_CHANGE: 464*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, 465*27b942c8SAlfredo Cardigliano "Notifyq IONIC_EVENT_LINK_CHANGE eid=%jd link_status=%d link_speed=%d", 466*27b942c8SAlfredo Cardigliano cq_desc->event.eid, 467*27b942c8SAlfredo Cardigliano cq_desc->link_change.link_status, 468*27b942c8SAlfredo Cardigliano cq_desc->link_change.link_speed); 469*27b942c8SAlfredo Cardigliano 470*27b942c8SAlfredo Cardigliano lif->state |= IONIC_LIF_F_LINK_CHECK_NEEDED; 471*27b942c8SAlfredo Cardigliano 472*27b942c8SAlfredo Cardigliano break; 473*27b942c8SAlfredo Cardigliano default: 474*27b942c8SAlfredo Cardigliano IONIC_PRINT(WARNING, "Notifyq bad event ecode=%d eid=%jd", 475*27b942c8SAlfredo Cardigliano cq_desc->event.ecode, cq_desc->event.eid); 476*27b942c8SAlfredo Cardigliano break; 477*27b942c8SAlfredo Cardigliano } 478*27b942c8SAlfredo Cardigliano 479*27b942c8SAlfredo Cardigliano return true; 480*27b942c8SAlfredo Cardigliano } 481*27b942c8SAlfredo Cardigliano 482*27b942c8SAlfredo Cardigliano int 483*27b942c8SAlfredo Cardigliano ionic_notifyq_handler(struct ionic_lif *lif, int budget) 484*27b942c8SAlfredo Cardigliano { 485*27b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 486*27b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 487*27b942c8SAlfredo Cardigliano uint32_t work_done; 488*27b942c8SAlfredo Cardigliano 489*27b942c8SAlfredo Cardigliano if (!(qcq->flags & IONIC_QCQ_F_INITED)) { 490*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Notifyq not yet initialized"); 491*27b942c8SAlfredo Cardigliano return -1; 492*27b942c8SAlfredo Cardigliano } 493*27b942c8SAlfredo Cardigliano 494*27b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 495*27b942c8SAlfredo Cardigliano IONIC_INTR_MASK_SET); 496*27b942c8SAlfredo Cardigliano 497*27b942c8SAlfredo Cardigliano work_done = ionic_qcq_service(qcq, budget, ionic_notifyq_cb, lif); 498*27b942c8SAlfredo Cardigliano 499*27b942c8SAlfredo Cardigliano if (lif->state & IONIC_LIF_F_LINK_CHECK_NEEDED) 500*27b942c8SAlfredo Cardigliano ionic_link_status_check(lif); 501*27b942c8SAlfredo Cardigliano 502*27b942c8SAlfredo Cardigliano ionic_intr_credits(idev->intr_ctrl, qcq->intr.index, 503*27b942c8SAlfredo Cardigliano work_done, IONIC_INTR_CRED_RESET_COALESCE); 504*27b942c8SAlfredo Cardigliano 505*27b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 506*27b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 507*27b942c8SAlfredo Cardigliano 508*27b942c8SAlfredo Cardigliano return 0; 509*27b942c8SAlfredo Cardigliano } 510*27b942c8SAlfredo Cardigliano 51101a6c311SAlfredo Cardigliano static int 51201a6c311SAlfredo Cardigliano ionic_lif_adminq_init(struct ionic_lif *lif) 51301a6c311SAlfredo Cardigliano { 51401a6c311SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 51501a6c311SAlfredo Cardigliano struct ionic_qcq *qcq = lif->adminqcq; 51601a6c311SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 51701a6c311SAlfredo Cardigliano struct ionic_q_init_comp comp; 51801a6c311SAlfredo Cardigliano int err; 51901a6c311SAlfredo Cardigliano 52001a6c311SAlfredo Cardigliano ionic_dev_cmd_adminq_init(idev, qcq, lif->index, qcq->intr.index); 52101a6c311SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 52201a6c311SAlfredo Cardigliano if (err) 52301a6c311SAlfredo Cardigliano return err; 52401a6c311SAlfredo Cardigliano 52501a6c311SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 52601a6c311SAlfredo Cardigliano 52701a6c311SAlfredo Cardigliano q->hw_type = comp.hw_type; 52801a6c311SAlfredo Cardigliano q->hw_index = comp.hw_index; 52901a6c311SAlfredo Cardigliano q->db = ionic_db_map(lif, q); 53001a6c311SAlfredo Cardigliano 53101a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_type %d", q->hw_type); 53201a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->hw_index %d", q->hw_index); 53301a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "adminq->db %p", q->db); 53401a6c311SAlfredo Cardigliano 53501a6c311SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 53601a6c311SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 53701a6c311SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 53801a6c311SAlfredo Cardigliano 53901a6c311SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 54001a6c311SAlfredo Cardigliano 54101a6c311SAlfredo Cardigliano return 0; 54201a6c311SAlfredo Cardigliano } 54301a6c311SAlfredo Cardigliano 544*27b942c8SAlfredo Cardigliano static int 545*27b942c8SAlfredo Cardigliano ionic_lif_notifyq_init(struct ionic_lif *lif) 546*27b942c8SAlfredo Cardigliano { 547*27b942c8SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 548*27b942c8SAlfredo Cardigliano struct ionic_qcq *qcq = lif->notifyqcq; 549*27b942c8SAlfredo Cardigliano struct ionic_queue *q = &qcq->q; 550*27b942c8SAlfredo Cardigliano int err; 551*27b942c8SAlfredo Cardigliano 552*27b942c8SAlfredo Cardigliano struct ionic_admin_ctx ctx = { 553*27b942c8SAlfredo Cardigliano .pending_work = true, 554*27b942c8SAlfredo Cardigliano .cmd.q_init = { 555*27b942c8SAlfredo Cardigliano .opcode = IONIC_CMD_Q_INIT, 556*27b942c8SAlfredo Cardigliano .lif_index = lif->index, 557*27b942c8SAlfredo Cardigliano .type = q->type, 558*27b942c8SAlfredo Cardigliano .index = q->index, 559*27b942c8SAlfredo Cardigliano .flags = (IONIC_QINIT_F_IRQ | IONIC_QINIT_F_ENA), 560*27b942c8SAlfredo Cardigliano .intr_index = qcq->intr.index, 561*27b942c8SAlfredo Cardigliano .pid = q->pid, 562*27b942c8SAlfredo Cardigliano .ring_size = rte_log2_u32(q->num_descs), 563*27b942c8SAlfredo Cardigliano .ring_base = q->base_pa, 564*27b942c8SAlfredo Cardigliano } 565*27b942c8SAlfredo Cardigliano }; 566*27b942c8SAlfredo Cardigliano 567*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.pid %d", ctx.cmd.q_init.pid); 568*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.index %d", 569*27b942c8SAlfredo Cardigliano ctx.cmd.q_init.index); 570*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_base 0x%" PRIx64 "", 571*27b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_base); 572*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq_init.ring_size %d", 573*27b942c8SAlfredo Cardigliano ctx.cmd.q_init.ring_size); 574*27b942c8SAlfredo Cardigliano 575*27b942c8SAlfredo Cardigliano err = ionic_adminq_post_wait(lif, &ctx); 576*27b942c8SAlfredo Cardigliano if (err) 577*27b942c8SAlfredo Cardigliano return err; 578*27b942c8SAlfredo Cardigliano 579*27b942c8SAlfredo Cardigliano q->hw_type = ctx.comp.q_init.hw_type; 580*27b942c8SAlfredo Cardigliano q->hw_index = ctx.comp.q_init.hw_index; 581*27b942c8SAlfredo Cardigliano q->db = NULL; 582*27b942c8SAlfredo Cardigliano 583*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_type %d", q->hw_type); 584*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->hw_index %d", q->hw_index); 585*27b942c8SAlfredo Cardigliano IONIC_PRINT(DEBUG, "notifyq->db %p", q->db); 586*27b942c8SAlfredo Cardigliano 587*27b942c8SAlfredo Cardigliano if (qcq->flags & IONIC_QCQ_F_INTR) 588*27b942c8SAlfredo Cardigliano ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, 589*27b942c8SAlfredo Cardigliano IONIC_INTR_MASK_CLEAR); 590*27b942c8SAlfredo Cardigliano 591*27b942c8SAlfredo Cardigliano qcq->flags |= IONIC_QCQ_F_INITED; 592*27b942c8SAlfredo Cardigliano 593*27b942c8SAlfredo Cardigliano return 0; 594*27b942c8SAlfredo Cardigliano } 595*27b942c8SAlfredo Cardigliano 596669c8de6SAlfredo Cardigliano int 597669c8de6SAlfredo Cardigliano ionic_lif_init(struct ionic_lif *lif) 598669c8de6SAlfredo Cardigliano { 599669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &lif->adapter->idev; 600669c8de6SAlfredo Cardigliano struct ionic_q_init_comp comp; 601669c8de6SAlfredo Cardigliano int err; 602669c8de6SAlfredo Cardigliano 603669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa); 604669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 605669c8de6SAlfredo Cardigliano ionic_dev_cmd_comp(idev, &comp); 606669c8de6SAlfredo Cardigliano if (err) 607669c8de6SAlfredo Cardigliano return err; 608669c8de6SAlfredo Cardigliano 609669c8de6SAlfredo Cardigliano lif->hw_index = comp.hw_index; 610669c8de6SAlfredo Cardigliano 61101a6c311SAlfredo Cardigliano err = ionic_lif_adminq_init(lif); 61201a6c311SAlfredo Cardigliano if (err) 61301a6c311SAlfredo Cardigliano return err; 61401a6c311SAlfredo Cardigliano 615*27b942c8SAlfredo Cardigliano err = ionic_lif_notifyq_init(lif); 616*27b942c8SAlfredo Cardigliano if (err) 617*27b942c8SAlfredo Cardigliano goto err_out_adminq_deinit; 618*27b942c8SAlfredo Cardigliano 619669c8de6SAlfredo Cardigliano lif->state |= IONIC_LIF_F_INITED; 620669c8de6SAlfredo Cardigliano 621669c8de6SAlfredo Cardigliano return 0; 622*27b942c8SAlfredo Cardigliano 623*27b942c8SAlfredo Cardigliano err_out_adminq_deinit: 624*27b942c8SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->adminqcq); 625*27b942c8SAlfredo Cardigliano 626*27b942c8SAlfredo Cardigliano return err; 627669c8de6SAlfredo Cardigliano } 628669c8de6SAlfredo Cardigliano 629669c8de6SAlfredo Cardigliano void 630669c8de6SAlfredo Cardigliano ionic_lif_deinit(struct ionic_lif *lif) 631669c8de6SAlfredo Cardigliano { 632669c8de6SAlfredo Cardigliano if (!(lif->state & IONIC_LIF_F_INITED)) 633669c8de6SAlfredo Cardigliano return; 634669c8de6SAlfredo Cardigliano 635*27b942c8SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->notifyqcq); 63601a6c311SAlfredo Cardigliano ionic_lif_qcq_deinit(lif, lif->adminqcq); 63701a6c311SAlfredo Cardigliano 638669c8de6SAlfredo Cardigliano lif->state &= ~IONIC_LIF_F_INITED; 639669c8de6SAlfredo Cardigliano } 640669c8de6SAlfredo Cardigliano 641669c8de6SAlfredo Cardigliano int 642669c8de6SAlfredo Cardigliano ionic_lif_identify(struct ionic_adapter *adapter) 643669c8de6SAlfredo Cardigliano { 644669c8de6SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 645669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 646669c8de6SAlfredo Cardigliano int err; 647669c8de6SAlfredo Cardigliano unsigned int i; 648669c8de6SAlfredo Cardigliano unsigned int lif_words = sizeof(ident->lif.words) / 649669c8de6SAlfredo Cardigliano sizeof(ident->lif.words[0]); 650669c8de6SAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 651669c8de6SAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 652669c8de6SAlfredo Cardigliano unsigned int nwords; 653669c8de6SAlfredo Cardigliano 654669c8de6SAlfredo Cardigliano ionic_dev_cmd_lif_identify(idev, IONIC_LIF_TYPE_CLASSIC, 655669c8de6SAlfredo Cardigliano IONIC_IDENTITY_VERSION_1); 656669c8de6SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 657669c8de6SAlfredo Cardigliano if (err) 658669c8de6SAlfredo Cardigliano return (err); 659669c8de6SAlfredo Cardigliano 660669c8de6SAlfredo Cardigliano nwords = RTE_MIN(lif_words, cmd_words); 661669c8de6SAlfredo Cardigliano for (i = 0; i < nwords; i++) 662669c8de6SAlfredo Cardigliano ident->lif.words[i] = ioread32(&idev->dev_cmd->data[i]); 663669c8de6SAlfredo Cardigliano 664669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "capabilities 0x%" PRIx64 " ", 665669c8de6SAlfredo Cardigliano ident->lif.capabilities); 666669c8de6SAlfredo Cardigliano 667669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_ucast_filters 0x%" PRIx32 " ", 668669c8de6SAlfredo Cardigliano ident->lif.eth.max_ucast_filters); 669669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.max_mcast_filters 0x%" PRIx32 " ", 670669c8de6SAlfredo Cardigliano ident->lif.eth.max_mcast_filters); 671669c8de6SAlfredo Cardigliano 672669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.features 0x%" PRIx64 " ", 673669c8de6SAlfredo Cardigliano ident->lif.eth.config.features); 674669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_ADMINQ] 0x%" PRIx32 " ", 675669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_ADMINQ]); 676669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_NOTIFYQ] 0x%" PRIx32 " ", 677669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_NOTIFYQ]); 678669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_RXQ] 0x%" PRIx32 " ", 679669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]); 680669c8de6SAlfredo Cardigliano IONIC_PRINT(INFO, "eth.queue_count[IONIC_QTYPE_TXQ] 0x%" PRIx32 " ", 681669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]); 682669c8de6SAlfredo Cardigliano 683669c8de6SAlfredo Cardigliano return 0; 684669c8de6SAlfredo Cardigliano } 685669c8de6SAlfredo Cardigliano 686669c8de6SAlfredo Cardigliano int 687669c8de6SAlfredo Cardigliano ionic_lifs_size(struct ionic_adapter *adapter) 688669c8de6SAlfredo Cardigliano { 689669c8de6SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 690669c8de6SAlfredo Cardigliano uint32_t nlifs = ident->dev.nlifs; 691669c8de6SAlfredo Cardigliano uint32_t nintrs, dev_nintrs = ident->dev.nintrs; 692669c8de6SAlfredo Cardigliano 693669c8de6SAlfredo Cardigliano adapter->max_ntxqs_per_lif = 694669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_TXQ]; 695669c8de6SAlfredo Cardigliano adapter->max_nrxqs_per_lif = 696669c8de6SAlfredo Cardigliano ident->lif.eth.config.queue_count[IONIC_QTYPE_RXQ]; 697669c8de6SAlfredo Cardigliano 698669c8de6SAlfredo Cardigliano nintrs = nlifs * 1 /* notifyq */; 699669c8de6SAlfredo Cardigliano 700669c8de6SAlfredo Cardigliano if (nintrs > dev_nintrs) { 701669c8de6SAlfredo Cardigliano IONIC_PRINT(ERR, "At most %d intr queues supported, minimum required is %u", 702669c8de6SAlfredo Cardigliano dev_nintrs, nintrs); 703669c8de6SAlfredo Cardigliano return -ENOSPC; 704669c8de6SAlfredo Cardigliano } 705669c8de6SAlfredo Cardigliano 706669c8de6SAlfredo Cardigliano adapter->nintrs = nintrs; 707669c8de6SAlfredo Cardigliano 708669c8de6SAlfredo Cardigliano return 0; 709669c8de6SAlfredo Cardigliano } 710