xref: /linux/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_devlink.c (revision 8e1bb4a41aa78d6105e59186af3dcd545fc66e70)
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