diff options
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 3 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 34 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 16 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 60 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 24 | ||||
-rw-r--r-- | include/linux/if_link.h | 7 |
6 files changed, 118 insertions, 26 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index ac48f86f2384..196eb52f0035 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -523,6 +523,9 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, | |||
523 | int __init ipoib_netlink_init(void); | 523 | int __init ipoib_netlink_init(void); |
524 | void __exit ipoib_netlink_fini(void); | 524 | void __exit ipoib_netlink_fini(void); |
525 | 525 | ||
526 | void ipoib_set_umcast(struct net_device *ndev, int umcast_val); | ||
527 | int ipoib_set_mode(struct net_device *dev, const char *buf); | ||
528 | |||
526 | void ipoib_setup(struct net_device *dev); | 529 | void ipoib_setup(struct net_device *dev); |
527 | 530 | ||
528 | void ipoib_pkey_poll(struct work_struct *work); | 531 | void ipoib_pkey_poll(struct work_struct *work); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 24683fda8e21..175581cf478c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -1448,15 +1448,10 @@ static ssize_t show_mode(struct device *d, struct device_attribute *attr, | |||
1448 | return sprintf(buf, "datagram\n"); | 1448 | return sprintf(buf, "datagram\n"); |
1449 | } | 1449 | } |
1450 | 1450 | ||
1451 | static ssize_t set_mode(struct device *d, struct device_attribute *attr, | 1451 | int ipoib_set_mode(struct net_device *dev, const char *buf) |
1452 | const char *buf, size_t count) | ||
1453 | { | 1452 | { |
1454 | struct net_device *dev = to_net_dev(d); | ||
1455 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 1453 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
1456 | 1454 | ||
1457 | if (!rtnl_trylock()) | ||
1458 | return restart_syscall(); | ||
1459 | |||
1460 | /* flush paths if we switch modes so that connections are restarted */ | 1455 | /* flush paths if we switch modes so that connections are restarted */ |
1461 | if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { | 1456 | if (IPOIB_CM_SUPPORTED(dev->dev_addr) && !strcmp(buf, "connected\n")) { |
1462 | set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); | 1457 | set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); |
@@ -1467,7 +1462,8 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1467 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; | 1462 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; |
1468 | 1463 | ||
1469 | ipoib_flush_paths(dev); | 1464 | ipoib_flush_paths(dev); |
1470 | return count; | 1465 | rtnl_lock(); |
1466 | return 0; | ||
1471 | } | 1467 | } |
1472 | 1468 | ||
1473 | if (!strcmp(buf, "datagram\n")) { | 1469 | if (!strcmp(buf, "datagram\n")) { |
@@ -1476,14 +1472,32 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr, | |||
1476 | dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); | 1472 | dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); |
1477 | rtnl_unlock(); | 1473 | rtnl_unlock(); |
1478 | ipoib_flush_paths(dev); | 1474 | ipoib_flush_paths(dev); |
1479 | 1475 | rtnl_lock(); | |
1480 | return count; | 1476 | return 0; |
1481 | } | 1477 | } |
1482 | rtnl_unlock(); | ||
1483 | 1478 | ||
1484 | return -EINVAL; | 1479 | return -EINVAL; |
1485 | } | 1480 | } |
1486 | 1481 | ||
1482 | static ssize_t set_mode(struct device *d, struct device_attribute *attr, | ||
1483 | const char *buf, size_t count) | ||
1484 | { | ||
1485 | struct net_device *dev = to_net_dev(d); | ||
1486 | int ret; | ||
1487 | |||
1488 | if (!rtnl_trylock()) | ||
1489 | return restart_syscall(); | ||
1490 | |||
1491 | ret = ipoib_set_mode(dev, buf); | ||
1492 | |||
1493 | rtnl_unlock(); | ||
1494 | |||
1495 | if (!ret) | ||
1496 | return count; | ||
1497 | |||
1498 | return ret; | ||
1499 | } | ||
1500 | |||
1487 | static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode); | 1501 | static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode); |
1488 | 1502 | ||
1489 | int ipoib_cm_add_mode_attr(struct net_device *dev) | 1503 | int ipoib_cm_add_mode_attr(struct net_device *dev) |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 128fab102054..3f9a9ba2f9ec 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -1381,12 +1381,9 @@ static ssize_t show_umcast(struct device *dev, | |||
1381 | return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags)); | 1381 | return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags)); |
1382 | } | 1382 | } |
1383 | 1383 | ||
1384 | static ssize_t set_umcast(struct device *dev, | 1384 | void ipoib_set_umcast(struct net_device *ndev, int umcast_val) |
1385 | struct device_attribute *attr, | ||
1386 | const char *buf, size_t count) | ||
1387 | { | 1385 | { |
1388 | struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev)); | 1386 | struct ipoib_dev_priv *priv = netdev_priv(ndev); |
1389 | unsigned long umcast_val = simple_strtoul(buf, NULL, 0); | ||
1390 | 1387 | ||
1391 | if (umcast_val > 0) { | 1388 | if (umcast_val > 0) { |
1392 | set_bit(IPOIB_FLAG_UMCAST, &priv->flags); | 1389 | set_bit(IPOIB_FLAG_UMCAST, &priv->flags); |
@@ -1394,6 +1391,15 @@ static ssize_t set_umcast(struct device *dev, | |||
1394 | "by userspace\n"); | 1391 | "by userspace\n"); |
1395 | } else | 1392 | } else |
1396 | clear_bit(IPOIB_FLAG_UMCAST, &priv->flags); | 1393 | clear_bit(IPOIB_FLAG_UMCAST, &priv->flags); |
1394 | } | ||
1395 | |||
1396 | static ssize_t set_umcast(struct device *dev, | ||
1397 | struct device_attribute *attr, | ||
1398 | const char *buf, size_t count) | ||
1399 | { | ||
1400 | unsigned long umcast_val = simple_strtoul(buf, NULL, 0); | ||
1401 | |||
1402 | ipoib_set_umcast(to_net_dev(dev), umcast_val); | ||
1397 | 1403 | ||
1398 | return count; | 1404 | return count; |
1399 | } | 1405 | } |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index a7dc5ea8370e..74685936c948 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c | |||
@@ -37,8 +37,60 @@ | |||
37 | 37 | ||
38 | static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = { | 38 | static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = { |
39 | [IFLA_IPOIB_PKEY] = { .type = NLA_U16 }, | 39 | [IFLA_IPOIB_PKEY] = { .type = NLA_U16 }, |
40 | [IFLA_IPOIB_MODE] = { .type = NLA_U16 }, | ||
41 | [IFLA_IPOIB_UMCAST] = { .type = NLA_U16 }, | ||
40 | }; | 42 | }; |
41 | 43 | ||
44 | static int ipoib_fill_info(struct sk_buff *skb, const struct net_device *dev) | ||
45 | { | ||
46 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
47 | u16 val; | ||
48 | |||
49 | if (nla_put_u16(skb, IFLA_IPOIB_PKEY, priv->pkey)) | ||
50 | goto nla_put_failure; | ||
51 | |||
52 | val = test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); | ||
53 | if (nla_put_u16(skb, IFLA_IPOIB_MODE, val)) | ||
54 | goto nla_put_failure; | ||
55 | |||
56 | val = test_bit(IPOIB_FLAG_UMCAST, &priv->flags); | ||
57 | if (nla_put_u16(skb, IFLA_IPOIB_UMCAST, val)) | ||
58 | goto nla_put_failure; | ||
59 | |||
60 | return 0; | ||
61 | |||
62 | nla_put_failure: | ||
63 | return -EMSGSIZE; | ||
64 | } | ||
65 | |||
66 | static int ipoib_changelink(struct net_device *dev, | ||
67 | struct nlattr *tb[], struct nlattr *data[]) | ||
68 | { | ||
69 | u16 mode, umcast; | ||
70 | int ret = 0; | ||
71 | |||
72 | if (data[IFLA_IPOIB_MODE]) { | ||
73 | mode = nla_get_u16(data[IFLA_IPOIB_MODE]); | ||
74 | if (mode == IPOIB_MODE_DATAGRAM) | ||
75 | ret = ipoib_set_mode(dev, "datagram\n"); | ||
76 | else if (mode == IPOIB_MODE_CONNECTED) | ||
77 | ret = ipoib_set_mode(dev, "connected\n"); | ||
78 | else | ||
79 | ret = -EINVAL; | ||
80 | |||
81 | if (ret < 0) | ||
82 | goto out_err; | ||
83 | } | ||
84 | |||
85 | if (data[IFLA_IPOIB_UMCAST]) { | ||
86 | umcast = nla_get_u16(data[IFLA_IPOIB_UMCAST]); | ||
87 | ipoib_set_umcast(dev, umcast); | ||
88 | } | ||
89 | |||
90 | out_err: | ||
91 | return ret; | ||
92 | } | ||
93 | |||
42 | static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, | 94 | static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, |
43 | struct nlattr *tb[], struct nlattr *data[]) | 95 | struct nlattr *tb[], struct nlattr *data[]) |
44 | { | 96 | { |
@@ -69,6 +121,8 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, | |||
69 | 121 | ||
70 | err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD); | 122 | err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD); |
71 | 123 | ||
124 | if (!err && data) | ||
125 | err = ipoib_changelink(dev, tb, data); | ||
72 | return err; | 126 | return err; |
73 | } | 127 | } |
74 | 128 | ||
@@ -87,7 +141,9 @@ static void ipoib_unregister_child_dev(struct net_device *dev, struct list_head | |||
87 | 141 | ||
88 | static size_t ipoib_get_size(const struct net_device *dev) | 142 | static size_t ipoib_get_size(const struct net_device *dev) |
89 | { | 143 | { |
90 | return nla_total_size(2); /* IFLA_IPOIB_PKEY */ | 144 | return nla_total_size(2) + /* IFLA_IPOIB_PKEY */ |
145 | nla_total_size(2) + /* IFLA_IPOIB_MODE */ | ||
146 | nla_total_size(2); /* IFLA_IPOIB_UMCAST */ | ||
91 | } | 147 | } |
92 | 148 | ||
93 | static struct rtnl_link_ops ipoib_link_ops __read_mostly = { | 149 | static struct rtnl_link_ops ipoib_link_ops __read_mostly = { |
@@ -97,8 +153,10 @@ static struct rtnl_link_ops ipoib_link_ops __read_mostly = { | |||
97 | .priv_size = sizeof(struct ipoib_dev_priv), | 153 | .priv_size = sizeof(struct ipoib_dev_priv), |
98 | .setup = ipoib_setup, | 154 | .setup = ipoib_setup, |
99 | .newlink = ipoib_new_child_link, | 155 | .newlink = ipoib_new_child_link, |
156 | .changelink = ipoib_changelink, | ||
100 | .dellink = ipoib_unregister_child_dev, | 157 | .dellink = ipoib_unregister_child_dev, |
101 | .get_size = ipoib_get_size, | 158 | .get_size = ipoib_get_size, |
159 | .fill_info = ipoib_fill_info, | ||
102 | }; | 160 | }; |
103 | 161 | ||
104 | int __init ipoib_netlink_init(void) | 162 | int __init ipoib_netlink_init(void) |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 238bbf9b2bea..8292554bccb5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c | |||
@@ -88,17 +88,21 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, | |||
88 | 88 | ||
89 | ipoib_create_debug_files(priv->dev); | 89 | ipoib_create_debug_files(priv->dev); |
90 | 90 | ||
91 | if (ipoib_cm_add_mode_attr(priv->dev)) | 91 | /* RTNL childs don't need proprietary sysfs entries */ |
92 | goto sysfs_failed; | 92 | if (type == IPOIB_LEGACY_CHILD) { |
93 | if (ipoib_add_pkey_attr(priv->dev)) | 93 | if (ipoib_cm_add_mode_attr(priv->dev)) |
94 | goto sysfs_failed; | 94 | goto sysfs_failed; |
95 | if (ipoib_add_umcast_attr(priv->dev)) | 95 | if (ipoib_add_pkey_attr(priv->dev)) |
96 | goto sysfs_failed; | 96 | goto sysfs_failed; |
97 | 97 | if (ipoib_add_umcast_attr(priv->dev)) | |
98 | if (device_create_file(&priv->dev->dev, &dev_attr_parent)) | 98 | goto sysfs_failed; |
99 | goto sysfs_failed; | 99 | |
100 | if (device_create_file(&priv->dev->dev, &dev_attr_parent)) | ||
101 | goto sysfs_failed; | ||
102 | } | ||
100 | 103 | ||
101 | priv->child_type = type; | 104 | priv->child_type = type; |
105 | priv->dev->iflink = ppriv->dev->ifindex; | ||
102 | list_add_tail(&priv->list, &ppriv->child_intfs); | 106 | list_add_tail(&priv->list, &ppriv->child_intfs); |
103 | 107 | ||
104 | return 0; | 108 | return 0; |
diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 24c0dd09af54..4491177e984d 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h | |||
@@ -404,9 +404,16 @@ struct ifla_port_vsi { | |||
404 | enum { | 404 | enum { |
405 | IFLA_IPOIB_UNSPEC, | 405 | IFLA_IPOIB_UNSPEC, |
406 | IFLA_IPOIB_PKEY, | 406 | IFLA_IPOIB_PKEY, |
407 | IFLA_IPOIB_MODE, | ||
408 | IFLA_IPOIB_UMCAST, | ||
407 | __IFLA_IPOIB_MAX | 409 | __IFLA_IPOIB_MAX |
408 | }; | 410 | }; |
409 | 411 | ||
412 | enum { | ||
413 | IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ | ||
414 | IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ | ||
415 | }; | ||
416 | |||
410 | #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) | 417 | #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) |
411 | 418 | ||
412 | #endif /* _LINUX_IF_LINK_H */ | 419 | #endif /* _LINUX_IF_LINK_H */ |