aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c34
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c16
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_netlink.c60
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c24
-rw-r--r--include/linux/if_link.h7
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,
523int __init ipoib_netlink_init(void); 523int __init ipoib_netlink_init(void);
524void __exit ipoib_netlink_fini(void); 524void __exit ipoib_netlink_fini(void);
525 525
526void ipoib_set_umcast(struct net_device *ndev, int umcast_val);
527int ipoib_set_mode(struct net_device *dev, const char *buf);
528
526void ipoib_setup(struct net_device *dev); 529void ipoib_setup(struct net_device *dev);
527 530
528void ipoib_pkey_poll(struct work_struct *work); 531void 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
1451static ssize_t set_mode(struct device *d, struct device_attribute *attr, 1451int 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
1482static 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
1487static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode); 1501static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, show_mode, set_mode);
1488 1502
1489int ipoib_cm_add_mode_attr(struct net_device *dev) 1503int 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
1384static ssize_t set_umcast(struct device *dev, 1384void 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
1396static 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
38static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = { 38static 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
44static 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
62nla_put_failure:
63 return -EMSGSIZE;
64}
65
66static 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
90out_err:
91 return ret;
92}
93
42static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, 94static 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
88static size_t ipoib_get_size(const struct net_device *dev) 142static 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
93static struct rtnl_link_ops ipoib_link_ops __read_mostly = { 149static 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
104int __init ipoib_netlink_init(void) 162int __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 {
404enum { 404enum {
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
412enum {
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 */