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_malloc.h> 6 7 #include "ionic_dev.h" 8 #include "ionic_lif.h" 9 #include "ionic.h" 10 11 int 12 ionic_dev_setup(struct ionic_adapter *adapter) 13 { 14 struct ionic_dev_bar *bar = adapter->bars; 15 unsigned int num_bars = adapter->num_bars; 16 struct ionic_dev *idev = &adapter->idev; 17 uint32_t sig; 18 u_char *bar0_base; 19 20 /* BAR0: dev_cmd and interrupts */ 21 if (num_bars < 1) { 22 IONIC_PRINT(ERR, "No bars found, aborting"); 23 return -EFAULT; 24 } 25 26 if (bar->len < IONIC_BAR0_SIZE) { 27 IONIC_PRINT(ERR, 28 "Resource bar size %lu too small, aborting", 29 bar->len); 30 return -EFAULT; 31 } 32 33 bar0_base = bar->vaddr; 34 idev->dev_info = (union ionic_dev_info_regs *) 35 &bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET]; 36 idev->dev_cmd = (union ionic_dev_cmd_regs *) 37 &bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET]; 38 idev->intr_status = (struct ionic_intr_status *) 39 &bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET]; 40 idev->intr_ctrl = (struct ionic_intr *) 41 &bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET]; 42 43 sig = ioread32(&idev->dev_info->signature); 44 if (sig != IONIC_DEV_INFO_SIGNATURE) { 45 IONIC_PRINT(ERR, "Incompatible firmware signature %" PRIx32 "", 46 sig); 47 return -EFAULT; 48 } 49 50 /* BAR1: doorbells */ 51 bar++; 52 if (num_bars < 2) { 53 IONIC_PRINT(ERR, "Doorbell bar missing, aborting"); 54 return -EFAULT; 55 } 56 57 idev->db_pages = bar->vaddr; 58 idev->phy_db_pages = bar->bus_addr; 59 60 return 0; 61 } 62 63 /* Devcmd Interface */ 64 65 uint8_t 66 ionic_dev_cmd_status(struct ionic_dev *idev) 67 { 68 return ioread8(&idev->dev_cmd->comp.comp.status); 69 } 70 71 bool 72 ionic_dev_cmd_done(struct ionic_dev *idev) 73 { 74 return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE; 75 } 76 77 void 78 ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem) 79 { 80 union ionic_dev_cmd_comp *comp = mem; 81 unsigned int i; 82 uint32_t comp_size = sizeof(comp->words) / 83 sizeof(comp->words[0]); 84 85 for (i = 0; i < comp_size; i++) 86 comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]); 87 } 88 89 void 90 ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd) 91 { 92 unsigned int i; 93 uint32_t cmd_size = sizeof(cmd->words) / 94 sizeof(cmd->words[0]); 95 96 for (i = 0; i < cmd_size; i++) 97 iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]); 98 99 iowrite32(0, &idev->dev_cmd->done); 100 iowrite32(1, &idev->dev_cmd->doorbell); 101 } 102 103 /* Device commands */ 104 105 void 106 ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver) 107 { 108 union ionic_dev_cmd cmd = { 109 .identify.opcode = IONIC_CMD_IDENTIFY, 110 .identify.ver = ver, 111 }; 112 113 ionic_dev_cmd_go(idev, &cmd); 114 } 115 116 void 117 ionic_dev_cmd_init(struct ionic_dev *idev) 118 { 119 union ionic_dev_cmd cmd = { 120 .init.opcode = IONIC_CMD_INIT, 121 .init.type = 0, 122 }; 123 124 ionic_dev_cmd_go(idev, &cmd); 125 } 126 127 void 128 ionic_dev_cmd_reset(struct ionic_dev *idev) 129 { 130 union ionic_dev_cmd cmd = { 131 .reset.opcode = IONIC_CMD_RESET, 132 }; 133 134 ionic_dev_cmd_go(idev, &cmd); 135 } 136 137 /* Port commands */ 138 139 void 140 ionic_dev_cmd_port_identify(struct ionic_dev *idev) 141 { 142 union ionic_dev_cmd cmd = { 143 .port_init.opcode = IONIC_CMD_PORT_IDENTIFY, 144 .port_init.index = 0, 145 }; 146 147 ionic_dev_cmd_go(idev, &cmd); 148 } 149 150 void 151 ionic_dev_cmd_port_init(struct ionic_dev *idev) 152 { 153 union ionic_dev_cmd cmd = { 154 .port_init.opcode = IONIC_CMD_PORT_INIT, 155 .port_init.index = 0, 156 .port_init.info_pa = idev->port_info_pa, 157 }; 158 159 ionic_dev_cmd_go(idev, &cmd); 160 } 161 162 void 163 ionic_dev_cmd_port_reset(struct ionic_dev *idev) 164 { 165 union ionic_dev_cmd cmd = { 166 .port_reset.opcode = IONIC_CMD_PORT_RESET, 167 .port_reset.index = 0, 168 }; 169 170 ionic_dev_cmd_go(idev, &cmd); 171 } 172 173 void 174 ionic_dev_cmd_port_state(struct ionic_dev *idev, uint8_t state) 175 { 176 union ionic_dev_cmd cmd = { 177 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 178 .port_setattr.index = 0, 179 .port_setattr.attr = IONIC_PORT_ATTR_STATE, 180 .port_setattr.state = state, 181 }; 182 183 ionic_dev_cmd_go(idev, &cmd); 184 } 185 186 void 187 ionic_dev_cmd_port_speed(struct ionic_dev *idev, uint32_t speed) 188 { 189 union ionic_dev_cmd cmd = { 190 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 191 .port_setattr.index = 0, 192 .port_setattr.attr = IONIC_PORT_ATTR_SPEED, 193 .port_setattr.speed = speed, 194 }; 195 196 ionic_dev_cmd_go(idev, &cmd); 197 } 198 199 void 200 ionic_dev_cmd_port_mtu(struct ionic_dev *idev, uint32_t mtu) 201 { 202 union ionic_dev_cmd cmd = { 203 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 204 .port_setattr.index = 0, 205 .port_setattr.attr = IONIC_PORT_ATTR_MTU, 206 .port_setattr.mtu = mtu, 207 }; 208 209 ionic_dev_cmd_go(idev, &cmd); 210 } 211 212 void 213 ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, uint8_t an_enable) 214 { 215 union ionic_dev_cmd cmd = { 216 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 217 .port_setattr.index = 0, 218 .port_setattr.attr = IONIC_PORT_ATTR_AUTONEG, 219 .port_setattr.an_enable = an_enable, 220 }; 221 222 ionic_dev_cmd_go(idev, &cmd); 223 } 224 225 void 226 ionic_dev_cmd_port_fec(struct ionic_dev *idev, uint8_t fec_type) 227 { 228 union ionic_dev_cmd cmd = { 229 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 230 .port_setattr.index = 0, 231 .port_setattr.attr = IONIC_PORT_ATTR_FEC, 232 .port_setattr.fec_type = fec_type, 233 }; 234 235 ionic_dev_cmd_go(idev, &cmd); 236 } 237 238 void 239 ionic_dev_cmd_port_pause(struct ionic_dev *idev, uint8_t pause_type) 240 { 241 union ionic_dev_cmd cmd = { 242 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 243 .port_setattr.index = 0, 244 .port_setattr.attr = IONIC_PORT_ATTR_PAUSE, 245 .port_setattr.pause_type = pause_type, 246 }; 247 248 ionic_dev_cmd_go(idev, &cmd); 249 } 250 251 void 252 ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode) 253 { 254 union ionic_dev_cmd cmd = { 255 .port_setattr.opcode = IONIC_CMD_PORT_SETATTR, 256 .port_setattr.index = 0, 257 .port_setattr.attr = IONIC_PORT_ATTR_LOOPBACK, 258 .port_setattr.loopback_mode = loopback_mode, 259 }; 260 261 ionic_dev_cmd_go(idev, &cmd); 262 } 263 264 /* LIF commands */ 265 266 void 267 ionic_dev_cmd_lif_identify(struct ionic_dev *idev, uint8_t type, uint8_t ver) 268 { 269 union ionic_dev_cmd cmd = { 270 .lif_identify.opcode = IONIC_CMD_LIF_IDENTIFY, 271 .lif_identify.type = type, 272 .lif_identify.ver = ver, 273 }; 274 275 ionic_dev_cmd_go(idev, &cmd); 276 } 277 278 void 279 ionic_dev_cmd_lif_init(struct ionic_dev *idev, uint16_t lif_index, 280 rte_iova_t info_pa) 281 { 282 union ionic_dev_cmd cmd = { 283 .lif_init.opcode = IONIC_CMD_LIF_INIT, 284 .lif_init.index = lif_index, 285 .lif_init.info_pa = info_pa, 286 }; 287 288 ionic_dev_cmd_go(idev, &cmd); 289 } 290 291 void 292 ionic_dev_cmd_lif_reset(struct ionic_dev *idev, uint16_t lif_index) 293 { 294 union ionic_dev_cmd cmd = { 295 .lif_init.opcode = IONIC_CMD_LIF_RESET, 296 .lif_init.index = lif_index, 297 }; 298 299 ionic_dev_cmd_go(idev, &cmd); 300 } 301 302 int 303 ionic_db_page_num(struct ionic_lif *lif, int pid) 304 { 305 return (lif->index * 0) + pid; 306 } 307 308 void 309 ionic_intr_init(struct ionic_dev *idev, struct ionic_intr_info *intr, 310 unsigned long index) 311 { 312 ionic_intr_clean(idev->intr_ctrl, index); 313 intr->index = index; 314 } 315