diff options
-rw-r--r-- | drivers/net/ixgbe/ixgbe_dcb_nl.c | 42 | ||||
-rw-r--r-- | include/linux/dcbnl.h | 37 | ||||
-rw-r--r-- | include/net/dcbnl.h | 1 | ||||
-rw-r--r-- | net/dcb/dcbnl.c | 82 |
4 files changed, 161 insertions, 1 deletions
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 50bff2af6b04..eb3a6cea1aaa 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c | |||
@@ -337,6 +337,45 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) | |||
337 | return ret; | 337 | return ret; |
338 | } | 338 | } |
339 | 339 | ||
340 | static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) | ||
341 | { | ||
342 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
343 | u8 rval = 0; | ||
344 | |||
345 | if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { | ||
346 | switch (capid) { | ||
347 | case DCB_CAP_ATTR_PG: | ||
348 | *cap = true; | ||
349 | break; | ||
350 | case DCB_CAP_ATTR_PFC: | ||
351 | *cap = true; | ||
352 | break; | ||
353 | case DCB_CAP_ATTR_UP2TC: | ||
354 | *cap = false; | ||
355 | break; | ||
356 | case DCB_CAP_ATTR_PG_TCS: | ||
357 | *cap = 0x80; | ||
358 | break; | ||
359 | case DCB_CAP_ATTR_PFC_TCS: | ||
360 | *cap = 0x80; | ||
361 | break; | ||
362 | case DCB_CAP_ATTR_GSP: | ||
363 | *cap = true; | ||
364 | break; | ||
365 | case DCB_CAP_ATTR_BCN: | ||
366 | *cap = false; | ||
367 | break; | ||
368 | default: | ||
369 | rval = -EINVAL; | ||
370 | break; | ||
371 | } | ||
372 | } else { | ||
373 | rval = -EINVAL; | ||
374 | } | ||
375 | |||
376 | return rval; | ||
377 | } | ||
378 | |||
340 | struct dcbnl_rtnl_ops dcbnl_ops = { | 379 | struct dcbnl_rtnl_ops dcbnl_ops = { |
341 | .getstate = ixgbe_dcbnl_get_state, | 380 | .getstate = ixgbe_dcbnl_get_state, |
342 | .setstate = ixgbe_dcbnl_set_state, | 381 | .setstate = ixgbe_dcbnl_set_state, |
@@ -351,6 +390,7 @@ struct dcbnl_rtnl_ops dcbnl_ops = { | |||
351 | .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx, | 390 | .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx, |
352 | .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, | 391 | .setpfccfg = ixgbe_dcbnl_set_pfc_cfg, |
353 | .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, | 392 | .getpfccfg = ixgbe_dcbnl_get_pfc_cfg, |
354 | .setall = ixgbe_dcbnl_set_all | 393 | .setall = ixgbe_dcbnl_set_all, |
394 | .getcap = ixgbe_dcbnl_getcap | ||
355 | }; | 395 | }; |
356 | 396 | ||
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h index 32d32c1ee410..13f0c638a695 100644 --- a/include/linux/dcbnl.h +++ b/include/linux/dcbnl.h | |||
@@ -43,6 +43,7 @@ struct dcbmsg { | |||
43 | * @DCB_CMD_SET_ALL: apply all changes to the underlying device | 43 | * @DCB_CMD_SET_ALL: apply all changes to the underlying device |
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 | */ | 47 | */ |
47 | enum dcbnl_commands { | 48 | enum dcbnl_commands { |
48 | DCB_CMD_UNDEFINED, | 49 | DCB_CMD_UNDEFINED, |
@@ -60,6 +61,7 @@ enum dcbnl_commands { | |||
60 | 61 | ||
61 | DCB_CMD_SET_ALL, | 62 | DCB_CMD_SET_ALL, |
62 | DCB_CMD_GPERM_HWADDR, | 63 | DCB_CMD_GPERM_HWADDR, |
64 | DCB_CMD_GCAP, | ||
63 | 65 | ||
64 | __DCB_CMD_ENUM_MAX, | 66 | __DCB_CMD_ENUM_MAX, |
65 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, | 67 | DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1, |
@@ -78,6 +80,7 @@ enum dcbnl_commands { | |||
78 | * @DCB_ATTR_PG_CFG: priority group configuration (NLA_NESTED) | 80 | * @DCB_ATTR_PG_CFG: priority group configuration (NLA_NESTED) |
79 | * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) | 81 | * @DCB_ATTR_SET_ALL: bool to commit changes to hardware or not (NLA_U8) |
80 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) | 82 | * @DCB_ATTR_PERM_HWADDR: MAC address of the physical device (NLA_NESTED) |
83 | * @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED) | ||
81 | */ | 84 | */ |
82 | enum dcbnl_attrs { | 85 | enum dcbnl_attrs { |
83 | DCB_ATTR_UNDEFINED, | 86 | DCB_ATTR_UNDEFINED, |
@@ -90,6 +93,7 @@ enum dcbnl_attrs { | |||
90 | DCB_ATTR_PG_CFG, | 93 | DCB_ATTR_PG_CFG, |
91 | DCB_ATTR_SET_ALL, | 94 | DCB_ATTR_SET_ALL, |
92 | DCB_ATTR_PERM_HWADDR, | 95 | DCB_ATTR_PERM_HWADDR, |
96 | DCB_ATTR_CAP, | ||
93 | 97 | ||
94 | __DCB_ATTR_ENUM_MAX, | 98 | __DCB_ATTR_ENUM_MAX, |
95 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, | 99 | DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1, |
@@ -217,6 +221,39 @@ enum dcbnl_tc_attrs { | |||
217 | }; | 221 | }; |
218 | 222 | ||
219 | /** | 223 | /** |
224 | * enum dcbnl_cap_attrs - DCB Capability attributes | ||
225 | * | ||
226 | * @DCB_CAP_ATTR_UNDEFINED: unspecified attribute to catch errors | ||
227 | * @DCB_CAP_ATTR_ALL: (NLA_FLAG) all capability parameters | ||
228 | * @DCB_CAP_ATTR_PG: (NLA_U8) device supports Priority Groups | ||
229 | * @DCB_CAP_ATTR_PFC: (NLA_U8) device supports Priority Flow Control | ||
230 | * @DCB_CAP_ATTR_UP2TC: (NLA_U8) device supports user priority to | ||
231 | * traffic class mapping | ||
232 | * @DCB_CAP_ATTR_PG_TCS: (NLA_U8) bitmap where each bit represents a | ||
233 | * number of traffic classes the device | ||
234 | * can be configured to use for Priority Groups | ||
235 | * @DCB_CAP_ATTR_PFC_TCS: (NLA_U8) bitmap where each bit represents a | ||
236 | * number of traffic classes the device can be | ||
237 | * configured to use for Priority Flow Control | ||
238 | * @DCB_CAP_ATTR_GSP: (NLA_U8) device supports group strict priority | ||
239 | * @DCB_CAP_ATTR_BCN: (NLA_U8) device supports Backwards Congestion | ||
240 | * Notification | ||
241 | */ | ||
242 | enum dcbnl_cap_attrs { | ||
243 | DCB_CAP_ATTR_UNDEFINED, | ||
244 | DCB_CAP_ATTR_ALL, | ||
245 | DCB_CAP_ATTR_PG, | ||
246 | DCB_CAP_ATTR_PFC, | ||
247 | DCB_CAP_ATTR_UP2TC, | ||
248 | DCB_CAP_ATTR_PG_TCS, | ||
249 | DCB_CAP_ATTR_PFC_TCS, | ||
250 | DCB_CAP_ATTR_GSP, | ||
251 | DCB_CAP_ATTR_BCN, | ||
252 | |||
253 | __DCB_CAP_ATTR_ENUM_MAX, | ||
254 | DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1, | ||
255 | }; | ||
256 | /** | ||
220 | * enum dcb_general_attr_values - general DCB attribute values | 257 | * enum dcb_general_attr_values - general DCB attribute values |
221 | * | 258 | * |
222 | * @DCB_ATTR_UNDEFINED: value used to indicate an attribute is not supported | 259 | * @DCB_ATTR_UNDEFINED: value used to indicate an attribute is not supported |
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index 0ef0c5a46d8b..183ed040cf4c 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h | |||
@@ -39,6 +39,7 @@ struct dcbnl_rtnl_ops { | |||
39 | void (*setpfccfg)(struct net_device *, int, u8); | 39 | void (*setpfccfg)(struct net_device *, int, u8); |
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 | }; | 43 | }; |
43 | 44 | ||
44 | #endif /* __NET_DCBNL_H__ */ | 45 | #endif /* __NET_DCBNL_H__ */ |
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 516e8be83d72..de61d64d102d 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -61,6 +61,7 @@ static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { | |||
61 | [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, | 61 | [DCB_ATTR_PG_CFG] = {.type = NLA_NESTED}, |
62 | [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, | 62 | [DCB_ATTR_SET_ALL] = {.type = NLA_U8}, |
63 | [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, | 63 | [DCB_ATTR_PERM_HWADDR] = {.type = NLA_FLAG}, |
64 | [DCB_ATTR_CAP] = {.type = NLA_NESTED}, | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | /* DCB priority flow control to User Priority nested attributes */ | 67 | /* DCB priority flow control to User Priority nested attributes */ |
@@ -107,6 +108,17 @@ static struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { | |||
107 | [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, | 108 | [DCB_TC_ATTR_PARAM_ALL] = {.type = NLA_FLAG}, |
108 | }; | 109 | }; |
109 | 110 | ||
111 | /* DCB capabilities nested attributes. */ | ||
112 | static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { | ||
113 | [DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG}, | ||
114 | [DCB_CAP_ATTR_PG] = {.type = NLA_U8}, | ||
115 | [DCB_CAP_ATTR_PFC] = {.type = NLA_U8}, | ||
116 | [DCB_CAP_ATTR_UP2TC] = {.type = NLA_U8}, | ||
117 | [DCB_CAP_ATTR_PG_TCS] = {.type = NLA_U8}, | ||
118 | [DCB_CAP_ATTR_PFC_TCS] = {.type = NLA_U8}, | ||
119 | [DCB_CAP_ATTR_GSP] = {.type = NLA_U8}, | ||
120 | [DCB_CAP_ATTR_BCN] = {.type = NLA_U8}, | ||
121 | }; | ||
110 | 122 | ||
111 | /* standard netlink reply call */ | 123 | /* standard netlink reply call */ |
112 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, | 124 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, |
@@ -269,6 +281,72 @@ err_out: | |||
269 | return -EINVAL; | 281 | return -EINVAL; |
270 | } | 282 | } |
271 | 283 | ||
284 | static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb, | ||
285 | u32 pid, u32 seq, u16 flags) | ||
286 | { | ||
287 | struct sk_buff *dcbnl_skb; | ||
288 | struct nlmsghdr *nlh; | ||
289 | struct dcbmsg *dcb; | ||
290 | struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest; | ||
291 | u8 value; | ||
292 | int ret = -EINVAL; | ||
293 | int i; | ||
294 | int getall = 0; | ||
295 | |||
296 | if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap) | ||
297 | return ret; | ||
298 | |||
299 | ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP], | ||
300 | dcbnl_cap_nest); | ||
301 | if (ret) | ||
302 | goto err_out; | ||
303 | |||
304 | dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
305 | if (!dcbnl_skb) | ||
306 | goto err_out; | ||
307 | |||
308 | nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | ||
309 | |||
310 | dcb = NLMSG_DATA(nlh); | ||
311 | dcb->dcb_family = AF_UNSPEC; | ||
312 | dcb->cmd = DCB_CMD_GCAP; | ||
313 | |||
314 | nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP); | ||
315 | if (!nest) | ||
316 | goto err; | ||
317 | |||
318 | if (data[DCB_CAP_ATTR_ALL]) | ||
319 | getall = 1; | ||
320 | |||
321 | for (i = DCB_CAP_ATTR_ALL+1; i <= DCB_CAP_ATTR_MAX; i++) { | ||
322 | if (!getall && !data[i]) | ||
323 | continue; | ||
324 | |||
325 | if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { | ||
326 | ret = nla_put_u8(dcbnl_skb, i, value); | ||
327 | |||
328 | if (ret) { | ||
329 | nla_nest_cancel(dcbnl_skb, nest); | ||
330 | goto err; | ||
331 | } | ||
332 | } | ||
333 | } | ||
334 | nla_nest_end(dcbnl_skb, nest); | ||
335 | |||
336 | nlmsg_end(dcbnl_skb, nlh); | ||
337 | |||
338 | ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | ||
339 | if (ret) | ||
340 | goto err; | ||
341 | |||
342 | return 0; | ||
343 | nlmsg_failure: | ||
344 | err: | ||
345 | kfree(dcbnl_skb); | ||
346 | err_out: | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | |||
272 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, | 350 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, |
273 | u32 pid, u32 seq, u16 flags, int dir) | 351 | u32 pid, u32 seq, u16 flags, int dir) |
274 | { | 352 | { |
@@ -675,6 +753,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
675 | ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, | 753 | ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, |
676 | nlh->nlmsg_flags); | 754 | nlh->nlmsg_flags); |
677 | goto out; | 755 | goto out; |
756 | case DCB_CMD_GCAP: | ||
757 | ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, | ||
758 | nlh->nlmsg_flags); | ||
759 | goto out; | ||
678 | default: | 760 | default: |
679 | goto errout; | 761 | goto errout; |
680 | } | 762 | } |