1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2018-2022 Advanced Micro Devices, Inc. 3 */ 4 5 #include <stdbool.h> 6 7 #include <rte_malloc.h> 8 9 #include "ionic_dev.h" 10 #include "ionic_lif.h" 11 #include "ionic.h" 12 13 /* Devcmd Interface */ 14 15 uint8_t 16 ionic_dev_cmd_status(struct ionic_dev *idev) 17 { 18 return ioread8(&idev->dev_cmd->comp.comp.status); 19 } 20 21 bool 22 ionic_dev_cmd_done(struct ionic_dev *idev) 23 { 24 return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE; 25 } 26 27 void 28 ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem) 29 { 30 union ionic_dev_cmd_comp *comp = mem; 31 uint32_t comp_size = RTE_DIM(comp->words); 32 uint32_t i; 33 34 for (i = 0; i < comp_size; i++) 35 comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]); 36 } 37 38 void 39 ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd) 40 { 41 uint32_t cmd_size = RTE_DIM(cmd->words); 42 uint32_t i; 43 44 IONIC_PRINT(DEBUG, "Sending %s (%d) via dev_cmd", 45 ionic_opcode_to_str(cmd->cmd.opcode), cmd->cmd.opcode); 46 47 for (i = 0; i < cmd_size; i++) 48 iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]); 49 50 iowrite32(0, &idev->dev_cmd->done); 51 iowrite32(1, &idev->dev_cmd->doorbell); 52 } 53 54 /* Device commands */ 55 56 void 57 ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver) 58 { 59 union ionic_dev_cmd cmd = { 60 .identify.opcode = IONIC_CMD_IDENTIFY, 61 .identify.ver = ver, 62 }; 63 64 ionic_dev_cmd_go(idev, &cmd); 65 } 66 67 void 68 ionic_dev_cmd_init(struct ionic_dev *idev) 69 { 70 union ionic_dev_cmd cmd = { 71 .init.opcode = IONIC_CMD_INIT, 72 .init.type = 0, 73 }; 74 75 ionic_dev_cmd_go(idev, &cmd); 76 } 77 78 void 79 ionic_dev_cmd_reset(struct ionic_dev *idev) 80 { 81 union ionic_dev_cmd cmd = { 82 .reset.opcode = IONIC_CMD_RESET, 83 }; 84 85 ionic_dev_cmd_go(idev, &cmd); 86 } 87 88 /* Port commands */ 89 90 void 91 ionic_dev_cmd_port_identify(struct ionic_dev *idev) 92 { 93 union ionic_dev_cmd cmd = { 94 .port_init.opcode = IONIC_CMD_PORT_IDENTIFY, 95 .port_init.index = 0, 96 }; 97 98 ionic_dev_cmd_go(idev, &cmd); 99 } 100 101 void 102 ionic_dev_cmd_port_init(struct ionic_dev *idev) 103 { 104 union ionic_dev_cmd cmd = { 105 .port_init.opcode = IONIC_CMD_PORT_INIT, 106 .port_init.index = 0, 107 .port_init.info_pa = rte_cpu_to_le_64(idev->port_info_pa), 108 }; 109 110 ionic_dev_cmd_go(idev, &cmd); 111 } 112 113 void 114 ionic_dev_cmd_port_reset(struct ionic_dev *idev) 115 { 116 union ionic_dev_cmd cmd = { 117 .port_reset.opcode = IONIC_CMD_PORT_RESET, 118 .port_reset.index = 0, 119 }; 120 121 ionic_dev_cmd_go(idev, &cmd); 122 } 123 124 void 125 ionic_dev_cmd_port_state(struct ionic_dev *idev, uint8_t state) 126 { 127 union ionic_dev_cmd cmd = { 128 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 129 .port_setattr.index = 0, 130 .port_setattr.attr = IONIC_PORT_ATTR_STATE, 131 .port_setattr.state = state, 132 }; 133 134 ionic_dev_cmd_go(idev, &cmd); 135 } 136 137 void 138 ionic_dev_cmd_port_speed(struct ionic_dev *idev, uint32_t speed) 139 { 140 union ionic_dev_cmd cmd = { 141 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 142 .port_setattr.index = 0, 143 .port_setattr.attr = IONIC_PORT_ATTR_SPEED, 144 .port_setattr.speed = rte_cpu_to_le_32(speed), 145 }; 146 147 ionic_dev_cmd_go(idev, &cmd); 148 } 149 150 void 151 ionic_dev_cmd_port_mtu(struct ionic_dev *idev, uint32_t mtu) 152 { 153 union ionic_dev_cmd cmd = { 154 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 155 .port_setattr.index = 0, 156 .port_setattr.attr = IONIC_PORT_ATTR_MTU, 157 .port_setattr.mtu = rte_cpu_to_le_32(mtu), 158 }; 159 160 ionic_dev_cmd_go(idev, &cmd); 161 } 162 163 void 164 ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, uint8_t an_enable) 165 { 166 union ionic_dev_cmd cmd = { 167 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 168 .port_setattr.index = 0, 169 .port_setattr.attr = IONIC_PORT_ATTR_AUTONEG, 170 .port_setattr.an_enable = an_enable, 171 }; 172 173 ionic_dev_cmd_go(idev, &cmd); 174 } 175 176 void 177 ionic_dev_cmd_port_fec(struct ionic_dev *idev, uint8_t fec_type) 178 { 179 union ionic_dev_cmd cmd = { 180 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 181 .port_setattr.index = 0, 182 .port_setattr.attr = IONIC_PORT_ATTR_FEC, 183 .port_setattr.fec_type = fec_type, 184 }; 185 186 ionic_dev_cmd_go(idev, &cmd); 187 } 188 189 void 190 ionic_dev_cmd_port_pause(struct ionic_dev *idev, uint8_t pause_type) 191 { 192 union ionic_dev_cmd cmd = { 193 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 194 .port_setattr.index = 0, 195 .port_setattr.attr = IONIC_PORT_ATTR_PAUSE, 196 .port_setattr.pause_type = pause_type, 197 }; 198 199 ionic_dev_cmd_go(idev, &cmd); 200 } 201 202 void 203 ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode) 204 { 205 union ionic_dev_cmd cmd = { 206 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 207 .port_setattr.index = 0, 208 .port_setattr.attr = IONIC_PORT_ATTR_LOOPBACK, 209 .port_setattr.loopback_mode = loopback_mode, 210 }; 211 212 ionic_dev_cmd_go(idev, &cmd); 213 } 214 215 /* LIF commands */ 216 217 void 218 ionic_dev_cmd_queue_identify(struct ionic_dev *idev, 219 uint16_t lif_type, uint8_t qtype, uint8_t qver) 220 { 221 union ionic_dev_cmd cmd = { 222 .q_identify.opcode = IONIC_CMD_Q_IDENTIFY, 223 .q_identify.lif_type = rte_cpu_to_le_16(lif_type), 224 .q_identify.type = qtype, 225 .q_identify.ver = qver, 226 }; 227 228 ionic_dev_cmd_go(idev, &cmd); 229 } 230 231 void 232 ionic_dev_cmd_lif_identify(struct ionic_dev *idev, uint8_t type, uint8_t ver) 233 { 234 union ionic_dev_cmd cmd = { 235 .lif_identify.opcode = IONIC_CMD_LIF_IDENTIFY, 236 .lif_identify.type = type, 237 .lif_identify.ver = ver, 238 }; 239 240 ionic_dev_cmd_go(idev, &cmd); 241 } 242 243 void 244 ionic_dev_cmd_lif_init(struct ionic_dev *idev, rte_iova_t info_pa) 245 { 246 union ionic_dev_cmd cmd = { 247 .lif_init.opcode = IONIC_CMD_LIF_INIT, 248 .lif_init.info_pa = rte_cpu_to_le_64(info_pa), 249 }; 250 251 ionic_dev_cmd_go(idev, &cmd); 252 } 253 254 void 255 ionic_dev_cmd_lif_reset(struct ionic_dev *idev) 256 { 257 union ionic_dev_cmd cmd = { 258 .lif_init.opcode = IONIC_CMD_LIF_RESET, 259 }; 260 261 ionic_dev_cmd_go(idev, &cmd); 262 } 263 264 struct ionic_doorbell * 265 ionic_db_map(struct ionic_lif *lif, struct ionic_queue *q) 266 { 267 return lif->kern_dbpage + q->hw_type; 268 } 269 270 void 271 ionic_intr_init(struct ionic_dev *idev, struct ionic_intr_info *intr, 272 unsigned long index) 273 { 274 ionic_intr_clean(idev->intr_ctrl, index); 275 intr->index = index; 276 } 277 278 void 279 ionic_dev_cmd_adminq_init(struct ionic_dev *idev, struct ionic_qcq *qcq) 280 { 281 struct ionic_queue *q = &qcq->q; 282 struct ionic_cq *cq = &qcq->cq; 283 284 union ionic_dev_cmd cmd = { 285 .q_init.opcode = IONIC_CMD_Q_INIT, 286 .q_init.type = q->type, 287 .q_init.ver = qcq->lif->qtype_info[q->type].version, 288 .q_init.index = rte_cpu_to_le_32(q->index), 289 .q_init.flags = rte_cpu_to_le_16(IONIC_QINIT_F_ENA), 290 .q_init.intr_index = rte_cpu_to_le_16(IONIC_INTR_NONE), 291 .q_init.ring_size = rte_log2_u32(q->num_descs), 292 .q_init.ring_base = rte_cpu_to_le_64(q->base_pa), 293 .q_init.cq_ring_base = rte_cpu_to_le_64(cq->base_pa), 294 }; 295 296 IONIC_PRINT(DEBUG, "adminq.q_init.ver %u", cmd.q_init.ver); 297 298 ionic_dev_cmd_go(idev, &cmd); 299 } 300 301 int 302 ionic_cq_init(struct ionic_cq *cq, uint16_t num_descs) 303 { 304 if (!rte_is_power_of_2(num_descs) || 305 num_descs < IONIC_MIN_RING_DESC || 306 num_descs > IONIC_MAX_RING_DESC) { 307 IONIC_PRINT(ERR, "%u descriptors (min: %u max: %u)", 308 num_descs, IONIC_MIN_RING_DESC, IONIC_MAX_RING_DESC); 309 return -EINVAL; 310 } 311 312 cq->num_descs = num_descs; 313 cq->size_mask = num_descs - 1; 314 cq->tail_idx = 0; 315 cq->done_color = 1; 316 317 return 0; 318 } 319 320 void 321 ionic_cq_reset(struct ionic_cq *cq) 322 { 323 cq->tail_idx = 0; 324 cq->done_color = 1; 325 326 memset(cq->base, 0, sizeof(struct ionic_nop_comp) * cq->num_descs); 327 } 328 329 void 330 ionic_cq_map(struct ionic_cq *cq, void *base, rte_iova_t base_pa) 331 { 332 cq->base = base; 333 cq->base_pa = base_pa; 334 } 335 336 uint32_t 337 ionic_cq_service(struct ionic_cq *cq, uint32_t work_to_do, 338 ionic_cq_cb cb, void *cb_arg) 339 { 340 uint32_t work_done = 0; 341 342 if (work_to_do == 0) 343 return 0; 344 345 while (cb(cq, cq->tail_idx, cb_arg)) { 346 cq->tail_idx = Q_NEXT_TO_SRVC(cq, 1); 347 if (cq->tail_idx == 0) 348 cq->done_color = !cq->done_color; 349 350 if (++work_done == work_to_do) 351 break; 352 } 353 354 return work_done; 355 } 356 357 int 358 ionic_q_init(struct ionic_queue *q, uint32_t index, uint16_t num_descs) 359 { 360 uint32_t ring_size; 361 362 if (!rte_is_power_of_2(num_descs)) 363 return -EINVAL; 364 365 ring_size = rte_log2_u32(num_descs); 366 if (ring_size < 2 || ring_size > 16) 367 return -EINVAL; 368 369 q->index = index; 370 q->num_descs = num_descs; 371 q->size_mask = num_descs - 1; 372 ionic_q_reset(q); 373 374 return 0; 375 } 376 377 void 378 ionic_q_map(struct ionic_queue *q, void *base, rte_iova_t base_pa, 379 void *cmb_base, rte_iova_t cmb_base_pa) 380 { 381 q->base = base; 382 q->base_pa = base_pa; 383 q->cmb_base = cmb_base; 384 q->cmb_base_pa = cmb_base_pa; 385 } 386 387 void 388 ionic_q_sg_map(struct ionic_queue *q, void *base, rte_iova_t base_pa) 389 { 390 q->sg_base = base; 391 q->sg_base_pa = base_pa; 392 } 393 394 void 395 ionic_q_reset(struct ionic_queue *q) 396 { 397 q->head_idx = 0; 398 q->cmb_head_idx = 0; 399 q->tail_idx = 0; 400 } 401