.. | .. |
---|
102 | 102 | struct mlxsw_pci { |
---|
103 | 103 | struct pci_dev *pdev; |
---|
104 | 104 | u8 __iomem *hw_addr; |
---|
| 105 | + u64 free_running_clock_offset; |
---|
105 | 106 | struct mlxsw_pci_queue_type_group queues[MLXSW_PCI_QUEUE_TYPE_COUNT]; |
---|
106 | 107 | u32 doorbell_offset; |
---|
107 | 108 | struct mlxsw_core *core; |
---|
.. | .. |
---|
283 | 284 | static int mlxsw_pci_sdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, |
---|
284 | 285 | struct mlxsw_pci_queue *q) |
---|
285 | 286 | { |
---|
| 287 | + int tclass; |
---|
| 288 | + int lp; |
---|
286 | 289 | int i; |
---|
287 | 290 | int err; |
---|
288 | 291 | |
---|
289 | 292 | q->producer_counter = 0; |
---|
290 | 293 | q->consumer_counter = 0; |
---|
| 294 | + tclass = q->num == MLXSW_PCI_SDQ_EMAD_INDEX ? MLXSW_PCI_SDQ_EMAD_TC : |
---|
| 295 | + MLXSW_PCI_SDQ_CTL_TC; |
---|
| 296 | + lp = q->num == MLXSW_PCI_SDQ_EMAD_INDEX ? MLXSW_CMD_MBOX_SW2HW_DQ_SDQ_LP_IGNORE_WQE : |
---|
| 297 | + MLXSW_CMD_MBOX_SW2HW_DQ_SDQ_LP_WQE; |
---|
291 | 298 | |
---|
292 | 299 | /* Set CQ of same number of this SDQ. */ |
---|
293 | 300 | mlxsw_cmd_mbox_sw2hw_dq_cq_set(mbox, q->num); |
---|
294 | | - mlxsw_cmd_mbox_sw2hw_dq_sdq_tclass_set(mbox, 3); |
---|
| 301 | + mlxsw_cmd_mbox_sw2hw_dq_sdq_lp_set(mbox, lp); |
---|
| 302 | + mlxsw_cmd_mbox_sw2hw_dq_sdq_tclass_set(mbox, tclass); |
---|
295 | 303 | mlxsw_cmd_mbox_sw2hw_dq_log2_dq_sz_set(mbox, 3); /* 8 pages */ |
---|
296 | 304 | for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) { |
---|
297 | 305 | dma_addr_t mapaddr = __mlxsw_pci_queue_page_get(q, i); |
---|
.. | .. |
---|
349 | 357 | struct sk_buff *skb; |
---|
350 | 358 | int err; |
---|
351 | 359 | |
---|
352 | | - elem_info->u.rdq.skb = NULL; |
---|
353 | 360 | skb = netdev_alloc_skb_ip_align(NULL, buf_len); |
---|
354 | 361 | if (!skb) |
---|
355 | 362 | return -ENOMEM; |
---|
356 | | - |
---|
357 | | - /* Assume that wqe was previously zeroed. */ |
---|
358 | 363 | |
---|
359 | 364 | err = mlxsw_pci_wqe_frag_map(mlxsw_pci, wqe, 0, skb->data, |
---|
360 | 365 | buf_len, DMA_FROM_DEVICE); |
---|
.. | .. |
---|
507 | 512 | { |
---|
508 | 513 | struct pci_dev *pdev = mlxsw_pci->pdev; |
---|
509 | 514 | struct mlxsw_pci_queue_elem_info *elem_info; |
---|
| 515 | + struct mlxsw_tx_info tx_info; |
---|
510 | 516 | char *wqe; |
---|
511 | 517 | struct sk_buff *skb; |
---|
512 | 518 | int i; |
---|
513 | 519 | |
---|
514 | 520 | spin_lock(&q->lock); |
---|
515 | 521 | elem_info = mlxsw_pci_queue_elem_info_consumer_get(q); |
---|
| 522 | + tx_info = mlxsw_skb_cb(elem_info->u.sdq.skb)->tx_info; |
---|
516 | 523 | skb = elem_info->u.sdq.skb; |
---|
517 | 524 | wqe = elem_info->elem; |
---|
518 | 525 | for (i = 0; i < MLXSW_PCI_WQE_SG_ENTRIES; i++) |
---|
519 | 526 | mlxsw_pci_wqe_frag_unmap(mlxsw_pci, wqe, i, DMA_TO_DEVICE); |
---|
520 | | - dev_kfree_skb_any(skb); |
---|
| 527 | + |
---|
| 528 | + if (unlikely(!tx_info.is_emad && |
---|
| 529 | + skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { |
---|
| 530 | + mlxsw_core_ptp_transmitted(mlxsw_pci->core, skb, |
---|
| 531 | + tx_info.local_port); |
---|
| 532 | + skb = NULL; |
---|
| 533 | + } |
---|
| 534 | + |
---|
| 535 | + if (skb) |
---|
| 536 | + dev_kfree_skb_any(skb); |
---|
521 | 537 | elem_info->u.sdq.skb = NULL; |
---|
522 | 538 | |
---|
523 | 539 | if (q->consumer_counter++ != consumer_counter_limit) |
---|
.. | .. |
---|
532 | 548 | { |
---|
533 | 549 | struct pci_dev *pdev = mlxsw_pci->pdev; |
---|
534 | 550 | struct mlxsw_pci_queue_elem_info *elem_info; |
---|
535 | | - char *wqe; |
---|
| 551 | + struct mlxsw_rx_info rx_info = {}; |
---|
| 552 | + char wqe[MLXSW_PCI_WQE_SIZE]; |
---|
536 | 553 | struct sk_buff *skb; |
---|
537 | | - struct mlxsw_rx_info rx_info; |
---|
538 | 554 | u16 byte_count; |
---|
539 | 555 | int err; |
---|
540 | 556 | |
---|
541 | 557 | elem_info = mlxsw_pci_queue_elem_info_consumer_get(q); |
---|
542 | | - skb = elem_info->u.sdq.skb; |
---|
543 | | - if (!skb) |
---|
544 | | - return; |
---|
545 | | - wqe = elem_info->elem; |
---|
546 | | - mlxsw_pci_wqe_frag_unmap(mlxsw_pci, wqe, 0, DMA_FROM_DEVICE); |
---|
| 558 | + skb = elem_info->u.rdq.skb; |
---|
| 559 | + memcpy(wqe, elem_info->elem, MLXSW_PCI_WQE_SIZE); |
---|
547 | 560 | |
---|
548 | 561 | if (q->consumer_counter++ != consumer_counter_limit) |
---|
549 | 562 | dev_dbg_ratelimited(&pdev->dev, "Consumer counter does not match limit in RDQ\n"); |
---|
| 563 | + |
---|
| 564 | + err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info); |
---|
| 565 | + if (err) { |
---|
| 566 | + dev_err_ratelimited(&pdev->dev, "Failed to alloc skb for RDQ\n"); |
---|
| 567 | + goto out; |
---|
| 568 | + } |
---|
| 569 | + |
---|
| 570 | + mlxsw_pci_wqe_frag_unmap(mlxsw_pci, wqe, 0, DMA_FROM_DEVICE); |
---|
550 | 571 | |
---|
551 | 572 | if (mlxsw_pci_cqe_lag_get(cqe_v, cqe)) { |
---|
552 | 573 | rx_info.is_lag = true; |
---|
.. | .. |
---|
560 | 581 | |
---|
561 | 582 | rx_info.trap_id = mlxsw_pci_cqe_trap_id_get(cqe); |
---|
562 | 583 | |
---|
| 584 | + if (rx_info.trap_id == MLXSW_TRAP_ID_DISCARD_INGRESS_ACL || |
---|
| 585 | + rx_info.trap_id == MLXSW_TRAP_ID_DISCARD_EGRESS_ACL) { |
---|
| 586 | + u32 cookie_index = 0; |
---|
| 587 | + |
---|
| 588 | + if (mlxsw_pci->max_cqe_ver >= MLXSW_PCI_CQE_V2) |
---|
| 589 | + cookie_index = mlxsw_pci_cqe2_user_def_val_orig_pkt_len_get(cqe); |
---|
| 590 | + mlxsw_skb_cb(skb)->cookie_index = cookie_index; |
---|
| 591 | + } else if (rx_info.trap_id >= MLXSW_TRAP_ID_MIRROR_SESSION0 && |
---|
| 592 | + rx_info.trap_id <= MLXSW_TRAP_ID_MIRROR_SESSION7 && |
---|
| 593 | + mlxsw_pci->max_cqe_ver >= MLXSW_PCI_CQE_V2) { |
---|
| 594 | + rx_info.mirror_reason = mlxsw_pci_cqe2_mirror_reason_get(cqe); |
---|
| 595 | + } |
---|
| 596 | + |
---|
563 | 597 | byte_count = mlxsw_pci_cqe_byte_count_get(cqe); |
---|
564 | 598 | if (mlxsw_pci_cqe_crc_get(cqe_v, cqe)) |
---|
565 | 599 | byte_count -= ETH_FCS_LEN; |
---|
566 | 600 | skb_put(skb, byte_count); |
---|
567 | 601 | mlxsw_core_skb_receive(mlxsw_pci->core, skb, &rx_info); |
---|
568 | 602 | |
---|
569 | | - memset(wqe, 0, q->elem_size); |
---|
570 | | - err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info); |
---|
571 | | - if (err) |
---|
572 | | - dev_dbg_ratelimited(&pdev->dev, "Failed to alloc skb for RDQ\n"); |
---|
| 603 | +out: |
---|
573 | 604 | /* Everything is set up, ring doorbell to pass elem to HW */ |
---|
574 | 605 | q->producer_counter++; |
---|
575 | 606 | mlxsw_pci_queue_doorbell_producer_ring(mlxsw_pci, q); |
---|
.. | .. |
---|
592 | 623 | return elem; |
---|
593 | 624 | } |
---|
594 | 625 | |
---|
595 | | -static void mlxsw_pci_cq_tasklet(unsigned long data) |
---|
| 626 | +static void mlxsw_pci_cq_tasklet(struct tasklet_struct *t) |
---|
596 | 627 | { |
---|
597 | | - struct mlxsw_pci_queue *q = (struct mlxsw_pci_queue *) data; |
---|
| 628 | + struct mlxsw_pci_queue *q = from_tasklet(q, t, tasklet); |
---|
598 | 629 | struct mlxsw_pci *mlxsw_pci = q->pci; |
---|
599 | 630 | char *cqe; |
---|
600 | 631 | int items = 0; |
---|
.. | .. |
---|
705 | 736 | return elem; |
---|
706 | 737 | } |
---|
707 | 738 | |
---|
708 | | -static void mlxsw_pci_eq_tasklet(unsigned long data) |
---|
| 739 | +static void mlxsw_pci_eq_tasklet(struct tasklet_struct *t) |
---|
709 | 740 | { |
---|
710 | | - struct mlxsw_pci_queue *q = (struct mlxsw_pci_queue *) data; |
---|
| 741 | + struct mlxsw_pci_queue *q = from_tasklet(q, t, tasklet); |
---|
711 | 742 | struct mlxsw_pci *mlxsw_pci = q->pci; |
---|
712 | 743 | u8 cq_count = mlxsw_pci_cq_count(mlxsw_pci); |
---|
713 | 744 | unsigned long active_cqns[BITS_TO_LONGS(MLXSW_PCI_CQS_MAX)]; |
---|
.. | .. |
---|
764 | 795 | struct mlxsw_pci_queue *q); |
---|
765 | 796 | void (*fini)(struct mlxsw_pci *mlxsw_pci, |
---|
766 | 797 | struct mlxsw_pci_queue *q); |
---|
767 | | - void (*tasklet)(unsigned long data); |
---|
| 798 | + void (*tasklet)(struct tasklet_struct *t); |
---|
768 | 799 | u16 (*elem_count_f)(const struct mlxsw_pci_queue *q); |
---|
769 | 800 | u8 (*elem_size_f)(const struct mlxsw_pci_queue *q); |
---|
770 | 801 | u16 elem_count; |
---|
.. | .. |
---|
827 | 858 | q->pci = mlxsw_pci; |
---|
828 | 859 | |
---|
829 | 860 | if (q_ops->tasklet) |
---|
830 | | - tasklet_init(&q->tasklet, q_ops->tasklet, (unsigned long) q); |
---|
| 861 | + tasklet_setup(&q->tasklet, q_ops->tasklet); |
---|
831 | 862 | |
---|
832 | 863 | mem_item->size = MLXSW_PCI_AQ_SIZE; |
---|
833 | 864 | mem_item->buf = pci_alloc_consistent(mlxsw_pci->pdev, |
---|
.. | .. |
---|
835 | 866 | &mem_item->mapaddr); |
---|
836 | 867 | if (!mem_item->buf) |
---|
837 | 868 | return -ENOMEM; |
---|
838 | | - memset(mem_item->buf, 0, mem_item->size); |
---|
839 | 869 | |
---|
840 | 870 | q->elem_info = kcalloc(q->count, sizeof(*q->elem_info), GFP_KERNEL); |
---|
841 | 871 | if (!q->elem_info) { |
---|
.. | .. |
---|
952 | 982 | eq_log2sz = mlxsw_cmd_mbox_query_aq_cap_log_max_eq_sz_get(mbox); |
---|
953 | 983 | |
---|
954 | 984 | if (num_sdqs + num_rdqs > num_cqs || |
---|
| 985 | + num_sdqs < MLXSW_PCI_SDQS_MIN || |
---|
955 | 986 | num_cqs > MLXSW_PCI_CQS_MAX || num_eqs != MLXSW_PCI_EQS_COUNT) { |
---|
956 | 987 | dev_err(&pdev->dev, "Unsupported number of queues\n"); |
---|
957 | 988 | return -EINVAL; |
---|
.. | .. |
---|
1037 | 1068 | mask |= 2; |
---|
1038 | 1069 | } |
---|
1039 | 1070 | mlxsw_cmd_mbox_config_profile_swid_config_mask_set(mbox, index, mask); |
---|
1040 | | -} |
---|
1041 | | - |
---|
1042 | | -static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox, |
---|
1043 | | - struct mlxsw_res *res) |
---|
1044 | | -{ |
---|
1045 | | - int index, i; |
---|
1046 | | - u64 data; |
---|
1047 | | - u16 id; |
---|
1048 | | - int err; |
---|
1049 | | - |
---|
1050 | | - if (!res) |
---|
1051 | | - return 0; |
---|
1052 | | - |
---|
1053 | | - mlxsw_cmd_mbox_zero(mbox); |
---|
1054 | | - |
---|
1055 | | - for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES; |
---|
1056 | | - index++) { |
---|
1057 | | - err = mlxsw_cmd_query_resources(mlxsw_pci->core, mbox, index); |
---|
1058 | | - if (err) |
---|
1059 | | - return err; |
---|
1060 | | - |
---|
1061 | | - for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) { |
---|
1062 | | - id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i); |
---|
1063 | | - data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i); |
---|
1064 | | - |
---|
1065 | | - if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID) |
---|
1066 | | - return 0; |
---|
1067 | | - |
---|
1068 | | - mlxsw_res_parse(res, id, data); |
---|
1069 | | - } |
---|
1070 | | - } |
---|
1071 | | - |
---|
1072 | | - /* If after MLXSW_RESOURCES_QUERY_MAX_QUERIES we still didn't get |
---|
1073 | | - * MLXSW_RESOURCES_TABLE_END_ID, something went bad in the FW. |
---|
1074 | | - */ |
---|
1075 | | - return -EIO; |
---|
1076 | 1071 | } |
---|
1077 | 1072 | |
---|
1078 | 1073 | static int |
---|
.. | .. |
---|
1343 | 1338 | mbox->mapaddr); |
---|
1344 | 1339 | } |
---|
1345 | 1340 | |
---|
1346 | | -static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci, |
---|
1347 | | - const struct pci_device_id *id) |
---|
| 1341 | +static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci, |
---|
| 1342 | + const struct pci_device_id *id, |
---|
| 1343 | + u32 *p_sys_status) |
---|
1348 | 1344 | { |
---|
1349 | 1345 | unsigned long end; |
---|
1350 | | - char mrsr_pl[MLXSW_REG_MRSR_LEN]; |
---|
1351 | | - int err; |
---|
| 1346 | + u32 val; |
---|
1352 | 1347 | |
---|
1353 | | - mlxsw_reg_mrsr_pack(mrsr_pl); |
---|
1354 | | - err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl); |
---|
1355 | | - if (err) |
---|
1356 | | - return err; |
---|
1357 | 1348 | if (id->device == PCI_DEVICE_ID_MELLANOX_SWITCHX2) { |
---|
1358 | 1349 | msleep(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS); |
---|
1359 | 1350 | return 0; |
---|
1360 | 1351 | } |
---|
1361 | 1352 | |
---|
1362 | | - /* We must wait for the HW to become responsive once again. */ |
---|
| 1353 | + /* We must wait for the HW to become responsive. */ |
---|
1363 | 1354 | msleep(MLXSW_PCI_SW_RESET_WAIT_MSECS); |
---|
1364 | 1355 | |
---|
1365 | 1356 | end = jiffies + msecs_to_jiffies(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS); |
---|
1366 | 1357 | do { |
---|
1367 | | - u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY); |
---|
1368 | | - |
---|
| 1358 | + val = mlxsw_pci_read32(mlxsw_pci, FW_READY); |
---|
1369 | 1359 | if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC) |
---|
1370 | 1360 | return 0; |
---|
1371 | 1361 | cond_resched(); |
---|
1372 | 1362 | } while (time_before(jiffies, end)); |
---|
| 1363 | + |
---|
| 1364 | + *p_sys_status = val & MLXSW_PCI_FW_READY_MASK; |
---|
| 1365 | + |
---|
1373 | 1366 | return -EBUSY; |
---|
| 1367 | +} |
---|
| 1368 | + |
---|
| 1369 | +static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci, |
---|
| 1370 | + const struct pci_device_id *id) |
---|
| 1371 | +{ |
---|
| 1372 | + struct pci_dev *pdev = mlxsw_pci->pdev; |
---|
| 1373 | + char mrsr_pl[MLXSW_REG_MRSR_LEN]; |
---|
| 1374 | + u32 sys_status; |
---|
| 1375 | + int err; |
---|
| 1376 | + |
---|
| 1377 | + err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status); |
---|
| 1378 | + if (err) { |
---|
| 1379 | + dev_err(&pdev->dev, "Failed to reach system ready status before reset. Status is 0x%x\n", |
---|
| 1380 | + sys_status); |
---|
| 1381 | + return err; |
---|
| 1382 | + } |
---|
| 1383 | + |
---|
| 1384 | + mlxsw_reg_mrsr_pack(mrsr_pl); |
---|
| 1385 | + err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl); |
---|
| 1386 | + if (err) |
---|
| 1387 | + return err; |
---|
| 1388 | + |
---|
| 1389 | + err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status); |
---|
| 1390 | + if (err) { |
---|
| 1391 | + dev_err(&pdev->dev, "Failed to reach system ready status after reset. Status is 0x%x\n", |
---|
| 1392 | + sys_status); |
---|
| 1393 | + return err; |
---|
| 1394 | + } |
---|
| 1395 | + |
---|
| 1396 | + return 0; |
---|
1374 | 1397 | } |
---|
1375 | 1398 | |
---|
1376 | 1399 | static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci) |
---|
.. | .. |
---|
1398 | 1421 | u16 num_pages; |
---|
1399 | 1422 | int err; |
---|
1400 | 1423 | |
---|
1401 | | - mutex_init(&mlxsw_pci->cmd.lock); |
---|
1402 | | - init_waitqueue_head(&mlxsw_pci->cmd.wait); |
---|
1403 | | - |
---|
1404 | 1424 | mlxsw_pci->core = mlxsw_core; |
---|
1405 | 1425 | |
---|
1406 | 1426 | mbox = mlxsw_cmd_mbox_alloc(); |
---|
1407 | 1427 | if (!mbox) |
---|
1408 | 1428 | return -ENOMEM; |
---|
1409 | | - |
---|
1410 | | - err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.in_mbox); |
---|
1411 | | - if (err) |
---|
1412 | | - goto mbox_put; |
---|
1413 | | - |
---|
1414 | | - err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.out_mbox); |
---|
1415 | | - if (err) |
---|
1416 | | - goto err_out_mbox_alloc; |
---|
1417 | 1429 | |
---|
1418 | 1430 | err = mlxsw_pci_sw_reset(mlxsw_pci, mlxsw_pci->id); |
---|
1419 | 1431 | if (err) |
---|
.. | .. |
---|
1450 | 1462 | mlxsw_pci->doorbell_offset = |
---|
1451 | 1463 | mlxsw_cmd_mbox_query_fw_doorbell_page_offset_get(mbox); |
---|
1452 | 1464 | |
---|
| 1465 | + if (mlxsw_cmd_mbox_query_fw_fr_rn_clk_bar_get(mbox) != 0) { |
---|
| 1466 | + dev_err(&pdev->dev, "Unsupported free running clock BAR queried from hw\n"); |
---|
| 1467 | + err = -EINVAL; |
---|
| 1468 | + goto err_fr_rn_clk_bar; |
---|
| 1469 | + } |
---|
| 1470 | + |
---|
| 1471 | + mlxsw_pci->free_running_clock_offset = |
---|
| 1472 | + mlxsw_cmd_mbox_query_fw_free_running_clock_offset_get(mbox); |
---|
| 1473 | + |
---|
1453 | 1474 | num_pages = mlxsw_cmd_mbox_query_fw_fw_pages_get(mbox); |
---|
1454 | 1475 | err = mlxsw_pci_fw_area_init(mlxsw_pci, mbox, num_pages); |
---|
1455 | 1476 | if (err) |
---|
.. | .. |
---|
1459 | 1480 | if (err) |
---|
1460 | 1481 | goto err_boardinfo; |
---|
1461 | 1482 | |
---|
1462 | | - err = mlxsw_pci_resources_query(mlxsw_pci, mbox, res); |
---|
| 1483 | + err = mlxsw_core_resources_query(mlxsw_core, mbox, res); |
---|
1463 | 1484 | if (err) |
---|
1464 | 1485 | goto err_query_resources; |
---|
1465 | 1486 | |
---|
.. | .. |
---|
1505 | 1526 | err_boardinfo: |
---|
1506 | 1527 | mlxsw_pci_fw_area_fini(mlxsw_pci); |
---|
1507 | 1528 | err_fw_area_init: |
---|
| 1529 | +err_fr_rn_clk_bar: |
---|
1508 | 1530 | err_doorbell_page_bar: |
---|
1509 | 1531 | err_iface_rev: |
---|
1510 | 1532 | err_query_fw: |
---|
1511 | 1533 | mlxsw_pci_free_irq_vectors(mlxsw_pci); |
---|
1512 | 1534 | err_alloc_irq: |
---|
1513 | 1535 | err_sw_reset: |
---|
1514 | | - mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox); |
---|
1515 | | -err_out_mbox_alloc: |
---|
1516 | | - mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox); |
---|
1517 | 1536 | mbox_put: |
---|
1518 | 1537 | mlxsw_cmd_mbox_free(mbox); |
---|
1519 | 1538 | return err; |
---|
.. | .. |
---|
1527 | 1546 | mlxsw_pci_aqs_fini(mlxsw_pci); |
---|
1528 | 1547 | mlxsw_pci_fw_area_fini(mlxsw_pci); |
---|
1529 | 1548 | mlxsw_pci_free_irq_vectors(mlxsw_pci); |
---|
1530 | | - mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox); |
---|
1531 | | - mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox); |
---|
1532 | 1549 | } |
---|
1533 | 1550 | |
---|
1534 | 1551 | static struct mlxsw_pci_queue * |
---|
1535 | 1552 | mlxsw_pci_sdq_pick(struct mlxsw_pci *mlxsw_pci, |
---|
1536 | 1553 | const struct mlxsw_tx_info *tx_info) |
---|
1537 | 1554 | { |
---|
1538 | | - u8 sdqn = tx_info->local_port % mlxsw_pci_sdq_count(mlxsw_pci); |
---|
| 1555 | + u8 ctl_sdq_count = mlxsw_pci_sdq_count(mlxsw_pci) - 1; |
---|
| 1556 | + u8 sdqn; |
---|
| 1557 | + |
---|
| 1558 | + if (tx_info->is_emad) { |
---|
| 1559 | + sdqn = MLXSW_PCI_SDQ_EMAD_INDEX; |
---|
| 1560 | + } else { |
---|
| 1561 | + BUILD_BUG_ON(MLXSW_PCI_SDQ_EMAD_INDEX != 0); |
---|
| 1562 | + sdqn = 1 + (tx_info->local_port % ctl_sdq_count); |
---|
| 1563 | + } |
---|
1539 | 1564 | |
---|
1540 | 1565 | return mlxsw_pci_sdq_get(mlxsw_pci, sdqn); |
---|
1541 | 1566 | } |
---|
.. | .. |
---|
1573 | 1598 | err = -EAGAIN; |
---|
1574 | 1599 | goto unlock; |
---|
1575 | 1600 | } |
---|
| 1601 | + mlxsw_skb_cb(skb)->tx_info = *tx_info; |
---|
1576 | 1602 | elem_info->u.sdq.skb = skb; |
---|
1577 | 1603 | |
---|
1578 | 1604 | wqe = elem_info->elem; |
---|
1579 | 1605 | mlxsw_pci_wqe_c_set(wqe, 1); /* always report completion */ |
---|
1580 | | - mlxsw_pci_wqe_lp_set(wqe, !!tx_info->is_emad); |
---|
| 1606 | + mlxsw_pci_wqe_lp_set(wqe, 0); |
---|
1581 | 1607 | mlxsw_pci_wqe_type_set(wqe, MLXSW_PCI_WQE_TYPE_ETHERNET); |
---|
1582 | 1608 | |
---|
1583 | 1609 | err = mlxsw_pci_wqe_frag_map(mlxsw_pci, wqe, 0, skb->data, |
---|
.. | .. |
---|
1595 | 1621 | if (err) |
---|
1596 | 1622 | goto unmap_frags; |
---|
1597 | 1623 | } |
---|
| 1624 | + |
---|
| 1625 | + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) |
---|
| 1626 | + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; |
---|
1598 | 1627 | |
---|
1599 | 1628 | /* Set unused sq entries byte count to zero. */ |
---|
1600 | 1629 | for (i++; i < MLXSW_PCI_WQE_SG_ENTRIES; i++) |
---|
.. | .. |
---|
1708 | 1737 | return err; |
---|
1709 | 1738 | } |
---|
1710 | 1739 | |
---|
| 1740 | +static u32 mlxsw_pci_read_frc_h(void *bus_priv) |
---|
| 1741 | +{ |
---|
| 1742 | + struct mlxsw_pci *mlxsw_pci = bus_priv; |
---|
| 1743 | + u64 frc_offset; |
---|
| 1744 | + |
---|
| 1745 | + frc_offset = mlxsw_pci->free_running_clock_offset; |
---|
| 1746 | + return mlxsw_pci_read32(mlxsw_pci, FREE_RUNNING_CLOCK_H(frc_offset)); |
---|
| 1747 | +} |
---|
| 1748 | + |
---|
| 1749 | +static u32 mlxsw_pci_read_frc_l(void *bus_priv) |
---|
| 1750 | +{ |
---|
| 1751 | + struct mlxsw_pci *mlxsw_pci = bus_priv; |
---|
| 1752 | + u64 frc_offset; |
---|
| 1753 | + |
---|
| 1754 | + frc_offset = mlxsw_pci->free_running_clock_offset; |
---|
| 1755 | + return mlxsw_pci_read32(mlxsw_pci, FREE_RUNNING_CLOCK_L(frc_offset)); |
---|
| 1756 | +} |
---|
| 1757 | + |
---|
1711 | 1758 | static const struct mlxsw_bus mlxsw_pci_bus = { |
---|
1712 | 1759 | .kind = "pci", |
---|
1713 | 1760 | .init = mlxsw_pci_init, |
---|
.. | .. |
---|
1715 | 1762 | .skb_transmit_busy = mlxsw_pci_skb_transmit_busy, |
---|
1716 | 1763 | .skb_transmit = mlxsw_pci_skb_transmit, |
---|
1717 | 1764 | .cmd_exec = mlxsw_pci_cmd_exec, |
---|
| 1765 | + .read_frc_h = mlxsw_pci_read_frc_h, |
---|
| 1766 | + .read_frc_l = mlxsw_pci_read_frc_l, |
---|
1718 | 1767 | .features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET, |
---|
1719 | 1768 | }; |
---|
| 1769 | + |
---|
| 1770 | +static int mlxsw_pci_cmd_init(struct mlxsw_pci *mlxsw_pci) |
---|
| 1771 | +{ |
---|
| 1772 | + int err; |
---|
| 1773 | + |
---|
| 1774 | + mutex_init(&mlxsw_pci->cmd.lock); |
---|
| 1775 | + init_waitqueue_head(&mlxsw_pci->cmd.wait); |
---|
| 1776 | + |
---|
| 1777 | + err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.in_mbox); |
---|
| 1778 | + if (err) |
---|
| 1779 | + goto err_in_mbox_alloc; |
---|
| 1780 | + |
---|
| 1781 | + err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.out_mbox); |
---|
| 1782 | + if (err) |
---|
| 1783 | + goto err_out_mbox_alloc; |
---|
| 1784 | + |
---|
| 1785 | + return 0; |
---|
| 1786 | + |
---|
| 1787 | +err_out_mbox_alloc: |
---|
| 1788 | + mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox); |
---|
| 1789 | +err_in_mbox_alloc: |
---|
| 1790 | + mutex_destroy(&mlxsw_pci->cmd.lock); |
---|
| 1791 | + return err; |
---|
| 1792 | +} |
---|
| 1793 | + |
---|
| 1794 | +static void mlxsw_pci_cmd_fini(struct mlxsw_pci *mlxsw_pci) |
---|
| 1795 | +{ |
---|
| 1796 | + mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox); |
---|
| 1797 | + mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox); |
---|
| 1798 | + mutex_destroy(&mlxsw_pci->cmd.lock); |
---|
| 1799 | +} |
---|
1720 | 1800 | |
---|
1721 | 1801 | static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
---|
1722 | 1802 | { |
---|
1723 | 1803 | const char *driver_name = pdev->driver->name; |
---|
1724 | 1804 | struct mlxsw_pci *mlxsw_pci; |
---|
1725 | | - bool called_again = false; |
---|
1726 | 1805 | int err; |
---|
1727 | 1806 | |
---|
1728 | 1807 | mlxsw_pci = kzalloc(sizeof(*mlxsw_pci), GFP_KERNEL); |
---|
.. | .. |
---|
1774 | 1853 | mlxsw_pci->pdev = pdev; |
---|
1775 | 1854 | pci_set_drvdata(pdev, mlxsw_pci); |
---|
1776 | 1855 | |
---|
| 1856 | + err = mlxsw_pci_cmd_init(mlxsw_pci); |
---|
| 1857 | + if (err) |
---|
| 1858 | + goto err_pci_cmd_init; |
---|
| 1859 | + |
---|
1777 | 1860 | mlxsw_pci->bus_info.device_kind = driver_name; |
---|
1778 | 1861 | mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev); |
---|
1779 | 1862 | mlxsw_pci->bus_info.dev = &pdev->dev; |
---|
| 1863 | + mlxsw_pci->bus_info.read_frc_capable = true; |
---|
1780 | 1864 | mlxsw_pci->id = id; |
---|
1781 | 1865 | |
---|
1782 | | -again: |
---|
1783 | 1866 | err = mlxsw_core_bus_device_register(&mlxsw_pci->bus_info, |
---|
1784 | 1867 | &mlxsw_pci_bus, mlxsw_pci, false, |
---|
1785 | | - NULL); |
---|
1786 | | - /* -EAGAIN is returned in case the FW was updated. FW needs |
---|
1787 | | - * a reset, so lets try to call mlxsw_core_bus_device_register() |
---|
1788 | | - * again. |
---|
1789 | | - */ |
---|
1790 | | - if (err == -EAGAIN && !called_again) { |
---|
1791 | | - called_again = true; |
---|
1792 | | - goto again; |
---|
1793 | | - } else if (err) { |
---|
| 1868 | + NULL, NULL); |
---|
| 1869 | + if (err) { |
---|
1794 | 1870 | dev_err(&pdev->dev, "cannot register bus device\n"); |
---|
1795 | 1871 | goto err_bus_device_register; |
---|
1796 | 1872 | } |
---|
.. | .. |
---|
1798 | 1874 | return 0; |
---|
1799 | 1875 | |
---|
1800 | 1876 | err_bus_device_register: |
---|
| 1877 | + mlxsw_pci_cmd_fini(mlxsw_pci); |
---|
| 1878 | +err_pci_cmd_init: |
---|
1801 | 1879 | iounmap(mlxsw_pci->hw_addr); |
---|
1802 | 1880 | err_ioremap: |
---|
1803 | 1881 | err_pci_resource_len_check: |
---|
.. | .. |
---|
1815 | 1893 | struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev); |
---|
1816 | 1894 | |
---|
1817 | 1895 | mlxsw_core_bus_device_unregister(mlxsw_pci->core, false); |
---|
| 1896 | + mlxsw_pci_cmd_fini(mlxsw_pci); |
---|
1818 | 1897 | iounmap(mlxsw_pci->hw_addr); |
---|
1819 | 1898 | pci_release_regions(mlxsw_pci->pdev); |
---|
1820 | 1899 | pci_disable_device(mlxsw_pci->pdev); |
---|