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 5e40303ebSSunil Kumar Kori #include <stdbool.h> 6e40303ebSSunil Kumar Kori 723bf4ddbSAlfredo Cardigliano #include <rte_memzone.h> 823bf4ddbSAlfredo Cardigliano 95ef51809SAlfredo Cardigliano #include "ionic.h" 1001a6c311SAlfredo Cardigliano #include "ionic_ethdev.h" 1101a6c311SAlfredo Cardigliano #include "ionic_lif.h" 1201a6c311SAlfredo Cardigliano 1301a6c311SAlfredo Cardigliano static const char * 1401a6c311SAlfredo Cardigliano ionic_error_to_str(enum ionic_status_code code) 1501a6c311SAlfredo Cardigliano { 1601a6c311SAlfredo Cardigliano switch (code) { 1701a6c311SAlfredo Cardigliano case IONIC_RC_SUCCESS: 1801a6c311SAlfredo Cardigliano return "IONIC_RC_SUCCESS"; 1901a6c311SAlfredo Cardigliano case IONIC_RC_EVERSION: 2001a6c311SAlfredo Cardigliano return "IONIC_RC_EVERSION"; 2101a6c311SAlfredo Cardigliano case IONIC_RC_EOPCODE: 2201a6c311SAlfredo Cardigliano return "IONIC_RC_EOPCODE"; 2301a6c311SAlfredo Cardigliano case IONIC_RC_EIO: 2401a6c311SAlfredo Cardigliano return "IONIC_RC_EIO"; 2501a6c311SAlfredo Cardigliano case IONIC_RC_EPERM: 2601a6c311SAlfredo Cardigliano return "IONIC_RC_EPERM"; 2701a6c311SAlfredo Cardigliano case IONIC_RC_EQID: 2801a6c311SAlfredo Cardigliano return "IONIC_RC_EQID"; 2901a6c311SAlfredo Cardigliano case IONIC_RC_EQTYPE: 3001a6c311SAlfredo Cardigliano return "IONIC_RC_EQTYPE"; 3101a6c311SAlfredo Cardigliano case IONIC_RC_ENOENT: 3201a6c311SAlfredo Cardigliano return "IONIC_RC_ENOENT"; 3301a6c311SAlfredo Cardigliano case IONIC_RC_EINTR: 3401a6c311SAlfredo Cardigliano return "IONIC_RC_EINTR"; 3501a6c311SAlfredo Cardigliano case IONIC_RC_EAGAIN: 3601a6c311SAlfredo Cardigliano return "IONIC_RC_EAGAIN"; 3701a6c311SAlfredo Cardigliano case IONIC_RC_ENOMEM: 3801a6c311SAlfredo Cardigliano return "IONIC_RC_ENOMEM"; 3901a6c311SAlfredo Cardigliano case IONIC_RC_EFAULT: 4001a6c311SAlfredo Cardigliano return "IONIC_RC_EFAULT"; 4101a6c311SAlfredo Cardigliano case IONIC_RC_EBUSY: 4201a6c311SAlfredo Cardigliano return "IONIC_RC_EBUSY"; 4301a6c311SAlfredo Cardigliano case IONIC_RC_EEXIST: 4401a6c311SAlfredo Cardigliano return "IONIC_RC_EEXIST"; 4501a6c311SAlfredo Cardigliano case IONIC_RC_EINVAL: 4601a6c311SAlfredo Cardigliano return "IONIC_RC_EINVAL"; 4701a6c311SAlfredo Cardigliano case IONIC_RC_ENOSPC: 4801a6c311SAlfredo Cardigliano return "IONIC_RC_ENOSPC"; 4901a6c311SAlfredo Cardigliano case IONIC_RC_ERANGE: 5001a6c311SAlfredo Cardigliano return "IONIC_RC_ERANGE"; 5101a6c311SAlfredo Cardigliano case IONIC_RC_BAD_ADDR: 5201a6c311SAlfredo Cardigliano return "IONIC_RC_BAD_ADDR"; 5301a6c311SAlfredo Cardigliano case IONIC_RC_DEV_CMD: 5401a6c311SAlfredo Cardigliano return "IONIC_RC_DEV_CMD"; 5501a6c311SAlfredo Cardigliano case IONIC_RC_ERROR: 5601a6c311SAlfredo Cardigliano return "IONIC_RC_ERROR"; 5701a6c311SAlfredo Cardigliano case IONIC_RC_ERDMA: 5801a6c311SAlfredo Cardigliano return "IONIC_RC_ERDMA"; 5901a6c311SAlfredo Cardigliano default: 6001a6c311SAlfredo Cardigliano return "IONIC_RC_UNKNOWN"; 6101a6c311SAlfredo Cardigliano } 6201a6c311SAlfredo Cardigliano } 6301a6c311SAlfredo Cardigliano 6401a6c311SAlfredo Cardigliano static const char * 6501a6c311SAlfredo Cardigliano ionic_opcode_to_str(enum ionic_cmd_opcode opcode) 6601a6c311SAlfredo Cardigliano { 6701a6c311SAlfredo Cardigliano switch (opcode) { 6801a6c311SAlfredo Cardigliano case IONIC_CMD_NOP: 6901a6c311SAlfredo Cardigliano return "IONIC_CMD_NOP"; 7001a6c311SAlfredo Cardigliano case IONIC_CMD_INIT: 7101a6c311SAlfredo Cardigliano return "IONIC_CMD_INIT"; 7201a6c311SAlfredo Cardigliano case IONIC_CMD_RESET: 7301a6c311SAlfredo Cardigliano return "IONIC_CMD_RESET"; 7401a6c311SAlfredo Cardigliano case IONIC_CMD_IDENTIFY: 7501a6c311SAlfredo Cardigliano return "IONIC_CMD_IDENTIFY"; 7601a6c311SAlfredo Cardigliano case IONIC_CMD_GETATTR: 7701a6c311SAlfredo Cardigliano return "IONIC_CMD_GETATTR"; 7801a6c311SAlfredo Cardigliano case IONIC_CMD_SETATTR: 7901a6c311SAlfredo Cardigliano return "IONIC_CMD_SETATTR"; 8001a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_IDENTIFY: 8101a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_IDENTIFY"; 8201a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_INIT: 8301a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_INIT"; 8401a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_RESET: 8501a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_RESET"; 8601a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_GETATTR: 8701a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_GETATTR"; 8801a6c311SAlfredo Cardigliano case IONIC_CMD_PORT_SETATTR: 8901a6c311SAlfredo Cardigliano return "IONIC_CMD_PORT_SETATTR"; 9001a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_INIT: 9101a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_INIT"; 9201a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_RESET: 9301a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_RESET"; 9401a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_IDENTIFY: 9501a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_IDENTIFY"; 9601a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_SETATTR: 9701a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_SETATTR"; 9801a6c311SAlfredo Cardigliano case IONIC_CMD_LIF_GETATTR: 9901a6c311SAlfredo Cardigliano return "IONIC_CMD_LIF_GETATTR"; 10001a6c311SAlfredo Cardigliano case IONIC_CMD_RX_MODE_SET: 10101a6c311SAlfredo Cardigliano return "IONIC_CMD_RX_MODE_SET"; 10201a6c311SAlfredo Cardigliano case IONIC_CMD_RX_FILTER_ADD: 10301a6c311SAlfredo Cardigliano return "IONIC_CMD_RX_FILTER_ADD"; 10401a6c311SAlfredo Cardigliano case IONIC_CMD_RX_FILTER_DEL: 10501a6c311SAlfredo Cardigliano return "IONIC_CMD_RX_FILTER_DEL"; 10601a6c311SAlfredo Cardigliano case IONIC_CMD_Q_INIT: 10701a6c311SAlfredo Cardigliano return "IONIC_CMD_Q_INIT"; 10801a6c311SAlfredo Cardigliano case IONIC_CMD_Q_CONTROL: 10901a6c311SAlfredo Cardigliano return "IONIC_CMD_Q_CONTROL"; 11001a6c311SAlfredo Cardigliano case IONIC_CMD_RDMA_RESET_LIF: 11101a6c311SAlfredo Cardigliano return "IONIC_CMD_RDMA_RESET_LIF"; 11201a6c311SAlfredo Cardigliano case IONIC_CMD_RDMA_CREATE_EQ: 11301a6c311SAlfredo Cardigliano return "IONIC_CMD_RDMA_CREATE_EQ"; 11401a6c311SAlfredo Cardigliano case IONIC_CMD_RDMA_CREATE_CQ: 11501a6c311SAlfredo Cardigliano return "IONIC_CMD_RDMA_CREATE_CQ"; 11601a6c311SAlfredo Cardigliano case IONIC_CMD_RDMA_CREATE_ADMINQ: 11701a6c311SAlfredo Cardigliano return "IONIC_CMD_RDMA_CREATE_ADMINQ"; 11801a6c311SAlfredo Cardigliano default: 11901a6c311SAlfredo Cardigliano return "DEVCMD_UNKNOWN"; 12001a6c311SAlfredo Cardigliano } 12101a6c311SAlfredo Cardigliano } 12201a6c311SAlfredo Cardigliano 12301a6c311SAlfredo Cardigliano int 12401a6c311SAlfredo Cardigliano ionic_adminq_check_err(struct ionic_admin_ctx *ctx, bool timeout) 12501a6c311SAlfredo Cardigliano { 12601a6c311SAlfredo Cardigliano const char *name; 12701a6c311SAlfredo Cardigliano const char *status; 12801a6c311SAlfredo Cardigliano 12901a6c311SAlfredo Cardigliano if (ctx->comp.comp.status || timeout) { 13001a6c311SAlfredo Cardigliano name = ionic_opcode_to_str(ctx->cmd.cmd.opcode); 13101a6c311SAlfredo Cardigliano status = ionic_error_to_str(ctx->comp.comp.status); 13201a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "%s (%d) failed: %s (%d)", 13301a6c311SAlfredo Cardigliano name, 13401a6c311SAlfredo Cardigliano ctx->cmd.cmd.opcode, 13501a6c311SAlfredo Cardigliano timeout ? "TIMEOUT" : status, 13601a6c311SAlfredo Cardigliano timeout ? -1 : ctx->comp.comp.status); 13701a6c311SAlfredo Cardigliano return -EIO; 13801a6c311SAlfredo Cardigliano } 13901a6c311SAlfredo Cardigliano 14001a6c311SAlfredo Cardigliano return 0; 14101a6c311SAlfredo Cardigliano } 14201a6c311SAlfredo Cardigliano 14301a6c311SAlfredo Cardigliano static int 14401a6c311SAlfredo Cardigliano ionic_wait_ctx_for_completion(struct ionic_lif *lif, struct ionic_qcq *qcq, 14501a6c311SAlfredo Cardigliano struct ionic_admin_ctx *ctx, unsigned long max_wait) 14601a6c311SAlfredo Cardigliano { 14747dc2bd3SAndrew Boyer unsigned long step_usec = IONIC_DEVCMD_CHECK_PERIOD_US; 14847dc2bd3SAndrew Boyer unsigned long max_wait_usec = max_wait * 1000000L; 14947dc2bd3SAndrew Boyer unsigned long elapsed_usec = 0; 15001a6c311SAlfredo Cardigliano int budget = 8; 15101a6c311SAlfredo Cardigliano 15247dc2bd3SAndrew Boyer while (ctx->pending_work && elapsed_usec < max_wait_usec) { 15301a6c311SAlfredo Cardigliano /* 15401a6c311SAlfredo Cardigliano * Locking here as adminq is served inline (this could be called 15501a6c311SAlfredo Cardigliano * from multiple places) 15601a6c311SAlfredo Cardigliano */ 15701a6c311SAlfredo Cardigliano rte_spinlock_lock(&lif->adminq_service_lock); 15801a6c311SAlfredo Cardigliano 15901a6c311SAlfredo Cardigliano ionic_qcq_service(qcq, budget, ionic_adminq_service, NULL); 16001a6c311SAlfredo Cardigliano 16101a6c311SAlfredo Cardigliano rte_spinlock_unlock(&lif->adminq_service_lock); 16201a6c311SAlfredo Cardigliano 16347dc2bd3SAndrew Boyer rte_delay_us_block(step_usec); 16447dc2bd3SAndrew Boyer elapsed_usec += step_usec; 16501a6c311SAlfredo Cardigliano } 16601a6c311SAlfredo Cardigliano 16701a6c311SAlfredo Cardigliano return (!ctx->pending_work); 16801a6c311SAlfredo Cardigliano } 16901a6c311SAlfredo Cardigliano 17001a6c311SAlfredo Cardigliano int 17101a6c311SAlfredo Cardigliano ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) 17201a6c311SAlfredo Cardigliano { 17301a6c311SAlfredo Cardigliano struct ionic_qcq *qcq = lif->adminqcq; 17401a6c311SAlfredo Cardigliano bool done; 17501a6c311SAlfredo Cardigliano int err; 17601a6c311SAlfredo Cardigliano 17701a6c311SAlfredo Cardigliano IONIC_PRINT(DEBUG, "Sending %s to the admin queue", 17801a6c311SAlfredo Cardigliano ionic_opcode_to_str(ctx->cmd.cmd.opcode)); 17901a6c311SAlfredo Cardigliano 18001a6c311SAlfredo Cardigliano err = ionic_adminq_post(lif, ctx); 18101a6c311SAlfredo Cardigliano if (err) { 18201a6c311SAlfredo Cardigliano IONIC_PRINT(ERR, "Failure posting to the admin queue %d (%d)", 18301a6c311SAlfredo Cardigliano ctx->cmd.cmd.opcode, err); 18401a6c311SAlfredo Cardigliano 18501a6c311SAlfredo Cardigliano return err; 18601a6c311SAlfredo Cardigliano } 18701a6c311SAlfredo Cardigliano 18801a6c311SAlfredo Cardigliano done = ionic_wait_ctx_for_completion(lif, qcq, ctx, 18901a6c311SAlfredo Cardigliano IONIC_DEVCMD_TIMEOUT); 19001a6c311SAlfredo Cardigliano 191*75f96902SAndrew Boyer return ionic_adminq_check_err(ctx, !done /* timed out */); 19201a6c311SAlfredo Cardigliano } 1935ef51809SAlfredo Cardigliano 1945ef51809SAlfredo Cardigliano static int 1955ef51809SAlfredo Cardigliano ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait) 1965ef51809SAlfredo Cardigliano { 19747dc2bd3SAndrew Boyer unsigned long step_usec = IONIC_DEVCMD_CHECK_PERIOD_US; 19847dc2bd3SAndrew Boyer unsigned long max_wait_usec = max_wait * 1000000L; 19947dc2bd3SAndrew Boyer unsigned long elapsed_usec = 0; 2005ef51809SAlfredo Cardigliano int done; 2015ef51809SAlfredo Cardigliano 2025ef51809SAlfredo Cardigliano /* Wait for dev cmd to complete.. but no more than max_wait sec */ 2035ef51809SAlfredo Cardigliano 2045ef51809SAlfredo Cardigliano do { 2055ef51809SAlfredo Cardigliano done = ionic_dev_cmd_done(idev); 2065ef51809SAlfredo Cardigliano if (done) { 20747dc2bd3SAndrew Boyer IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld usecs", 20847dc2bd3SAndrew Boyer ioread8(&idev->dev_cmd->cmd.cmd.opcode), 20947dc2bd3SAndrew Boyer elapsed_usec); 2105ef51809SAlfredo Cardigliano return 0; 2115ef51809SAlfredo Cardigliano } 2125ef51809SAlfredo Cardigliano 21347dc2bd3SAndrew Boyer rte_delay_us_block(step_usec); 2145ef51809SAlfredo Cardigliano 21547dc2bd3SAndrew Boyer elapsed_usec += step_usec; 21647dc2bd3SAndrew Boyer } while (elapsed_usec < max_wait_usec); 2175ef51809SAlfredo Cardigliano 21847dc2bd3SAndrew Boyer IONIC_PRINT(ERR, "DEVCMD %d timeout after %ld usecs", 21947dc2bd3SAndrew Boyer ioread8(&idev->dev_cmd->cmd.cmd.opcode), 22047dc2bd3SAndrew Boyer elapsed_usec); 2215ef51809SAlfredo Cardigliano 2225ef51809SAlfredo Cardigliano return -ETIMEDOUT; 2235ef51809SAlfredo Cardigliano } 2245ef51809SAlfredo Cardigliano 2255ef51809SAlfredo Cardigliano static int 2265ef51809SAlfredo Cardigliano ionic_dev_cmd_check_error(struct ionic_dev *idev) 2275ef51809SAlfredo Cardigliano { 2285ef51809SAlfredo Cardigliano uint8_t status; 2295ef51809SAlfredo Cardigliano 2305ef51809SAlfredo Cardigliano status = ionic_dev_cmd_status(idev); 2315ef51809SAlfredo Cardigliano if (status == 0) 2325ef51809SAlfredo Cardigliano return 0; 2335ef51809SAlfredo Cardigliano 2345ef51809SAlfredo Cardigliano return -EIO; 2355ef51809SAlfredo Cardigliano } 2365ef51809SAlfredo Cardigliano 2375ef51809SAlfredo Cardigliano int 2385ef51809SAlfredo Cardigliano ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait) 2395ef51809SAlfredo Cardigliano { 2405ef51809SAlfredo Cardigliano int err; 2415ef51809SAlfredo Cardigliano 2425ef51809SAlfredo Cardigliano err = ionic_dev_cmd_wait(idev, max_wait); 2435ef51809SAlfredo Cardigliano 244*75f96902SAndrew Boyer if (!err) 245*75f96902SAndrew Boyer err = ionic_dev_cmd_check_error(idev); 246*75f96902SAndrew Boyer 247*75f96902SAndrew Boyer return err; 2485ef51809SAlfredo Cardigliano } 2495ef51809SAlfredo Cardigliano 2505ef51809SAlfredo Cardigliano int 2515ef51809SAlfredo Cardigliano ionic_setup(struct ionic_adapter *adapter) 2525ef51809SAlfredo Cardigliano { 2535ef51809SAlfredo Cardigliano return ionic_dev_setup(adapter); 2545ef51809SAlfredo Cardigliano } 2555ef51809SAlfredo Cardigliano 2565ef51809SAlfredo Cardigliano int 2575ef51809SAlfredo Cardigliano ionic_identify(struct ionic_adapter *adapter) 2585ef51809SAlfredo Cardigliano { 2595ef51809SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 2605ef51809SAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 2615ef51809SAlfredo Cardigliano int err = 0; 2625ef51809SAlfredo Cardigliano uint32_t i; 2635ef51809SAlfredo Cardigliano unsigned int nwords; 2645ef51809SAlfredo Cardigliano uint32_t drv_size = sizeof(ident->drv.words) / 2655ef51809SAlfredo Cardigliano sizeof(ident->drv.words[0]); 2665ef51809SAlfredo Cardigliano uint32_t cmd_size = sizeof(idev->dev_cmd->data) / 2675ef51809SAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 2685ef51809SAlfredo Cardigliano uint32_t dev_size = sizeof(ident->dev.words) / 2695ef51809SAlfredo Cardigliano sizeof(ident->dev.words[0]); 2705ef51809SAlfredo Cardigliano 2715ef51809SAlfredo Cardigliano memset(ident, 0, sizeof(*ident)); 2725ef51809SAlfredo Cardigliano 2735ef51809SAlfredo Cardigliano ident->drv.os_type = IONIC_OS_TYPE_LINUX; 2745ef51809SAlfredo Cardigliano ident->drv.os_dist = 0; 2755ef51809SAlfredo Cardigliano snprintf(ident->drv.os_dist_str, 2765ef51809SAlfredo Cardigliano sizeof(ident->drv.os_dist_str), "Unknown"); 2775ef51809SAlfredo Cardigliano ident->drv.kernel_ver = 0; 2785ef51809SAlfredo Cardigliano snprintf(ident->drv.kernel_ver_str, 2795ef51809SAlfredo Cardigliano sizeof(ident->drv.kernel_ver_str), "DPDK"); 2805ef51809SAlfredo Cardigliano strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION, 2815ef51809SAlfredo Cardigliano sizeof(ident->drv.driver_ver_str) - 1); 2825ef51809SAlfredo Cardigliano 2835ef51809SAlfredo Cardigliano nwords = RTE_MIN(drv_size, cmd_size); 2845ef51809SAlfredo Cardigliano for (i = 0; i < nwords; i++) 2855ef51809SAlfredo Cardigliano iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]); 2865ef51809SAlfredo Cardigliano 2875ef51809SAlfredo Cardigliano ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1); 2885ef51809SAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 2895ef51809SAlfredo Cardigliano if (!err) { 2905ef51809SAlfredo Cardigliano nwords = RTE_MIN(dev_size, cmd_size); 2915ef51809SAlfredo Cardigliano for (i = 0; i < nwords; i++) 2925ef51809SAlfredo Cardigliano ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]); 2935ef51809SAlfredo Cardigliano } 2945ef51809SAlfredo Cardigliano 2955ef51809SAlfredo Cardigliano return err; 2965ef51809SAlfredo Cardigliano } 2975ef51809SAlfredo Cardigliano 2985ef51809SAlfredo Cardigliano int 2995ef51809SAlfredo Cardigliano ionic_init(struct ionic_adapter *adapter) 3005ef51809SAlfredo Cardigliano { 3015ef51809SAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 3025ef51809SAlfredo Cardigliano 3035ef51809SAlfredo Cardigliano ionic_dev_cmd_init(idev); 304*75f96902SAndrew Boyer return ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 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 3125ef51809SAlfredo Cardigliano ionic_dev_cmd_reset(idev); 313*75f96902SAndrew Boyer return ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 3145ef51809SAlfredo Cardigliano } 31523bf4ddbSAlfredo Cardigliano 31623bf4ddbSAlfredo Cardigliano int 31723bf4ddbSAlfredo Cardigliano ionic_port_identify(struct ionic_adapter *adapter) 31823bf4ddbSAlfredo Cardigliano { 31923bf4ddbSAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 32023bf4ddbSAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 32123bf4ddbSAlfredo Cardigliano unsigned int port_words = sizeof(ident->port.words) / 32223bf4ddbSAlfredo Cardigliano sizeof(ident->port.words[0]); 32323bf4ddbSAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 32423bf4ddbSAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 32523bf4ddbSAlfredo Cardigliano unsigned int i; 32623bf4ddbSAlfredo Cardigliano unsigned int nwords; 32723bf4ddbSAlfredo Cardigliano int err; 32823bf4ddbSAlfredo Cardigliano 32923bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_identify(idev); 33023bf4ddbSAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 33123bf4ddbSAlfredo Cardigliano if (!err) { 33223bf4ddbSAlfredo Cardigliano nwords = RTE_MIN(port_words, cmd_words); 33323bf4ddbSAlfredo Cardigliano for (i = 0; i < nwords; i++) 33423bf4ddbSAlfredo Cardigliano ident->port.words[i] = 33523bf4ddbSAlfredo Cardigliano ioread32(&idev->dev_cmd->data[i]); 33623bf4ddbSAlfredo Cardigliano } 33723bf4ddbSAlfredo Cardigliano 33823bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "speed %d ", ident->port.config.speed); 33923bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "mtu %d ", ident->port.config.mtu); 34023bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "state %d ", ident->port.config.state); 34123bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "an_enable %d ", ident->port.config.an_enable); 34223bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "fec_type %d ", ident->port.config.fec_type); 34323bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "pause_type %d ", ident->port.config.pause_type); 34423bf4ddbSAlfredo Cardigliano IONIC_PRINT(INFO, "loopback_mode %d", 34523bf4ddbSAlfredo Cardigliano ident->port.config.loopback_mode); 34623bf4ddbSAlfredo Cardigliano 34723bf4ddbSAlfredo Cardigliano return err; 34823bf4ddbSAlfredo Cardigliano } 34923bf4ddbSAlfredo Cardigliano 35023bf4ddbSAlfredo Cardigliano static const struct rte_memzone * 35123bf4ddbSAlfredo Cardigliano ionic_memzone_reserve(const char *name, uint32_t len, int socket_id) 35223bf4ddbSAlfredo Cardigliano { 35323bf4ddbSAlfredo Cardigliano const struct rte_memzone *mz; 35423bf4ddbSAlfredo Cardigliano 35523bf4ddbSAlfredo Cardigliano mz = rte_memzone_lookup(name); 35623bf4ddbSAlfredo Cardigliano if (mz) 35723bf4ddbSAlfredo Cardigliano return mz; 35823bf4ddbSAlfredo Cardigliano 35923bf4ddbSAlfredo Cardigliano mz = rte_memzone_reserve_aligned(name, len, socket_id, 36023bf4ddbSAlfredo Cardigliano RTE_MEMZONE_IOVA_CONTIG, IONIC_ALIGN); 36123bf4ddbSAlfredo Cardigliano return mz; 36223bf4ddbSAlfredo Cardigliano } 36323bf4ddbSAlfredo Cardigliano 36423bf4ddbSAlfredo Cardigliano int 36523bf4ddbSAlfredo Cardigliano ionic_port_init(struct ionic_adapter *adapter) 36623bf4ddbSAlfredo Cardigliano { 36723bf4ddbSAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 36823bf4ddbSAlfredo Cardigliano struct ionic_identity *ident = &adapter->ident; 36923bf4ddbSAlfredo Cardigliano char z_name[RTE_MEMZONE_NAMESIZE]; 37023bf4ddbSAlfredo Cardigliano unsigned int config_words = sizeof(ident->port.config.words) / 37123bf4ddbSAlfredo Cardigliano sizeof(ident->port.config.words[0]); 37223bf4ddbSAlfredo Cardigliano unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 37323bf4ddbSAlfredo Cardigliano sizeof(idev->dev_cmd->data[0]); 37423bf4ddbSAlfredo Cardigliano unsigned int nwords; 37523bf4ddbSAlfredo Cardigliano unsigned int i; 37623bf4ddbSAlfredo Cardigliano int err; 37723bf4ddbSAlfredo Cardigliano 37823bf4ddbSAlfredo Cardigliano if (idev->port_info) 37923bf4ddbSAlfredo Cardigliano return 0; 38023bf4ddbSAlfredo Cardigliano 38123bf4ddbSAlfredo Cardigliano idev->port_info_sz = RTE_ALIGN(sizeof(*idev->port_info), PAGE_SIZE); 38223bf4ddbSAlfredo Cardigliano 38323bf4ddbSAlfredo Cardigliano snprintf(z_name, sizeof(z_name), "%s_port_%s_info", 38423bf4ddbSAlfredo Cardigliano IONIC_DRV_NAME, 38523bf4ddbSAlfredo Cardigliano adapter->pci_dev->device.name); 38623bf4ddbSAlfredo Cardigliano 38723bf4ddbSAlfredo Cardigliano idev->port_info_z = ionic_memzone_reserve(z_name, idev->port_info_sz, 38823bf4ddbSAlfredo Cardigliano SOCKET_ID_ANY); 38923bf4ddbSAlfredo Cardigliano if (!idev->port_info_z) { 39023bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Cannot reserve port info DMA memory"); 39123bf4ddbSAlfredo Cardigliano return -ENOMEM; 39223bf4ddbSAlfredo Cardigliano } 39323bf4ddbSAlfredo Cardigliano 39423bf4ddbSAlfredo Cardigliano idev->port_info = idev->port_info_z->addr; 39523bf4ddbSAlfredo Cardigliano idev->port_info_pa = idev->port_info_z->iova; 39623bf4ddbSAlfredo Cardigliano 39723bf4ddbSAlfredo Cardigliano nwords = RTE_MIN(config_words, cmd_words); 39823bf4ddbSAlfredo Cardigliano 39923bf4ddbSAlfredo Cardigliano for (i = 0; i < nwords; i++) 40023bf4ddbSAlfredo Cardigliano iowrite32(ident->port.config.words[i], &idev->dev_cmd->data[i]); 40123bf4ddbSAlfredo Cardigliano 40223bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_init(idev); 40323bf4ddbSAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 40423bf4ddbSAlfredo Cardigliano if (err) { 40523bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Failed to init port"); 40623bf4ddbSAlfredo Cardigliano return err; 40723bf4ddbSAlfredo Cardigliano } 40823bf4ddbSAlfredo Cardigliano 40923bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP); 41023bf4ddbSAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 41123bf4ddbSAlfredo Cardigliano if (err) { 41223bf4ddbSAlfredo Cardigliano IONIC_PRINT(WARNING, "Failed to bring port UP"); 41323bf4ddbSAlfredo Cardigliano return err; 41423bf4ddbSAlfredo Cardigliano } 41523bf4ddbSAlfredo Cardigliano 41623bf4ddbSAlfredo Cardigliano return 0; 41723bf4ddbSAlfredo Cardigliano } 41823bf4ddbSAlfredo Cardigliano 41923bf4ddbSAlfredo Cardigliano int 42023bf4ddbSAlfredo Cardigliano ionic_port_reset(struct ionic_adapter *adapter) 42123bf4ddbSAlfredo Cardigliano { 42223bf4ddbSAlfredo Cardigliano struct ionic_dev *idev = &adapter->idev; 42323bf4ddbSAlfredo Cardigliano int err; 42423bf4ddbSAlfredo Cardigliano 42523bf4ddbSAlfredo Cardigliano if (!idev->port_info) 42623bf4ddbSAlfredo Cardigliano return 0; 42723bf4ddbSAlfredo Cardigliano 42823bf4ddbSAlfredo Cardigliano ionic_dev_cmd_port_reset(idev); 42923bf4ddbSAlfredo Cardigliano err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 43023bf4ddbSAlfredo Cardigliano if (err) { 43123bf4ddbSAlfredo Cardigliano IONIC_PRINT(ERR, "Failed to reset port"); 43223bf4ddbSAlfredo Cardigliano return err; 43323bf4ddbSAlfredo Cardigliano } 43423bf4ddbSAlfredo Cardigliano 43523bf4ddbSAlfredo Cardigliano idev->port_info = NULL; 43623bf4ddbSAlfredo Cardigliano idev->port_info_pa = 0; 43723bf4ddbSAlfredo Cardigliano 43823bf4ddbSAlfredo Cardigliano return 0; 43923bf4ddbSAlfredo Cardigliano } 440