aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/iseries_veth.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 25481ea67474..9536962f5cd2 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -167,6 +167,8 @@ struct veth_port {
167 int promiscuous; 167 int promiscuous;
168 int num_mcast; 168 int num_mcast;
169 u64 mcast_addr[VETH_MAX_MCAST]; 169 u64 mcast_addr[VETH_MAX_MCAST];
170
171 struct kobject kobject;
170}; 172};
171 173
172static HvLpIndex this_lp; 174static HvLpIndex this_lp;
@@ -350,6 +352,62 @@ static struct kobj_type veth_lpar_connection_ktype = {
350 .default_attrs = veth_cnx_default_attrs 352 .default_attrs = veth_cnx_default_attrs
351}; 353};
352 354
355struct veth_port_attribute {
356 struct attribute attr;
357 ssize_t (*show)(struct veth_port *, char *buf);
358 ssize_t (*store)(struct veth_port *, const char *buf);
359};
360
361static ssize_t veth_port_attribute_show(struct kobject *kobj,
362 struct attribute *attr, char *buf)
363{
364 struct veth_port_attribute *port_attr;
365 struct veth_port *port;
366
367 port_attr = container_of(attr, struct veth_port_attribute, attr);
368 port = container_of(kobj, struct veth_port, kobject);
369
370 if (!port_attr->show)
371 return -EIO;
372
373 return port_attr->show(port, buf);
374}
375
376#define CUSTOM_PORT_ATTR(_name, _format, _expression) \
377static ssize_t _name##_show(struct veth_port *port, char *buf) \
378{ \
379 return sprintf(buf, _format, _expression); \
380} \
381struct veth_port_attribute veth_port_attr_##_name = __ATTR_RO(_name)
382
383#define SIMPLE_PORT_ATTR(_name) \
384 CUSTOM_PORT_ATTR(_name, "%lu\n", (unsigned long)port->_name)
385
386SIMPLE_PORT_ATTR(promiscuous);
387SIMPLE_PORT_ATTR(num_mcast);
388CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map);
389CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map);
390CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr);
391
392#define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr)
393static struct attribute *veth_port_default_attrs[] = {
394 GET_PORT_ATTR(mac_addr),
395 GET_PORT_ATTR(lpar_map),
396 GET_PORT_ATTR(stopped_map),
397 GET_PORT_ATTR(promiscuous),
398 GET_PORT_ATTR(num_mcast),
399 NULL
400};
401
402static struct sysfs_ops veth_port_sysfs_ops = {
403 .show = veth_port_attribute_show
404};
405
406static struct kobj_type veth_port_ktype = {
407 .sysfs_ops = &veth_port_sysfs_ops,
408 .default_attrs = veth_port_default_attrs
409};
410
353/* 411/*
354 * LPAR connection code 412 * LPAR connection code
355 */ 413 */
@@ -992,6 +1050,13 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
992 return NULL; 1050 return NULL;
993 } 1051 }
994 1052
1053 kobject_init(&port->kobject);
1054 port->kobject.parent = &dev->class_dev.kobj;
1055 port->kobject.ktype = &veth_port_ktype;
1056 kobject_set_name(&port->kobject, "veth_port");
1057 if (0 != kobject_add(&port->kobject))
1058 veth_error("Failed adding port for %s to sysfs.\n", dev->name);
1059
995 veth_info("%s attached to iSeries vlan %d (LPAR map = 0x%.4X)\n", 1060 veth_info("%s attached to iSeries vlan %d (LPAR map = 0x%.4X)\n",
996 dev->name, vlan, port->lpar_map); 1061 dev->name, vlan, port->lpar_map);
997 1062
@@ -1486,6 +1551,8 @@ static int veth_remove(struct vio_dev *vdev)
1486 } 1551 }
1487 1552
1488 veth_dev[vdev->unit_address] = NULL; 1553 veth_dev[vdev->unit_address] = NULL;
1554 kobject_del(&port->kobject);
1555 kobject_put(&port->kobject);
1489 unregister_netdev(dev); 1556 unregister_netdev(dev);
1490 free_netdev(dev); 1557 free_netdev(dev);
1491 1558