diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw/pci.c')
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/pci.c | 138 |
1 files changed, 96 insertions, 42 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index f91dde4df152..50527adc5b5a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -103,6 +103,8 @@ struct mlxsw_pci { struct pci_dev *pdev; u8 __iomem *hw_addr; u64 free_running_clock_offset; + u64 utc_sec_offset; + u64 utc_nsec_offset; struct mlxsw_pci_queue_type_group queues[MLXSW_PCI_QUEUE_TYPE_COUNT]; u32 doorbell_offset; struct mlxsw_core *core; @@ -456,9 +458,9 @@ static void mlxsw_pci_cq_pre_init(struct mlxsw_pci *mlxsw_pci, { q->u.cq.v = mlxsw_pci->max_cqe_ver; - /* For SDQ it is pointless to use CQEv2, so use CQEv1 instead */ if (q->u.cq.v == MLXSW_PCI_CQE_V2 && - q->num < mlxsw_pci->num_sdq_cqs) + q->num < mlxsw_pci->num_sdq_cqs && + !mlxsw_core_sdq_supports_cqe_v2(mlxsw_pci->core)) q->u.cq.v = MLXSW_PCI_CQE_V1; } @@ -505,9 +507,32 @@ static void mlxsw_pci_cq_fini(struct mlxsw_pci *mlxsw_pci, mlxsw_cmd_hw2sw_cq(mlxsw_pci->core, q->num); } +static unsigned int mlxsw_pci_read32_off(struct mlxsw_pci *mlxsw_pci, + ptrdiff_t off) +{ + return ioread32be(mlxsw_pci->hw_addr + off); +} + +static void mlxsw_pci_skb_cb_ts_set(struct mlxsw_pci *mlxsw_pci, + struct sk_buff *skb, + enum mlxsw_pci_cqe_v cqe_v, char *cqe) +{ + if (cqe_v != MLXSW_PCI_CQE_V2) + return; + + if (mlxsw_pci_cqe2_time_stamp_type_get(cqe) != + MLXSW_PCI_CQE_TIME_STAMP_TYPE_UTC) + return; + + mlxsw_skb_cb(skb)->cqe_ts.sec = mlxsw_pci_cqe2_time_stamp_sec_get(cqe); + mlxsw_skb_cb(skb)->cqe_ts.nsec = + mlxsw_pci_cqe2_time_stamp_nsec_get(cqe); +} + static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci, struct mlxsw_pci_queue *q, u16 consumer_counter_limit, + enum mlxsw_pci_cqe_v cqe_v, char *cqe) { struct pci_dev *pdev = mlxsw_pci->pdev; @@ -527,6 +552,7 @@ static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci, if (unlikely(!tx_info.is_emad && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + mlxsw_pci_skb_cb_ts_set(mlxsw_pci, skb, cqe_v, cqe); mlxsw_core_ptp_transmitted(mlxsw_pci->core, skb, tx_info.local_port); skb = NULL; @@ -647,6 +673,8 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci, mlxsw_pci_cqe_rdq_md_tx_port_init(skb, cqe); } + mlxsw_pci_skb_cb_ts_set(mlxsw_pci, skb, cqe_v, cqe); + byte_count = mlxsw_pci_cqe_byte_count_get(cqe); if (mlxsw_pci_cqe_crc_get(cqe_v, cqe)) byte_count -= ETH_FCS_LEN; @@ -698,7 +726,7 @@ static void mlxsw_pci_cq_tasklet(struct tasklet_struct *t) sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn); mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq, - wqe_counter, ncqe); + wqe_counter, q->u.cq.v, ncqe); q->u.cq.comp_sdq_count++; } else { struct mlxsw_pci_queue *rdq; @@ -1235,6 +1263,11 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_config_profile_adaptive_routing_group_cap_set( mbox, profile->adaptive_routing_group_cap); } + if (profile->used_ubridge) { + mlxsw_cmd_mbox_config_profile_set_ubridge_set(mbox, 1); + mlxsw_cmd_mbox_config_profile_ubridge_set(mbox, + profile->ubridge); + } if (profile->used_kvd_sizes && MLXSW_RES_VALID(res, KVD_SIZE)) { err = mlxsw_pci_profile_get_kvd_sizes(mlxsw_pci, profile, res); if (err) @@ -1252,12 +1285,6 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_config_profile_kvd_hash_double_size_set(mbox, MLXSW_RES_GET(res, KVD_DOUBLE_SIZE)); } - if (profile->used_kvh_xlt_cache_mode) { - mlxsw_cmd_mbox_config_profile_set_kvh_xlt_cache_mode_set( - mbox, 1); - mlxsw_cmd_mbox_config_profile_kvh_xlt_cache_mode_set( - mbox, profile->kvh_xlt_cache_mode); - } for (i = 0; i < MLXSW_CONFIG_PROFILE_SWID_COUNT; i++) mlxsw_pci_config_profile_swid_config(mlxsw_pci, mbox, i, @@ -1268,31 +1295,14 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_config_profile_cqe_version_set(mbox, 1); } - return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox); -} - -static int mlxsw_pci_boardinfo_xm_process(struct mlxsw_pci *mlxsw_pci, - struct mlxsw_bus_info *bus_info, - char *mbox) -{ - int count = mlxsw_cmd_mbox_boardinfo_xm_num_local_ports_get(mbox); - int i; - - if (!mlxsw_cmd_mbox_boardinfo_xm_exists_get(mbox)) - return 0; - - bus_info->xm_exists = true; - - if (count > MLXSW_BUS_INFO_XM_LOCAL_PORTS_MAX) { - dev_err(&mlxsw_pci->pdev->dev, "Invalid number of XM local ports\n"); - return -EINVAL; + if (profile->used_cqe_time_stamp_type) { + mlxsw_cmd_mbox_config_profile_set_cqe_time_stamp_type_set(mbox, + 1); + mlxsw_cmd_mbox_config_profile_cqe_time_stamp_type_set(mbox, + profile->cqe_time_stamp_type); } - bus_info->xm_local_ports_count = count; - for (i = 0; i < count; i++) - bus_info->xm_local_ports[i] = - mlxsw_cmd_mbox_boardinfo_xm_local_port_entry_get(mbox, - i); - return 0; + + return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox); } static int mlxsw_pci_boardinfo(struct mlxsw_pci *mlxsw_pci, char *mbox) @@ -1306,8 +1316,7 @@ static int mlxsw_pci_boardinfo(struct mlxsw_pci *mlxsw_pci, char *mbox) return err; mlxsw_cmd_mbox_boardinfo_vsd_memcpy_from(mbox, bus_info->vsd); mlxsw_cmd_mbox_boardinfo_psid_memcpy_from(mbox, bus_info->psid); - - return mlxsw_pci_boardinfo_xm_process(mlxsw_pci, bus_info, mbox); + return 0; } static int mlxsw_pci_fw_area_init(struct mlxsw_pci *mlxsw_pci, char *mbox, @@ -1550,6 +1559,24 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, mlxsw_pci->free_running_clock_offset = mlxsw_cmd_mbox_query_fw_free_running_clock_offset_get(mbox); + if (mlxsw_cmd_mbox_query_fw_utc_sec_bar_get(mbox) != 0) { + dev_err(&pdev->dev, "Unsupported UTC sec BAR queried from hw\n"); + err = -EINVAL; + goto err_utc_sec_bar; + } + + mlxsw_pci->utc_sec_offset = + mlxsw_cmd_mbox_query_fw_utc_sec_offset_get(mbox); + + if (mlxsw_cmd_mbox_query_fw_utc_nsec_bar_get(mbox) != 0) { + dev_err(&pdev->dev, "Unsupported UTC nsec BAR queried from hw\n"); + err = -EINVAL; + goto err_utc_nsec_bar; + } + + mlxsw_pci->utc_nsec_offset = + mlxsw_cmd_mbox_query_fw_utc_nsec_offset_get(mbox); + num_pages = mlxsw_cmd_mbox_query_fw_fw_pages_get(mbox); err = mlxsw_pci_fw_area_init(mlxsw_pci, mbox, num_pages); if (err) @@ -1582,6 +1609,14 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, if (err) goto err_config_profile; + /* Some resources depend on unified bridge model, which is configured + * as part of config_profile. Query the resources again to get correct + * values. + */ + err = mlxsw_core_resources_query(mlxsw_core, mbox, res); + if (err) + goto err_requery_resources; + err = mlxsw_pci_aqs_init(mlxsw_pci, mbox); if (err) goto err_aqs_init; @@ -1599,12 +1634,15 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, err_request_eq_irq: mlxsw_pci_aqs_fini(mlxsw_pci); err_aqs_init: +err_requery_resources: err_config_profile: err_cqe_v_check: err_query_resources: err_boardinfo: mlxsw_pci_fw_area_fini(mlxsw_pci); err_fw_area_init: +err_utc_nsec_bar: +err_utc_sec_bar: err_fr_rn_clk_bar: err_doorbell_page_bar: err_iface_rev: @@ -1819,19 +1857,33 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod, static u32 mlxsw_pci_read_frc_h(void *bus_priv) { struct mlxsw_pci *mlxsw_pci = bus_priv; - u64 frc_offset; + u64 frc_offset_h; - frc_offset = mlxsw_pci->free_running_clock_offset; - return mlxsw_pci_read32(mlxsw_pci, FREE_RUNNING_CLOCK_H(frc_offset)); + frc_offset_h = mlxsw_pci->free_running_clock_offset; + return mlxsw_pci_read32_off(mlxsw_pci, frc_offset_h); } static u32 mlxsw_pci_read_frc_l(void *bus_priv) { struct mlxsw_pci *mlxsw_pci = bus_priv; - u64 frc_offset; + u64 frc_offset_l; + + frc_offset_l = mlxsw_pci->free_running_clock_offset + 4; + return mlxsw_pci_read32_off(mlxsw_pci, frc_offset_l); +} + +static u32 mlxsw_pci_read_utc_sec(void *bus_priv) +{ + struct mlxsw_pci *mlxsw_pci = bus_priv; + + return mlxsw_pci_read32_off(mlxsw_pci, mlxsw_pci->utc_sec_offset); +} + +static u32 mlxsw_pci_read_utc_nsec(void *bus_priv) +{ + struct mlxsw_pci *mlxsw_pci = bus_priv; - frc_offset = mlxsw_pci->free_running_clock_offset; - return mlxsw_pci_read32(mlxsw_pci, FREE_RUNNING_CLOCK_L(frc_offset)); + return mlxsw_pci_read32_off(mlxsw_pci, mlxsw_pci->utc_nsec_offset); } static const struct mlxsw_bus mlxsw_pci_bus = { @@ -1843,6 +1895,8 @@ static const struct mlxsw_bus mlxsw_pci_bus = { .cmd_exec = mlxsw_pci_cmd_exec, .read_frc_h = mlxsw_pci_read_frc_h, .read_frc_l = mlxsw_pci_read_frc_l, + .read_utc_sec = mlxsw_pci_read_utc_sec, + .read_utc_nsec = mlxsw_pci_read_utc_nsec, .features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET, }; @@ -1933,7 +1987,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mlxsw_pci->bus_info.device_kind = driver_name; mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev); mlxsw_pci->bus_info.dev = &pdev->dev; - mlxsw_pci->bus_info.read_frc_capable = true; + mlxsw_pci->bus_info.read_clock_capable = true; mlxsw_pci->id = id; err = mlxsw_core_bus_device_register(&mlxsw_pci->bus_info, |