aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c42
-rw-r--r--include/linux/dcbnl.h37
-rw-r--r--include/net/dcbnl.h1
-rw-r--r--net/dcb/dcbnl.c82
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
340static 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
340struct dcbnl_rtnl_ops dcbnl_ops = { 379struct 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 */
47enum dcbnl_commands { 48enum 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 */
82enum dcbnl_attrs { 85enum 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 */
242enum 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. */
112static 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 */
112static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 124static 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
284static 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;
343nlmsg_failure:
344err:
345 kfree(dcbnl_skb);
346err_out:
347 return -EINVAL;
348}
349
272static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, 350static 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 }