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_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)8 static int hclge_devlink_info_get(struct devlink *devlink,
9 				  struct devlink_info_req *req,
10 				  struct netlink_ext_ack *extack)
11 {
12 #define	HCLGE_DEVLINK_FW_STRING_LEN	32
13 	struct hclge_devlink_priv *priv = devlink_priv(devlink);
14 	char version_str[HCLGE_DEVLINK_FW_STRING_LEN];
15 	struct hclge_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 
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)32 static int hclge_devlink_reload_down(struct devlink *devlink, bool netns_change,
33 				     enum devlink_reload_action action,
34 				     enum devlink_reload_limit limit,
35 				     struct netlink_ext_ack *extack)
36 {
37 	struct hclge_devlink_priv *priv = devlink_priv(devlink);
38 	struct hclge_dev *hdev = priv->hdev;
39 	struct hnae3_handle *h = &hdev->vport->nic;
40 	struct pci_dev *pdev = hdev->pdev;
41 	int ret;
42 
43 	if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) {
44 		dev_err(&pdev->dev, "reset is handling\n");
45 		return -EBUSY;
46 	}
47 
48 	switch (action) {
49 	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
50 		rtnl_lock();
51 		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_DOWN_CLIENT);
52 		if (ret) {
53 			rtnl_unlock();
54 			return ret;
55 		}
56 
57 		ret = hdev->nic_client->ops->reset_notify(h,
58 							  HNAE3_UNINIT_CLIENT);
59 		rtnl_unlock();
60 		return ret;
61 	default:
62 		return -EOPNOTSUPP;
63 	}
64 }
65 
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)66 static int hclge_devlink_reload_up(struct devlink *devlink,
67 				   enum devlink_reload_action action,
68 				   enum devlink_reload_limit limit,
69 				   u32 *actions_performed,
70 				   struct netlink_ext_ack *extack)
71 {
72 	struct hclge_devlink_priv *priv = devlink_priv(devlink);
73 	struct hclge_dev *hdev = priv->hdev;
74 	struct hnae3_handle *h = &hdev->vport->nic;
75 	int ret;
76 
77 	*actions_performed = BIT(action);
78 	switch (action) {
79 	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
80 		rtnl_lock();
81 		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_INIT_CLIENT);
82 		if (ret) {
83 			rtnl_unlock();
84 			return ret;
85 		}
86 
87 		ret = hdev->nic_client->ops->reset_notify(h, HNAE3_UP_CLIENT);
88 		rtnl_unlock();
89 		return ret;
90 	default:
91 		return -EOPNOTSUPP;
92 	}
93 }
94 
95 static const struct devlink_ops hclge_devlink_ops = {
96 	.info_get = hclge_devlink_info_get,
97 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
98 	.reload_down = hclge_devlink_reload_down,
99 	.reload_up = hclge_devlink_reload_up,
100 };
101 
hclge_devlink_init(struct hclge_dev * hdev)102 int hclge_devlink_init(struct hclge_dev *hdev)
103 {
104 	struct pci_dev *pdev = hdev->pdev;
105 	struct hclge_devlink_priv *priv;
106 	struct devlink *devlink;
107 
108 	devlink = devlink_alloc(&hclge_devlink_ops,
109 				sizeof(struct hclge_devlink_priv), &pdev->dev);
110 	if (!devlink)
111 		return -ENOMEM;
112 
113 	priv = devlink_priv(devlink);
114 	priv->hdev = hdev;
115 	hdev->devlink = devlink;
116 
117 	devlink_register(devlink);
118 	return 0;
119 }
120 
hclge_devlink_uninit(struct hclge_dev * hdev)121 void hclge_devlink_uninit(struct hclge_dev *hdev)
122 {
123 	struct devlink *devlink = hdev->devlink;
124 
125 	devlink_unregister(devlink);
126 
127 	devlink_free(devlink);
128 }
129