aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2008-11-21 00:08:19 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-21 00:08:19 -0500
commit33dbabc4a7f7bd72313c73a3c199f31f3900336f (patch)
treef56e24fec9369ca1d1ef12eb18e4000a09fb5c3e
parent46132188bf72e22ef097f16ed5c969ee8cea1e8b (diff)
DCB: Add interface to query # of TCs supported by device
Adds interface for Data Center Bridging (DCB) to query (and set if supported) the number of traffic classes currently supported by the device for the two (DCB) features: priority groups (PG) and priority flow control (PFC). Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c33
-rw-r--r--include/linux/dcbnl.h27
-rw-r--r--include/net/dcbnl.h2
-rw-r--r--net/dcb/dcbnl.c132
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
379static 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
403static u8 ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)
404{
405 return -EINVAL;
406}
407
379struct dcbnl_rtnl_ops dcbnl_ops = { 408struct 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 */
48enum dcbnl_commands { 50enum 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 */
85enum dcbnl_attrs { 90enum 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 */
273enum 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. */
124static 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 */
124static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 131static 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
357static 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;
428nlmsg_failure:
429err:
430 kfree(dcbnl_skb);
431err_out:
432 return ret;
433}
434
435static 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
466operr:
467 ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS,
468 DCB_ATTR_NUMTCS, pid, seq, flags);
469
470err:
471 return ret;
472}
473
350static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, 474static 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 }