File Index
Files and directories
Sign in
FILE

module.c

File preview with syntax highlighting.

linux-6.19.14/net/ethtool/module.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2
  3#include <linux/ethtool.h>
  4#include <linux/firmware.h>
  5#include <linux/sfp.h>
  6#include <net/devlink.h>
  7#include <net/netdev_lock.h>
  8
  9#include "netlink.h"
 10#include "common.h"
 11#include "bitset.h"
 12#include "module_fw.h"
 13
 14struct module_req_info {
 15	struct ethnl_req_info base;
 16};
 17
 18struct module_reply_data {
 19	struct ethnl_reply_data	base;
 20	struct ethtool_module_power_mode_params power;
 21};
 22
 23#define MODULE_REPDATA(__reply_base) \
 24	container_of(__reply_base, struct module_reply_data, base)
 25
 26/* MODULE_GET */
 27
 28const struct nla_policy ethnl_module_get_policy[ETHTOOL_A_MODULE_HEADER + 1] = {
 29	[ETHTOOL_A_MODULE_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
 30};
 31
 32static int module_get_power_mode(struct net_device *dev,
 33				 struct module_reply_data *data,
 34				 struct netlink_ext_ack *extack)
 35{
 36	const struct ethtool_ops *ops = dev->ethtool_ops;
 37
 38	if (!ops->get_module_power_mode)
 39		return 0;
 40
 41	if (dev->ethtool->module_fw_flash_in_progress) {
 42		NL_SET_ERR_MSG(extack,
 43			       "Module firmware flashing is in progress");
 44		return -EBUSY;
 45	}
 46
 47	return ops->get_module_power_mode(dev, &data->power, extack);
 48}
 49
 50static int module_prepare_data(const struct ethnl_req_info *req_base,
 51			       struct ethnl_reply_data *reply_base,
 52			       const struct genl_info *info)
 53{
 54	struct module_reply_data *data = MODULE_REPDATA(reply_base);
 55	struct net_device *dev = reply_base->dev;
 56	int ret;
 57
 58	ret = ethnl_ops_begin(dev);
 59	if (ret < 0)
 60		return ret;
 61
 62	ret = module_get_power_mode(dev, data, info->extack);
 63	if (ret < 0)
 64		goto out_complete;
 65
 66out_complete:
 67	ethnl_ops_complete(dev);
 68	return ret;
 69}
 70
 71static int module_reply_size(const struct ethnl_req_info *req_base,
 72			     const struct ethnl_reply_data *reply_base)
 73{
 74	struct module_reply_data *data = MODULE_REPDATA(reply_base);
 75	int len = 0;
 76
 77	if (data->power.policy)
 78		len += nla_total_size(sizeof(u8));	/* _MODULE_POWER_MODE_POLICY */
 79
 80	if (data->power.mode)
 81		len += nla_total_size(sizeof(u8));	/* _MODULE_POWER_MODE */
 82
 83	return len;
 84}
 85
 86static int module_fill_reply(struct sk_buff *skb,
 87			     const struct ethnl_req_info *req_base,
 88			     const struct ethnl_reply_data *reply_base)
 89{
 90	const struct module_reply_data *data = MODULE_REPDATA(reply_base);
 91
 92	if (data->power.policy &&
 93	    nla_put_u8(skb, ETHTOOL_A_MODULE_POWER_MODE_POLICY,
 94		       data->power.policy))
 95		return -EMSGSIZE;
 96
 97	if (data->power.mode &&
 98	    nla_put_u8(skb, ETHTOOL_A_MODULE_POWER_MODE, data->power.mode))
 99		return -EMSGSIZE;
100
101	return 0;
102}
103
104/* MODULE_SET */
105
106const struct nla_policy ethnl_module_set_policy[ETHTOOL_A_MODULE_POWER_MODE_POLICY + 1] = {
107	[ETHTOOL_A_MODULE_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
108	[ETHTOOL_A_MODULE_POWER_MODE_POLICY] =
109		NLA_POLICY_RANGE(NLA_U8, ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH,
110				 ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO),
111};
112
113static int
114ethnl_set_module_validate(struct ethnl_req_info *req_info,
115			  struct genl_info *info)
116{
117	const struct ethtool_ops *ops = req_info->dev->ethtool_ops;
118	struct nlattr **tb = info->attrs;
119
120	if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY])
121		return 0;
122
123	if (req_info->dev->ethtool->module_fw_flash_in_progress) {
124		NL_SET_ERR_MSG(info->extack,
125			       "Module firmware flashing is in progress");
126		return -EBUSY;
127	}
128
129	if (!ops->get_module_power_mode || !ops->set_module_power_mode) {
130		NL_SET_ERR_MSG_ATTR(info->extack,
131				    tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY],
132				    "Setting power mode policy is not supported by this device");
133		return -EOPNOTSUPP;
134	}
135
136	return 1;
137}
138
139static int
140ethnl_set_module(struct ethnl_req_info *req_info, struct genl_info *info)
141{
142	struct ethtool_module_power_mode_params power = {};
143	struct ethtool_module_power_mode_params power_new;
144	const struct ethtool_ops *ops;
145	struct net_device *dev = req_info->dev;
146	struct nlattr **tb = info->attrs;
147	int ret;
148
149	ops = dev->ethtool_ops;
150
151	power_new.policy = nla_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]);
152	ret = ops->get_module_power_mode(dev, &power, info->extack);
153	if (ret < 0)
154		return ret;
155
156	if (power_new.policy == power.policy)
157		return 0;
158
159	ret = ops->set_module_power_mode(dev, &power_new, info->extack);
160	return ret < 0 ? ret : 1;
161}
162
163const struct ethnl_request_ops ethnl_module_request_ops = {
164	.request_cmd		= ETHTOOL_MSG_MODULE_GET,
165	.reply_cmd		= ETHTOOL_MSG_MODULE_GET_REPLY,
166	.hdr_attr		= ETHTOOL_A_MODULE_HEADER,
167	.req_info_size		= sizeof(struct module_req_info),
168	.reply_data_size	= sizeof(struct module_reply_data),
169
170	.prepare_data		= module_prepare_data,
171	.reply_size		= module_reply_size,
172	.fill_reply		= module_fill_reply,
173
174	.set_validate		= ethnl_set_module_validate,
175	.set			= ethnl_set_module,
176	.set_ntf_cmd		= ETHTOOL_MSG_MODULE_NTF,
177};
178
179/* MODULE_FW_FLASH_ACT */
180
181const struct nla_policy
182ethnl_module_fw_flash_act_policy[ETHTOOL_A_MODULE_FW_FLASH_PASSWORD + 1] = {
183	[ETHTOOL_A_MODULE_FW_FLASH_HEADER] =
184		NLA_POLICY_NESTED(ethnl_header_policy),
185	[ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME] = { .type = NLA_NUL_STRING },
186	[ETHTOOL_A_MODULE_FW_FLASH_PASSWORD] = { .type = NLA_U32 },
187};
188
189static LIST_HEAD(module_fw_flash_work_list);
190static DEFINE_SPINLOCK(module_fw_flash_work_list_lock);
191
192static int
193module_flash_fw_work_list_add(struct ethtool_module_fw_flash *module_fw,
194			      struct genl_info *info)
195{
196	struct ethtool_module_fw_flash *work;
197
198	/* First, check if already registered. */
199	spin_lock(&module_fw_flash_work_list_lock);
200	list_for_each_entry(work, &module_fw_flash_work_list, list) {
201		if (work->fw_update.ntf_params.portid == info->snd_portid &&
202		    work->fw_update.dev == module_fw->fw_update.dev) {
203			spin_unlock(&module_fw_flash_work_list_lock);
204			return -EALREADY;
205		}
206	}
207
208	list_add_tail(&module_fw->list, &module_fw_flash_work_list);
209	spin_unlock(&module_fw_flash_work_list_lock);
210
211	return 0;
212}
213
214static void module_flash_fw_work_list_del(struct list_head *list)
215{
216	spin_lock(&module_fw_flash_work_list_lock);
217	list_del(list);
218	spin_unlock(&module_fw_flash_work_list_lock);
219}
220
221static void module_flash_fw_work(struct work_struct *work)
222{
223	struct ethtool_module_fw_flash *module_fw;
224
225	module_fw = container_of(work, struct ethtool_module_fw_flash, work);
226
227	ethtool_cmis_fw_update(&module_fw->fw_update);
228
229	module_flash_fw_work_list_del(&module_fw->list);
230	module_fw->fw_update.dev->ethtool->module_fw_flash_in_progress = false;
231	netdev_put(module_fw->fw_update.dev, &module_fw->dev_tracker);
232	release_firmware(module_fw->fw_update.fw);
233	kfree(module_fw);
234}
235
236#define MODULE_EEPROM_PHYS_ID_PAGE	0
237#define MODULE_EEPROM_PHYS_ID_I2C_ADDR	0x50
238
239static int module_flash_fw_work_init(struct ethtool_module_fw_flash *module_fw,
240				     struct net_device *dev,
241				     struct netlink_ext_ack *extack)
242{
243	const struct ethtool_ops *ops = dev->ethtool_ops;
244	struct ethtool_module_eeprom page_data = {};
245	u8 phys_id;
246	int err;
247
248	/* Fetch the SFF-8024 Identifier Value. For all supported standards, it
249	 * is located at I2C address 0x50, byte 0. See section 4.1 in SFF-8024,
250	 * revision 4.9.
251	 */
252	page_data.page = MODULE_EEPROM_PHYS_ID_PAGE;
253	page_data.offset = SFP_PHYS_ID;
254	page_data.length = sizeof(phys_id);
255	page_data.i2c_address = MODULE_EEPROM_PHYS_ID_I2C_ADDR;
256	page_data.data = &phys_id;
257
258	err = ops->get_module_eeprom_by_page(dev, &page_data, extack);
259	if (err < 0)
260		return err;
261
262	switch (phys_id) {
263	case SFF8024_ID_QSFP_DD:
264	case SFF8024_ID_OSFP:
265	case SFF8024_ID_DSFP:
266	case SFF8024_ID_QSFP_PLUS_CMIS:
267	case SFF8024_ID_SFP_DD_CMIS:
268	case SFF8024_ID_SFP_PLUS_CMIS:
269		INIT_WORK(&module_fw->work, module_flash_fw_work);
270		break;
271	default:
272		NL_SET_ERR_MSG(extack,
273			       "Module type does not support firmware flashing");
274		return -EOPNOTSUPP;
275	}
276
277	return 0;
278}
279
280void ethnl_module_fw_flash_sock_destroy(struct ethnl_sock_priv *sk_priv)
281{
282	struct ethtool_module_fw_flash *work;
283
284	spin_lock(&module_fw_flash_work_list_lock);
285	list_for_each_entry(work, &module_fw_flash_work_list, list) {
286		if (work->fw_update.dev == sk_priv->dev &&
287		    work->fw_update.ntf_params.portid == sk_priv->portid) {
288			work->fw_update.ntf_params.closed_sock = true;
289			break;
290		}
291	}
292	spin_unlock(&module_fw_flash_work_list_lock);
293}
294
295static int
296module_flash_fw_schedule(struct net_device *dev, const char *file_name,
297			 struct ethtool_module_fw_flash_params *params,
298			 struct sk_buff *skb, struct genl_info *info)
299{
300	struct ethtool_cmis_fw_update_params *fw_update;
301	struct ethtool_module_fw_flash *module_fw;
302	int err;
303
304	module_fw = kzalloc(sizeof(*module_fw), GFP_KERNEL);
305	if (!module_fw)
306		return -ENOMEM;
307
308	fw_update = &module_fw->fw_update;
309	fw_update->params = *params;
310	err = request_firmware_direct(&fw_update->fw,
311				      file_name, &dev->dev);
312	if (err) {
313		NL_SET_ERR_MSG(info->extack,
314			       "Failed to request module firmware image");
315		goto err_free;
316	}
317
318	err = module_flash_fw_work_init(module_fw, dev, info->extack);
319	if (err < 0)
320		goto err_release_firmware;
321
322	dev->ethtool->module_fw_flash_in_progress = true;
323	netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
324	fw_update->dev = dev;
325	fw_update->ntf_params.portid = info->snd_portid;
326	fw_update->ntf_params.seq = info->snd_seq;
327	fw_update->ntf_params.closed_sock = false;
328
329	err = ethnl_sock_priv_set(skb, dev, fw_update->ntf_params.portid,
330				  ETHTOOL_SOCK_TYPE_MODULE_FW_FLASH);
331	if (err < 0)
332		goto err_release_firmware;
333
334	err = module_flash_fw_work_list_add(module_fw, info);
335	if (err < 0)
336		goto err_release_firmware;
337
338	schedule_work(&module_fw->work);
339
340	return 0;
341
342err_release_firmware:
343	release_firmware(fw_update->fw);
344err_free:
345	kfree(module_fw);
346	return err;
347}
348
349static int module_flash_fw(struct net_device *dev, struct nlattr **tb,
350			   struct sk_buff *skb, struct genl_info *info)
351{
352	struct ethtool_module_fw_flash_params params = {};
353	const char *file_name;
354	struct nlattr *attr;
355
356	if (GENL_REQ_ATTR_CHECK(info, ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME))
357		return -EINVAL;
358
359	file_name = nla_data(tb[ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME]);
360
361	attr = tb[ETHTOOL_A_MODULE_FW_FLASH_PASSWORD];
362	if (attr) {
363		params.password = cpu_to_be32(nla_get_u32(attr));
364		params.password_valid = true;
365	}
366
367	return module_flash_fw_schedule(dev, file_name, &params, skb, info);
368}
369
370static int ethnl_module_fw_flash_validate(struct net_device *dev,
371					  struct netlink_ext_ack *extack)
372{
373	struct devlink_port *devlink_port = dev->devlink_port;
374	const struct ethtool_ops *ops = dev->ethtool_ops;
375
376	if (!ops->set_module_eeprom_by_page ||
377	    !ops->get_module_eeprom_by_page) {
378		NL_SET_ERR_MSG(extack,
379			       "Flashing module firmware is not supported by this device");
380		return -EOPNOTSUPP;
381	}
382
383	if (!ops->reset) {
384		NL_SET_ERR_MSG(extack,
385			       "Reset module is not supported by this device, so flashing is not permitted");
386		return -EOPNOTSUPP;
387	}
388
389	if (dev->ethtool->module_fw_flash_in_progress) {
390		NL_SET_ERR_MSG(extack, "Module firmware flashing already in progress");
391		return -EBUSY;
392	}
393
394	if (dev->flags & IFF_UP) {
395		NL_SET_ERR_MSG(extack, "Netdevice is up, so flashing is not permitted");
396		return -EBUSY;
397	}
398
399	if (devlink_port && devlink_port->attrs.split) {
400		NL_SET_ERR_MSG(extack, "Can't perform firmware flashing on a split port");
401		return -EOPNOTSUPP;
402	}
403
404	return 0;
405}
406
407int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info)
408{
409	struct ethnl_req_info req_info = {};
410	struct nlattr **tb = info->attrs;
411	struct net_device *dev;
412	int ret;
413
414	ret = ethnl_parse_header_dev_get(&req_info,
415					 tb[ETHTOOL_A_MODULE_FW_FLASH_HEADER],
416					 genl_info_net(info), info->extack,
417					 true);
418	if (ret < 0)
419		return ret;
420	dev = req_info.dev;
421
422	rtnl_lock();
423	netdev_lock_ops(dev);
424	ret = ethnl_ops_begin(dev);
425	if (ret < 0)
426		goto out_unlock;
427
428	ret = ethnl_module_fw_flash_validate(dev, info->extack);
429	if (ret < 0)
430		goto out_unlock;
431
432	ret = module_flash_fw(dev, tb, skb, info);
433
434	ethnl_ops_complete(dev);
435
436out_unlock:
437	netdev_unlock_ops(dev);
438	rtnl_unlock();
439	ethnl_parse_header_dev_put(&req_info);
440	return ret;
441}
442
443/* MODULE_FW_FLASH_NTF */
444
445static int
446ethnl_module_fw_flash_ntf_put_err(struct sk_buff *skb, char *err_msg,
447				  char *sub_err_msg)
448{
449	int err_msg_len, sub_err_msg_len, total_len;
450	struct nlattr *attr;
451
452	if (!err_msg)
453		return 0;
454
455	err_msg_len = strlen(err_msg);
456	total_len = err_msg_len + 2; /* For period and NUL. */
457
458	if (sub_err_msg) {
459		sub_err_msg_len = strlen(sub_err_msg);
460		total_len += sub_err_msg_len + 2; /* For ", ". */
461	}
462
463	attr = nla_reserve(skb, ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG,
464			   total_len);
465	if (!attr)
466		return -ENOMEM;
467
468	if (sub_err_msg)
469		sprintf(nla_data(attr), "%s, %s.", err_msg, sub_err_msg);
470	else
471		sprintf(nla_data(attr), "%s.", err_msg);
472
473	return 0;
474}
475
476static void
477ethnl_module_fw_flash_ntf(struct net_device *dev,
478			  enum ethtool_module_fw_flash_status status,
479			  struct ethnl_module_fw_flash_ntf_params *ntf_params,
480			  char *err_msg, char *sub_err_msg,
481			  u64 done, u64 total)
482{
483	struct sk_buff *skb;
484	void *hdr;
485	int ret;
486
487	if (ntf_params->closed_sock)
488		return;
489
490	skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
491	if (!skb)
492		return;
493
494	hdr = ethnl_unicast_put(skb, ntf_params->portid, ++ntf_params->seq,
495				ETHTOOL_MSG_MODULE_FW_FLASH_NTF);
496	if (!hdr)
497		goto err_skb;
498
499	ret = ethnl_fill_reply_header(skb, dev,
500				      ETHTOOL_A_MODULE_FW_FLASH_HEADER);
501	if (ret < 0)
502		goto err_skb;
503
504	if (nla_put_u32(skb, ETHTOOL_A_MODULE_FW_FLASH_STATUS, status))
505		goto err_skb;
506
507	ret = ethnl_module_fw_flash_ntf_put_err(skb, err_msg, sub_err_msg);
508	if (ret < 0)
509		goto err_skb;
510
511	if (nla_put_uint(skb, ETHTOOL_A_MODULE_FW_FLASH_DONE, done))
512		goto err_skb;
513
514	if (nla_put_uint(skb, ETHTOOL_A_MODULE_FW_FLASH_TOTAL, total))
515		goto err_skb;
516
517	genlmsg_end(skb, hdr);
518	genlmsg_unicast(dev_net(dev), skb, ntf_params->portid);
519	return;
520
521err_skb:
522	nlmsg_free(skb);
523}
524
525void ethnl_module_fw_flash_ntf_err(struct net_device *dev,
526				   struct ethnl_module_fw_flash_ntf_params *params,
527				   char *err_msg, char *sub_err_msg)
528{
529	ethnl_module_fw_flash_ntf(dev, ETHTOOL_MODULE_FW_FLASH_STATUS_ERROR,
530				  params, err_msg, sub_err_msg, 0, 0);
531}
532
533void
534ethnl_module_fw_flash_ntf_start(struct net_device *dev,
535				struct ethnl_module_fw_flash_ntf_params *params)
536{
537	ethnl_module_fw_flash_ntf(dev, ETHTOOL_MODULE_FW_FLASH_STATUS_STARTED,
538				  params, NULL, NULL, 0, 0);
539}
540
541void
542ethnl_module_fw_flash_ntf_complete(struct net_device *dev,
543				   struct ethnl_module_fw_flash_ntf_params *params)
544{
545	ethnl_module_fw_flash_ntf(dev, ETHTOOL_MODULE_FW_FLASH_STATUS_COMPLETED,
546				  params, NULL, NULL, 0, 0);
547}
548
549void
550ethnl_module_fw_flash_ntf_in_progress(struct net_device *dev,
551				      struct ethnl_module_fw_flash_ntf_params *params,
552				      u64 done, u64 total)
553{
554	ethnl_module_fw_flash_ntf(dev,
555				  ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS,
556				  params, NULL, NULL, done, total);
557}
~/ Read-only file preview.