15ef51809SAlfredo Cardigliano /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 25ef51809SAlfredo Cardigliano * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. 35ef51809SAlfredo Cardigliano */ 45ef51809SAlfredo Cardigliano 523bf4ddbSAlfredo Cardigliano #include <rte_memzone.h> 623bf4ddbSAlfredo Cardigliano 75ef51809SAlfredo Cardigliano #include "ionic.h" 8*01a6c311SAlfredo Cardigliano #include "ionic_ethdev.h" 9*01a6c311SAlfredo Cardigliano #include "ionic_lif.h" 10*01a6c311SAlfredo Cardigliano 11*01a6c311SAlfredo Cardigliano static const char * 12*01a6c311SAlfredo Cardigliano ionic_error_to_str(enum ionic_status_code code) 13*01a6c311SAlfredo Cardigliano { 14*01a6c311SAlfredo Cardigliano switch (code) { 15*01a6c311SAlfredo Cardigliano case IONIC_RC_SUCCESS: 16*01a6c311SAlfredo Cardigliano return "IONIC_RC_SUCCESS"; 17*01a6c311SAlfredo Cardigliano case IONIC_RC_EVERSION: 18*01a6c311SAlfredo Cardigliano return "IONIC_RC_EVERSION"; 19*01a6c311SAlfredo Cardigliano case IONIC_RC_EOPCODE: 20*01a6c311SAlfredo Cardigliano return "IONIC_RC_EOPCODE"; 21*01a6c311SAlfredo Cardigliano case IONIC_RC_EIO: 22*01a6c311SAlfredo Cardigliano return "IONIC_RC_EIO"; 23*01a6c311SAlfredo Cardigliano case IONIC_RC_EPERM: 24*01a6c311SAlfredo Cardigliano return "IONIC_RC_EPERM"; 25*01a6c311SAlfredo Cardigliano case IONIC_RC_EQID: 26*01a6c311SAlfredo Cardigliano return "IONIC_RC_EQID"; 27*01a6c311SAlfredo Cardigliano case IONIC_RC_EQTYPE: 28*01a6c311SAlfredo Cardigliano return "IONIC_RC_EQTYPE"; 29*01a6c311SAlfredo Cardigliano case IONIC_RC_ENOENT: 30*01a6c311SAlfredo Cardigliano return "IONIC_RC_ENOENT"; 31*01a6c311SAlfredo Cardigliano case IONIC_RC_EINTR: 32*01a6c311SAlfredo Cardigliano return "IONIC_RC_EINTR"; 33*01a6c311SAlfredo Cardigliano case IONIC_RC_EAGAIN: 34*01a6c311SAlfredo Cardigliano return "IONIC_RC_EAGAIN"; 35*01a6c311SAlfredo Cardigliano case IONIC_RC_ENOMEM: 36*01a6c311SAlfredo Cardigliano return "IONIC_RC_ENOMEM"; 37*01a6c311SAlfredo Cardigliano case IONIC_RC_EFAULT: 38*01a6c311SAlfredo Cardigliano return "IONIC_RC_EFAULT"; 39*01a6c311SAlfredo Cardigliano case IONIC_RC_EBUSY: 40*01a6c311SAlfredo Cardigliano return "IONIC_RC_EBUSY"; 41*01a6c311SAlfredo Cardigliano case IONIC_RC_EEXIST: 42*01a6c311SAlfredo Cardigliano return "IONIC_RC_EEXIST"; 43*01a6c311SAlfredo Cardigliano case IONIC_RC_EINVAL: 44*01a6c311SAlfredo Cardigliano return "IONIC_RC_EINVAL"; 45*01a6c311SAlfredo Cardigliano case IONIC_RC_ENOSPC: 46*01a6c311SAlfredo Cardigliano return "IONIC_RC_ENOSPC"; 47*01a6c311SAlfredo Cardigliano case IONIC_RC_ERANGE: 48*01a6c311SAlfredo Cardigliano return "IONIC_RC_ERANGE"; 49*01a6c311SAlfredo Cardigliano case IONIC_RC_BAD_ADDR: 50*01a6c311SAlfredo Cardigliano return "IONIC_RC_BAD_ADDR"; 51*01a6c311SAlfredo Cardigliano case IONIC_RC_DEV_CMD: 52*01a6c311SAlfredo Cardigliano return "IONIC_RC_DEV_CMD"; 53*01a6c311SAlfredo Cardigliano case IONIC_RC_ERROR: 54*01a6c311SAlfredo Cardigliano return "IONIC_RC_ERROR"; 55*01a6c311SAlfredo Cardigliano case IONIC_RC_ERDMA: 56*01a6c311SAlfredo Cardigliano return "IONIC_RC_ERDMA"; 57*01a6c311SAlfredo Cardigliano default: 58*01a6c311SAlfredo Cardigliano return "IONIC_RC_UNKNOWN"; 59*01a6c311SAlfredo Cardigliano } 60*01a6c311SAlfredo Cardigliano } 61*01a6c311SAlfredo Cardigliano 62*01a6c311SAlfredo Cardigliano static const char * 63*01a6c311SAlfredo Cardigliano ionic_opcode_to_str(enum ionic_cmd_opcode opcode) 64*01a6c311SAlfredo Cardigliano { 65*01a6c311SAlfredo Cardigliano switch (opcode) { 66*01a6c311SAlfredo Cardigliano case IONIC_CMD_NOP: 67*01a6c311SAlfredo Cardigliano return "IONIC_CMD_NOP"; 68*01a6c311SAlfredo Cardigliano case IONIC_CMD_INIT: 69*01a6c311SAlfredo Cardigliano return "IONIC_CMD_INIT"; 70*01a6c311SAlfredo Cardigliano case IONIC_CMD_RESET: 71*01a6c311SAlfredo Cardigliano return "IONIC_CMD_RESET"; 72*01a6c311SAlfredo Cardigliano case IONIC_CMD_IDENTIFY: 73*01a6c311SAlfredo Cardigliano return "IONIC_CMD_IDENTIFY"; 74*01a6c311SAlfredo Cardigliano case IONIC_CMD_GETATTR: 75*01a6c311SAlfredo Cardigliano return "IONIC_CMD_GETATTR"; 76*01a6c311SAlfredo Cardigliano case IONIC_CMD_SETATTR: 77*01a6c311SAlfredo Cardigliano return "IONIC_CMD_SETATTR"; 78*01a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_IDENTIFY: 79*01a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_IDENTIFY"; 80*01a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_INIT: 81*01a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_INIT"; 82*01a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_RESET: 83*01a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_RESET"; 84*01a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_GETATTR: 85*01a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_GETATTR"; 86*01a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_SETATTR: 87*01a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_SETATTR"; 88*01a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_INIT: 89*01a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_INIT"; 90*01a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_RESET: 91*01a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_RESET"; 92*01a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_IDENTIFY: 93*01a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_IDENTIFY"; 94*01a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_SETATTR: 95*01a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_SETATTR"; 96*01a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_GETATTR: 97*01a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_GETATTR"; 98*01a6c311SAlfredo Cardigliano case IONIC_CMD_RX_MODE_SET: 99*01a6c311SAlfredo Cardigliano return "IONIC_CMD_RX_MODE_SET"; 100*01a6c311SAlfredo Cardigliano case IONIC_CMD_RX_FILTER_ADD: 101*01a6c311SAlfredo Cardigliano return "IONIC_CMD_RX_FILTER_ADD"; 102*01a6c311SAlfredo Cardigliano case IONIC_CMD_RX_FILTER_DEL: 103*01a6c311SAlfredo Cardigliano return "IONIC_CMD_RX_FILTER_DEL"; 104*01a6c311SAlfredo Cardigliano case IONIC_CMD_Q_INIT: 105*01a6c311SAlfredo Cardigliano return "IONIC_CMD_Q_INIT"; 106*01a6c311SAlfredo Cardigliano case IONIC_CMD_Q_CONTROL: 107*01a6c311SAlfredo Cardigliano return "IONIC_CMD_Q_CONTROL"; 108*01a6c311SAlfredo Cardigliano case IONIC_CMD_RDMA_RESET_LIF: 109*01a6c311SAlfredo Cardigliano return "IONIC_CMD_RDMA_RESET_LIF"; 110*01a6c311SAlfredo Cardigliano case IONIC_CMD_RDMA_CREATE_EQ: 111*01a6c311SAlfredo Cardigliano return "IONIC_CMD_RDMA_CREATE_EQ"; 112*01a6c311SAlfredo Cardigliano case IONIC_CMD_RDMA_CREATE_CQ: 113*01a6c311SAlfredo Cardigliano return "IONIC_CMD_RDMA_CREATE_CQ"; 114*01a6c311SAlfredo Cardigliano case IONIC_CMD_RDMA_CREATE_ADMINQ: 115*01a6c311SAlfredo Cardigliano return "IONIC_CMD_RDMA_CREATE_ADMINQ"; 116*01a6c311SAlfredo Cardigliano default: 117*01a6c311SAlfredo Cardigliano return "DEVCMD_UNKNOWN"; 118*01a6c311SAlfredo Cardigliano } 119*01a6c311SAlfredo Cardigliano } 120*01a6c311SAlfredo Cardigliano 121*01a6c311SAlfredo Cardigliano int 122*01a6c311SAlfredo Cardigliano ionic_adminq_check_err(struct ionic_admin_ctx *ctx, bool timeout) 123*01a6c311SAlfredo Cardigliano { 124*01a6c311SAlfredo Cardigliano const char *name; 125*01a6c311SAlfredo Cardigliano const char *status; 126*01a6c311SAlfredo Cardigliano 127*01a6c311SAlfredo Cardigliano if (ctx->comp.comp.status || timeout) { 128*01a6c311SAlfredo Cardigliano name = ionic_opcode_to_str(ctx->cmd.cmd.opcode); 129*01a6c311SAlfredo Cardigliano status = ionic_error_to_str(ctx->comp.comp.status); 130*01a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "%s (%d) failed: %s (%d)", 131*01a6c311SAlfredo Cardigliano name, 132*01a6c311SAlfredo Cardigliano ctx->cmd.cmd.opcode, 133*01a6c311SAlfredo Cardigliano timeout ? "TIMEOUT" : status, 134*01a6c311SAlfredo Cardigliano timeout ? -1 : ctx->comp.comp.status); 135*01a6c311SAlfredo Cardigliano return -EIO; 136*01a6c311SAlfredo Cardigliano } 137*01a6c311SAlfredo Cardigliano 138*01a6c311SAlfredo Cardigliano return 0; 139*01a6c311SAlfredo Cardigliano } 140*01a6c311SAlfredo Cardigliano 141*01a6c311SAlfredo Cardigliano static int 142*01a6c311SAlfredo Cardigliano ionic_wait_ctx_for_completion(struct ionic_lif *lif, struct ionic_qcq *qcq, 143*01a6c311SAlfredo Cardigliano struct ionic_admin_ctx *ctx, unsigned long max_wait) 144*01a6c311SAlfredo Cardigliano { 145*01a6c311SAlfredo Cardigliano unsigned long step_msec = 1; 146*01a6c311SAlfredo Cardigliano unsigned int max_wait_msec = max_wait * 1000; 147*01a6c311SAlfredo Cardigliano unsigned long elapsed_msec = 0; 148*01a6c311SAlfredo Cardigliano int budget = 8; 149*01a6c311SAlfredo Cardigliano 150*01a6c311SAlfredo Cardigliano while (ctx->pending_work && elapsed_msec < max_wait_msec) { 151*01a6c311SAlfredo Cardigliano /* 152*01a6c311SAlfredo Cardigliano * Locking here as adminq is served inline (this could be called 153*01a6c311SAlfredo Cardigliano * from multiple places) 154*01a6c311SAlfredo Cardigliano */ 155*01a6c311SAlfredo Cardigliano rte_spinlock_lock(&lif->adminq_service_lock); 156*01a6c311SAlfredo Cardigliano 157*01a6c311SAlfredo Cardigliano ionic_qcq_service(qcq, budget, ionic_adminq_service, NULL); 158*01a6c311SAlfredo Cardigliano 159*01a6c311SAlfredo Cardigliano rte_spinlock_unlock(&lif->adminq_service_lock); 160*01a6c311SAlfredo Cardigliano 161*01a6c311SAlfredo Cardigliano msec_delay(step_msec); 162*01a6c311SAlfredo Cardigliano elapsed_msec += step_msec; 163*01a6c311SAlfredo Cardigliano } 164*01a6c311SAlfredo Cardigliano 165*01a6c311SAlfredo Cardigliano return (!ctx->pending_work); 166*01a6c311SAlfredo Cardigliano } 167*01a6c311SAlfredo Cardigliano 168*01a6c311SAlfredo Cardigliano int 169*01a6c311SAlfredo Cardigliano ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) 170*01a6c311SAlfredo Cardigliano { 171*01a6c311SAlfredo Cardigliano struct ionic_qcq *qcq = lif->adminqcq; 172*01a6c311SAlfredo Cardigliano bool done; 173*01a6c311SAlfredo Cardigliano int err; 174*01a6c311SAlfredo Cardigliano 175*01a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Sending %s to the admin queue", 176*01a6c311SAlfredo Cardigliano ionic_opcode_to_str(ctx->cmd.cmd.opcode)); 177*01a6c311SAlfredo Cardigliano 178*01a6c311SAlfredo Cardigliano err = ionic_adminq_post(lif, ctx); 179*01a6c311SAlfredo Cardigliano if (err) { 180*01a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure posting to the admin queue %d (%d)", 181*01a6c311SAlfredo Cardigliano ctx->cmd.cmd.opcode, err); 182*01a6c311SAlfredo Cardigliano 183*01a6c311SAlfredo Cardigliano return err; 184*01a6c311SAlfredo Cardigliano } 185*01a6c311SAlfredo Cardigliano 186*01a6c311SAlfredo Cardigliano done = ionic_wait_ctx_for_completion(lif, qcq, ctx, 187*01a6c311SAlfredo Cardigliano IONIC_DEVCMD_TIMEOUT); 188*01a6c311SAlfredo Cardigliano 189*01a6c311SAlfredo Cardigliano err = ionic_adminq_check_err(ctx, !done /* timed out */); 190*01a6c311SAlfredo Cardigliano return err; 191*01a6c311SAlfredo Cardigliano } 1925ef51809SAlfredo Cardigliano 1935ef51809SAlfredo Cardigliano static int 1945ef51809SAlfredo Cardigliano ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait) 1955ef51809SAlfredo Cardigliano { 1965ef51809SAlfredo Cardigliano unsigned long step_msec = 100; 1975ef51809SAlfredo Cardigliano unsigned int max_wait_msec = max_wait * 1000; 1985ef51809SAlfredo Cardigliano unsigned long elapsed_msec = 0; 1995ef51809SAlfredo Cardigliano int done; 2005ef51809SAlfredo Cardigliano 2015ef51809SAlfredo Cardigliano /* Wait for dev cmd to complete.. but no more than max_wait sec */ 2025ef51809SAlfredo Cardigliano 2035ef51809SAlfredo Cardigliano do { 2045ef51809SAlfredo Cardigliano done = ionic_dev_cmd_done(idev); 2055ef51809SAlfredo Cardigliano if (done) { 2065ef51809SAlfredo Cardigliano IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld msecs", 2075ef51809SAlfredo Cardigliano idev->dev_cmd->cmd.cmd.opcode, 2085ef51809SAlfredo Cardigliano elapsed_msec); 2095ef51809SAlfredo Cardigliano return 0; 2105ef51809SAlfredo Cardigliano } 2115ef51809SAlfredo Cardigliano 2125ef51809SAlfredo Cardigliano msec_delay(step_msec); 2135ef51809SAlfredo Cardigliano 2145ef51809SAlfredo Cardigliano elapsed_msec += step_msec; 2155ef51809SAlfredo Cardigliano } while (elapsed_msec < max_wait_msec); 2165ef51809SAlfredo Cardigliano 2175ef51809SAlfredo Cardigliano IONIC_PRINT(DEBUG, "DEVCMD %d timeout after %ld msecs", 2185ef51809SAlfredo Cardigliano idev->dev_cmd->cmd.cmd.opcode, 2195ef51809SAlfredo Cardigliano elapsed_msec); 2205ef51809SAlfredo Cardigliano 2215ef51809SAlfredo Cardigliano return -ETIMEDOUT; 2225ef51809SAlfredo Cardigliano } 2235ef51809SAlfredo Cardigliano 2245ef51809SAlfredo Cardigliano static int 2255ef51809SAlfredo Cardigliano ionic_dev_cmd_check_error(struct ionic_dev *idev) 2265ef51809SAlfredo Cardigliano { 2275ef51809SAlfredo Cardigliano uint8_t status; 2285ef51809SAlfredo Cardigliano 2295ef51809SAlfredo Cardigliano status = ionic_dev_cmd_status(idev); 2305ef51809SAlfredo Cardigliano if (status == 0) 2315ef51809SAlfredo Cardigliano return 0; 2325ef51809SAlfredo Cardigliano 2335ef51809SAlfredo Cardigliano return -EIO; 2345ef51809SAlfredo Cardigliano } 2355ef51809SAlfredo Cardigliano 2365ef51809SAlfredo Cardigliano int 2375ef51809SAlfredo Cardigliano ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait) 2385ef51809SAlfredo Cardigliano { 2395ef51809SAlfredo Cardigliano int err; 2405ef51809SAlfredo Cardigliano 2415ef51809SAlfredo Cardigliano err = ionic_dev_cmd_wait(idev, max_wait); 2425ef51809SAlfredo Cardigliano if (err) 2435ef51809SAlfredo Cardigliano return err; 2445ef51809SAlfredo Cardigliano 2455ef51809SAlfredo Cardigliano return ionic_dev_cmd_check_error(idev); 2465ef51809SAlfredo Cardigliano } 2475ef51809SAlfredo Cardigliano 2485ef51809SAlfredo Cardigliano int 2495ef51809SAlfredo Cardigliano ionic_setup(struct ionic_adapter *adapter) 2505ef51809SAlfredo Cardigliano { 2515ef51809SAlfredo Cardigliano return ionic_dev_setup(adapter); 2525ef51809SAlfredo Cardigliano } 2535ef51809SAlfredo Cardigliano 2545ef51809SAlfredo Cardigliano int 2555ef51809SAlfredo Cardigliano ionic_identify(struct ionic_adapter *adapter) 2565ef51809SAlfredo Cardigliano { 2575ef51809SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 2585ef51809SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 2595ef51809SAlfredo Cardigliano int err = 0; 2605ef51809SAlfredo Cardigliano uint32_t i; 2615ef51809SAlfredo Cardigliano unsigned int nwords; 2625ef51809SAlfredo Cardigliano uint32_t drv_size = sizeof(ident->drv.words) / 2635ef51809SAlfredo Cardigliano sizeof(ident->drv.words[0]); 2645ef51809SAlfredo Cardigliano uint32_t cmd_size = sizeof(idev->dev_cmd->data) / 2655ef51809SAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 2665ef51809SAlfredo Cardigliano uint32_t dev_size = sizeof(ident->dev.words) / 2675ef51809SAlfredo Cardigliano sizeof(ident->dev.words[0]); 2685ef51809SAlfredo Cardigliano 2695ef51809SAlfredo Cardigliano memset(ident, 0, sizeof(*ident)); 2705ef51809SAlfredo Cardigliano 2715ef51809SAlfredo Cardigliano ident->drv.os_type = IONIC_OS_TYPE_LINUX; 2725ef51809SAlfredo Cardigliano ident->drv.os_dist = 0; 2735ef51809SAlfredo Cardigliano snprintf(ident->drv.os_dist_str, 2745ef51809SAlfredo Cardigliano sizeof(ident->drv.os_dist_str), "Unknown"); 2755ef51809SAlfredo Cardigliano ident->drv.kernel_ver = 0; 2765ef51809SAlfredo Cardigliano snprintf(ident->drv.kernel_ver_str, 2775ef51809SAlfredo Cardigliano sizeof(ident->drv.kernel_ver_str), "DPDK"); 2785ef51809SAlfredo Cardigliano strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION, 2795ef51809SAlfredo Cardigliano sizeof(ident->drv.driver_ver_str) - 1); 2805ef51809SAlfredo Cardigliano 2815ef51809SAlfredo Cardigliano nwords = RTE_MIN(drv_size, cmd_size); 2825ef51809SAlfredo Cardigliano for (i = 0; i < nwords; i++) 2835ef51809SAlfredo Cardigliano iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]); 2845ef51809SAlfredo Cardigliano 2855ef51809SAlfredo Cardigliano ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1); 2865ef51809SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 2875ef51809SAlfredo Cardigliano if (!err) { 2885ef51809SAlfredo Cardigliano nwords = RTE_MIN(dev_size, cmd_size); 2895ef51809SAlfredo Cardigliano for (i = 0; i < nwords; i++) 2905ef51809SAlfredo Cardigliano ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]); 2915ef51809SAlfredo Cardigliano } 2925ef51809SAlfredo Cardigliano 2935ef51809SAlfredo Cardigliano return err; 2945ef51809SAlfredo Cardigliano } 2955ef51809SAlfredo Cardigliano 2965ef51809SAlfredo Cardigliano int 2975ef51809SAlfredo Cardigliano ionic_init(struct ionic_adapter *adapter) 2985ef51809SAlfredo Cardigliano { 2995ef51809SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 3005ef51809SAlfredo Cardigliano int err; 3015ef51809SAlfredo Cardigliano 3025ef51809SAlfredo Cardigliano ionic_dev_cmd_init(idev); 3035ef51809SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 3045ef51809SAlfredo Cardigliano return err; 3055ef51809SAlfredo Cardigliano } 3065ef51809SAlfredo Cardigliano 3075ef51809SAlfredo Cardigliano int 3085ef51809SAlfredo Cardigliano ionic_reset(struct ionic_adapter *adapter) 3095ef51809SAlfredo Cardigliano { 3105ef51809SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 3115ef51809SAlfredo Cardigliano int err; 3125ef51809SAlfredo Cardigliano 3135ef51809SAlfredo Cardigliano ionic_dev_cmd_reset(idev); 3145ef51809SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 3155ef51809SAlfredo Cardigliano return err; 3165ef51809SAlfredo Cardigliano } 31723bf4ddbSAlfredo Cardigliano 31823bf4ddbSAlfredo Cardigliano int 31923bf4ddbSAlfredo Cardigliano ionic_port_identify(struct ionic_adapter *adapter) 32023bf4ddbSAlfredo Cardigliano { 32123bf4ddbSAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 32223bf4ddbSAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 32323bf4ddbSAlfredo Cardigliano unsigned int port_words = sizeof(ident->port.words) / 32423bf4ddbSAlfredo Cardigliano sizeof(ident->port.words[0]); 32523bf4ddbSAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 32623bf4ddbSAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 32723bf4ddbSAlfredo Cardigliano unsigned int i; 32823bf4ddbSAlfredo Cardigliano unsigned int nwords; 32923bf4ddbSAlfredo Cardigliano int err; 33023bf4ddbSAlfredo Cardigliano 33123bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_identify(idev); 33223bf4ddbSAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 33323bf4ddbSAlfredo Cardigliano if (!err) { 33423bf4ddbSAlfredo Cardigliano nwords = RTE_MIN(port_words, cmd_words); 33523bf4ddbSAlfredo Cardigliano for (i = 0; i < nwords; i++) 33623bf4ddbSAlfredo Cardigliano ident->port.words[i] = 33723bf4ddbSAlfredo Cardigliano ioread32(&idev->dev_cmd->data[i]); 33823bf4ddbSAlfredo Cardigliano } 33923bf4ddbSAlfredo Cardigliano 34023bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "speed %d ", ident->port.config.speed); 34123bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "mtu %d ", ident->port.config.mtu); 34223bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "state %d ", ident->port.config.state); 34323bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "an_enable %d ", ident->port.config.an_enable); 34423bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "fec_type %d ", ident->port.config.fec_type); 34523bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "pause_type %d ", ident->port.config.pause_type); 34623bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "loopback_mode %d", 34723bf4ddbSAlfredo Cardigliano ident->port.config.loopback_mode); 34823bf4ddbSAlfredo Cardigliano 34923bf4ddbSAlfredo Cardigliano return err; 35023bf4ddbSAlfredo Cardigliano } 35123bf4ddbSAlfredo Cardigliano 35223bf4ddbSAlfredo Cardigliano static const struct rte_memzone * 35323bf4ddbSAlfredo Cardigliano ionic_memzone_reserve(const char *name, uint32_t len, int socket_id) 35423bf4ddbSAlfredo Cardigliano { 35523bf4ddbSAlfredo Cardigliano const struct rte_memzone *mz; 35623bf4ddbSAlfredo Cardigliano 35723bf4ddbSAlfredo Cardigliano mz = rte_memzone_lookup(name); 35823bf4ddbSAlfredo Cardigliano if (mz) 35923bf4ddbSAlfredo Cardigliano return mz; 36023bf4ddbSAlfredo Cardigliano 36123bf4ddbSAlfredo Cardigliano mz = rte_memzone_reserve_aligned(name, len, socket_id, 36223bf4ddbSAlfredo Cardigliano RTE_MEMZONE_IOVA_CONTIG, IONIC_ALIGN); 36323bf4ddbSAlfredo Cardigliano return mz; 36423bf4ddbSAlfredo Cardigliano } 36523bf4ddbSAlfredo Cardigliano 36623bf4ddbSAlfredo Cardigliano int 36723bf4ddbSAlfredo Cardigliano ionic_port_init(struct ionic_adapter *adapter) 36823bf4ddbSAlfredo Cardigliano { 36923bf4ddbSAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 37023bf4ddbSAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 37123bf4ddbSAlfredo Cardigliano char z_name[RTE_MEMZONE_NAMESIZE]; 37223bf4ddbSAlfredo Cardigliano unsigned int config_words = sizeof(ident->port.config.words) / 37323bf4ddbSAlfredo Cardigliano sizeof(ident->port.config.words[0]); 37423bf4ddbSAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 37523bf4ddbSAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 37623bf4ddbSAlfredo Cardigliano unsigned int nwords; 37723bf4ddbSAlfredo Cardigliano unsigned int i; 37823bf4ddbSAlfredo Cardigliano int err; 37923bf4ddbSAlfredo Cardigliano 38023bf4ddbSAlfredo Cardigliano if (idev->port_info) 38123bf4ddbSAlfredo Cardigliano return 0; 38223bf4ddbSAlfredo Cardigliano 38323bf4ddbSAlfredo Cardigliano idev->port_info_sz = RTE_ALIGN(sizeof(*idev->port_info), PAGE_SIZE); 38423bf4ddbSAlfredo Cardigliano 38523bf4ddbSAlfredo Cardigliano snprintf(z_name, sizeof(z_name), "%s_port_%s_info", 38623bf4ddbSAlfredo Cardigliano IONIC_DRV_NAME, 38723bf4ddbSAlfredo Cardigliano adapter->pci_dev->device.name); 38823bf4ddbSAlfredo Cardigliano 38923bf4ddbSAlfredo Cardigliano idev->port_info_z = ionic_memzone_reserve(z_name, idev->port_info_sz, 39023bf4ddbSAlfredo Cardigliano SOCKET_ID_ANY); 39123bf4ddbSAlfredo Cardigliano if (!idev->port_info_z) { 39223bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve port info DMA memory"); 39323bf4ddbSAlfredo Cardigliano return -ENOMEM; 39423bf4ddbSAlfredo Cardigliano } 39523bf4ddbSAlfredo Cardigliano 39623bf4ddbSAlfredo Cardigliano idev->port_info = idev->port_info_z->addr; 39723bf4ddbSAlfredo Cardigliano idev->port_info_pa = idev->port_info_z->iova; 39823bf4ddbSAlfredo Cardigliano 39923bf4ddbSAlfredo Cardigliano nwords = RTE_MIN(config_words, cmd_words); 40023bf4ddbSAlfredo Cardigliano 40123bf4ddbSAlfredo Cardigliano for (i = 0; i < nwords; i++) 40223bf4ddbSAlfredo Cardigliano iowrite32(ident->port.config.words[i], &idev->dev_cmd->data[i]); 40323bf4ddbSAlfredo Cardigliano 40423bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_init(idev); 40523bf4ddbSAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 40623bf4ddbSAlfredo Cardigliano if (err) { 40723bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Failed to init port"); 40823bf4ddbSAlfredo Cardigliano return err; 40923bf4ddbSAlfredo Cardigliano } 41023bf4ddbSAlfredo Cardigliano 41123bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP); 41223bf4ddbSAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 41323bf4ddbSAlfredo Cardigliano if (err) { 41423bf4ddbSAlfredo Cardigliano IONIC_PRINT(WARNING, "Failed to bring port UP"); 41523bf4ddbSAlfredo Cardigliano return err; 41623bf4ddbSAlfredo Cardigliano } 41723bf4ddbSAlfredo Cardigliano 41823bf4ddbSAlfredo Cardigliano return 0; 41923bf4ddbSAlfredo Cardigliano } 42023bf4ddbSAlfredo Cardigliano 42123bf4ddbSAlfredo Cardigliano int 42223bf4ddbSAlfredo Cardigliano ionic_port_reset(struct ionic_adapter *adapter) 42323bf4ddbSAlfredo Cardigliano { 42423bf4ddbSAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 42523bf4ddbSAlfredo Cardigliano int err; 42623bf4ddbSAlfredo Cardigliano 42723bf4ddbSAlfredo Cardigliano if (!idev->port_info) 42823bf4ddbSAlfredo Cardigliano return 0; 42923bf4ddbSAlfredo Cardigliano 43023bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_reset(idev); 43123bf4ddbSAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 43223bf4ddbSAlfredo Cardigliano if (err) { 43323bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Failed to reset port"); 43423bf4ddbSAlfredo Cardigliano return err; 43523bf4ddbSAlfredo Cardigliano } 43623bf4ddbSAlfredo Cardigliano 43723bf4ddbSAlfredo Cardigliano idev->port_info = NULL; 43823bf4ddbSAlfredo Cardigliano idev->port_info_pa = 0; 43923bf4ddbSAlfredo Cardigliano 44023bf4ddbSAlfredo Cardigliano return 0; 44123bf4ddbSAlfredo Cardigliano } 442