projects/linux·blob assoc-array-fixes · refs

566 lines · 14.5 KiB

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 "bitset.h"
10#include "common.h"
11#include "module_fw.h"
12#include "netlink.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 (!ops->get_module_power_mode || !ops->set_module_power_mode) {
124 NL_SET_ERR_MSG_ATTR(info->extack,
125 tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY],
126 "Setting power mode policy is not supported by this device");
127 return -EOPNOTSUPP;
128 }
129
130 return 1;
131}
132
133static int
134ethnl_set_module(struct ethnl_req_info *req_info, struct genl_info *info)
135{
136 struct ethtool_module_power_mode_params power = {};
137 struct ethtool_module_power_mode_params power_new;
138 const struct ethtool_ops *ops;
139 struct net_device *dev = req_info->dev;
140 struct nlattr **tb = info->attrs;
141 int ret;
142
143 ops = dev->ethtool_ops;
144
145 if (dev->ethtool->module_fw_flash_in_progress) {
146 NL_SET_ERR_MSG(info->extack,
147 "Module firmware flashing is in progress");
148 return -EBUSY;
149 }
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 struct net_device *dev;
225
226 module_fw = container_of(work, struct ethtool_module_fw_flash, work);
227 dev = module_fw->fw_update.dev;
228
229 netdev_lock_ops(dev);
230 ethtool_cmis_fw_update(&module_fw->fw_update);
231 netdev_unlock_ops(dev);
232
233 module_flash_fw_work_list_del(&module_fw->list);
234
235 rtnl_lock();
236 netdev_lock_ops(dev);
237 dev->ethtool->module_fw_flash_in_progress = false;
238 netdev_unlock_ops(dev);
239 rtnl_unlock();
240
241 netdev_put(dev, &module_fw->dev_tracker);
242 release_firmware(module_fw->fw_update.fw);
243 kfree(module_fw);
244}
245
246#define MODULE_EEPROM_PHYS_ID_PAGE 0
247#define MODULE_EEPROM_PHYS_ID_I2C_ADDR 0x50
248
249static int module_flash_fw_work_init(struct ethtool_module_fw_flash *module_fw,
250 struct net_device *dev,
251 struct netlink_ext_ack *extack)
252{
253 const struct ethtool_ops *ops = dev->ethtool_ops;
254 struct ethtool_module_eeprom page_data = {};
255 u8 phys_id;
256 int err;
257
258 /* Fetch the SFF-8024 Identifier Value. For all supported standards, it
259 * is located at I2C address 0x50, byte 0. See section 4.1 in SFF-8024,
260 * revision 4.9.
261 */
262 page_data.page = MODULE_EEPROM_PHYS_ID_PAGE;
263 page_data.offset = SFP_PHYS_ID;
264 page_data.length = sizeof(phys_id);
265 page_data.i2c_address = MODULE_EEPROM_PHYS_ID_I2C_ADDR;
266 page_data.data = &phys_id;
267
268 err = ops->get_module_eeprom_by_page(dev, &page_data, extack);
269 if (err < 0)
270 return err;
271
272 switch (phys_id) {
273 case SFF8024_ID_QSFP_DD:
274 case SFF8024_ID_OSFP:
275 case SFF8024_ID_DSFP:
276 case SFF8024_ID_QSFP_PLUS_CMIS:
277 case SFF8024_ID_SFP_DD_CMIS:
278 case SFF8024_ID_SFP_PLUS_CMIS:
279 INIT_WORK(&module_fw->work, module_flash_fw_work);
280 break;
281 default:
282 NL_SET_ERR_MSG(extack,
283 "Module type does not support firmware flashing");
284 return -EOPNOTSUPP;
285 }
286
287 return 0;
288}
289
290void ethnl_module_fw_flash_sock_destroy(struct ethnl_sock_priv *sk_priv)
291{
292 struct ethtool_module_fw_flash *work;
293
294 spin_lock(&module_fw_flash_work_list_lock);
295 list_for_each_entry(work, &module_fw_flash_work_list, list) {
296 if (work->fw_update.ntf_params.portid == sk_priv->portid &&
297 dev_net(work->fw_update.dev) == sk_priv->net)
298 work->fw_update.ntf_params.closed_sock = true;
299 }
300 spin_unlock(&module_fw_flash_work_list_lock);
301}
302
303static int
304module_flash_fw_schedule(struct net_device *dev, const char *file_name,
305 struct ethtool_module_fw_flash_params *params,
306 struct sk_buff *skb, struct genl_info *info)
307{
308 struct ethtool_cmis_fw_update_params *fw_update;
309 struct ethtool_module_fw_flash *module_fw;
310 int err;
311
312 module_fw = kzalloc_obj(*module_fw);
313 if (!module_fw)
314 return -ENOMEM;
315
316 fw_update = &module_fw->fw_update;
317 fw_update->params = *params;
318 err = request_firmware_direct(&fw_update->fw,
319 file_name, &dev->dev);
320 if (err) {
321 NL_SET_ERR_MSG(info->extack,
322 "Failed to request module firmware image");
323 goto err_free;
324 }
325
326 err = module_flash_fw_work_init(module_fw, dev, info->extack);
327 if (err < 0)
328 goto err_release_firmware;
329
330 fw_update->dev = dev;
331 fw_update->ntf_params.portid = info->snd_portid;
332 fw_update->ntf_params.seq = info->snd_seq;
333 fw_update->ntf_params.closed_sock = false;
334
335 err = ethnl_sock_priv_set(skb, dev_net(dev),
336 fw_update->ntf_params.portid,
337 ETHTOOL_SOCK_TYPE_MODULE_FW_FLASH);
338 if (err < 0)
339 goto err_release_firmware;
340
341 err = module_flash_fw_work_list_add(module_fw, info);
342 if (err < 0)
343 goto err_release_firmware;
344
345 dev->ethtool->module_fw_flash_in_progress = true;
346 netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
347
348 schedule_work(&module_fw->work);
349
350 return 0;
351
352err_release_firmware:
353 release_firmware(fw_update->fw);
354err_free:
355 kfree(module_fw);
356 return err;
357}
358
359static int module_flash_fw(struct net_device *dev, struct nlattr **tb,
360 struct sk_buff *skb, struct genl_info *info)
361{
362 struct ethtool_module_fw_flash_params params = {};
363 const char *file_name;
364 struct nlattr *attr;
365
366 if (GENL_REQ_ATTR_CHECK(info, ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME))
367 return -EINVAL;
368
369 file_name = nla_data(tb[ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME]);
370
371 attr = tb[ETHTOOL_A_MODULE_FW_FLASH_PASSWORD];
372 if (attr) {
373 params.password = cpu_to_be32(nla_get_u32(attr));
374 params.password_valid = true;
375 }
376
377 return module_flash_fw_schedule(dev, file_name, &params, skb, info);
378}
379
380static int ethnl_module_fw_flash_validate(struct net_device *dev,
381 struct netlink_ext_ack *extack)
382{
383 struct devlink_port *devlink_port = dev->devlink_port;
384 const struct ethtool_ops *ops = dev->ethtool_ops;
385
386 if (!ops->set_module_eeprom_by_page ||
387 !ops->get_module_eeprom_by_page) {
388 NL_SET_ERR_MSG(extack,
389 "Flashing module firmware is not supported by this device");
390 return -EOPNOTSUPP;
391 }
392
393 if (!ops->reset) {
394 NL_SET_ERR_MSG(extack,
395 "Reset module is not supported by this device, so flashing is not permitted");
396 return -EOPNOTSUPP;
397 }
398
399 if (dev->ethtool->module_fw_flash_in_progress) {
400 NL_SET_ERR_MSG(extack, "Module firmware flashing already in progress");
401 return -EBUSY;
402 }
403
404 if (dev->flags & IFF_UP) {
405 NL_SET_ERR_MSG(extack, "Netdevice is up, so flashing is not permitted");
406 return -EBUSY;
407 }
408
409 if (devlink_port && devlink_port->attrs.split) {
410 NL_SET_ERR_MSG(extack, "Can't perform firmware flashing on a split port");
411 return -EOPNOTSUPP;
412 }
413
414 return 0;
415}
416
417int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info)
418{
419 struct ethnl_req_info req_info = {};
420 struct nlattr **tb = info->attrs;
421 struct net_device *dev;
422 int ret;
423
424 ret = ethnl_parse_header_dev_get(&req_info,
425 tb[ETHTOOL_A_MODULE_FW_FLASH_HEADER],
426 genl_info_net(info), info->extack,
427 true);
428 if (ret < 0)
429 return ret;
430 dev = req_info.dev;
431
432 netdev_lock_ops_compat(dev);
433 ret = ethnl_ops_begin(dev);
434 if (ret < 0)
435 goto out_unlock;
436
437 ret = ethnl_module_fw_flash_validate(dev, info->extack);
438 if (ret < 0)
439 goto out_complete;
440
441 ret = module_flash_fw(dev, tb, skb, info);
442
443out_complete:
444 ethnl_ops_complete(dev);
445
446out_unlock:
447 netdev_unlock_ops_compat(dev);
448 ethnl_parse_header_dev_put(&req_info);
449 return ret;
450}
451
452/* MODULE_FW_FLASH_NTF */
453
454static int
455ethnl_module_fw_flash_ntf_put_err(struct sk_buff *skb, char *err_msg,
456 char *sub_err_msg)
457{
458 int err_msg_len, sub_err_msg_len, total_len;
459 struct nlattr *attr;
460
461 if (!err_msg)
462 return 0;
463
464 err_msg_len = strlen(err_msg);
465 total_len = err_msg_len + 2; /* For period and NUL. */
466
467 if (sub_err_msg) {
468 sub_err_msg_len = strlen(sub_err_msg);
469 total_len += sub_err_msg_len + 2; /* For ", ". */
470 }
471
472 attr = nla_reserve(skb, ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG,
473 total_len);
474 if (!attr)
475 return -ENOMEM;
476
477 if (sub_err_msg)
478 sprintf(nla_data(attr), "%s, %s.", err_msg, sub_err_msg);
479 else
480 sprintf(nla_data(attr), "%s.", err_msg);
481
482 return 0;
483}
484
485static void
486ethnl_module_fw_flash_ntf(struct net_device *dev,
487 enum ethtool_module_fw_flash_status status,
488 struct ethnl_module_fw_flash_ntf_params *ntf_params,
489 char *err_msg, char *sub_err_msg,
490 u64 done, u64 total)
491{
492 struct sk_buff *skb;
493 void *hdr;
494 int ret;
495
496 if (ntf_params->closed_sock)
497 return;
498
499 skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
500 if (!skb)
501 return;
502
503 hdr = ethnl_unicast_put(skb, ntf_params->portid, ++ntf_params->seq,
504 ETHTOOL_MSG_MODULE_FW_FLASH_NTF);
505 if (!hdr)
506 goto err_skb;
507
508 ret = ethnl_fill_reply_header(skb, dev,
509 ETHTOOL_A_MODULE_FW_FLASH_HEADER);
510 if (ret < 0)
511 goto err_skb;
512
513 if (nla_put_u32(skb, ETHTOOL_A_MODULE_FW_FLASH_STATUS, status))
514 goto err_skb;
515
516 ret = ethnl_module_fw_flash_ntf_put_err(skb, err_msg, sub_err_msg);
517 if (ret < 0)
518 goto err_skb;
519
520 if (nla_put_uint(skb, ETHTOOL_A_MODULE_FW_FLASH_DONE, done))
521 goto err_skb;
522
523 if (nla_put_uint(skb, ETHTOOL_A_MODULE_FW_FLASH_TOTAL, total))
524 goto err_skb;
525
526 genlmsg_end(skb, hdr);
527 genlmsg_unicast(dev_net(dev), skb, ntf_params->portid);
528 return;
529
530err_skb:
531 nlmsg_free(skb);
532}
533
534void ethnl_module_fw_flash_ntf_err(struct net_device *dev,
535 struct ethnl_module_fw_flash_ntf_params *params,
536 char *err_msg, char *sub_err_msg)
537{
538 ethnl_module_fw_flash_ntf(dev, ETHTOOL_MODULE_FW_FLASH_STATUS_ERROR,
539 params, err_msg, sub_err_msg, 0, 0);
540}
541
542void
543ethnl_module_fw_flash_ntf_start(struct net_device *dev,
544 struct ethnl_module_fw_flash_ntf_params *params)
545{
546 ethnl_module_fw_flash_ntf(dev, ETHTOOL_MODULE_FW_FLASH_STATUS_STARTED,
547 params, NULL, NULL, 0, 0);
548}
549
550void
551ethnl_module_fw_flash_ntf_complete(struct net_device *dev,
552 struct ethnl_module_fw_flash_ntf_params *params)
553{
554 ethnl_module_fw_flash_ntf(dev, ETHTOOL_MODULE_FW_FLASH_STATUS_COMPLETED,
555 params, NULL, NULL, 0, 0);
556}
557
558void
559ethnl_module_fw_flash_ntf_in_progress(struct net_device *dev,
560 struct ethnl_module_fw_flash_ntf_params *params,
561 u64 done, u64 total)
562{
563 ethnl_module_fw_flash_ntf(dev,
564 ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS,
565 params, NULL, NULL, done, total);
566}