1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Copyright (c) 2021 Hisilicon Limited. */ 3 4 #include <net/devlink.h> 5 6 #include "hclge_devlink.h" 7 8 static int hclge_devlink_scc_info_get(struct devlink *devlink, 9 struct devlink_info_req *req) 10 { 11 struct hclge_devlink_priv *priv = devlink_priv(devlink); 12 char scc_version[HCLGE_DEVLINK_FW_SCC_LEN]; 13 struct hclge_dev *hdev = priv->hdev; 14 u32 scc_version_tmp; 15 int ret; 16 17 ret = hclge_query_scc_version(hdev, &scc_version_tmp); 18 if (ret) { 19 dev_err(&hdev->pdev->dev, 20 "failed to get scc version, ret = %d\n", ret); 21 return ret; 22 } 23 24 snprintf(scc_version, sizeof(scc_version), "%lu.%lu.%lu.%lu", 25 hnae3_get_field(scc_version_tmp, HNAE3_SCC_VERSION_BYTE3_MASK, 26 HNAE3_FW_VERSION_BYTE3_SHIFT), 27 hnae3_get_field(scc_version_tmp, HNAE3_SCC_VERSION_BYTE2_MASK, 28 HNAE3_FW_VERSION_BYTE2_SHIFT), 29 hnae3_get_field(scc_version_tmp, HNAE3_SCC_VERSION_BYTE1_MASK, 30 HNAE3_FW_VERSION_BYTE1_SHIFT), 31 hnae3_get_field(scc_version_tmp, HNAE3_SCC_VERSION_BYTE0_MASK, 32 HNAE3_FW_VERSION_BYTE0_SHIFT)); 33 return devlink_info_version_running_put(req, "fw.scc", scc_version); 34 } 35 36 static int hclge_devlink_info_get(struct devlink *devlink, 37 struct devlink_info_req *req, 38 struct netlink_ext_ack *extack) 39 { 40 #define HCLGE_DEVLINK_FW_STRING_LEN 32 41 struct hclge_devlink_priv *priv = devlink_priv(devlink); 42 char version_str[HCLGE_DEVLINK_FW_STRING_LEN]; 43 struct hclge_dev *hdev = priv->hdev; 44 int ret; 45 46 snprintf(version_str, sizeof(version_str), "%lu.%lu.%lu.%lu", 47 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE3_MASK, 48 HNAE3_FW_VERSION_BYTE3_SHIFT), 49 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE2_MASK, 50 HNAE3_FW_VERSION_BYTE2_SHIFT), 51 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE1_MASK, 52 HNAE3_FW_VERSION_BYTE1_SHIFT), 53 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE0_MASK, 54 HNAE3_FW_VERSION_BYTE0_SHIFT)); 55 56 ret = devlink_info_version_running_put(req, 57 DEVLINK_INFO_VERSION_GENERIC_FW, 58 version_str); 59 if (ret) { 60 dev_err(&hdev->pdev->dev, "failed to set running version of fw\n"); 61 return ret; 62 } 63 64 if (hdev->pdev->revision > HNAE3_DEVICE_VERSION_V2) 65 ret = hclge_devlink_scc_info_get(devlink, req); 66 67 return ret; 68 } 69 70 static int hclge_devlink_reload_down(struct devlink *devlink, bool netns_change, 71 enum devlink_reload_action action, 72 enum devlink_reload_limit limit, 73 struct netlink_ext_ack *extack) 74 { 75 struct hclge_devlink_priv *priv = devlink_priv(devlink); 76 struct hclge_dev *hdev = priv->hdev; 77 struct hnae3_handle *h = &hdev->vport->nic; 78 struct pci_dev *pdev = hdev->pdev; 79 int ret; 80 81 if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) { 82 dev_err(&pdev->dev, "reset is handling\n"); 83 return -EBUSY; 84 } 85 86 switch (action) { 87 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 88 rtnl_lock(); 89 ret = hdev->nic_client->ops->reset_notify(h, HNAE3_DOWN_CLIENT); 90 if (ret) { 91 rtnl_unlock(); 92 return ret; 93 } 94 95 ret = hdev->nic_client->ops->reset_notify(h, 96 HNAE3_UNINIT_CLIENT); 97 rtnl_unlock(); 98 return ret; 99 default: 100 return -EOPNOTSUPP; 101 } 102 } 103 104 static int hclge_devlink_reload_up(struct devlink *devlink, 105 enum devlink_reload_action action, 106 enum devlink_reload_limit limit, 107 u32 *actions_performed, 108 struct netlink_ext_ack *extack) 109 { 110 struct hclge_devlink_priv *priv = devlink_priv(devlink); 111 struct hclge_dev *hdev = priv->hdev; 112 struct hnae3_handle *h = &hdev->vport->nic; 113 int ret; 114 115 *actions_performed = BIT(action); 116 switch (action) { 117 case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: 118 rtnl_lock(); 119 ret = hdev->nic_client->ops->reset_notify(h, HNAE3_INIT_CLIENT); 120 if (ret) { 121 rtnl_unlock(); 122 return ret; 123 } 124 125 ret = hdev->nic_client->ops->reset_notify(h, HNAE3_UP_CLIENT); 126 rtnl_unlock(); 127 return ret; 128 default: 129 return -EOPNOTSUPP; 130 } 131 } 132 133 static const struct devlink_ops hclge_devlink_ops = { 134 .info_get = hclge_devlink_info_get, 135 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT), 136 .reload_down = hclge_devlink_reload_down, 137 .reload_up = hclge_devlink_reload_up, 138 }; 139 140 int hclge_devlink_init(struct hclge_dev *hdev) 141 { 142 struct pci_dev *pdev = hdev->pdev; 143 struct hclge_devlink_priv *priv; 144 struct devlink *devlink; 145 146 devlink = devlink_alloc(&hclge_devlink_ops, 147 sizeof(struct hclge_devlink_priv), &pdev->dev); 148 if (!devlink) 149 return -ENOMEM; 150 151 priv = devlink_priv(devlink); 152 priv->hdev = hdev; 153 hdev->devlink = devlink; 154 155 devlink_register(devlink); 156 return 0; 157 } 158 159 void hclge_devlink_uninit(struct hclge_dev *hdev) 160 { 161 struct devlink *devlink = hdev->devlink; 162 163 devlink_unregister(devlink); 164 165 devlink_free(devlink); 166 } 167