| .. | .. |
|---|
| 25 | 25 | module_param(max_devices, int, 0644); |
|---|
| 26 | 26 | MODULE_PARM_DESC(max_devices, "max number of switchtec device instances"); |
|---|
| 27 | 27 | |
|---|
| 28 | +static bool use_dma_mrpc = true; |
|---|
| 29 | +module_param(use_dma_mrpc, bool, 0644); |
|---|
| 30 | +MODULE_PARM_DESC(use_dma_mrpc, |
|---|
| 31 | + "Enable the use of the DMA MRPC feature"); |
|---|
| 32 | + |
|---|
| 33 | +static int nirqs = 32; |
|---|
| 34 | +module_param(nirqs, int, 0644); |
|---|
| 35 | +MODULE_PARM_DESC(nirqs, "number of interrupts to allocate (more may be useful for NTB applications)"); |
|---|
| 36 | + |
|---|
| 28 | 37 | static dev_t switchtec_devt; |
|---|
| 29 | 38 | static DEFINE_IDA(switchtec_minor_ida); |
|---|
| 30 | 39 | |
|---|
| .. | .. |
|---|
| 114 | 123 | |
|---|
| 115 | 124 | static void mrpc_complete_cmd(struct switchtec_dev *stdev); |
|---|
| 116 | 125 | |
|---|
| 126 | +static void flush_wc_buf(struct switchtec_dev *stdev) |
|---|
| 127 | +{ |
|---|
| 128 | + struct ntb_dbmsg_regs __iomem *mmio_dbmsg; |
|---|
| 129 | + |
|---|
| 130 | + /* |
|---|
| 131 | + * odb (outbound doorbell) register is processed by low latency |
|---|
| 132 | + * hardware and w/o side effect |
|---|
| 133 | + */ |
|---|
| 134 | + mmio_dbmsg = (void __iomem *)stdev->mmio_ntb + |
|---|
| 135 | + SWITCHTEC_NTB_REG_DBMSG_OFFSET; |
|---|
| 136 | + ioread32(&mmio_dbmsg->odb); |
|---|
| 137 | +} |
|---|
| 138 | + |
|---|
| 117 | 139 | static void mrpc_cmd_submit(struct switchtec_dev *stdev) |
|---|
| 118 | 140 | { |
|---|
| 119 | 141 | /* requires the mrpc_mutex to already be held when called */ |
|---|
| .. | .. |
|---|
| 129 | 151 | stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user, |
|---|
| 130 | 152 | list); |
|---|
| 131 | 153 | |
|---|
| 154 | + if (stdev->dma_mrpc) { |
|---|
| 155 | + stdev->dma_mrpc->status = SWITCHTEC_MRPC_STATUS_INPROGRESS; |
|---|
| 156 | + memset(stdev->dma_mrpc->data, 0xFF, SWITCHTEC_MRPC_PAYLOAD_SIZE); |
|---|
| 157 | + } |
|---|
| 158 | + |
|---|
| 132 | 159 | stuser_set_state(stuser, MRPC_RUNNING); |
|---|
| 133 | 160 | stdev->mrpc_busy = 1; |
|---|
| 134 | 161 | memcpy_toio(&stdev->mmio_mrpc->input_data, |
|---|
| 135 | 162 | stuser->data, stuser->data_len); |
|---|
| 163 | + flush_wc_buf(stdev); |
|---|
| 136 | 164 | iowrite32(stuser->cmd, &stdev->mmio_mrpc->cmd); |
|---|
| 137 | 165 | |
|---|
| 138 | 166 | schedule_delayed_work(&stdev->mrpc_timeout, |
|---|
| .. | .. |
|---|
| 167 | 195 | stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user, |
|---|
| 168 | 196 | list); |
|---|
| 169 | 197 | |
|---|
| 170 | | - stuser->status = ioread32(&stdev->mmio_mrpc->status); |
|---|
| 198 | + if (stdev->dma_mrpc) |
|---|
| 199 | + stuser->status = stdev->dma_mrpc->status; |
|---|
| 200 | + else |
|---|
| 201 | + stuser->status = ioread32(&stdev->mmio_mrpc->status); |
|---|
| 202 | + |
|---|
| 171 | 203 | if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS) |
|---|
| 172 | 204 | return; |
|---|
| 173 | 205 | |
|---|
| .. | .. |
|---|
| 177 | 209 | if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE) |
|---|
| 178 | 210 | goto out; |
|---|
| 179 | 211 | |
|---|
| 180 | | - stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value); |
|---|
| 212 | + if (stdev->dma_mrpc) |
|---|
| 213 | + stuser->return_code = stdev->dma_mrpc->rtn_code; |
|---|
| 214 | + else |
|---|
| 215 | + stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value); |
|---|
| 181 | 216 | if (stuser->return_code != 0) |
|---|
| 182 | 217 | goto out; |
|---|
| 183 | 218 | |
|---|
| 184 | | - memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data, |
|---|
| 185 | | - stuser->read_len); |
|---|
| 186 | | - |
|---|
| 219 | + if (stdev->dma_mrpc) |
|---|
| 220 | + memcpy(stuser->data, &stdev->dma_mrpc->data, |
|---|
| 221 | + stuser->read_len); |
|---|
| 222 | + else |
|---|
| 223 | + memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data, |
|---|
| 224 | + stuser->read_len); |
|---|
| 187 | 225 | out: |
|---|
| 188 | 226 | stuser->cmd_done = true; |
|---|
| 189 | 227 | wake_up_interruptible(&stuser->cmd_comp); |
|---|
| .. | .. |
|---|
| 219 | 257 | |
|---|
| 220 | 258 | mutex_lock(&stdev->mrpc_mutex); |
|---|
| 221 | 259 | |
|---|
| 222 | | - status = ioread32(&stdev->mmio_mrpc->status); |
|---|
| 260 | + if (stdev->dma_mrpc) |
|---|
| 261 | + status = stdev->dma_mrpc->status; |
|---|
| 262 | + else |
|---|
| 263 | + status = ioread32(&stdev->mmio_mrpc->status); |
|---|
| 223 | 264 | if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) { |
|---|
| 224 | 265 | schedule_delayed_work(&stdev->mrpc_timeout, |
|---|
| 225 | 266 | msecs_to_jiffies(500)); |
|---|
| .. | .. |
|---|
| 227 | 268 | } |
|---|
| 228 | 269 | |
|---|
| 229 | 270 | mrpc_complete_cmd(stdev); |
|---|
| 230 | | - |
|---|
| 231 | 271 | out: |
|---|
| 232 | 272 | mutex_unlock(&stdev->mrpc_mutex); |
|---|
| 233 | 273 | } |
|---|
| .. | .. |
|---|
| 279 | 319 | struct device_attribute *attr, char *buf) \ |
|---|
| 280 | 320 | { \ |
|---|
| 281 | 321 | struct switchtec_dev *stdev = to_stdev(dev); \ |
|---|
| 282 | | - return io_string_show(buf, &stdev->mmio_sys_info->field, \ |
|---|
| 283 | | - sizeof(stdev->mmio_sys_info->field)); \ |
|---|
| 322 | + struct sys_info_regs __iomem *si = stdev->mmio_sys_info; \ |
|---|
| 323 | + if (stdev->gen == SWITCHTEC_GEN3) \ |
|---|
| 324 | + return io_string_show(buf, &si->gen3.field, \ |
|---|
| 325 | + sizeof(si->gen3.field)); \ |
|---|
| 326 | + else if (stdev->gen == SWITCHTEC_GEN4) \ |
|---|
| 327 | + return io_string_show(buf, &si->gen4.field, \ |
|---|
| 328 | + sizeof(si->gen4.field)); \ |
|---|
| 329 | + else \ |
|---|
| 330 | + return -ENOTSUPP; \ |
|---|
| 284 | 331 | } \ |
|---|
| 285 | 332 | \ |
|---|
| 286 | 333 | static DEVICE_ATTR_RO(field) |
|---|
| .. | .. |
|---|
| 288 | 335 | DEVICE_ATTR_SYS_INFO_STR(vendor_id); |
|---|
| 289 | 336 | DEVICE_ATTR_SYS_INFO_STR(product_id); |
|---|
| 290 | 337 | DEVICE_ATTR_SYS_INFO_STR(product_revision); |
|---|
| 291 | | -DEVICE_ATTR_SYS_INFO_STR(component_vendor); |
|---|
| 338 | + |
|---|
| 339 | +static ssize_t component_vendor_show(struct device *dev, |
|---|
| 340 | + struct device_attribute *attr, char *buf) |
|---|
| 341 | +{ |
|---|
| 342 | + struct switchtec_dev *stdev = to_stdev(dev); |
|---|
| 343 | + struct sys_info_regs __iomem *si = stdev->mmio_sys_info; |
|---|
| 344 | + |
|---|
| 345 | + /* component_vendor field not supported after gen3 */ |
|---|
| 346 | + if (stdev->gen != SWITCHTEC_GEN3) |
|---|
| 347 | + return sprintf(buf, "none\n"); |
|---|
| 348 | + |
|---|
| 349 | + return io_string_show(buf, &si->gen3.component_vendor, |
|---|
| 350 | + sizeof(si->gen3.component_vendor)); |
|---|
| 351 | +} |
|---|
| 352 | +static DEVICE_ATTR_RO(component_vendor); |
|---|
| 292 | 353 | |
|---|
| 293 | 354 | static ssize_t component_id_show(struct device *dev, |
|---|
| 294 | 355 | struct device_attribute *attr, char *buf) |
|---|
| 295 | 356 | { |
|---|
| 296 | 357 | struct switchtec_dev *stdev = to_stdev(dev); |
|---|
| 297 | | - int id = ioread16(&stdev->mmio_sys_info->component_id); |
|---|
| 358 | + int id = ioread16(&stdev->mmio_sys_info->gen3.component_id); |
|---|
| 359 | + |
|---|
| 360 | + /* component_id field not supported after gen3 */ |
|---|
| 361 | + if (stdev->gen != SWITCHTEC_GEN3) |
|---|
| 362 | + return sprintf(buf, "none\n"); |
|---|
| 298 | 363 | |
|---|
| 299 | 364 | return sprintf(buf, "PM%04X\n", id); |
|---|
| 300 | 365 | } |
|---|
| .. | .. |
|---|
| 304 | 369 | struct device_attribute *attr, char *buf) |
|---|
| 305 | 370 | { |
|---|
| 306 | 371 | struct switchtec_dev *stdev = to_stdev(dev); |
|---|
| 307 | | - int rev = ioread8(&stdev->mmio_sys_info->component_revision); |
|---|
| 372 | + int rev = ioread8(&stdev->mmio_sys_info->gen3.component_revision); |
|---|
| 373 | + |
|---|
| 374 | + /* component_revision field not supported after gen3 */ |
|---|
| 375 | + if (stdev->gen != SWITCHTEC_GEN3) |
|---|
| 376 | + return sprintf(buf, "255\n"); |
|---|
| 308 | 377 | |
|---|
| 309 | 378 | return sprintf(buf, "%d\n", rev); |
|---|
| 310 | 379 | } |
|---|
| .. | .. |
|---|
| 412 | 481 | rc = -EFAULT; |
|---|
| 413 | 482 | goto out; |
|---|
| 414 | 483 | } |
|---|
| 484 | + if (((MRPC_CMD_ID(stuser->cmd) == MRPC_GAS_WRITE) || |
|---|
| 485 | + (MRPC_CMD_ID(stuser->cmd) == MRPC_GAS_READ)) && |
|---|
| 486 | + !capable(CAP_SYS_ADMIN)) { |
|---|
| 487 | + rc = -EPERM; |
|---|
| 488 | + goto out; |
|---|
| 489 | + } |
|---|
| 415 | 490 | |
|---|
| 416 | 491 | data += sizeof(stuser->cmd); |
|---|
| 417 | 492 | rc = copy_from_user(&stuser->data, data, size - sizeof(stuser->cmd)); |
|---|
| .. | .. |
|---|
| 456 | 531 | mutex_unlock(&stdev->mrpc_mutex); |
|---|
| 457 | 532 | |
|---|
| 458 | 533 | if (filp->f_flags & O_NONBLOCK) { |
|---|
| 459 | | - if (!READ_ONCE(stuser->cmd_done)) |
|---|
| 534 | + if (!stuser->cmd_done) |
|---|
| 460 | 535 | return -EAGAIN; |
|---|
| 461 | 536 | } else { |
|---|
| 462 | 537 | rc = wait_event_interruptible(stuser->cmd_comp, |
|---|
| .. | .. |
|---|
| 516 | 591 | |
|---|
| 517 | 592 | mutex_unlock(&stdev->mrpc_mutex); |
|---|
| 518 | 593 | |
|---|
| 519 | | - if (READ_ONCE(stuser->cmd_done)) |
|---|
| 594 | + if (stuser->cmd_done) |
|---|
| 520 | 595 | ret |= EPOLLIN | EPOLLRDNORM; |
|---|
| 521 | 596 | |
|---|
| 522 | 597 | if (stuser->event_cnt != atomic_read(&stdev->event_cnt)) |
|---|
| .. | .. |
|---|
| 531 | 606 | struct switchtec_ioctl_flash_info info = {0}; |
|---|
| 532 | 607 | struct flash_info_regs __iomem *fi = stdev->mmio_flash_info; |
|---|
| 533 | 608 | |
|---|
| 534 | | - info.flash_length = ioread32(&fi->flash_length); |
|---|
| 535 | | - info.num_partitions = SWITCHTEC_IOCTL_NUM_PARTITIONS; |
|---|
| 609 | + if (stdev->gen == SWITCHTEC_GEN3) { |
|---|
| 610 | + info.flash_length = ioread32(&fi->gen3.flash_length); |
|---|
| 611 | + info.num_partitions = SWITCHTEC_NUM_PARTITIONS_GEN3; |
|---|
| 612 | + } else if (stdev->gen == SWITCHTEC_GEN4) { |
|---|
| 613 | + info.flash_length = ioread32(&fi->gen4.flash_length); |
|---|
| 614 | + info.num_partitions = SWITCHTEC_NUM_PARTITIONS_GEN4; |
|---|
| 615 | + } else { |
|---|
| 616 | + return -ENOTSUPP; |
|---|
| 617 | + } |
|---|
| 536 | 618 | |
|---|
| 537 | 619 | if (copy_to_user(uinfo, &info, sizeof(info))) |
|---|
| 538 | 620 | return -EFAULT; |
|---|
| .. | .. |
|---|
| 547 | 629 | info->length = ioread32(&pi->length); |
|---|
| 548 | 630 | } |
|---|
| 549 | 631 | |
|---|
| 550 | | -static int ioctl_flash_part_info(struct switchtec_dev *stdev, |
|---|
| 551 | | - struct switchtec_ioctl_flash_part_info __user *uinfo) |
|---|
| 632 | +static int flash_part_info_gen3(struct switchtec_dev *stdev, |
|---|
| 633 | + struct switchtec_ioctl_flash_part_info *info) |
|---|
| 552 | 634 | { |
|---|
| 553 | | - struct switchtec_ioctl_flash_part_info info = {0}; |
|---|
| 554 | | - struct flash_info_regs __iomem *fi = stdev->mmio_flash_info; |
|---|
| 555 | | - struct sys_info_regs __iomem *si = stdev->mmio_sys_info; |
|---|
| 635 | + struct flash_info_regs_gen3 __iomem *fi = |
|---|
| 636 | + &stdev->mmio_flash_info->gen3; |
|---|
| 637 | + struct sys_info_regs_gen3 __iomem *si = &stdev->mmio_sys_info->gen3; |
|---|
| 556 | 638 | u32 active_addr = -1; |
|---|
| 557 | 639 | |
|---|
| 558 | | - if (copy_from_user(&info, uinfo, sizeof(info))) |
|---|
| 559 | | - return -EFAULT; |
|---|
| 560 | | - |
|---|
| 561 | | - switch (info.flash_partition) { |
|---|
| 640 | + switch (info->flash_partition) { |
|---|
| 562 | 641 | case SWITCHTEC_IOCTL_PART_CFG0: |
|---|
| 563 | 642 | active_addr = ioread32(&fi->active_cfg); |
|---|
| 564 | | - set_fw_info_part(&info, &fi->cfg0); |
|---|
| 565 | | - if (ioread16(&si->cfg_running) == SWITCHTEC_CFG0_RUNNING) |
|---|
| 566 | | - info.active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 643 | + set_fw_info_part(info, &fi->cfg0); |
|---|
| 644 | + if (ioread16(&si->cfg_running) == SWITCHTEC_GEN3_CFG0_RUNNING) |
|---|
| 645 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 567 | 646 | break; |
|---|
| 568 | 647 | case SWITCHTEC_IOCTL_PART_CFG1: |
|---|
| 569 | 648 | active_addr = ioread32(&fi->active_cfg); |
|---|
| 570 | | - set_fw_info_part(&info, &fi->cfg1); |
|---|
| 571 | | - if (ioread16(&si->cfg_running) == SWITCHTEC_CFG1_RUNNING) |
|---|
| 572 | | - info.active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 649 | + set_fw_info_part(info, &fi->cfg1); |
|---|
| 650 | + if (ioread16(&si->cfg_running) == SWITCHTEC_GEN3_CFG1_RUNNING) |
|---|
| 651 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 573 | 652 | break; |
|---|
| 574 | 653 | case SWITCHTEC_IOCTL_PART_IMG0: |
|---|
| 575 | 654 | active_addr = ioread32(&fi->active_img); |
|---|
| 576 | | - set_fw_info_part(&info, &fi->img0); |
|---|
| 577 | | - if (ioread16(&si->img_running) == SWITCHTEC_IMG0_RUNNING) |
|---|
| 578 | | - info.active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 655 | + set_fw_info_part(info, &fi->img0); |
|---|
| 656 | + if (ioread16(&si->img_running) == SWITCHTEC_GEN3_IMG0_RUNNING) |
|---|
| 657 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 579 | 658 | break; |
|---|
| 580 | 659 | case SWITCHTEC_IOCTL_PART_IMG1: |
|---|
| 581 | 660 | active_addr = ioread32(&fi->active_img); |
|---|
| 582 | | - set_fw_info_part(&info, &fi->img1); |
|---|
| 583 | | - if (ioread16(&si->img_running) == SWITCHTEC_IMG1_RUNNING) |
|---|
| 584 | | - info.active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 661 | + set_fw_info_part(info, &fi->img1); |
|---|
| 662 | + if (ioread16(&si->img_running) == SWITCHTEC_GEN3_IMG1_RUNNING) |
|---|
| 663 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 585 | 664 | break; |
|---|
| 586 | 665 | case SWITCHTEC_IOCTL_PART_NVLOG: |
|---|
| 587 | | - set_fw_info_part(&info, &fi->nvlog); |
|---|
| 666 | + set_fw_info_part(info, &fi->nvlog); |
|---|
| 588 | 667 | break; |
|---|
| 589 | 668 | case SWITCHTEC_IOCTL_PART_VENDOR0: |
|---|
| 590 | | - set_fw_info_part(&info, &fi->vendor[0]); |
|---|
| 669 | + set_fw_info_part(info, &fi->vendor[0]); |
|---|
| 591 | 670 | break; |
|---|
| 592 | 671 | case SWITCHTEC_IOCTL_PART_VENDOR1: |
|---|
| 593 | | - set_fw_info_part(&info, &fi->vendor[1]); |
|---|
| 672 | + set_fw_info_part(info, &fi->vendor[1]); |
|---|
| 594 | 673 | break; |
|---|
| 595 | 674 | case SWITCHTEC_IOCTL_PART_VENDOR2: |
|---|
| 596 | | - set_fw_info_part(&info, &fi->vendor[2]); |
|---|
| 675 | + set_fw_info_part(info, &fi->vendor[2]); |
|---|
| 597 | 676 | break; |
|---|
| 598 | 677 | case SWITCHTEC_IOCTL_PART_VENDOR3: |
|---|
| 599 | | - set_fw_info_part(&info, &fi->vendor[3]); |
|---|
| 678 | + set_fw_info_part(info, &fi->vendor[3]); |
|---|
| 600 | 679 | break; |
|---|
| 601 | 680 | case SWITCHTEC_IOCTL_PART_VENDOR4: |
|---|
| 602 | | - set_fw_info_part(&info, &fi->vendor[4]); |
|---|
| 681 | + set_fw_info_part(info, &fi->vendor[4]); |
|---|
| 603 | 682 | break; |
|---|
| 604 | 683 | case SWITCHTEC_IOCTL_PART_VENDOR5: |
|---|
| 605 | | - set_fw_info_part(&info, &fi->vendor[5]); |
|---|
| 684 | + set_fw_info_part(info, &fi->vendor[5]); |
|---|
| 606 | 685 | break; |
|---|
| 607 | 686 | case SWITCHTEC_IOCTL_PART_VENDOR6: |
|---|
| 608 | | - set_fw_info_part(&info, &fi->vendor[6]); |
|---|
| 687 | + set_fw_info_part(info, &fi->vendor[6]); |
|---|
| 609 | 688 | break; |
|---|
| 610 | 689 | case SWITCHTEC_IOCTL_PART_VENDOR7: |
|---|
| 611 | | - set_fw_info_part(&info, &fi->vendor[7]); |
|---|
| 690 | + set_fw_info_part(info, &fi->vendor[7]); |
|---|
| 612 | 691 | break; |
|---|
| 613 | 692 | default: |
|---|
| 614 | 693 | return -EINVAL; |
|---|
| 615 | 694 | } |
|---|
| 616 | 695 | |
|---|
| 617 | | - if (info.address == active_addr) |
|---|
| 618 | | - info.active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 696 | + if (info->address == active_addr) |
|---|
| 697 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 698 | + |
|---|
| 699 | + return 0; |
|---|
| 700 | +} |
|---|
| 701 | + |
|---|
| 702 | +static int flash_part_info_gen4(struct switchtec_dev *stdev, |
|---|
| 703 | + struct switchtec_ioctl_flash_part_info *info) |
|---|
| 704 | +{ |
|---|
| 705 | + struct flash_info_regs_gen4 __iomem *fi = &stdev->mmio_flash_info->gen4; |
|---|
| 706 | + struct sys_info_regs_gen4 __iomem *si = &stdev->mmio_sys_info->gen4; |
|---|
| 707 | + struct active_partition_info_gen4 __iomem *af = &fi->active_flag; |
|---|
| 708 | + |
|---|
| 709 | + switch (info->flash_partition) { |
|---|
| 710 | + case SWITCHTEC_IOCTL_PART_MAP_0: |
|---|
| 711 | + set_fw_info_part(info, &fi->map0); |
|---|
| 712 | + break; |
|---|
| 713 | + case SWITCHTEC_IOCTL_PART_MAP_1: |
|---|
| 714 | + set_fw_info_part(info, &fi->map1); |
|---|
| 715 | + break; |
|---|
| 716 | + case SWITCHTEC_IOCTL_PART_KEY_0: |
|---|
| 717 | + set_fw_info_part(info, &fi->key0); |
|---|
| 718 | + if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY0_ACTIVE) |
|---|
| 719 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 720 | + if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY0_RUNNING) |
|---|
| 721 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 722 | + break; |
|---|
| 723 | + case SWITCHTEC_IOCTL_PART_KEY_1: |
|---|
| 724 | + set_fw_info_part(info, &fi->key1); |
|---|
| 725 | + if (ioread8(&af->key) == SWITCHTEC_GEN4_KEY1_ACTIVE) |
|---|
| 726 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 727 | + if (ioread16(&si->key_running) == SWITCHTEC_GEN4_KEY1_RUNNING) |
|---|
| 728 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 729 | + break; |
|---|
| 730 | + case SWITCHTEC_IOCTL_PART_BL2_0: |
|---|
| 731 | + set_fw_info_part(info, &fi->bl2_0); |
|---|
| 732 | + if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_0_ACTIVE) |
|---|
| 733 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 734 | + if (ioread16(&si->bl2_running) == SWITCHTEC_GEN4_BL2_0_RUNNING) |
|---|
| 735 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 736 | + break; |
|---|
| 737 | + case SWITCHTEC_IOCTL_PART_BL2_1: |
|---|
| 738 | + set_fw_info_part(info, &fi->bl2_1); |
|---|
| 739 | + if (ioread8(&af->bl2) == SWITCHTEC_GEN4_BL2_1_ACTIVE) |
|---|
| 740 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 741 | + if (ioread16(&si->bl2_running) == SWITCHTEC_GEN4_BL2_1_RUNNING) |
|---|
| 742 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 743 | + break; |
|---|
| 744 | + case SWITCHTEC_IOCTL_PART_CFG0: |
|---|
| 745 | + set_fw_info_part(info, &fi->cfg0); |
|---|
| 746 | + if (ioread8(&af->cfg) == SWITCHTEC_GEN4_CFG0_ACTIVE) |
|---|
| 747 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 748 | + if (ioread16(&si->cfg_running) == SWITCHTEC_GEN4_CFG0_RUNNING) |
|---|
| 749 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 750 | + break; |
|---|
| 751 | + case SWITCHTEC_IOCTL_PART_CFG1: |
|---|
| 752 | + set_fw_info_part(info, &fi->cfg1); |
|---|
| 753 | + if (ioread8(&af->cfg) == SWITCHTEC_GEN4_CFG1_ACTIVE) |
|---|
| 754 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 755 | + if (ioread16(&si->cfg_running) == SWITCHTEC_GEN4_CFG1_RUNNING) |
|---|
| 756 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 757 | + break; |
|---|
| 758 | + case SWITCHTEC_IOCTL_PART_IMG0: |
|---|
| 759 | + set_fw_info_part(info, &fi->img0); |
|---|
| 760 | + if (ioread8(&af->img) == SWITCHTEC_GEN4_IMG0_ACTIVE) |
|---|
| 761 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 762 | + if (ioread16(&si->img_running) == SWITCHTEC_GEN4_IMG0_RUNNING) |
|---|
| 763 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 764 | + break; |
|---|
| 765 | + case SWITCHTEC_IOCTL_PART_IMG1: |
|---|
| 766 | + set_fw_info_part(info, &fi->img1); |
|---|
| 767 | + if (ioread8(&af->img) == SWITCHTEC_GEN4_IMG1_ACTIVE) |
|---|
| 768 | + info->active |= SWITCHTEC_IOCTL_PART_ACTIVE; |
|---|
| 769 | + if (ioread16(&si->img_running) == SWITCHTEC_GEN4_IMG1_RUNNING) |
|---|
| 770 | + info->active |= SWITCHTEC_IOCTL_PART_RUNNING; |
|---|
| 771 | + break; |
|---|
| 772 | + case SWITCHTEC_IOCTL_PART_NVLOG: |
|---|
| 773 | + set_fw_info_part(info, &fi->nvlog); |
|---|
| 774 | + break; |
|---|
| 775 | + case SWITCHTEC_IOCTL_PART_VENDOR0: |
|---|
| 776 | + set_fw_info_part(info, &fi->vendor[0]); |
|---|
| 777 | + break; |
|---|
| 778 | + case SWITCHTEC_IOCTL_PART_VENDOR1: |
|---|
| 779 | + set_fw_info_part(info, &fi->vendor[1]); |
|---|
| 780 | + break; |
|---|
| 781 | + case SWITCHTEC_IOCTL_PART_VENDOR2: |
|---|
| 782 | + set_fw_info_part(info, &fi->vendor[2]); |
|---|
| 783 | + break; |
|---|
| 784 | + case SWITCHTEC_IOCTL_PART_VENDOR3: |
|---|
| 785 | + set_fw_info_part(info, &fi->vendor[3]); |
|---|
| 786 | + break; |
|---|
| 787 | + case SWITCHTEC_IOCTL_PART_VENDOR4: |
|---|
| 788 | + set_fw_info_part(info, &fi->vendor[4]); |
|---|
| 789 | + break; |
|---|
| 790 | + case SWITCHTEC_IOCTL_PART_VENDOR5: |
|---|
| 791 | + set_fw_info_part(info, &fi->vendor[5]); |
|---|
| 792 | + break; |
|---|
| 793 | + case SWITCHTEC_IOCTL_PART_VENDOR6: |
|---|
| 794 | + set_fw_info_part(info, &fi->vendor[6]); |
|---|
| 795 | + break; |
|---|
| 796 | + case SWITCHTEC_IOCTL_PART_VENDOR7: |
|---|
| 797 | + set_fw_info_part(info, &fi->vendor[7]); |
|---|
| 798 | + break; |
|---|
| 799 | + default: |
|---|
| 800 | + return -EINVAL; |
|---|
| 801 | + } |
|---|
| 802 | + |
|---|
| 803 | + return 0; |
|---|
| 804 | +} |
|---|
| 805 | + |
|---|
| 806 | +static int ioctl_flash_part_info(struct switchtec_dev *stdev, |
|---|
| 807 | + struct switchtec_ioctl_flash_part_info __user *uinfo) |
|---|
| 808 | +{ |
|---|
| 809 | + int ret; |
|---|
| 810 | + struct switchtec_ioctl_flash_part_info info = {0}; |
|---|
| 811 | + |
|---|
| 812 | + if (copy_from_user(&info, uinfo, sizeof(info))) |
|---|
| 813 | + return -EFAULT; |
|---|
| 814 | + |
|---|
| 815 | + if (stdev->gen == SWITCHTEC_GEN3) { |
|---|
| 816 | + ret = flash_part_info_gen3(stdev, &info); |
|---|
| 817 | + if (ret) |
|---|
| 818 | + return ret; |
|---|
| 819 | + } else if (stdev->gen == SWITCHTEC_GEN4) { |
|---|
| 820 | + ret = flash_part_info_gen4(stdev, &info); |
|---|
| 821 | + if (ret) |
|---|
| 822 | + return ret; |
|---|
| 823 | + } else { |
|---|
| 824 | + return -ENOTSUPP; |
|---|
| 825 | + } |
|---|
| 619 | 826 | |
|---|
| 620 | 827 | if (copy_to_user(uinfo, &info, sizeof(info))) |
|---|
| 621 | 828 | return -EFAULT; |
|---|
| .. | .. |
|---|
| 625 | 832 | |
|---|
| 626 | 833 | static int ioctl_event_summary(struct switchtec_dev *stdev, |
|---|
| 627 | 834 | struct switchtec_user *stuser, |
|---|
| 628 | | - struct switchtec_ioctl_event_summary __user *usum) |
|---|
| 835 | + struct switchtec_ioctl_event_summary __user *usum, |
|---|
| 836 | + size_t size) |
|---|
| 629 | 837 | { |
|---|
| 630 | | - struct switchtec_ioctl_event_summary s = {0}; |
|---|
| 838 | + struct switchtec_ioctl_event_summary *s; |
|---|
| 631 | 839 | int i; |
|---|
| 632 | 840 | u32 reg; |
|---|
| 841 | + int ret = 0; |
|---|
| 633 | 842 | |
|---|
| 634 | | - s.global = ioread32(&stdev->mmio_sw_event->global_summary); |
|---|
| 635 | | - s.part_bitmap = readq(&stdev->mmio_sw_event->part_event_bitmap); |
|---|
| 636 | | - s.local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary); |
|---|
| 843 | + s = kzalloc(sizeof(*s), GFP_KERNEL); |
|---|
| 844 | + if (!s) |
|---|
| 845 | + return -ENOMEM; |
|---|
| 846 | + |
|---|
| 847 | + s->global = ioread32(&stdev->mmio_sw_event->global_summary); |
|---|
| 848 | + s->part_bitmap = ioread64(&stdev->mmio_sw_event->part_event_bitmap); |
|---|
| 849 | + s->local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary); |
|---|
| 637 | 850 | |
|---|
| 638 | 851 | for (i = 0; i < stdev->partition_count; i++) { |
|---|
| 639 | 852 | reg = ioread32(&stdev->mmio_part_cfg_all[i].part_event_summary); |
|---|
| 640 | | - s.part[i] = reg; |
|---|
| 853 | + s->part[i] = reg; |
|---|
| 641 | 854 | } |
|---|
| 642 | 855 | |
|---|
| 643 | | - for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) { |
|---|
| 644 | | - reg = ioread16(&stdev->mmio_pff_csr[i].vendor_id); |
|---|
| 645 | | - if (reg != PCI_VENDOR_ID_MICROSEMI) |
|---|
| 646 | | - break; |
|---|
| 647 | | - |
|---|
| 856 | + for (i = 0; i < stdev->pff_csr_count; i++) { |
|---|
| 648 | 857 | reg = ioread32(&stdev->mmio_pff_csr[i].pff_event_summary); |
|---|
| 649 | | - s.pff[i] = reg; |
|---|
| 858 | + s->pff[i] = reg; |
|---|
| 650 | 859 | } |
|---|
| 651 | 860 | |
|---|
| 652 | | - if (copy_to_user(usum, &s, sizeof(s))) |
|---|
| 653 | | - return -EFAULT; |
|---|
| 861 | + if (copy_to_user(usum, s, size)) { |
|---|
| 862 | + ret = -EFAULT; |
|---|
| 863 | + goto error_case; |
|---|
| 864 | + } |
|---|
| 654 | 865 | |
|---|
| 655 | 866 | stuser->event_cnt = atomic_read(&stdev->event_cnt); |
|---|
| 656 | 867 | |
|---|
| 657 | | - return 0; |
|---|
| 868 | +error_case: |
|---|
| 869 | + kfree(s); |
|---|
| 870 | + return ret; |
|---|
| 658 | 871 | } |
|---|
| 659 | 872 | |
|---|
| 660 | 873 | static u32 __iomem *global_ev_reg(struct switchtec_dev *stdev, |
|---|
| .. | .. |
|---|
| 704 | 917 | EV_PAR(SWITCHTEC_IOCTL_EVENT_MRPC_COMP, mrpc_comp_hdr), |
|---|
| 705 | 918 | EV_PAR(SWITCHTEC_IOCTL_EVENT_MRPC_COMP_ASYNC, mrpc_comp_async_hdr), |
|---|
| 706 | 919 | EV_PAR(SWITCHTEC_IOCTL_EVENT_DYN_PART_BIND_COMP, dyn_binding_hdr), |
|---|
| 920 | + EV_PAR(SWITCHTEC_IOCTL_EVENT_INTERCOMM_REQ_NOTIFY, |
|---|
| 921 | + intercomm_notify_hdr), |
|---|
| 707 | 922 | EV_PFF(SWITCHTEC_IOCTL_EVENT_AER_IN_P2P, aer_in_p2p_hdr), |
|---|
| 708 | 923 | EV_PFF(SWITCHTEC_IOCTL_EVENT_AER_IN_VEP, aer_in_vep_hdr), |
|---|
| 709 | 924 | EV_PFF(SWITCHTEC_IOCTL_EVENT_DPC, dpc_hdr), |
|---|
| 710 | 925 | EV_PFF(SWITCHTEC_IOCTL_EVENT_CTS, cts_hdr), |
|---|
| 926 | + EV_PFF(SWITCHTEC_IOCTL_EVENT_UEC, uec_hdr), |
|---|
| 711 | 927 | EV_PFF(SWITCHTEC_IOCTL_EVENT_HOTPLUG, hotplug_hdr), |
|---|
| 712 | 928 | EV_PFF(SWITCHTEC_IOCTL_EVENT_IER, ier_hdr), |
|---|
| 713 | 929 | EV_PFF(SWITCHTEC_IOCTL_EVENT_THRESH, threshold_hdr), |
|---|
| .. | .. |
|---|
| 724 | 940 | size_t off; |
|---|
| 725 | 941 | |
|---|
| 726 | 942 | if (event_id < 0 || event_id >= SWITCHTEC_IOCTL_MAX_EVENTS) |
|---|
| 727 | | - return ERR_PTR(-EINVAL); |
|---|
| 943 | + return (u32 __iomem *)ERR_PTR(-EINVAL); |
|---|
| 728 | 944 | |
|---|
| 729 | 945 | off = event_regs[event_id].offset; |
|---|
| 730 | 946 | |
|---|
| .. | .. |
|---|
| 732 | 948 | if (index == SWITCHTEC_IOCTL_EVENT_LOCAL_PART_IDX) |
|---|
| 733 | 949 | index = stdev->partition; |
|---|
| 734 | 950 | else if (index < 0 || index >= stdev->partition_count) |
|---|
| 735 | | - return ERR_PTR(-EINVAL); |
|---|
| 951 | + return (u32 __iomem *)ERR_PTR(-EINVAL); |
|---|
| 736 | 952 | } else if (event_regs[event_id].map_reg == pff_ev_reg) { |
|---|
| 737 | 953 | if (index < 0 || index >= stdev->pff_csr_count) |
|---|
| 738 | | - return ERR_PTR(-EINVAL); |
|---|
| 954 | + return (u32 __iomem *)ERR_PTR(-EINVAL); |
|---|
| 739 | 955 | } |
|---|
| 740 | 956 | |
|---|
| 741 | 957 | return event_regs[event_id].map_reg(stdev, off, index); |
|---|
| .. | .. |
|---|
| 841 | 1057 | } |
|---|
| 842 | 1058 | |
|---|
| 843 | 1059 | static int ioctl_pff_to_port(struct switchtec_dev *stdev, |
|---|
| 844 | | - struct switchtec_ioctl_pff_port *up) |
|---|
| 1060 | + struct switchtec_ioctl_pff_port __user *up) |
|---|
| 845 | 1061 | { |
|---|
| 846 | 1062 | int i, part; |
|---|
| 847 | 1063 | u32 reg; |
|---|
| 848 | | - struct part_cfg_regs *pcfg; |
|---|
| 1064 | + struct part_cfg_regs __iomem *pcfg; |
|---|
| 849 | 1065 | struct switchtec_ioctl_pff_port p; |
|---|
| 850 | 1066 | |
|---|
| 851 | 1067 | if (copy_from_user(&p, up, sizeof(p))) |
|---|
| .. | .. |
|---|
| 888 | 1104 | } |
|---|
| 889 | 1105 | |
|---|
| 890 | 1106 | static int ioctl_port_to_pff(struct switchtec_dev *stdev, |
|---|
| 891 | | - struct switchtec_ioctl_pff_port *up) |
|---|
| 1107 | + struct switchtec_ioctl_pff_port __user *up) |
|---|
| 892 | 1108 | { |
|---|
| 893 | 1109 | struct switchtec_ioctl_pff_port p; |
|---|
| 894 | | - struct part_cfg_regs *pcfg; |
|---|
| 1110 | + struct part_cfg_regs __iomem *pcfg; |
|---|
| 895 | 1111 | |
|---|
| 896 | 1112 | if (copy_from_user(&p, up, sizeof(p))) |
|---|
| 897 | 1113 | return -EFAULT; |
|---|
| .. | .. |
|---|
| 944 | 1160 | case SWITCHTEC_IOCTL_FLASH_PART_INFO: |
|---|
| 945 | 1161 | rc = ioctl_flash_part_info(stdev, argp); |
|---|
| 946 | 1162 | break; |
|---|
| 947 | | - case SWITCHTEC_IOCTL_EVENT_SUMMARY: |
|---|
| 948 | | - rc = ioctl_event_summary(stdev, stuser, argp); |
|---|
| 1163 | + case SWITCHTEC_IOCTL_EVENT_SUMMARY_LEGACY: |
|---|
| 1164 | + rc = ioctl_event_summary(stdev, stuser, argp, |
|---|
| 1165 | + sizeof(struct switchtec_ioctl_event_summary_legacy)); |
|---|
| 949 | 1166 | break; |
|---|
| 950 | 1167 | case SWITCHTEC_IOCTL_EVENT_CTL: |
|---|
| 951 | 1168 | rc = ioctl_event_ctl(stdev, argp); |
|---|
| .. | .. |
|---|
| 955 | 1172 | break; |
|---|
| 956 | 1173 | case SWITCHTEC_IOCTL_PORT_TO_PFF: |
|---|
| 957 | 1174 | rc = ioctl_port_to_pff(stdev, argp); |
|---|
| 1175 | + break; |
|---|
| 1176 | + case SWITCHTEC_IOCTL_EVENT_SUMMARY: |
|---|
| 1177 | + rc = ioctl_event_summary(stdev, stuser, argp, |
|---|
| 1178 | + sizeof(struct switchtec_ioctl_event_summary)); |
|---|
| 958 | 1179 | break; |
|---|
| 959 | 1180 | default: |
|---|
| 960 | 1181 | rc = -ENOTTY; |
|---|
| .. | .. |
|---|
| 973 | 1194 | .read = switchtec_dev_read, |
|---|
| 974 | 1195 | .poll = switchtec_dev_poll, |
|---|
| 975 | 1196 | .unlocked_ioctl = switchtec_dev_ioctl, |
|---|
| 976 | | - .compat_ioctl = switchtec_dev_ioctl, |
|---|
| 1197 | + .compat_ioctl = compat_ptr_ioctl, |
|---|
| 977 | 1198 | }; |
|---|
| 978 | 1199 | |
|---|
| 979 | 1200 | static void link_event_work(struct work_struct *work) |
|---|
| .. | .. |
|---|
| 1019 | 1240 | } |
|---|
| 1020 | 1241 | } |
|---|
| 1021 | 1242 | |
|---|
| 1243 | +static void enable_dma_mrpc(struct switchtec_dev *stdev) |
|---|
| 1244 | +{ |
|---|
| 1245 | + writeq(stdev->dma_mrpc_dma_addr, &stdev->mmio_mrpc->dma_addr); |
|---|
| 1246 | + flush_wc_buf(stdev); |
|---|
| 1247 | + iowrite32(SWITCHTEC_DMA_MRPC_EN, &stdev->mmio_mrpc->dma_en); |
|---|
| 1248 | +} |
|---|
| 1249 | + |
|---|
| 1022 | 1250 | static void stdev_release(struct device *dev) |
|---|
| 1023 | 1251 | { |
|---|
| 1024 | 1252 | struct switchtec_dev *stdev = to_stdev(dev); |
|---|
| 1025 | 1253 | |
|---|
| 1254 | + if (stdev->dma_mrpc) { |
|---|
| 1255 | + iowrite32(0, &stdev->mmio_mrpc->dma_en); |
|---|
| 1256 | + flush_wc_buf(stdev); |
|---|
| 1257 | + writeq(0, &stdev->mmio_mrpc->dma_addr); |
|---|
| 1258 | + dma_free_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc), |
|---|
| 1259 | + stdev->dma_mrpc, stdev->dma_mrpc_dma_addr); |
|---|
| 1260 | + } |
|---|
| 1026 | 1261 | kfree(stdev); |
|---|
| 1027 | 1262 | } |
|---|
| 1028 | 1263 | |
|---|
| .. | .. |
|---|
| 1116 | 1351 | if (!(hdr & SWITCHTEC_EVENT_OCCURRED && hdr & SWITCHTEC_EVENT_EN_IRQ)) |
|---|
| 1117 | 1352 | return 0; |
|---|
| 1118 | 1353 | |
|---|
| 1119 | | - if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE || |
|---|
| 1120 | | - eid == SWITCHTEC_IOCTL_EVENT_MRPC_COMP) |
|---|
| 1121 | | - return 0; |
|---|
| 1122 | | - |
|---|
| 1123 | 1354 | dev_dbg(&stdev->dev, "%s: %d %d %x\n", __func__, eid, idx, hdr); |
|---|
| 1124 | 1355 | hdr &= ~(SWITCHTEC_EVENT_EN_IRQ | SWITCHTEC_EVENT_OCCURRED); |
|---|
| 1125 | 1356 | iowrite32(hdr, hdr_reg); |
|---|
| .. | .. |
|---|
| 1166 | 1397 | |
|---|
| 1167 | 1398 | check_link_state_events(stdev); |
|---|
| 1168 | 1399 | |
|---|
| 1169 | | - for (eid = 0; eid < SWITCHTEC_IOCTL_MAX_EVENTS; eid++) |
|---|
| 1400 | + for (eid = 0; eid < SWITCHTEC_IOCTL_MAX_EVENTS; eid++) { |
|---|
| 1401 | + if (eid == SWITCHTEC_IOCTL_EVENT_LINK_STATE || |
|---|
| 1402 | + eid == SWITCHTEC_IOCTL_EVENT_MRPC_COMP) |
|---|
| 1403 | + continue; |
|---|
| 1404 | + |
|---|
| 1170 | 1405 | event_count += mask_all_events(stdev, eid); |
|---|
| 1406 | + } |
|---|
| 1171 | 1407 | |
|---|
| 1172 | 1408 | if (event_count) { |
|---|
| 1173 | 1409 | atomic_inc(&stdev->event_cnt); |
|---|
| .. | .. |
|---|
| 1180 | 1416 | return ret; |
|---|
| 1181 | 1417 | } |
|---|
| 1182 | 1418 | |
|---|
| 1419 | + |
|---|
| 1420 | +static irqreturn_t switchtec_dma_mrpc_isr(int irq, void *dev) |
|---|
| 1421 | +{ |
|---|
| 1422 | + struct switchtec_dev *stdev = dev; |
|---|
| 1423 | + irqreturn_t ret = IRQ_NONE; |
|---|
| 1424 | + |
|---|
| 1425 | + iowrite32(SWITCHTEC_EVENT_CLEAR | |
|---|
| 1426 | + SWITCHTEC_EVENT_EN_IRQ, |
|---|
| 1427 | + &stdev->mmio_part_cfg->mrpc_comp_hdr); |
|---|
| 1428 | + schedule_work(&stdev->mrpc_work); |
|---|
| 1429 | + |
|---|
| 1430 | + ret = IRQ_HANDLED; |
|---|
| 1431 | + return ret; |
|---|
| 1432 | +} |
|---|
| 1433 | + |
|---|
| 1183 | 1434 | static int switchtec_init_isr(struct switchtec_dev *stdev) |
|---|
| 1184 | 1435 | { |
|---|
| 1185 | 1436 | int nvecs; |
|---|
| 1186 | 1437 | int event_irq; |
|---|
| 1438 | + int dma_mrpc_irq; |
|---|
| 1439 | + int rc; |
|---|
| 1187 | 1440 | |
|---|
| 1188 | | - nvecs = pci_alloc_irq_vectors(stdev->pdev, 1, 4, |
|---|
| 1189 | | - PCI_IRQ_MSIX | PCI_IRQ_MSI); |
|---|
| 1441 | + if (nirqs < 4) |
|---|
| 1442 | + nirqs = 4; |
|---|
| 1443 | + |
|---|
| 1444 | + nvecs = pci_alloc_irq_vectors(stdev->pdev, 1, nirqs, |
|---|
| 1445 | + PCI_IRQ_MSIX | PCI_IRQ_MSI | |
|---|
| 1446 | + PCI_IRQ_VIRTUAL); |
|---|
| 1190 | 1447 | if (nvecs < 0) |
|---|
| 1191 | 1448 | return nvecs; |
|---|
| 1192 | 1449 | |
|---|
| .. | .. |
|---|
| 1198 | 1455 | if (event_irq < 0) |
|---|
| 1199 | 1456 | return event_irq; |
|---|
| 1200 | 1457 | |
|---|
| 1201 | | - return devm_request_irq(&stdev->pdev->dev, event_irq, |
|---|
| 1458 | + rc = devm_request_irq(&stdev->pdev->dev, event_irq, |
|---|
| 1202 | 1459 | switchtec_event_isr, 0, |
|---|
| 1203 | 1460 | KBUILD_MODNAME, stdev); |
|---|
| 1461 | + |
|---|
| 1462 | + if (rc) |
|---|
| 1463 | + return rc; |
|---|
| 1464 | + |
|---|
| 1465 | + if (!stdev->dma_mrpc) |
|---|
| 1466 | + return rc; |
|---|
| 1467 | + |
|---|
| 1468 | + dma_mrpc_irq = ioread32(&stdev->mmio_mrpc->dma_vector); |
|---|
| 1469 | + if (dma_mrpc_irq < 0 || dma_mrpc_irq >= nvecs) |
|---|
| 1470 | + return -EFAULT; |
|---|
| 1471 | + |
|---|
| 1472 | + dma_mrpc_irq = pci_irq_vector(stdev->pdev, dma_mrpc_irq); |
|---|
| 1473 | + if (dma_mrpc_irq < 0) |
|---|
| 1474 | + return dma_mrpc_irq; |
|---|
| 1475 | + |
|---|
| 1476 | + rc = devm_request_irq(&stdev->pdev->dev, dma_mrpc_irq, |
|---|
| 1477 | + switchtec_dma_mrpc_isr, 0, |
|---|
| 1478 | + KBUILD_MODNAME, stdev); |
|---|
| 1479 | + |
|---|
| 1480 | + return rc; |
|---|
| 1204 | 1481 | } |
|---|
| 1205 | 1482 | |
|---|
| 1206 | 1483 | static void init_pff(struct switchtec_dev *stdev) |
|---|
| 1207 | 1484 | { |
|---|
| 1208 | 1485 | int i; |
|---|
| 1209 | 1486 | u32 reg; |
|---|
| 1210 | | - struct part_cfg_regs *pcfg = stdev->mmio_part_cfg; |
|---|
| 1487 | + struct part_cfg_regs __iomem *pcfg = stdev->mmio_part_cfg; |
|---|
| 1211 | 1488 | |
|---|
| 1212 | 1489 | for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) { |
|---|
| 1213 | 1490 | reg = ioread16(&stdev->mmio_pff_csr[i].vendor_id); |
|---|
| .. | .. |
|---|
| 1218 | 1495 | stdev->pff_csr_count = i; |
|---|
| 1219 | 1496 | |
|---|
| 1220 | 1497 | reg = ioread32(&pcfg->usp_pff_inst_id); |
|---|
| 1221 | | - if (reg < SWITCHTEC_MAX_PFF_CSR) |
|---|
| 1498 | + if (reg < stdev->pff_csr_count) |
|---|
| 1222 | 1499 | stdev->pff_local[reg] = 1; |
|---|
| 1223 | 1500 | |
|---|
| 1224 | 1501 | reg = ioread32(&pcfg->vep_pff_inst_id); |
|---|
| 1225 | | - if (reg < SWITCHTEC_MAX_PFF_CSR) |
|---|
| 1502 | + if (reg < stdev->pff_csr_count) |
|---|
| 1226 | 1503 | stdev->pff_local[reg] = 1; |
|---|
| 1227 | 1504 | |
|---|
| 1228 | 1505 | for (i = 0; i < ARRAY_SIZE(pcfg->dsp_pff_inst_id); i++) { |
|---|
| 1229 | 1506 | reg = ioread32(&pcfg->dsp_pff_inst_id[i]); |
|---|
| 1230 | | - if (reg < SWITCHTEC_MAX_PFF_CSR) |
|---|
| 1507 | + if (reg < stdev->pff_csr_count) |
|---|
| 1231 | 1508 | stdev->pff_local[reg] = 1; |
|---|
| 1232 | 1509 | } |
|---|
| 1233 | 1510 | } |
|---|
| .. | .. |
|---|
| 1236 | 1513 | struct pci_dev *pdev) |
|---|
| 1237 | 1514 | { |
|---|
| 1238 | 1515 | int rc; |
|---|
| 1516 | + void __iomem *map; |
|---|
| 1517 | + unsigned long res_start, res_len; |
|---|
| 1518 | + u32 __iomem *part_id; |
|---|
| 1239 | 1519 | |
|---|
| 1240 | 1520 | rc = pcim_enable_device(pdev); |
|---|
| 1241 | 1521 | if (rc) |
|---|
| 1242 | 1522 | return rc; |
|---|
| 1243 | 1523 | |
|---|
| 1244 | | - rc = pcim_iomap_regions(pdev, 0x1, KBUILD_MODNAME); |
|---|
| 1524 | + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); |
|---|
| 1245 | 1525 | if (rc) |
|---|
| 1246 | 1526 | return rc; |
|---|
| 1247 | 1527 | |
|---|
| 1248 | 1528 | pci_set_master(pdev); |
|---|
| 1249 | 1529 | |
|---|
| 1250 | | - stdev->mmio = pcim_iomap_table(pdev)[0]; |
|---|
| 1251 | | - stdev->mmio_mrpc = stdev->mmio + SWITCHTEC_GAS_MRPC_OFFSET; |
|---|
| 1530 | + res_start = pci_resource_start(pdev, 0); |
|---|
| 1531 | + res_len = pci_resource_len(pdev, 0); |
|---|
| 1532 | + |
|---|
| 1533 | + if (!devm_request_mem_region(&pdev->dev, res_start, |
|---|
| 1534 | + res_len, KBUILD_MODNAME)) |
|---|
| 1535 | + return -EBUSY; |
|---|
| 1536 | + |
|---|
| 1537 | + stdev->mmio_mrpc = devm_ioremap_wc(&pdev->dev, res_start, |
|---|
| 1538 | + SWITCHTEC_GAS_TOP_CFG_OFFSET); |
|---|
| 1539 | + if (!stdev->mmio_mrpc) |
|---|
| 1540 | + return -ENOMEM; |
|---|
| 1541 | + |
|---|
| 1542 | + map = devm_ioremap(&pdev->dev, |
|---|
| 1543 | + res_start + SWITCHTEC_GAS_TOP_CFG_OFFSET, |
|---|
| 1544 | + res_len - SWITCHTEC_GAS_TOP_CFG_OFFSET); |
|---|
| 1545 | + if (!map) |
|---|
| 1546 | + return -ENOMEM; |
|---|
| 1547 | + |
|---|
| 1548 | + stdev->mmio = map - SWITCHTEC_GAS_TOP_CFG_OFFSET; |
|---|
| 1252 | 1549 | stdev->mmio_sw_event = stdev->mmio + SWITCHTEC_GAS_SW_EVENT_OFFSET; |
|---|
| 1253 | 1550 | stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET; |
|---|
| 1254 | 1551 | stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET; |
|---|
| 1255 | 1552 | stdev->mmio_ntb = stdev->mmio + SWITCHTEC_GAS_NTB_OFFSET; |
|---|
| 1256 | | - stdev->partition = ioread8(&stdev->mmio_sys_info->partition_id); |
|---|
| 1553 | + |
|---|
| 1554 | + if (stdev->gen == SWITCHTEC_GEN3) |
|---|
| 1555 | + part_id = &stdev->mmio_sys_info->gen3.partition_id; |
|---|
| 1556 | + else if (stdev->gen == SWITCHTEC_GEN4) |
|---|
| 1557 | + part_id = &stdev->mmio_sys_info->gen4.partition_id; |
|---|
| 1558 | + else |
|---|
| 1559 | + return -ENOTSUPP; |
|---|
| 1560 | + |
|---|
| 1561 | + stdev->partition = ioread8(part_id); |
|---|
| 1257 | 1562 | stdev->partition_count = ioread8(&stdev->mmio_ntb->partition_count); |
|---|
| 1258 | 1563 | stdev->mmio_part_cfg_all = stdev->mmio + SWITCHTEC_GAS_PART_CFG_OFFSET; |
|---|
| 1259 | 1564 | stdev->mmio_part_cfg = &stdev->mmio_part_cfg_all[stdev->partition]; |
|---|
| .. | .. |
|---|
| 1265 | 1570 | init_pff(stdev); |
|---|
| 1266 | 1571 | |
|---|
| 1267 | 1572 | pci_set_drvdata(pdev, stdev); |
|---|
| 1573 | + |
|---|
| 1574 | + if (!use_dma_mrpc) |
|---|
| 1575 | + return 0; |
|---|
| 1576 | + |
|---|
| 1577 | + if (ioread32(&stdev->mmio_mrpc->dma_ver) == 0) |
|---|
| 1578 | + return 0; |
|---|
| 1579 | + |
|---|
| 1580 | + stdev->dma_mrpc = dma_alloc_coherent(&stdev->pdev->dev, |
|---|
| 1581 | + sizeof(*stdev->dma_mrpc), |
|---|
| 1582 | + &stdev->dma_mrpc_dma_addr, |
|---|
| 1583 | + GFP_KERNEL); |
|---|
| 1584 | + if (stdev->dma_mrpc == NULL) |
|---|
| 1585 | + return -ENOMEM; |
|---|
| 1268 | 1586 | |
|---|
| 1269 | 1587 | return 0; |
|---|
| 1270 | 1588 | } |
|---|
| .. | .. |
|---|
| 1282 | 1600 | if (IS_ERR(stdev)) |
|---|
| 1283 | 1601 | return PTR_ERR(stdev); |
|---|
| 1284 | 1602 | |
|---|
| 1603 | + stdev->gen = id->driver_data; |
|---|
| 1604 | + |
|---|
| 1285 | 1605 | rc = switchtec_init_pci(stdev, pdev); |
|---|
| 1286 | 1606 | if (rc) |
|---|
| 1287 | 1607 | goto err_put; |
|---|
| .. | .. |
|---|
| 1296 | 1616 | SWITCHTEC_EVENT_EN_IRQ, |
|---|
| 1297 | 1617 | &stdev->mmio_part_cfg->mrpc_comp_hdr); |
|---|
| 1298 | 1618 | enable_link_state_events(stdev); |
|---|
| 1619 | + |
|---|
| 1620 | + if (stdev->dma_mrpc) |
|---|
| 1621 | + enable_dma_mrpc(stdev); |
|---|
| 1299 | 1622 | |
|---|
| 1300 | 1623 | rc = cdev_device_add(&stdev->cdev, &stdev->dev); |
|---|
| 1301 | 1624 | if (rc) |
|---|
| .. | .. |
|---|
| 1322 | 1645 | cdev_device_del(&stdev->cdev, &stdev->dev); |
|---|
| 1323 | 1646 | ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt)); |
|---|
| 1324 | 1647 | dev_info(&stdev->dev, "unregistered.\n"); |
|---|
| 1325 | | - |
|---|
| 1326 | 1648 | stdev_kill(stdev); |
|---|
| 1327 | 1649 | put_device(&stdev->dev); |
|---|
| 1328 | 1650 | } |
|---|
| 1329 | 1651 | |
|---|
| 1330 | | -#define SWITCHTEC_PCI_DEVICE(device_id) \ |
|---|
| 1652 | +#define SWITCHTEC_PCI_DEVICE(device_id, gen) \ |
|---|
| 1331 | 1653 | { \ |
|---|
| 1332 | 1654 | .vendor = PCI_VENDOR_ID_MICROSEMI, \ |
|---|
| 1333 | 1655 | .device = device_id, \ |
|---|
| .. | .. |
|---|
| 1335 | 1657 | .subdevice = PCI_ANY_ID, \ |
|---|
| 1336 | 1658 | .class = (PCI_CLASS_MEMORY_OTHER << 8), \ |
|---|
| 1337 | 1659 | .class_mask = 0xFFFFFFFF, \ |
|---|
| 1660 | + .driver_data = gen, \ |
|---|
| 1338 | 1661 | }, \ |
|---|
| 1339 | 1662 | { \ |
|---|
| 1340 | 1663 | .vendor = PCI_VENDOR_ID_MICROSEMI, \ |
|---|
| .. | .. |
|---|
| 1343 | 1666 | .subdevice = PCI_ANY_ID, \ |
|---|
| 1344 | 1667 | .class = (PCI_CLASS_BRIDGE_OTHER << 8), \ |
|---|
| 1345 | 1668 | .class_mask = 0xFFFFFFFF, \ |
|---|
| 1669 | + .driver_data = gen, \ |
|---|
| 1346 | 1670 | } |
|---|
| 1347 | 1671 | |
|---|
| 1348 | 1672 | static const struct pci_device_id switchtec_pci_tbl[] = { |
|---|
| 1349 | | - SWITCHTEC_PCI_DEVICE(0x8531), //PFX 24xG3 |
|---|
| 1350 | | - SWITCHTEC_PCI_DEVICE(0x8532), //PFX 32xG3 |
|---|
| 1351 | | - SWITCHTEC_PCI_DEVICE(0x8533), //PFX 48xG3 |
|---|
| 1352 | | - SWITCHTEC_PCI_DEVICE(0x8534), //PFX 64xG3 |
|---|
| 1353 | | - SWITCHTEC_PCI_DEVICE(0x8535), //PFX 80xG3 |
|---|
| 1354 | | - SWITCHTEC_PCI_DEVICE(0x8536), //PFX 96xG3 |
|---|
| 1355 | | - SWITCHTEC_PCI_DEVICE(0x8541), //PSX 24xG3 |
|---|
| 1356 | | - SWITCHTEC_PCI_DEVICE(0x8542), //PSX 32xG3 |
|---|
| 1357 | | - SWITCHTEC_PCI_DEVICE(0x8543), //PSX 48xG3 |
|---|
| 1358 | | - SWITCHTEC_PCI_DEVICE(0x8544), //PSX 64xG3 |
|---|
| 1359 | | - SWITCHTEC_PCI_DEVICE(0x8545), //PSX 80xG3 |
|---|
| 1360 | | - SWITCHTEC_PCI_DEVICE(0x8546), //PSX 96xG3 |
|---|
| 1361 | | - SWITCHTEC_PCI_DEVICE(0x8551), //PAX 24XG3 |
|---|
| 1362 | | - SWITCHTEC_PCI_DEVICE(0x8552), //PAX 32XG3 |
|---|
| 1363 | | - SWITCHTEC_PCI_DEVICE(0x8553), //PAX 48XG3 |
|---|
| 1364 | | - SWITCHTEC_PCI_DEVICE(0x8554), //PAX 64XG3 |
|---|
| 1365 | | - SWITCHTEC_PCI_DEVICE(0x8555), //PAX 80XG3 |
|---|
| 1366 | | - SWITCHTEC_PCI_DEVICE(0x8556), //PAX 96XG3 |
|---|
| 1367 | | - SWITCHTEC_PCI_DEVICE(0x8561), //PFXL 24XG3 |
|---|
| 1368 | | - SWITCHTEC_PCI_DEVICE(0x8562), //PFXL 32XG3 |
|---|
| 1369 | | - SWITCHTEC_PCI_DEVICE(0x8563), //PFXL 48XG3 |
|---|
| 1370 | | - SWITCHTEC_PCI_DEVICE(0x8564), //PFXL 64XG3 |
|---|
| 1371 | | - SWITCHTEC_PCI_DEVICE(0x8565), //PFXL 80XG3 |
|---|
| 1372 | | - SWITCHTEC_PCI_DEVICE(0x8566), //PFXL 96XG3 |
|---|
| 1373 | | - SWITCHTEC_PCI_DEVICE(0x8571), //PFXI 24XG3 |
|---|
| 1374 | | - SWITCHTEC_PCI_DEVICE(0x8572), //PFXI 32XG3 |
|---|
| 1375 | | - SWITCHTEC_PCI_DEVICE(0x8573), //PFXI 48XG3 |
|---|
| 1376 | | - SWITCHTEC_PCI_DEVICE(0x8574), //PFXI 64XG3 |
|---|
| 1377 | | - SWITCHTEC_PCI_DEVICE(0x8575), //PFXI 80XG3 |
|---|
| 1378 | | - SWITCHTEC_PCI_DEVICE(0x8576), //PFXI 96XG3 |
|---|
| 1673 | + SWITCHTEC_PCI_DEVICE(0x8531, SWITCHTEC_GEN3), //PFX 24xG3 |
|---|
| 1674 | + SWITCHTEC_PCI_DEVICE(0x8532, SWITCHTEC_GEN3), //PFX 32xG3 |
|---|
| 1675 | + SWITCHTEC_PCI_DEVICE(0x8533, SWITCHTEC_GEN3), //PFX 48xG3 |
|---|
| 1676 | + SWITCHTEC_PCI_DEVICE(0x8534, SWITCHTEC_GEN3), //PFX 64xG3 |
|---|
| 1677 | + SWITCHTEC_PCI_DEVICE(0x8535, SWITCHTEC_GEN3), //PFX 80xG3 |
|---|
| 1678 | + SWITCHTEC_PCI_DEVICE(0x8536, SWITCHTEC_GEN3), //PFX 96xG3 |
|---|
| 1679 | + SWITCHTEC_PCI_DEVICE(0x8541, SWITCHTEC_GEN3), //PSX 24xG3 |
|---|
| 1680 | + SWITCHTEC_PCI_DEVICE(0x8542, SWITCHTEC_GEN3), //PSX 32xG3 |
|---|
| 1681 | + SWITCHTEC_PCI_DEVICE(0x8543, SWITCHTEC_GEN3), //PSX 48xG3 |
|---|
| 1682 | + SWITCHTEC_PCI_DEVICE(0x8544, SWITCHTEC_GEN3), //PSX 64xG3 |
|---|
| 1683 | + SWITCHTEC_PCI_DEVICE(0x8545, SWITCHTEC_GEN3), //PSX 80xG3 |
|---|
| 1684 | + SWITCHTEC_PCI_DEVICE(0x8546, SWITCHTEC_GEN3), //PSX 96xG3 |
|---|
| 1685 | + SWITCHTEC_PCI_DEVICE(0x8551, SWITCHTEC_GEN3), //PAX 24XG3 |
|---|
| 1686 | + SWITCHTEC_PCI_DEVICE(0x8552, SWITCHTEC_GEN3), //PAX 32XG3 |
|---|
| 1687 | + SWITCHTEC_PCI_DEVICE(0x8553, SWITCHTEC_GEN3), //PAX 48XG3 |
|---|
| 1688 | + SWITCHTEC_PCI_DEVICE(0x8554, SWITCHTEC_GEN3), //PAX 64XG3 |
|---|
| 1689 | + SWITCHTEC_PCI_DEVICE(0x8555, SWITCHTEC_GEN3), //PAX 80XG3 |
|---|
| 1690 | + SWITCHTEC_PCI_DEVICE(0x8556, SWITCHTEC_GEN3), //PAX 96XG3 |
|---|
| 1691 | + SWITCHTEC_PCI_DEVICE(0x8561, SWITCHTEC_GEN3), //PFXL 24XG3 |
|---|
| 1692 | + SWITCHTEC_PCI_DEVICE(0x8562, SWITCHTEC_GEN3), //PFXL 32XG3 |
|---|
| 1693 | + SWITCHTEC_PCI_DEVICE(0x8563, SWITCHTEC_GEN3), //PFXL 48XG3 |
|---|
| 1694 | + SWITCHTEC_PCI_DEVICE(0x8564, SWITCHTEC_GEN3), //PFXL 64XG3 |
|---|
| 1695 | + SWITCHTEC_PCI_DEVICE(0x8565, SWITCHTEC_GEN3), //PFXL 80XG3 |
|---|
| 1696 | + SWITCHTEC_PCI_DEVICE(0x8566, SWITCHTEC_GEN3), //PFXL 96XG3 |
|---|
| 1697 | + SWITCHTEC_PCI_DEVICE(0x8571, SWITCHTEC_GEN3), //PFXI 24XG3 |
|---|
| 1698 | + SWITCHTEC_PCI_DEVICE(0x8572, SWITCHTEC_GEN3), //PFXI 32XG3 |
|---|
| 1699 | + SWITCHTEC_PCI_DEVICE(0x8573, SWITCHTEC_GEN3), //PFXI 48XG3 |
|---|
| 1700 | + SWITCHTEC_PCI_DEVICE(0x8574, SWITCHTEC_GEN3), //PFXI 64XG3 |
|---|
| 1701 | + SWITCHTEC_PCI_DEVICE(0x8575, SWITCHTEC_GEN3), //PFXI 80XG3 |
|---|
| 1702 | + SWITCHTEC_PCI_DEVICE(0x8576, SWITCHTEC_GEN3), //PFXI 96XG3 |
|---|
| 1703 | + SWITCHTEC_PCI_DEVICE(0x4000, SWITCHTEC_GEN4), //PFX 100XG4 |
|---|
| 1704 | + SWITCHTEC_PCI_DEVICE(0x4084, SWITCHTEC_GEN4), //PFX 84XG4 |
|---|
| 1705 | + SWITCHTEC_PCI_DEVICE(0x4068, SWITCHTEC_GEN4), //PFX 68XG4 |
|---|
| 1706 | + SWITCHTEC_PCI_DEVICE(0x4052, SWITCHTEC_GEN4), //PFX 52XG4 |
|---|
| 1707 | + SWITCHTEC_PCI_DEVICE(0x4036, SWITCHTEC_GEN4), //PFX 36XG4 |
|---|
| 1708 | + SWITCHTEC_PCI_DEVICE(0x4028, SWITCHTEC_GEN4), //PFX 28XG4 |
|---|
| 1709 | + SWITCHTEC_PCI_DEVICE(0x4100, SWITCHTEC_GEN4), //PSX 100XG4 |
|---|
| 1710 | + SWITCHTEC_PCI_DEVICE(0x4184, SWITCHTEC_GEN4), //PSX 84XG4 |
|---|
| 1711 | + SWITCHTEC_PCI_DEVICE(0x4168, SWITCHTEC_GEN4), //PSX 68XG4 |
|---|
| 1712 | + SWITCHTEC_PCI_DEVICE(0x4152, SWITCHTEC_GEN4), //PSX 52XG4 |
|---|
| 1713 | + SWITCHTEC_PCI_DEVICE(0x4136, SWITCHTEC_GEN4), //PSX 36XG4 |
|---|
| 1714 | + SWITCHTEC_PCI_DEVICE(0x4128, SWITCHTEC_GEN4), //PSX 28XG4 |
|---|
| 1715 | + SWITCHTEC_PCI_DEVICE(0x4200, SWITCHTEC_GEN4), //PAX 100XG4 |
|---|
| 1716 | + SWITCHTEC_PCI_DEVICE(0x4284, SWITCHTEC_GEN4), //PAX 84XG4 |
|---|
| 1717 | + SWITCHTEC_PCI_DEVICE(0x4268, SWITCHTEC_GEN4), //PAX 68XG4 |
|---|
| 1718 | + SWITCHTEC_PCI_DEVICE(0x4252, SWITCHTEC_GEN4), //PAX 52XG4 |
|---|
| 1719 | + SWITCHTEC_PCI_DEVICE(0x4236, SWITCHTEC_GEN4), //PAX 36XG4 |
|---|
| 1720 | + SWITCHTEC_PCI_DEVICE(0x4228, SWITCHTEC_GEN4), //PAX 28XG4 |
|---|
| 1379 | 1721 | {0} |
|---|
| 1380 | 1722 | }; |
|---|
| 1381 | 1723 | MODULE_DEVICE_TABLE(pci, switchtec_pci_tbl); |
|---|