Lines Matching +full:use +full:- +full:ncsi

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright Samuel Mendoza-Jonas, IBM Corporation 2018.
12 #include <net/ncsi.h>
15 #include <uapi/linux/ncsi.h>
18 #include "ncsi-pkt.h"
19 #include "ncsi-netlink.h"
46 pr_err("NCSI netlink: No device for ifindex %u\n", ifindex); in ndp_from_ifindex()
66 nla_put_u32(skb, NCSI_CHANNEL_ATTR_ID, nc->id); in ncsi_write_channel_info()
67 m = &nc->modes[NCSI_MODE_LINK]; in ncsi_write_channel_info()
68 nla_put_u32(skb, NCSI_CHANNEL_ATTR_LINK_STATE, m->data[2]); in ncsi_write_channel_info()
69 if (nc->state == NCSI_CHANNEL_ACTIVE) in ncsi_write_channel_info()
71 if (nc == nc->package->preferred_channel) in ncsi_write_channel_info()
74 nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MAJOR, nc->version.major); in ncsi_write_channel_info()
75 nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MINOR, nc->version.minor); in ncsi_write_channel_info()
76 nla_put_string(skb, NCSI_CHANNEL_ATTR_VERSION_STR, nc->version.fw_name); in ncsi_write_channel_info()
80 return -ENOMEM; in ncsi_write_channel_info()
81 ncf = &nc->vlan_filter; in ncsi_write_channel_info()
82 i = -1; in ncsi_write_channel_info()
83 while ((i = find_next_bit((void *)&ncf->bitmap, ncf->n_vids, in ncsi_write_channel_info()
84 i + 1)) < ncf->n_vids) { in ncsi_write_channel_info()
85 if (ncf->vids[i]) in ncsi_write_channel_info()
87 ncf->vids[i]); in ncsi_write_channel_info()
103 if (id > ndp->package_num - 1) { in ncsi_write_package_info()
104 netdev_info(ndp->ndev.dev, "NCSI: No package with id %u\n", id); in ncsi_write_package_info()
105 return -ENODEV; in ncsi_write_package_info()
110 if (np->id != id) in ncsi_write_package_info()
114 return -ENOMEM; in ncsi_write_package_info()
115 rc = nla_put_u32(skb, NCSI_PKG_ATTR_ID, np->id); in ncsi_write_package_info()
120 if ((0x1 << np->id) == ndp->package_whitelist) in ncsi_write_package_info()
125 return -ENOMEM; in ncsi_write_package_info()
132 return -ENOMEM; in ncsi_write_package_info()
149 return -ENODEV; in ncsi_write_package_info()
163 if (!info || !info->attrs) in ncsi_pkg_info_nl()
164 return -EINVAL; in ncsi_pkg_info_nl()
166 if (!info->attrs[NCSI_ATTR_IFINDEX]) in ncsi_pkg_info_nl()
167 return -EINVAL; in ncsi_pkg_info_nl()
169 if (!info->attrs[NCSI_ATTR_PACKAGE_ID]) in ncsi_pkg_info_nl()
170 return -EINVAL; in ncsi_pkg_info_nl()
173 nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX])); in ncsi_pkg_info_nl()
175 return -ENODEV; in ncsi_pkg_info_nl()
179 return -ENOMEM; in ncsi_pkg_info_nl()
181 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, in ncsi_pkg_info_nl()
185 return -EMSGSIZE; in ncsi_pkg_info_nl()
188 package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]); in ncsi_pkg_info_nl()
193 return -EMSGSIZE; in ncsi_pkg_info_nl()
223 rc = genlmsg_parse_deprecated(cb->nlh, &ncsi_genl_family, attrs, NCSI_ATTR_MAX, in ncsi_pkg_info_all_nl()
229 return -EINVAL; in ncsi_pkg_info_all_nl()
231 ndp = ndp_from_ifindex(get_net(sock_net(skb->sk)), in ncsi_pkg_info_all_nl()
235 return -ENODEV; in ncsi_pkg_info_all_nl()
237 package_id = cb->args[0]; in ncsi_pkg_info_all_nl()
240 if (np->id == package_id) in ncsi_pkg_info_all_nl()
246 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, in ncsi_pkg_info_all_nl()
249 rc = -EMSGSIZE; in ncsi_pkg_info_all_nl()
255 rc = -EMSGSIZE; in ncsi_pkg_info_all_nl()
258 rc = ncsi_write_package_info(skb, ndp, package->id); in ncsi_pkg_info_all_nl()
267 cb->args[0] = package_id + 1; in ncsi_pkg_info_all_nl()
269 return skb->len; in ncsi_pkg_info_all_nl()
283 if (!info || !info->attrs) in ncsi_set_interface_nl()
284 return -EINVAL; in ncsi_set_interface_nl()
286 if (!info->attrs[NCSI_ATTR_IFINDEX]) in ncsi_set_interface_nl()
287 return -EINVAL; in ncsi_set_interface_nl()
289 if (!info->attrs[NCSI_ATTR_PACKAGE_ID]) in ncsi_set_interface_nl()
290 return -EINVAL; in ncsi_set_interface_nl()
292 ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)), in ncsi_set_interface_nl()
293 nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX])); in ncsi_set_interface_nl()
295 return -ENODEV; in ncsi_set_interface_nl()
297 package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]); in ncsi_set_interface_nl()
301 if (np->id == package_id) in ncsi_set_interface_nl()
305 return -ERANGE; in ncsi_set_interface_nl()
309 if (info->attrs[NCSI_ATTR_CHANNEL_ID]) { in ncsi_set_interface_nl()
310 channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]); in ncsi_set_interface_nl()
312 if (nc->id == channel_id) { in ncsi_set_interface_nl()
317 netdev_info(ndp->ndev.dev, in ncsi_set_interface_nl()
318 "NCSI: Channel %u does not exist!\n", in ncsi_set_interface_nl()
320 return -ERANGE; in ncsi_set_interface_nl()
324 spin_lock_irqsave(&ndp->lock, flags); in ncsi_set_interface_nl()
325 ndp->package_whitelist = 0x1 << package->id; in ncsi_set_interface_nl()
326 ndp->multi_package = false; in ncsi_set_interface_nl()
327 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_set_interface_nl()
329 spin_lock_irqsave(&package->lock, flags); in ncsi_set_interface_nl()
330 package->multi_channel = false; in ncsi_set_interface_nl()
332 package->channel_whitelist = 0x1 << channel->id; in ncsi_set_interface_nl()
333 package->preferred_channel = channel; in ncsi_set_interface_nl()
336 package->channel_whitelist = UINT_MAX; in ncsi_set_interface_nl()
337 package->preferred_channel = NULL; in ncsi_set_interface_nl()
339 spin_unlock_irqrestore(&package->lock, flags); in ncsi_set_interface_nl()
342 netdev_info(ndp->ndev.dev, in ncsi_set_interface_nl()
346 netdev_info(ndp->ndev.dev, "Set package 0x%x as preferred\n", in ncsi_set_interface_nl()
350 if (!(ndp->flags & NCSI_DEV_RESET)) in ncsi_set_interface_nl()
351 ncsi_reset_dev(&ndp->ndev); in ncsi_set_interface_nl()
362 if (!info || !info->attrs) in ncsi_clear_interface_nl()
363 return -EINVAL; in ncsi_clear_interface_nl()
365 if (!info->attrs[NCSI_ATTR_IFINDEX]) in ncsi_clear_interface_nl()
366 return -EINVAL; in ncsi_clear_interface_nl()
368 ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)), in ncsi_clear_interface_nl()
369 nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX])); in ncsi_clear_interface_nl()
371 return -ENODEV; in ncsi_clear_interface_nl()
374 spin_lock_irqsave(&ndp->lock, flags); in ncsi_clear_interface_nl()
375 ndp->package_whitelist = UINT_MAX; in ncsi_clear_interface_nl()
376 ndp->multi_package = false; in ncsi_clear_interface_nl()
377 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_clear_interface_nl()
380 spin_lock_irqsave(&np->lock, flags); in ncsi_clear_interface_nl()
381 np->multi_channel = false; in ncsi_clear_interface_nl()
382 np->channel_whitelist = UINT_MAX; in ncsi_clear_interface_nl()
383 np->preferred_channel = NULL; in ncsi_clear_interface_nl()
384 spin_unlock_irqrestore(&np->lock, flags); in ncsi_clear_interface_nl()
386 netdev_info(ndp->ndev.dev, "NCSI: Cleared preferred package/channel\n"); in ncsi_clear_interface_nl()
389 if (!(ndp->flags & NCSI_DEV_RESET)) in ncsi_clear_interface_nl()
390 ncsi_reset_dev(&ndp->ndev); in ncsi_clear_interface_nl()
405 if (!info || !info->attrs) { in ncsi_send_cmd_nl()
406 ret = -EINVAL; in ncsi_send_cmd_nl()
410 if (!info->attrs[NCSI_ATTR_IFINDEX]) { in ncsi_send_cmd_nl()
411 ret = -EINVAL; in ncsi_send_cmd_nl()
415 if (!info->attrs[NCSI_ATTR_PACKAGE_ID]) { in ncsi_send_cmd_nl()
416 ret = -EINVAL; in ncsi_send_cmd_nl()
420 if (!info->attrs[NCSI_ATTR_CHANNEL_ID]) { in ncsi_send_cmd_nl()
421 ret = -EINVAL; in ncsi_send_cmd_nl()
425 if (!info->attrs[NCSI_ATTR_DATA]) { in ncsi_send_cmd_nl()
426 ret = -EINVAL; in ncsi_send_cmd_nl()
430 ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)), in ncsi_send_cmd_nl()
431 nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX])); in ncsi_send_cmd_nl()
433 ret = -ENODEV; in ncsi_send_cmd_nl()
437 package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]); in ncsi_send_cmd_nl()
438 channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]); in ncsi_send_cmd_nl()
441 ret = -ERANGE; in ncsi_send_cmd_nl()
445 len = nla_len(info->attrs[NCSI_ATTR_DATA]); in ncsi_send_cmd_nl()
447 netdev_info(ndp->ndev.dev, "NCSI: no command to send %u\n", in ncsi_send_cmd_nl()
449 ret = -EINVAL; in ncsi_send_cmd_nl()
452 data = (unsigned char *)nla_data(info->attrs[NCSI_ATTR_DATA]); in ncsi_send_cmd_nl()
460 nca.type = hdr->type; in ncsi_send_cmd_nl()
463 nca.payload = ntohs(hdr->length); in ncsi_send_cmd_nl()
469 netdev_err(ndp->ndev.dev, in ncsi_send_cmd_nl()
470 "NCSI: Error %d sending command\n", in ncsi_send_cmd_nl()
472 ncsi_send_netlink_err(ndp->ndev.dev, in ncsi_send_cmd_nl()
473 info->snd_seq, in ncsi_send_cmd_nl()
474 info->snd_portid, in ncsi_send_cmd_nl()
475 info->nlhdr, in ncsi_send_cmd_nl()
491 net = dev_net(nr->rsp->dev); in ncsi_send_netlink_rsp()
495 return -ENOMEM; in ncsi_send_netlink_rsp()
497 hdr = genlmsg_put(skb, nr->snd_portid, nr->snd_seq, in ncsi_send_netlink_rsp()
501 return -EMSGSIZE; in ncsi_send_netlink_rsp()
504 nla_put_u32(skb, NCSI_ATTR_IFINDEX, nr->rsp->dev->ifindex); in ncsi_send_netlink_rsp()
506 nla_put_u32(skb, NCSI_ATTR_PACKAGE_ID, np->id); in ncsi_send_netlink_rsp()
508 nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, nc->id); in ncsi_send_netlink_rsp()
512 rc = nla_put(skb, NCSI_ATTR_DATA, nr->rsp->len, (void *)nr->rsp->data); in ncsi_send_netlink_rsp()
517 return genlmsg_unicast(net, skb, nr->snd_portid); in ncsi_send_netlink_rsp()
534 return -ENOMEM; in ncsi_send_netlink_timeout()
536 hdr = genlmsg_put(skb, nr->snd_portid, nr->snd_seq, in ncsi_send_netlink_timeout()
540 return -EMSGSIZE; in ncsi_send_netlink_timeout()
543 net = dev_net(nr->cmd->dev); in ncsi_send_netlink_timeout()
545 nla_put_u32(skb, NCSI_ATTR_IFINDEX, nr->cmd->dev->ifindex); in ncsi_send_netlink_timeout()
548 nla_put_u32(skb, NCSI_ATTR_PACKAGE_ID, np->id); in ncsi_send_netlink_timeout()
552 nr->cmd->data)->channel))); in ncsi_send_netlink_timeout()
555 nla_put_u32(skb, NCSI_ATTR_CHANNEL_ID, nc->id); in ncsi_send_netlink_timeout()
560 return genlmsg_unicast(net, skb, nr->snd_portid); in ncsi_send_netlink_timeout()
576 return -ENOMEM; in ncsi_send_netlink_err()
583 nle->error = err; in ncsi_send_netlink_err()
584 memcpy(&nle->msg, nlhdr, sizeof(*nlh)); in ncsi_send_netlink_err()
588 return nlmsg_unicast(net->genl_sock, skb, snd_portid); in ncsi_send_netlink_err()
598 if (!info || !info->attrs) in ncsi_set_package_mask_nl()
599 return -EINVAL; in ncsi_set_package_mask_nl()
601 if (!info->attrs[NCSI_ATTR_IFINDEX]) in ncsi_set_package_mask_nl()
602 return -EINVAL; in ncsi_set_package_mask_nl()
604 if (!info->attrs[NCSI_ATTR_PACKAGE_MASK]) in ncsi_set_package_mask_nl()
605 return -EINVAL; in ncsi_set_package_mask_nl()
607 ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)), in ncsi_set_package_mask_nl()
608 nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX])); in ncsi_set_package_mask_nl()
610 return -ENODEV; in ncsi_set_package_mask_nl()
612 spin_lock_irqsave(&ndp->lock, flags); in ncsi_set_package_mask_nl()
613 if (nla_get_flag(info->attrs[NCSI_ATTR_MULTI_FLAG])) { in ncsi_set_package_mask_nl()
614 if (ndp->flags & NCSI_DEV_HWA) { in ncsi_set_package_mask_nl()
615 ndp->multi_package = true; in ncsi_set_package_mask_nl()
618 netdev_err(ndp->ndev.dev, in ncsi_set_package_mask_nl()
619 "NCSI: Can't use multiple packages without HWA\n"); in ncsi_set_package_mask_nl()
620 rc = -EPERM; in ncsi_set_package_mask_nl()
623 ndp->multi_package = false; in ncsi_set_package_mask_nl()
628 ndp->package_whitelist = in ncsi_set_package_mask_nl()
629 nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_MASK]); in ncsi_set_package_mask_nl()
630 spin_unlock_irqrestore(&ndp->lock, flags); in ncsi_set_package_mask_nl()
634 if (!(ndp->flags & NCSI_DEV_RESET)) in ncsi_set_package_mask_nl()
635 ncsi_reset_dev(&ndp->ndev); in ncsi_set_package_mask_nl()
650 if (!info || !info->attrs) in ncsi_set_channel_mask_nl()
651 return -EINVAL; in ncsi_set_channel_mask_nl()
653 if (!info->attrs[NCSI_ATTR_IFINDEX]) in ncsi_set_channel_mask_nl()
654 return -EINVAL; in ncsi_set_channel_mask_nl()
656 if (!info->attrs[NCSI_ATTR_PACKAGE_ID]) in ncsi_set_channel_mask_nl()
657 return -EINVAL; in ncsi_set_channel_mask_nl()
659 if (!info->attrs[NCSI_ATTR_CHANNEL_MASK]) in ncsi_set_channel_mask_nl()
660 return -EINVAL; in ncsi_set_channel_mask_nl()
662 ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)), in ncsi_set_channel_mask_nl()
663 nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX])); in ncsi_set_channel_mask_nl()
665 return -ENODEV; in ncsi_set_channel_mask_nl()
667 package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]); in ncsi_set_channel_mask_nl()
670 if (np->id == package_id) { in ncsi_set_channel_mask_nl()
675 return -ERANGE; in ncsi_set_channel_mask_nl()
677 spin_lock_irqsave(&package->lock, flags); in ncsi_set_channel_mask_nl()
680 if (info->attrs[NCSI_ATTR_CHANNEL_ID]) { in ncsi_set_channel_mask_nl()
681 channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]); in ncsi_set_channel_mask_nl()
683 if (nc->id == channel_id) { in ncsi_set_channel_mask_nl()
688 spin_unlock_irqrestore(&package->lock, flags); in ncsi_set_channel_mask_nl()
689 return -ERANGE; in ncsi_set_channel_mask_nl()
691 netdev_dbg(ndp->ndev.dev, in ncsi_set_channel_mask_nl()
692 "NCSI: Channel %u set as preferred channel\n", in ncsi_set_channel_mask_nl()
693 channel->id); in ncsi_set_channel_mask_nl()
696 package->channel_whitelist = in ncsi_set_channel_mask_nl()
697 nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_MASK]); in ncsi_set_channel_mask_nl()
698 if (package->channel_whitelist == 0) in ncsi_set_channel_mask_nl()
699 netdev_dbg(ndp->ndev.dev, in ncsi_set_channel_mask_nl()
700 "NCSI: Package %u set to all channels disabled\n", in ncsi_set_channel_mask_nl()
701 package->id); in ncsi_set_channel_mask_nl()
703 package->preferred_channel = channel; in ncsi_set_channel_mask_nl()
705 if (nla_get_flag(info->attrs[NCSI_ATTR_MULTI_FLAG])) { in ncsi_set_channel_mask_nl()
706 package->multi_channel = true; in ncsi_set_channel_mask_nl()
707 netdev_info(ndp->ndev.dev, in ncsi_set_channel_mask_nl()
708 "NCSI: Multi-channel enabled on package %u\n", in ncsi_set_channel_mask_nl()
711 package->multi_channel = false; in ncsi_set_channel_mask_nl()
714 spin_unlock_irqrestore(&package->lock, flags); in ncsi_set_channel_mask_nl()
717 if (!(ndp->flags & NCSI_DEV_RESET)) in ncsi_set_channel_mask_nl()
718 ncsi_reset_dev(&ndp->ndev); in ncsi_set_channel_mask_nl()
764 .name = "NCSI",