File Index
Files and directories
Sign in
FILE

ena_devlink.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/amazon/ena/ena_devlink.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2/* Copyright (c) Amazon.com, Inc. or its affiliates.
  3 * All rights reserved.
  4 */
  5
  6#include "linux/pci.h"
  7#include "ena_devlink.h"
  8#include "ena_phc.h"
  9
 10static int ena_devlink_enable_phc_validate(struct devlink *devlink, u32 id,
 11					   union devlink_param_value val,
 12					   struct netlink_ext_ack *extack)
 13{
 14	struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
 15
 16	if (!val.vbool)
 17		return 0;
 18
 19	if (!ena_com_phc_supported(adapter->ena_dev)) {
 20		NL_SET_ERR_MSG_MOD(extack, "Device doesn't support PHC");
 21		return -EOPNOTSUPP;
 22	}
 23
 24	return 0;
 25}
 26
 27static const struct devlink_param ena_devlink_params[] = {
 28	DEVLINK_PARAM_GENERIC(ENABLE_PHC,
 29			      BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
 30			      NULL,
 31			      NULL,
 32			      ena_devlink_enable_phc_validate),
 33};
 34
 35void ena_devlink_params_get(struct devlink *devlink)
 36{
 37	struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
 38	union devlink_param_value val;
 39	int err;
 40
 41	err = devl_param_driverinit_value_get(devlink,
 42					      DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
 43					      &val);
 44	if (err) {
 45		netdev_err(adapter->netdev, "Failed to query PHC param\n");
 46		return;
 47	}
 48
 49	ena_phc_enable(adapter, val.vbool);
 50}
 51
 52void ena_devlink_disable_phc_param(struct devlink *devlink)
 53{
 54	union devlink_param_value value;
 55
 56	devl_lock(devlink);
 57	value.vbool = false;
 58	devl_param_driverinit_value_set(devlink,
 59					DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
 60					value);
 61	devl_unlock(devlink);
 62}
 63
 64static void ena_devlink_port_register(struct devlink *devlink)
 65{
 66	struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
 67	struct devlink_port_attrs attrs = {};
 68
 69	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
 70	devlink_port_attrs_set(&adapter->devlink_port, &attrs);
 71	devl_port_register(devlink, &adapter->devlink_port, 0);
 72}
 73
 74static void ena_devlink_port_unregister(struct devlink *devlink)
 75{
 76	struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
 77
 78	devl_port_unregister(&adapter->devlink_port);
 79}
 80
 81static int ena_devlink_reload_down(struct devlink *devlink,
 82				   bool netns_change,
 83				   enum devlink_reload_action action,
 84				   enum devlink_reload_limit limit,
 85				   struct netlink_ext_ack *extack)
 86{
 87	struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
 88
 89	if (netns_change) {
 90		NL_SET_ERR_MSG_MOD(extack,
 91				   "Namespace change is not supported");
 92		return -EOPNOTSUPP;
 93	}
 94
 95	ena_devlink_port_unregister(devlink);
 96
 97	rtnl_lock();
 98	ena_destroy_device(adapter, false);
 99	rtnl_unlock();
100
101	return 0;
102}
103
104static int ena_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 ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
111	int err = 0;
112
113	rtnl_lock();
114	/* Check that no other routine initialized the device (e.g.
115	 * ena_fw_reset_device()). Also we're under devlink_mutex here,
116	 * so devlink isn't freed under our feet.
117	 */
118	if (!test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags))
119		err = ena_restore_device(adapter);
120
121	rtnl_unlock();
122
123	ena_devlink_port_register(devlink);
124
125	if (!err)
126		*actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
127
128	return err;
129}
130
131static const struct devlink_ops ena_devlink_ops = {
132	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
133	.reload_down	= ena_devlink_reload_down,
134	.reload_up	= ena_devlink_reload_up,
135};
136
137static int ena_devlink_configure_params(struct devlink *devlink)
138{
139	struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
140	union devlink_param_value value;
141	int rc;
142
143	rc = devlink_params_register(devlink, ena_devlink_params,
144				     ARRAY_SIZE(ena_devlink_params));
145	if (rc) {
146		netdev_err(adapter->netdev, "Failed to register devlink params\n");
147		return rc;
148	}
149
150	devl_lock(devlink);
151	value.vbool = ena_phc_is_enabled(adapter);
152	devl_param_driverinit_value_set(devlink,
153					DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
154					value);
155	devl_unlock(devlink);
156
157	return 0;
158}
159
160struct devlink *ena_devlink_alloc(struct ena_adapter *adapter)
161{
162	struct device *dev = &adapter->pdev->dev;
163	struct devlink *devlink;
164
165	devlink = devlink_alloc(&ena_devlink_ops,
166				sizeof(struct ena_adapter *),
167				dev);
168	if (!devlink) {
169		netdev_err(adapter->netdev,
170			   "Failed to allocate devlink struct\n");
171		return NULL;
172	}
173
174	ENA_DEVLINK_PRIV(devlink) = adapter;
175	adapter->devlink = devlink;
176
177	if (ena_devlink_configure_params(devlink))
178		goto free_devlink;
179
180	return devlink;
181
182free_devlink:
183	devlink_free(devlink);
184	return NULL;
185}
186
187static void ena_devlink_configure_params_clean(struct devlink *devlink)
188{
189	devlink_params_unregister(devlink, ena_devlink_params,
190				  ARRAY_SIZE(ena_devlink_params));
191}
192
193void ena_devlink_free(struct devlink *devlink)
194{
195	ena_devlink_configure_params_clean(devlink);
196
197	devlink_free(devlink);
198}
199
200void ena_devlink_register(struct devlink *devlink, struct device *dev)
201{
202	devl_lock(devlink);
203	ena_devlink_port_register(devlink);
204	devl_register(devlink);
205	devl_unlock(devlink);
206}
207
208void ena_devlink_unregister(struct devlink *devlink)
209{
210	devl_lock(devlink);
211	ena_devlink_port_unregister(devlink);
212	devl_unregister(devlink);
213	devl_unlock(devlink);
214}
~/ Read-only file preview.