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