diff options
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_nl.c | 33 | ||||
-rw-r--r-- | include/linux/dcbnl.h | 27 | ||||
-rw-r--r-- | include/net/dcbnl.h | 2 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 132 |
4 files changed, 193 insertions, 1 deletions
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index eb3a6cea1aaa..5921795f8403 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
@@ -376,6 +376,35 @@ static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) | |||
376 | return rval; | 376 | return rval; |
377 | } | 377 | } |
378 | 378 | ||
379 | static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) | ||
380 | { | ||
381 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
382 | u8 rval = 0; | ||
383 | |||
384 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
385 | switch (tcid) { | ||
386 | case DCB_NUMTCS_ATTR_PG: | ||
387 | *num = MAX_TRAFFIC_CLASS; | ||
388 | break; | ||
389 | case DCB_NUMTCS_ATTR_PFC: | ||
390 | *num = MAX_TRAFFIC_CLASS; | ||
391 | break; | ||
392 | default: | ||
393 | rval = -EINVAL; | ||
394 | break; | ||
395 | } | ||
396 | } else { | ||
397 | rval = -EINVAL; | ||
398 | } | ||
399 | |||
400 | return rval; | ||
401 | } | ||
402 | |||
403 | static u8 ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num) | ||
404 | { | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | |||
379 | struct dcbnl_rtnl_ops dcbnl_ops = { | 408 | struct dcbnl_rtnl_ops dcbnl_ops = { |
380 | .getstate = ixgbe_dcbnl_get_state, | 409 | .getstate = ixgbe_dcbnl_get_state, |
381 | .setstate = ixgbe_dcbnl_set_state, | 410 | .setstate = ixgbe_dcbnl_set_state, |
@@ -391,6 +420,8 @@ struct dcbnl_rtnl_ops dcbnl_ops = { | |||
391 | .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, | 420 | .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, |
392 | .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, | 421 | .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, |
393 | .setall = ixgbe_dcbnl_set_all, | 422 | .setall = ixgbe_dcbnl_set_all, |
394 | .getcap = ixgbe_dcbnl_getcap | 423 | .getcap = ixgbe_dcbnl_getcap, |
424 | .getnumtcs = ixgbe_dcbnl_getnumtcs, | ||
425 | .setnumtcs = ixgbe_dcbnl_setnumtcs | ||
395 | }; | 426 | }; |
396 | 427 | ||
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 13f0c638a695..1077fba1dadc 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h | |||
@@ -44,6 +44,8 @@ struct dcbmsg { | |||
44 | * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying | 44 | * @DCB_CMD_GPERM_HWADDR: get the permanent MAC address of the underlying |
45 | * device. Only useful when using bonding. | 45 | * device. Only useful when using bonding. |
46 | * @DCB_CMD_GCAP: request the DCB capabilities of the device | 46 | * @DCB_CMD_GCAP: request the DCB capabilities of the device |
47 | * @DCB_CMD_GNUMTCS: get the number of traffic classes currently supported | ||
48 | * @DCB_CMD_SNUMTCS: set the number of traffic classes | ||
47 | */ | 49 | */ |
48 | enum dcbnl_commands { | 50 | enum dcbnl_commands { |
49 | DCB_CMD_UNDEFINED, | 51 | DCB_CMD_UNDEFINED, |
@@ -62,6 +64,8 @@ enum dcbnl_commands { | |||
62 | DCB_CMD_SET_ALL, | 64 | DCB_CMD_SET_ALL, |
63 | DCB_CMD_GPERM_HWADDR, | 65 | DCB_CMD_GPERM_HWADDR, |
64 | DCB_CMD_GCAP, | 66 | DCB_CMD_GCAP, |
67 | DCB_CMD_GNUMTCS, | ||
68 | DCB_CMD_SNUMTCS, | ||
65 | 69 | ||
66 | __DCB_CMD_ENUM_MAX, | 70 | __DCB_CMD_ENUM_MAX, |
67 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, | 71 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, |
@@ -81,6 +85,7 @@ enum dcbnl_commands { | |||
81 | * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) | 85 | * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) |
82 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) | 86 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) |
83 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) | 87 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) |
88 | * @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED) | ||
84 | */ | 89 | */ |
85 | enum dcbnl_attrs { | 90 | enum dcbnl_attrs { |
86 | DCB_ATTR_UNDEFINED, | 91 | DCB_ATTR_UNDEFINED, |
@@ -94,6 +99,7 @@ enum dcbnl_attrs { | |||
94 | DCB_ATTR_SET_ALL, | 99 | DCB_ATTR_SET_ALL, |
95 | DCB_ATTR_PERM_HWADDR, | 100 | DCB_ATTR_PERM_HWADDR, |
96 | DCB_ATTR_CAP, | 101 | DCB_ATTR_CAP, |
102 | DCB_ATTR_NUMTCS, | ||
97 | 103 | ||
98 | __DCB_ATTR_ENUM_MAX, | 104 | __DCB_ATTR_ENUM_MAX, |
99 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, | 105 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
@@ -253,6 +259,27 @@ enum dcbnl_cap_attrs { | |||
253 | __DCB_CAP_ATTR_ENUM_MAX, | 259 | __DCB_CAP_ATTR_ENUM_MAX, |
254 | DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1, | 260 | DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1, |
255 | }; | 261 | }; |
262 | |||
263 | /** | ||
264 | * enum dcbnl_numtcs_attrs - number of traffic classes | ||
265 | * | ||
266 | * @DCB_NUMTCS_ATTR_UNDEFINED: unspecified attribute to catch errors | ||
267 | * @DCB_NUMTCS_ATTR_ALL: (NLA_FLAG) all traffic class attributes | ||
268 | * @DCB_NUMTCS_ATTR_PG: (NLA_U8) number of traffic classes used for | ||
269 | * priority groups | ||
270 | * @DCB_NUMTCS_ATTR_PFC: (NLA_U8) number of traffic classes which can | ||
271 | * support priority flow control | ||
272 | */ | ||
273 | enum dcbnl_numtcs_attrs { | ||
274 | DCB_NUMTCS_ATTR_UNDEFINED, | ||
275 | DCB_NUMTCS_ATTR_ALL, | ||
276 | DCB_NUMTCS_ATTR_PG, | ||
277 | DCB_NUMTCS_ATTR_PFC, | ||
278 | |||
279 | __DCB_NUMTCS_ATTR_ENUM_MAX, | ||
280 | DCB_NUMTCS_ATTR_MAX = __DCB_NUMTCS_ATTR_ENUM_MAX - 1, | ||
281 | }; | ||
282 | |||
256 | /** | 283 | /** |
257 | * enum dcb_general_attr_values - general DCB attribute values | 284 | * enum dcb_general_attr_values - general DCB attribute values |
258 | * | 285 | * |
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index 183ed040cf4c..f0a65281ea73 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h | |||
@@ -40,6 +40,8 @@ struct dcbnl_rtnl_ops { | |||
40 | void (*getpfccfg)(struct net_device *, int, u8 *); | 40 | void (*getpfccfg)(struct net_device *, int, u8 *); |
41 | u8 (*setall)(struct net_device *); | 41 | u8 (*setall)(struct net_device *); |
42 | u8 (*getcap)(struct net_device *, int, u8 *); | 42 | u8 (*getcap)(struct net_device *, int, u8 *); |
43 | u8 (*getnumtcs)(struct net_device *, int, u8 *); | ||
44 | u8 (*setnumtcs)(struct net_device *, int, u8); | ||
43 | }; | 45 | }; |
44 | 46 | ||
45 | #endif /* __NET_DCBNL_H__ */ | 47 | #endif /* __NET_DCBNL_H__ */ |
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index de61d64d102d..5ff7e3c0c172 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -120,6 +120,13 @@ static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { | |||
120 | [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, | 120 | [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, |
121 | }; | 121 | }; |
122 | 122 | ||
123 | /* DCB capabilities nested attributes. */ | ||
124 | static struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { | ||
125 | [DCB_NUMTCS_ATTR_ALL] = {.type = NLA_FLAG}, | ||
126 | [DCB_NUMTCS_ATTR_PG] = {.type = NLA_U8}, | ||
127 | [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, | ||
128 | }; | ||
129 | |||
123 | /* standard netlink reply call */ | 130 | /* standard netlink reply call */ |
124 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, | 131 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, |
125 | u32 seq, u16 flags) | 132 | u32 seq, u16 flags) |
@@ -347,6 +354,123 @@ err_out: | |||
347 | return -EINVAL; | 354 | return -EINVAL; |
348 | } | 355 | } |
349 | 356 | ||
357 | static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb, | ||
358 | u32 pid, u32 seq, u16 flags) | ||
359 | { | ||
360 | struct sk_buff *dcbnl_skb; | ||
361 | struct nlmsghdr *nlh; | ||
362 | struct dcbmsg *dcb; | ||
363 | struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; | ||
364 | u8 value; | ||
365 | int ret = -EINVAL; | ||
366 | int i; | ||
367 | int getall = 0; | ||
368 | |||
369 | if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs) | ||
370 | return ret; | ||
371 | |||
372 | ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], | ||
373 | dcbnl_numtcs_nest); | ||
374 | if (ret) { | ||
375 | ret = -EINVAL; | ||
376 | goto err_out; | ||
377 | } | ||
378 | |||
379 | dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
380 | if (!dcbnl_skb) { | ||
381 | ret = -EINVAL; | ||
382 | goto err_out; | ||
383 | } | ||
384 | |||
385 | nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | ||
386 | |||
387 | dcb = NLMSG_DATA(nlh); | ||
388 | dcb->dcb_family = AF_UNSPEC; | ||
389 | dcb->cmd = DCB_CMD_GNUMTCS; | ||
390 | |||
391 | nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS); | ||
392 | if (!nest) { | ||
393 | ret = -EINVAL; | ||
394 | goto err; | ||
395 | } | ||
396 | |||
397 | if (data[DCB_NUMTCS_ATTR_ALL]) | ||
398 | getall = 1; | ||
399 | |||
400 | for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { | ||
401 | if (!getall && !data[i]) | ||
402 | continue; | ||
403 | |||
404 | ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); | ||
405 | if (!ret) { | ||
406 | ret = nla_put_u8(dcbnl_skb, i, value); | ||
407 | |||
408 | if (ret) { | ||
409 | nla_nest_cancel(dcbnl_skb, nest); | ||
410 | ret = -EINVAL; | ||
411 | goto err; | ||
412 | } | ||
413 | } else { | ||
414 | goto err; | ||
415 | } | ||
416 | } | ||
417 | nla_nest_end(dcbnl_skb, nest); | ||
418 | |||
419 | nlmsg_end(dcbnl_skb, nlh); | ||
420 | |||
421 | ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | ||
422 | if (ret) { | ||
423 | ret = -EINVAL; | ||
424 | goto err; | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | nlmsg_failure: | ||
429 | err: | ||
430 | kfree(dcbnl_skb); | ||
431 | err_out: | ||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb, | ||
436 | u32 pid, u32 seq, u16 flags) | ||
437 | { | ||
438 | struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; | ||
439 | int ret = -EINVAL; | ||
440 | u8 value; | ||
441 | int i; | ||
442 | |||
443 | if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setstate) | ||
444 | return ret; | ||
445 | |||
446 | ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], | ||
447 | dcbnl_numtcs_nest); | ||
448 | |||
449 | if (ret) { | ||
450 | ret = -EINVAL; | ||
451 | goto err; | ||
452 | } | ||
453 | |||
454 | for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { | ||
455 | if (data[i] == NULL) | ||
456 | continue; | ||
457 | |||
458 | value = nla_get_u8(data[i]); | ||
459 | |||
460 | ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); | ||
461 | |||
462 | if (ret) | ||
463 | goto operr; | ||
464 | } | ||
465 | |||
466 | operr: | ||
467 | ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS, | ||
468 | DCB_ATTR_NUMTCS, pid, seq, flags); | ||
469 | |||
470 | err: | ||
471 | return ret; | ||
472 | } | ||
473 | |||
350 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, | 474 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, |
351 | u32 pid, u32 seq, u16 flags, int dir) | 475 | u32 pid, u32 seq, u16 flags, int dir) |
352 | { | 476 | { |
@@ -757,6 +881,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
757 | ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, | 881 | ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, |
758 | nlh->nlmsg_flags); | 882 | nlh->nlmsg_flags); |
759 | goto out; | 883 | goto out; |
884 | case DCB_CMD_GNUMTCS: | ||
885 | ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq, | ||
886 | nlh->nlmsg_flags); | ||
887 | goto out; | ||
888 | case DCB_CMD_SNUMTCS: | ||
889 | ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq, | ||
890 | nlh->nlmsg_flags); | ||
891 | goto out; | ||
760 | default: | 892 | default: |
761 | goto errout; | 893 | goto errout; |
762 | } | 894 | } |