1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2 * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved. 3 */ 4 5 #include <rte_memzone.h> 6 7 #include "ionic.h" 8 9 static int 10 ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait) 11 { 12 unsigned long step_msec = 100; 13 unsigned int max_wait_msec = max_wait * 1000; 14 unsigned long elapsed_msec = 0; 15 int done; 16 17 /* Wait for dev cmd to complete.. but no more than max_wait sec */ 18 19 do { 20 done = ionic_dev_cmd_done(idev); 21 if (done) { 22 IONIC_PRINT(DEBUG, "DEVCMD %d done took %ld msecs", 23 idev->dev_cmd->cmd.cmd.opcode, 24 elapsed_msec); 25 return 0; 26 } 27 28 msec_delay(step_msec); 29 30 elapsed_msec += step_msec; 31 } while (elapsed_msec < max_wait_msec); 32 33 IONIC_PRINT(DEBUG, "DEVCMD %d timeout after %ld msecs", 34 idev->dev_cmd->cmd.cmd.opcode, 35 elapsed_msec); 36 37 return -ETIMEDOUT; 38 } 39 40 static int 41 ionic_dev_cmd_check_error(struct ionic_dev *idev) 42 { 43 uint8_t status; 44 45 status = ionic_dev_cmd_status(idev); 46 if (status == 0) 47 return 0; 48 49 return -EIO; 50 } 51 52 int 53 ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait) 54 { 55 int err; 56 57 err = ionic_dev_cmd_wait(idev, max_wait); 58 if (err) 59 return err; 60 61 return ionic_dev_cmd_check_error(idev); 62 } 63 64 int 65 ionic_setup(struct ionic_adapter *adapter) 66 { 67 return ionic_dev_setup(adapter); 68 } 69 70 int 71 ionic_identify(struct ionic_adapter *adapter) 72 { 73 struct ionic_dev *idev = &adapter->idev; 74 struct ionic_identity *ident = &adapter->ident; 75 int err = 0; 76 uint32_t i; 77 unsigned int nwords; 78 uint32_t drv_size = sizeof(ident->drv.words) / 79 sizeof(ident->drv.words[0]); 80 uint32_t cmd_size = sizeof(idev->dev_cmd->data) / 81 sizeof(idev->dev_cmd->data[0]); 82 uint32_t dev_size = sizeof(ident->dev.words) / 83 sizeof(ident->dev.words[0]); 84 85 memset(ident, 0, sizeof(*ident)); 86 87 ident->drv.os_type = IONIC_OS_TYPE_LINUX; 88 ident->drv.os_dist = 0; 89 snprintf(ident->drv.os_dist_str, 90 sizeof(ident->drv.os_dist_str), "Unknown"); 91 ident->drv.kernel_ver = 0; 92 snprintf(ident->drv.kernel_ver_str, 93 sizeof(ident->drv.kernel_ver_str), "DPDK"); 94 strncpy(ident->drv.driver_ver_str, IONIC_DRV_VERSION, 95 sizeof(ident->drv.driver_ver_str) - 1); 96 97 nwords = RTE_MIN(drv_size, cmd_size); 98 for (i = 0; i < nwords; i++) 99 iowrite32(ident->drv.words[i], &idev->dev_cmd->data[i]); 100 101 ionic_dev_cmd_identify(idev, IONIC_IDENTITY_VERSION_1); 102 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 103 if (!err) { 104 nwords = RTE_MIN(dev_size, cmd_size); 105 for (i = 0; i < nwords; i++) 106 ident->dev.words[i] = ioread32(&idev->dev_cmd->data[i]); 107 } 108 109 return err; 110 } 111 112 int 113 ionic_init(struct ionic_adapter *adapter) 114 { 115 struct ionic_dev *idev = &adapter->idev; 116 int err; 117 118 ionic_dev_cmd_init(idev); 119 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 120 return err; 121 } 122 123 int 124 ionic_reset(struct ionic_adapter *adapter) 125 { 126 struct ionic_dev *idev = &adapter->idev; 127 int err; 128 129 ionic_dev_cmd_reset(idev); 130 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 131 return err; 132 } 133 134 int 135 ionic_port_identify(struct ionic_adapter *adapter) 136 { 137 struct ionic_dev *idev = &adapter->idev; 138 struct ionic_identity *ident = &adapter->ident; 139 unsigned int port_words = sizeof(ident->port.words) / 140 sizeof(ident->port.words[0]); 141 unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 142 sizeof(idev->dev_cmd->data[0]); 143 unsigned int i; 144 unsigned int nwords; 145 int err; 146 147 ionic_dev_cmd_port_identify(idev); 148 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 149 if (!err) { 150 nwords = RTE_MIN(port_words, cmd_words); 151 for (i = 0; i < nwords; i++) 152 ident->port.words[i] = 153 ioread32(&idev->dev_cmd->data[i]); 154 } 155 156 IONIC_PRINT(INFO, "speed %d ", ident->port.config.speed); 157 IONIC_PRINT(INFO, "mtu %d ", ident->port.config.mtu); 158 IONIC_PRINT(INFO, "state %d ", ident->port.config.state); 159 IONIC_PRINT(INFO, "an_enable %d ", ident->port.config.an_enable); 160 IONIC_PRINT(INFO, "fec_type %d ", ident->port.config.fec_type); 161 IONIC_PRINT(INFO, "pause_type %d ", ident->port.config.pause_type); 162 IONIC_PRINT(INFO, "loopback_mode %d", 163 ident->port.config.loopback_mode); 164 165 return err; 166 } 167 168 static const struct rte_memzone * 169 ionic_memzone_reserve(const char *name, uint32_t len, int socket_id) 170 { 171 const struct rte_memzone *mz; 172 173 mz = rte_memzone_lookup(name); 174 if (mz) 175 return mz; 176 177 mz = rte_memzone_reserve_aligned(name, len, socket_id, 178 RTE_MEMZONE_IOVA_CONTIG, IONIC_ALIGN); 179 return mz; 180 } 181 182 int 183 ionic_port_init(struct ionic_adapter *adapter) 184 { 185 struct ionic_dev *idev = &adapter->idev; 186 struct ionic_identity *ident = &adapter->ident; 187 char z_name[RTE_MEMZONE_NAMESIZE]; 188 unsigned int config_words = sizeof(ident->port.config.words) / 189 sizeof(ident->port.config.words[0]); 190 unsigned int cmd_words = sizeof(idev->dev_cmd->data) / 191 sizeof(idev->dev_cmd->data[0]); 192 unsigned int nwords; 193 unsigned int i; 194 int err; 195 196 if (idev->port_info) 197 return 0; 198 199 idev->port_info_sz = RTE_ALIGN(sizeof(*idev->port_info), PAGE_SIZE); 200 201 snprintf(z_name, sizeof(z_name), "%s_port_%s_info", 202 IONIC_DRV_NAME, 203 adapter->pci_dev->device.name); 204 205 idev->port_info_z = ionic_memzone_reserve(z_name, idev->port_info_sz, 206 SOCKET_ID_ANY); 207 if (!idev->port_info_z) { 208 IONIC_PRINT(ERR, "Cannot reserve port info DMA memory"); 209 return -ENOMEM; 210 } 211 212 idev->port_info = idev->port_info_z->addr; 213 idev->port_info_pa = idev->port_info_z->iova; 214 215 nwords = RTE_MIN(config_words, cmd_words); 216 217 for (i = 0; i < nwords; i++) 218 iowrite32(ident->port.config.words[i], &idev->dev_cmd->data[i]); 219 220 ionic_dev_cmd_port_init(idev); 221 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 222 if (err) { 223 IONIC_PRINT(ERR, "Failed to init port"); 224 return err; 225 } 226 227 ionic_dev_cmd_port_state(idev, IONIC_PORT_ADMIN_STATE_UP); 228 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 229 if (err) { 230 IONIC_PRINT(WARNING, "Failed to bring port UP"); 231 return err; 232 } 233 234 return 0; 235 } 236 237 int 238 ionic_port_reset(struct ionic_adapter *adapter) 239 { 240 struct ionic_dev *idev = &adapter->idev; 241 int err; 242 243 if (!idev->port_info) 244 return 0; 245 246 ionic_dev_cmd_port_reset(idev); 247 err = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT); 248 if (err) { 249 IONIC_PRINT(ERR, "Failed to reset port"); 250 return err; 251 } 252 253 idev->port_info = NULL; 254 idev->port_info_pa = 0; 255 256 return 0; 257 } 258