1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2021 Hisilicon Limited. */
3 
4 #include <net/devlink.h>
5 
6 #include "hclgevf_devlink.h"
7 
hclgevf_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)8 static int hclgevf_devlink_info_get(struct devlink *devlink,
9 				    struct devlink_info_req *req,
10 				    struct netlink_ext_ack *extack)
11 {
12 #define	HCLGEVF_DEVLINK_FW_STRING_LEN	32
13 	struct hclgevf_devlink_priv *priv = devlink_priv(devlink);
14 	char version_str[HCLGEVF_DEVLINK_FW_STRING_LEN];
15 	struct hclgevf_dev *hdev = priv->hdev;
16 	int ret;
17 
18 	ret = devlink_info_driver_name_put(req, KBUILD_MODNAME);
19 	if (ret)
20 		return ret;
21 
22 	snprintf(version_str, sizeof(version_str), "%lu.%lu.%lu.%lu",
23 		 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE3_MASK,
24 				 HNAE3_FW_VERSION_BYTE3_SHIFT),
25 		 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE2_MASK,
26 				 HNAE3_FW_VERSION_BYTE2_SHIFT),
27 		 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE1_MASK,
28 				 HNAE3_FW_VERSION_BYTE1_SHIFT),
29 		 hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE0_MASK,
30 				 HNAE3_FW_VERSION_BYTE0_SHIFT));
31 
32 	return devlink_info_version_running_put(req,
33 						DEVLINK_INFO_VERSION_GENERIC_FW,
34 						version_str);
35 }
36 
hclgevf_devlink_reload_down(struct devlink * devlink,bool netns_change,enum devlink_reload_action action,enum devlink_reload_limit limit,struct netlink_ext_ack * extack)37 static int hclgevf_devlink_reload_down(struct devlink *devlink,
38 				       bool netns_change,
39 				       enum devlink_reload_action action,
40 				       enum devlink_reload_limit limit,
41 				       struct netlink_ext_ack *extack)
42 {
43 	struct hclgevf_devlink_priv *priv = devlink_priv(devlink);
44 	struct hclgevf_dev *hdev = priv->hdev;
45 	struct hnae3_handle *h = &hdev->nic;
46 	struct pci_dev *pdev = hdev->pdev;
47 	int ret;
48 
49 	if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) {
50 		dev_err(&pdev->dev, "reset is handling\n");
51 		return -EBUSY;
52 	}
53 
54 	switch (action) {
55 	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
56 		rtnl_lock();
57 		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_DOWN_CLIENT);
58 		if (ret) {
59 			rtnl_unlock();
60 			return ret;
61 		}
62 
63 		ret = hdev->nic_client->ops->reset_notify(h,
64 							  HNAE3_UNINIT_CLIENT);
65 		rtnl_unlock();
66 		return ret;
67 	default:
68 		return -EOPNOTSUPP;
69 	}
70 }
71 
hclgevf_devlink_reload_up(struct devlink * devlink,enum devlink_reload_action action,enum devlink_reload_limit limit,u32 * actions_performed,struct netlink_ext_ack * extack)72 static int hclgevf_devlink_reload_up(struct devlink *devlink,
73 				     enum devlink_reload_action action,
74 				     enum devlink_reload_limit limit,
75 				     u32 *actions_performed,
76 				     struct netlink_ext_ack *extack)
77 {
78 	struct hclgevf_devlink_priv *priv = devlink_priv(devlink);
79 	struct hclgevf_dev *hdev = priv->hdev;
80 	struct hnae3_handle *h = &hdev->nic;
81 	int ret;
82 
83 	*actions_performed = BIT(action);
84 	switch (action) {
85 	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
86 		rtnl_lock();
87 		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_INIT_CLIENT);
88 		if (ret) {
89 			rtnl_unlock();
90 			return ret;
91 		}
92 
93 		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_UP_CLIENT);
94 		rtnl_unlock();
95 		return ret;
96 	default:
97 		return -EOPNOTSUPP;
98 	}
99 }
100 
101 static const struct devlink_ops hclgevf_devlink_ops = {
102 	.info_get = hclgevf_devlink_info_get,
103 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
104 	.reload_down = hclgevf_devlink_reload_down,
105 	.reload_up = hclgevf_devlink_reload_up,
106 };
107 
hclgevf_devlink_init(struct hclgevf_dev * hdev)108 int hclgevf_devlink_init(struct hclgevf_dev *hdev)
109 {
110 	struct pci_dev *pdev = hdev->pdev;
111 	struct hclgevf_devlink_priv *priv;
112 	struct devlink *devlink;
113 
114 	devlink =
115 		devlink_alloc(&hclgevf_devlink_ops,
116 			      sizeof(struct hclgevf_devlink_priv), &pdev->dev);
117 	if (!devlink)
118 		return -ENOMEM;
119 
120 	priv = devlink_priv(devlink);
121 	priv->hdev = hdev;
122 	hdev->devlink = devlink;
123 
124 	devlink_set_features(devlink, DEVLINK_F_RELOAD);
125 	devlink_register(devlink);
126 	return 0;
127 }
128 
hclgevf_devlink_uninit(struct hclgevf_dev * hdev)129 void hclgevf_devlink_uninit(struct hclgevf_dev *hdev)
130 {
131 	struct devlink *devlink = hdev->devlink;
132 
133 	devlink_unregister(devlink);
134 
135 	devlink_free(devlink);
136 }
137