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
hclge_devlink_scc_info_get(struct devlink * devlink,struct devlink_info_req * req)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
hclge_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)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
hclge_devlink_reload_down(struct devlink * devlink,bool netns_change,enum devlink_reload_action action,enum devlink_reload_limit limit,struct netlink_ext_ack * extack)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
hclge_devlink_reload_up(struct devlink * devlink,enum devlink_reload_action action,enum devlink_reload_limit limit,u32 * actions_performed,struct netlink_ext_ack * extack)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
hclge_devlink_init(struct hclge_dev * hdev)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
hclge_devlink_uninit(struct hclge_dev * hdev)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