1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <sys/ioctl.h> 6 #include <rte_vfio.h> 7 8 #include "ifpga_feature_dev.h" 9 10 /* 11 * Enable Port by clear the port soft reset bit, which is set by default. 12 * The AFU is unable to respond to any MMIO access while in reset. 13 * __fpga_port_enable function should only be used after __fpga_port_disable 14 * function. 15 */ 16 void __fpga_port_enable(struct ifpga_port_hw *port) 17 { 18 struct feature_port_header *port_hdr; 19 struct feature_port_control control; 20 21 WARN_ON(!port->disable_count); 22 23 if (--port->disable_count != 0) 24 return; 25 26 port_hdr = get_port_feature_ioaddr_by_index(port, 27 PORT_FEATURE_ID_HEADER); 28 WARN_ON(!port_hdr); 29 30 control.csr = readq(&port_hdr->control); 31 control.port_sftrst = 0x0; 32 writeq(control.csr, &port_hdr->control); 33 } 34 35 int __fpga_port_disable(struct ifpga_port_hw *port) 36 { 37 struct feature_port_header *port_hdr; 38 struct feature_port_control control; 39 40 if (port->disable_count++ != 0) 41 return 0; 42 43 port_hdr = get_port_feature_ioaddr_by_index(port, 44 PORT_FEATURE_ID_HEADER); 45 WARN_ON(!port_hdr); 46 47 /* Set port soft reset */ 48 control.csr = readq(&port_hdr->control); 49 control.port_sftrst = 0x1; 50 writeq(control.csr, &port_hdr->control); 51 52 /* 53 * HW sets ack bit to 1 when all outstanding requests have been drained 54 * on this port and minimum soft reset pulse width has elapsed. 55 * Driver polls port_soft_reset_ack to determine if reset done by HW. 56 */ 57 control.port_sftrst_ack = 1; 58 59 if (fpga_wait_register_field(port_sftrst_ack, control, 60 &port_hdr->control, RST_POLL_TIMEOUT, 61 RST_POLL_INVL)) { 62 dev_err(port, "timeout, fail to reset device\n"); 63 return -ETIMEDOUT; 64 } 65 66 return 0; 67 } 68 69 int fpga_get_afu_uuid(struct ifpga_port_hw *port, struct uuid *uuid) 70 { 71 struct feature_port_header *port_hdr; 72 u64 guidl, guidh; 73 74 if (!uuid) 75 return -EINVAL; 76 77 port_hdr = get_port_feature_ioaddr_by_index(port, PORT_FEATURE_ID_UAFU); 78 79 spinlock_lock(&port->lock); 80 guidl = readq(&port_hdr->afu_header.guid.b[0]); 81 guidh = readq(&port_hdr->afu_header.guid.b[8]); 82 spinlock_unlock(&port->lock); 83 84 opae_memcpy(uuid->b, &guidl, sizeof(u64)); 85 opae_memcpy(uuid->b + 8, &guidh, sizeof(u64)); 86 87 return 0; 88 } 89 90 /* Mask / Unmask Port Errors by the Error Mask register. */ 91 void port_err_mask(struct ifpga_port_hw *port, bool mask) 92 { 93 struct feature_port_error *port_err; 94 struct feature_port_err_key err_mask; 95 96 port_err = get_port_feature_ioaddr_by_index(port, 97 PORT_FEATURE_ID_ERROR); 98 99 if (mask) 100 err_mask.csr = PORT_ERR_MASK; 101 else 102 err_mask.csr = 0; 103 104 writeq(err_mask.csr, &port_err->error_mask); 105 } 106 107 /* Clear All Port Errors. */ 108 int port_err_clear(struct ifpga_port_hw *port, u64 err) 109 { 110 struct feature_port_header *port_hdr; 111 struct feature_port_error *port_err; 112 struct feature_port_err_key mask; 113 struct feature_port_first_err_key first; 114 struct feature_port_status status; 115 int ret = 0; 116 117 port_err = get_port_feature_ioaddr_by_index(port, 118 PORT_FEATURE_ID_ERROR); 119 port_hdr = get_port_feature_ioaddr_by_index(port, 120 PORT_FEATURE_ID_HEADER); 121 122 /* 123 * Clear All Port Errors 124 * 125 * - Check for AP6 State 126 * - Halt Port by keeping Port in reset 127 * - Set PORT Error mask to all 1 to mask errors 128 * - Clear all errors 129 * - Set Port mask to all 0 to enable errors 130 * - All errors start capturing new errors 131 * - Enable Port by pulling the port out of reset 132 */ 133 134 /* If device is still in AP6 state, can not clear any error.*/ 135 status.csr = readq(&port_hdr->status); 136 if (status.power_state == PORT_POWER_STATE_AP6) { 137 dev_err(dev, "Could not clear errors, device in AP6 state.\n"); 138 return -EBUSY; 139 } 140 141 /* Halt Port by keeping Port in reset */ 142 ret = __fpga_port_disable(port); 143 if (ret) 144 return ret; 145 146 /* Mask all errors */ 147 port_err_mask(port, true); 148 149 /* Clear errors if err input matches with current port errors.*/ 150 mask.csr = readq(&port_err->port_error); 151 152 if (mask.csr == err) { 153 writeq(mask.csr, &port_err->port_error); 154 155 first.csr = readq(&port_err->port_first_error); 156 writeq(first.csr, &port_err->port_first_error); 157 } else { 158 ret = -EBUSY; 159 } 160 161 /* Clear mask */ 162 port_err_mask(port, false); 163 164 /* Enable the Port by clear the reset */ 165 __fpga_port_enable(port); 166 167 return ret; 168 } 169 170 int port_clear_error(struct ifpga_port_hw *port) 171 { 172 struct feature_port_error *port_err; 173 struct feature_port_err_key error; 174 175 port_err = get_port_feature_ioaddr_by_index(port, 176 PORT_FEATURE_ID_ERROR); 177 error.csr = readq(&port_err->port_error); 178 179 dev_info(port, "read port error: 0x%lx\n", (unsigned long)error.csr); 180 181 return port_err_clear(port, error.csr); 182 } 183 184 static struct feature_driver fme_feature_drvs[] = { 185 {FEATURE_DRV(FME_FEATURE_ID_HEADER, FME_FEATURE_HEADER, 186 &fme_hdr_ops),}, 187 {FEATURE_DRV(FME_FEATURE_ID_THERMAL_MGMT, FME_FEATURE_THERMAL_MGMT, 188 &fme_thermal_mgmt_ops),}, 189 {FEATURE_DRV(FME_FEATURE_ID_POWER_MGMT, FME_FEATURE_POWER_MGMT, 190 &fme_power_mgmt_ops),}, 191 {FEATURE_DRV(FME_FEATURE_ID_GLOBAL_ERR, FME_FEATURE_GLOBAL_ERR, 192 &fme_global_err_ops),}, 193 {FEATURE_DRV(FME_FEATURE_ID_PR_MGMT, FME_FEATURE_PR_MGMT, 194 &fme_pr_mgmt_ops),}, 195 {FEATURE_DRV(FME_FEATURE_ID_GLOBAL_DPERF, FME_FEATURE_GLOBAL_DPERF, 196 &fme_global_dperf_ops),}, 197 {FEATURE_DRV(FME_FEATURE_ID_HSSI_ETH, FME_FEATURE_HSSI_ETH, 198 &fme_hssi_eth_ops),}, 199 {FEATURE_DRV(FME_FEATURE_ID_EMIF_MGMT, FME_FEATURE_EMIF_MGMT, 200 &fme_emif_ops),}, 201 {FEATURE_DRV(FME_FEATURE_ID_MAX10_SPI, FME_FEATURE_MAX10_SPI, 202 &fme_spi_master_ops),}, 203 {FEATURE_DRV(FME_FEATURE_ID_NIOS_SPI, FME_FEATURE_NIOS_SPI, 204 &fme_nios_spi_master_ops),}, 205 {FEATURE_DRV(FME_FEATURE_ID_I2C_MASTER, FME_FEATURE_I2C_MASTER, 206 &fme_i2c_master_ops),}, 207 {FEATURE_DRV(FME_FEATURE_ID_ETH_GROUP, FME_FEATURE_ETH_GROUP, 208 &fme_eth_group_ops),}, 209 {0, NULL, NULL}, /* end of arrary */ 210 }; 211 212 static struct feature_driver port_feature_drvs[] = { 213 {FEATURE_DRV(PORT_FEATURE_ID_HEADER, PORT_FEATURE_HEADER, 214 &ifpga_rawdev_port_hdr_ops)}, 215 {FEATURE_DRV(PORT_FEATURE_ID_ERROR, PORT_FEATURE_ERR, 216 &ifpga_rawdev_port_error_ops)}, 217 {FEATURE_DRV(PORT_FEATURE_ID_UINT, PORT_FEATURE_UINT, 218 &ifpga_rawdev_port_uint_ops)}, 219 {FEATURE_DRV(PORT_FEATURE_ID_STP, PORT_FEATURE_STP, 220 &ifpga_rawdev_port_stp_ops)}, 221 {FEATURE_DRV(PORT_FEATURE_ID_UAFU, PORT_FEATURE_UAFU, 222 &ifpga_rawdev_port_afu_ops)}, 223 {0, NULL, NULL}, /* end of array */ 224 }; 225 226 const char *get_fme_feature_name(unsigned int id) 227 { 228 struct feature_driver *drv = fme_feature_drvs; 229 230 while (drv->name) { 231 if (drv->id == id) 232 return drv->name; 233 234 drv++; 235 } 236 237 return NULL; 238 } 239 240 const char *get_port_feature_name(unsigned int id) 241 { 242 struct feature_driver *drv = port_feature_drvs; 243 244 while (drv->name) { 245 if (drv->id == id) 246 return drv->name; 247 248 drv++; 249 } 250 251 return NULL; 252 } 253 254 static void feature_uinit(struct ifpga_feature_list *list) 255 { 256 struct ifpga_feature *feature; 257 258 TAILQ_FOREACH(feature, list, next) { 259 if (feature->state != IFPGA_FEATURE_ATTACHED) 260 continue; 261 if (feature->ops && feature->ops->uinit) 262 feature->ops->uinit(feature); 263 } 264 } 265 266 static int feature_init(struct feature_driver *drv, 267 struct ifpga_feature_list *list) 268 { 269 struct ifpga_feature *feature; 270 int ret; 271 272 while (drv->ops) { 273 TAILQ_FOREACH(feature, list, next) { 274 if (feature->state != IFPGA_FEATURE_ATTACHED) 275 continue; 276 if (feature->id == drv->id) { 277 feature->ops = drv->ops; 278 feature->name = drv->name; 279 if (feature->ops->init) { 280 ret = feature->ops->init(feature); 281 if (ret) 282 goto error; 283 } 284 } 285 } 286 drv++; 287 } 288 289 return 0; 290 error: 291 feature_uinit(list); 292 return ret; 293 } 294 295 int fme_hw_init(struct ifpga_fme_hw *fme) 296 { 297 int ret; 298 299 if (fme->state != IFPGA_FME_IMPLEMENTED) 300 return -ENODEV; 301 302 ret = feature_init(fme_feature_drvs, &fme->feature_list); 303 if (ret) 304 return ret; 305 306 return 0; 307 } 308 309 void fme_hw_uinit(struct ifpga_fme_hw *fme) 310 { 311 feature_uinit(&fme->feature_list); 312 } 313 314 void port_hw_uinit(struct ifpga_port_hw *port) 315 { 316 feature_uinit(&port->feature_list); 317 } 318 319 int port_hw_init(struct ifpga_port_hw *port) 320 { 321 int ret; 322 323 if (port->state == IFPGA_PORT_UNUSED) 324 return 0; 325 326 ret = feature_init(port_feature_drvs, &port->feature_list); 327 if (ret) 328 goto error; 329 330 return 0; 331 error: 332 port_hw_uinit(port); 333 return ret; 334 } 335 336 #define FPGA_MAX_MSIX_VEC_COUNT 128 337 /* irq set buffer length for interrupt */ 338 #define MSIX_IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + \ 339 sizeof(int) * FPGA_MAX_MSIX_VEC_COUNT) 340 341 /* only support msix for now*/ 342 static int vfio_msix_enable_block(s32 vfio_dev_fd, unsigned int vec_start, 343 unsigned int count, s32 *fds) 344 { 345 char irq_set_buf[MSIX_IRQ_SET_BUF_LEN]; 346 struct vfio_irq_set *irq_set; 347 int len, ret; 348 int *fd_ptr; 349 350 len = sizeof(irq_set_buf); 351 352 irq_set = (struct vfio_irq_set *)irq_set_buf; 353 irq_set->argsz = len; 354 /* 0 < irq_set->count < FPGA_MAX_MSIX_VEC_COUNT */ 355 irq_set->count = count ? 356 (count > FPGA_MAX_MSIX_VEC_COUNT ? 357 FPGA_MAX_MSIX_VEC_COUNT : count) : 1; 358 irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | 359 VFIO_IRQ_SET_ACTION_TRIGGER; 360 irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; 361 irq_set->start = vec_start; 362 363 fd_ptr = (int *)&irq_set->data; 364 opae_memcpy(fd_ptr, fds, sizeof(int) * count); 365 366 ret = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); 367 if (ret) 368 printf("Error enabling MSI-X interrupts\n"); 369 370 return ret; 371 } 372 373 int fpga_msix_set_block(struct ifpga_feature *feature, unsigned int start, 374 unsigned int count, s32 *fds) 375 { 376 struct feature_irq_ctx *ctx = feature->ctx; 377 unsigned int i; 378 int ret; 379 380 if (start >= feature->ctx_num || start + count > feature->ctx_num) 381 return -EINVAL; 382 383 /* assume that each feature has continuous vector space in msix*/ 384 ret = vfio_msix_enable_block(feature->vfio_dev_fd, 385 ctx[start].idx, count, fds); 386 if (!ret) { 387 for (i = 0; i < count; i++) 388 ctx[i].eventfd = fds[i]; 389 } 390 391 return ret; 392 } 393