diff options
Diffstat (limited to 'drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c')
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 246 |
1 files changed, 163 insertions, 83 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index dd3354a57c62..e55ba2e511b1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -23,6 +23,7 @@ #include "hclge_tm.h" #include "hclge_err.h" #include "hnae3.h" +#include "hclge_devlink.h" #define HCLGE_NAME "hclge" #define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset))) @@ -91,23 +92,23 @@ static const struct pci_device_id ae_algo_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, ae_algo_pci_tbl); -static const u32 cmdq_reg_addr_list[] = {HCLGE_CMDQ_TX_ADDR_L_REG, - HCLGE_CMDQ_TX_ADDR_H_REG, - HCLGE_CMDQ_TX_DEPTH_REG, - HCLGE_CMDQ_TX_TAIL_REG, - HCLGE_CMDQ_TX_HEAD_REG, - HCLGE_CMDQ_RX_ADDR_L_REG, - HCLGE_CMDQ_RX_ADDR_H_REG, - HCLGE_CMDQ_RX_DEPTH_REG, - HCLGE_CMDQ_RX_TAIL_REG, - HCLGE_CMDQ_RX_HEAD_REG, +static const u32 cmdq_reg_addr_list[] = {HCLGE_NIC_CSQ_BASEADDR_L_REG, + HCLGE_NIC_CSQ_BASEADDR_H_REG, + HCLGE_NIC_CSQ_DEPTH_REG, + HCLGE_NIC_CSQ_TAIL_REG, + HCLGE_NIC_CSQ_HEAD_REG, + HCLGE_NIC_CRQ_BASEADDR_L_REG, + HCLGE_NIC_CRQ_BASEADDR_H_REG, + HCLGE_NIC_CRQ_DEPTH_REG, + HCLGE_NIC_CRQ_TAIL_REG, + HCLGE_NIC_CRQ_HEAD_REG, HCLGE_VECTOR0_CMDQ_SRC_REG, HCLGE_CMDQ_INTR_STS_REG, HCLGE_CMDQ_INTR_EN_REG, HCLGE_CMDQ_INTR_GEN_REG}; static const u32 common_reg_addr_list[] = {HCLGE_MISC_VECTOR_REG_BASE, - HCLGE_VECTOR0_OTER_EN_REG, + HCLGE_PF_OTHER_INT_REG, HCLGE_MISC_RESET_STS_REG, HCLGE_MISC_VECTOR_INT_STS, HCLGE_GLOBAL_RESET_REG, @@ -374,14 +375,14 @@ static const enum hclge_opcode_type hclge_dfx_reg_opcode_list[] = { }; static const struct key_info meta_data_key_info[] = { - { PACKET_TYPE_ID, 6}, - { IP_FRAGEMENT, 1}, - { ROCE_TYPE, 1}, - { NEXT_KEY, 5}, - { VLAN_NUMBER, 2}, - { SRC_VPORT, 12}, - { DST_VPORT, 12}, - { TUNNEL_PACKET, 1}, + { PACKET_TYPE_ID, 6 }, + { IP_FRAGEMENT, 1 }, + { ROCE_TYPE, 1 }, + { NEXT_KEY, 5 }, + { VLAN_NUMBER, 2 }, + { SRC_VPORT, 12 }, + { DST_VPORT, 12 }, + { TUNNEL_PACKET, 1 }, }; static const struct key_info tuple_key_info[] = { @@ -748,9 +749,9 @@ static void hclge_update_stats(struct hnae3_handle *handle, static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) { -#define HCLGE_LOOPBACK_TEST_FLAGS (HNAE3_SUPPORT_APP_LOOPBACK |\ - HNAE3_SUPPORT_PHY_LOOPBACK |\ - HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK |\ +#define HCLGE_LOOPBACK_TEST_FLAGS (HNAE3_SUPPORT_APP_LOOPBACK | \ + HNAE3_SUPPORT_PHY_LOOPBACK | \ + HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK | \ HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK) struct hclge_vport *vport = hclge_get_vport(handle); @@ -958,31 +959,31 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev) static int hclge_parse_speed(u8 speed_cmd, u32 *speed) { switch (speed_cmd) { - case 6: + case HCLGE_FW_MAC_SPEED_10M: *speed = HCLGE_MAC_SPEED_10M; break; - case 7: + case HCLGE_FW_MAC_SPEED_100M: *speed = HCLGE_MAC_SPEED_100M; break; - case 0: + case HCLGE_FW_MAC_SPEED_1G: *speed = HCLGE_MAC_SPEED_1G; break; - case 1: + case HCLGE_FW_MAC_SPEED_10G: *speed = HCLGE_MAC_SPEED_10G; break; - case 2: + case HCLGE_FW_MAC_SPEED_25G: *speed = HCLGE_MAC_SPEED_25G; break; - case 3: + case HCLGE_FW_MAC_SPEED_40G: *speed = HCLGE_MAC_SPEED_40G; break; - case 4: + case HCLGE_FW_MAC_SPEED_50G: *speed = HCLGE_MAC_SPEED_50G; break; - case 5: + case HCLGE_FW_MAC_SPEED_100G: *speed = HCLGE_MAC_SPEED_100G; break; - case 8: + case HCLGE_FW_MAC_SPEED_200G: *speed = HCLGE_MAC_SPEED_200G; break; default: @@ -992,44 +993,43 @@ static int hclge_parse_speed(u8 speed_cmd, u32 *speed) return 0; } +static const struct hclge_speed_bit_map speed_bit_map[] = { + {HCLGE_MAC_SPEED_10M, HCLGE_SUPPORT_10M_BIT}, + {HCLGE_MAC_SPEED_100M, HCLGE_SUPPORT_100M_BIT}, + {HCLGE_MAC_SPEED_1G, HCLGE_SUPPORT_1G_BIT}, + {HCLGE_MAC_SPEED_10G, HCLGE_SUPPORT_10G_BIT}, + {HCLGE_MAC_SPEED_25G, HCLGE_SUPPORT_25G_BIT}, + {HCLGE_MAC_SPEED_40G, HCLGE_SUPPORT_40G_BIT}, + {HCLGE_MAC_SPEED_50G, HCLGE_SUPPORT_50G_BIT}, + {HCLGE_MAC_SPEED_100G, HCLGE_SUPPORT_100G_BIT}, + {HCLGE_MAC_SPEED_200G, HCLGE_SUPPORT_200G_BIT}, +}; + +static int hclge_get_speed_bit(u32 speed, u32 *speed_bit) +{ + u16 i; + + for (i = 0; i < ARRAY_SIZE(speed_bit_map); i++) { + if (speed == speed_bit_map[i].speed) { + *speed_bit = speed_bit_map[i].speed_bit; + return 0; + } + } + + return -EINVAL; +} + static int hclge_check_port_speed(struct hnae3_handle *handle, u32 speed) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; u32 speed_ability = hdev->hw.mac.speed_ability; u32 speed_bit = 0; + int ret; - switch (speed) { - case HCLGE_MAC_SPEED_10M: - speed_bit = HCLGE_SUPPORT_10M_BIT; - break; - case HCLGE_MAC_SPEED_100M: - speed_bit = HCLGE_SUPPORT_100M_BIT; - break; - case HCLGE_MAC_SPEED_1G: - speed_bit = HCLGE_SUPPORT_1G_BIT; - break; - case HCLGE_MAC_SPEED_10G: - speed_bit = HCLGE_SUPPORT_10G_BIT; - break; - case HCLGE_MAC_SPEED_25G: - speed_bit = HCLGE_SUPPORT_25G_BIT; - break; - case HCLGE_MAC_SPEED_40G: - speed_bit = HCLGE_SUPPORT_40G_BIT; - break; - case HCLGE_MAC_SPEED_50G: - speed_bit = HCLGE_SUPPORT_50G_BIT; - break; - case HCLGE_MAC_SPEED_100G: - speed_bit = HCLGE_SUPPORT_100G_BIT; - break; - case HCLGE_MAC_SPEED_200G: - speed_bit = HCLGE_SUPPORT_200G_BIT; - break; - default: - return -EINVAL; - } + ret = hclge_get_speed_bit(speed, &speed_bit); + if (ret) + return ret; if (speed_bit & speed_ability) return 0; @@ -1550,6 +1550,7 @@ static int hclge_configure(struct hclge_dev *hdev) hdev->tm_info.hw_pfc_map = 0; hdev->wanted_umv_size = cfg.umv_space; hdev->tx_spare_buf_size = cfg.tx_spare_buf_size; + hdev->gro_en = true; if (cfg.vlan_fliter_cap == HCLGE_VLAN_FLTR_CAN_MDF) set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps); @@ -1618,7 +1619,7 @@ static int hclge_config_tso(struct hclge_dev *hdev, u16 tso_mss_min, return hclge_cmd_send(&hdev->hw, &desc, 1); } -static int hclge_config_gro(struct hclge_dev *hdev, bool en) +static int hclge_config_gro(struct hclge_dev *hdev) { struct hclge_cfg_gro_status_cmd *req; struct hclge_desc desc; @@ -1630,7 +1631,7 @@ static int hclge_config_gro(struct hclge_dev *hdev, bool en) hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_GRO_GENERIC_CONFIG, false); req = (struct hclge_cfg_gro_status_cmd *)desc.data; - req->gro_en = en ? 1 : 0; + req->gro_en = hdev->gro_en ? 1 : 0; ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) @@ -1813,6 +1814,7 @@ static int hclge_vport_setup(struct hclge_vport *vport, u16 num_tqps) nic->pdev = hdev->pdev; nic->ae_algo = &ae_algo; nic->numa_node_mask = hdev->numa_node_mask; + nic->kinfo.io_base = hdev->hw.io_base; ret = hclge_knic_setup(vport, num_tqps, hdev->num_tx_desc, hdev->num_rx_desc); @@ -2579,39 +2581,39 @@ static int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed, switch (speed) { case HCLGE_MAC_SPEED_10M: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 6); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_10M); break; case HCLGE_MAC_SPEED_100M: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 7); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_100M); break; case HCLGE_MAC_SPEED_1G: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 0); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_1G); break; case HCLGE_MAC_SPEED_10G: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 1); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_10G); break; case HCLGE_MAC_SPEED_25G: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 2); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_25G); break; case HCLGE_MAC_SPEED_40G: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 3); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_40G); break; case HCLGE_MAC_SPEED_50G: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 4); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_50G); break; case HCLGE_MAC_SPEED_100G: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 5); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_100G); break; case HCLGE_MAC_SPEED_200G: hnae3_set_field(req->speed_dup, HCLGE_CFG_SPEED_M, - HCLGE_CFG_SPEED_S, 8); + HCLGE_CFG_SPEED_S, HCLGE_FW_MAC_SPEED_200G); break; default: dev_err(&hdev->pdev->dev, "invalid speed (%d)\n", speed); @@ -2952,12 +2954,12 @@ static void hclge_update_link_status(struct hclge_dev *hdev) } if (state != hdev->hw.mac.link) { + hdev->hw.mac.link = state; client->ops->link_status_change(handle, state); hclge_config_mac_tnl_int(hdev, state); if (rclient && rclient->ops->link_status_change) rclient->ops->link_status_change(rhandle, state); - hdev->hw.mac.link = state; hclge_push_link_status(hdev); } @@ -3419,7 +3421,7 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data) hclge_enable_vector(&hdev->misc_vector, false); event_cause = hclge_check_event_cause(hdev, &clearval); - /* vector 0 interrupt is shared with reset and mailbox source events.*/ + /* vector 0 interrupt is shared with reset and mailbox source events. */ switch (event_cause) { case HCLGE_VECTOR0_EVENT_ERR: hclge_errhand_task_schedule(hdev); @@ -3788,6 +3790,12 @@ static void hclge_do_reset(struct hclge_dev *hdev) } switch (hdev->reset_type) { + case HNAE3_IMP_RESET: + dev_info(&pdev->dev, "IMP reset requested\n"); + val = hclge_read_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG); + hnae3_set_bit(val, HCLGE_TRIGGER_IMP_RESET_B, 1); + hclge_write_dev(&hdev->hw, HCLGE_PF_OTHER_INT_REG, val); + break; case HNAE3_GLOBAL_RESET: dev_info(&pdev->dev, "global reset requested\n"); val = hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG); @@ -5936,7 +5944,7 @@ static int hclge_config_key(struct hclge_dev *hdev, u8 stage, cur_key_x = key_x; cur_key_y = key_y; - for (i = 0 ; i < MAX_TUPLE; i++) { + for (i = 0; i < MAX_TUPLE; i++) { bool tuple_valid; tuple_size = tuple_key_info[i].key_length / 8; @@ -9552,13 +9560,17 @@ static int hclge_set_vport_vlan_filter(struct hclge_vport *vport, bool enable) if (ret) return ret; - if (test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, ae_dev->caps)) + if (test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, ae_dev->caps)) { ret = hclge_set_port_vlan_filter_bypass(hdev, vport->vport_id, !enable); - else if (!vport->vport_id) + } else if (!vport->vport_id) { + if (test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps)) + enable = false; + ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT, HCLGE_FILTER_FE_INGRESS, enable, 0); + } return ret; } @@ -10069,7 +10081,11 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev) static void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id, bool writen_to_tbl) { - struct hclge_vport_vlan_cfg *vlan; + struct hclge_vport_vlan_cfg *vlan, *tmp; + + list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) + if (vlan->vlan_id == vlan_id) + return; vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); if (!vlan) @@ -11439,6 +11455,28 @@ static void hclge_clear_resetting_state(struct hclge_dev *hdev) } } +static int hclge_clear_hw_resource(struct hclge_dev *hdev) +{ + struct hclge_desc desc; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CLEAR_HW_RESOURCE, false); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + /* This new command is only supported by new firmware, it will + * fail with older firmware. Error value -EOPNOSUPP can only be + * returned by older firmware running this command, to keep code + * backward compatible we will override this value and return + * success. + */ + if (ret && ret != -EOPNOTSUPP) { + dev_err(&hdev->pdev->dev, + "failed to clear hw resource, ret = %d\n", ret); + return ret; + } + return 0; +} + static void hclge_init_rxd_adv_layout(struct hclge_dev *hdev) { if (hnae3_ae_dev_rxd_adv_layout_supported(hdev->ae_dev)) @@ -11478,16 +11516,24 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) if (ret) goto out; + ret = hclge_devlink_init(hdev); + if (ret) + goto err_pci_uninit; + /* Firmware command queue initialize */ ret = hclge_cmd_queue_init(hdev); if (ret) - goto err_pci_uninit; + goto err_devlink_uninit; /* Firmware command initialize */ ret = hclge_cmd_init(hdev); if (ret) goto err_cmd_uninit; + ret = hclge_clear_hw_resource(hdev); + if (ret) + goto err_cmd_uninit; + ret = hclge_get_cap(hdev); if (ret) goto err_cmd_uninit; @@ -11552,7 +11598,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) goto err_mdiobus_unreg; } - ret = hclge_config_gro(hdev, true); + ret = hclge_config_gro(hdev); if (ret) goto err_mdiobus_unreg; @@ -11654,6 +11700,8 @@ err_msi_uninit: pci_free_irq_vectors(pdev); err_cmd_uninit: hclge_cmd_uninit(hdev); +err_devlink_uninit: + hclge_devlink_uninit(hdev); err_pci_uninit: pcim_iounmap(pdev, hdev->hw.io_base); pci_clear_master(pdev); @@ -11933,7 +11981,7 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) return ret; } - ret = hclge_config_gro(hdev, true); + ret = hclge_config_gro(hdev); if (ret) return ret; @@ -12044,6 +12092,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_cmd_uninit(hdev); hclge_misc_irq_uninit(hdev); + hclge_devlink_uninit(hdev); hclge_pci_uninit(hdev); mutex_destroy(&hdev->vport_lock); hclge_uninit_vport_vlan_table(hdev); @@ -12667,8 +12716,15 @@ static int hclge_gro_en(struct hnae3_handle *handle, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; + bool gro_en_old = hdev->gro_en; + int ret; + + hdev->gro_en = enable; + ret = hclge_config_gro(hdev); + if (ret) + hdev->gro_en = gro_en_old; - return hclge_config_gro(hdev, enable); + return ret; } static void hclge_sync_promisc_mode(struct hclge_dev *hdev) @@ -12825,6 +12881,29 @@ static int hclge_get_module_eeprom(struct hnae3_handle *handle, u32 offset, return 0; } +static int hclge_get_link_diagnosis_info(struct hnae3_handle *handle, + u32 *status_code) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; + struct hclge_desc desc; + int ret; + + if (hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) + return -EOPNOTSUPP; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_LINK_DIAGNOSIS, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to query link diagnosis info, ret = %d\n", ret); + return ret; + } + + *status_code = le32_to_cpu(desc.data[0]); + return 0; +} + static const struct hnae3_ae_ops hclge_ops = { .init_ae_dev = hclge_init_ae_dev, .uninit_ae_dev = hclge_uninit_ae_dev, @@ -12925,6 +13004,7 @@ static const struct hnae3_ae_ops hclge_ops = { .set_tx_hwts_info = hclge_ptp_set_tx_info, .get_rx_hwts = hclge_ptp_get_rx_hwts, .get_ts_info = hclge_ptp_get_ts_info, + .get_link_diagnosis_info = hclge_get_link_diagnosis_info, }; static struct hnae3_ae_algo ae_algo = { |