Merge branches 'cxgb4' and 'mlx5' into k.o/for-4.8
[cascardo/linux.git] / drivers / infiniband / core / sysfs.c
index ed04a7b..0d1ab73 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/netdevice.h>
+#include <linux/ethtool.h>
 
 #include <rdma/ib_mad.h>
 #include <rdma/ib_pma.h>
@@ -889,9 +890,9 @@ static struct attribute *alloc_hsa_lifespan(char *name, u8 port_num)
 static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
                           u8 port_num)
 {
-       struct attribute_group *hsag = NULL;
+       struct attribute_group *hsag;
        struct rdma_hw_stats *stats;
-       int i = 0, ret;
+       int i, ret;
 
        stats = device->alloc_hw_stats(device, port_num);
 
@@ -901,9 +902,12 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
        if (!stats->names || stats->num_counters <= 0)
                goto err_free_stats;
 
+       /*
+        * Two extra attribue elements here, one for the lifespan entry and
+        * one to NULL terminate the list for the sysfs core code
+        */
        hsag = kzalloc(sizeof(*hsag) +
-                      // 1 extra for the lifespan config entry
-                      sizeof(void *) * (stats->num_counters + 1),
+                      sizeof(void *) * (stats->num_counters + 2),
                       GFP_KERNEL);
        if (!hsag)
                goto err_free_stats;
@@ -911,7 +915,7 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
        ret = device->get_hw_stats(device, stats, port_num,
                                   stats->num_counters);
        if (ret != stats->num_counters)
-               goto err;
+               goto err_free_hsag;
 
        stats->timestamp = jiffies;
 
@@ -922,10 +926,13 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
                hsag->attrs[i] = alloc_hsa(i, port_num, stats->names[i]);
                if (!hsag->attrs[i])
                        goto err;
+               sysfs_attr_init(hsag->attrs[i]);
        }
 
        /* treat an error here as non-fatal */
        hsag->attrs[i] = alloc_hsa_lifespan("lifespan", port_num);
+       if (hsag->attrs[i])
+               sysfs_attr_init(hsag->attrs[i]);
 
        if (port) {
                struct kobject *kobj = &port->kobj;
@@ -948,6 +955,7 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
 err:
        for (; i >= 0; i--)
                kfree(hsag->attrs[i]);
+err_free_hsag:
        kfree(hsag);
 err_free_stats:
        kfree(stats);
@@ -1189,16 +1197,28 @@ static ssize_t set_node_desc(struct device *device,
        return count;
 }
 
+static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
+                          char *buf)
+{
+       struct ib_device *dev = container_of(device, struct ib_device, dev);
+
+       ib_get_device_fw_str(dev, buf, PAGE_SIZE);
+       strlcat(buf, "\n", PAGE_SIZE);
+       return strlen(buf);
+}
+
 static DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
 static DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
 static DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
 static DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, set_node_desc);
+static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
 
 static struct device_attribute *ib_class_attributes[] = {
        &dev_attr_node_type,
        &dev_attr_sys_image_guid,
        &dev_attr_node_guid,
-       &dev_attr_node_desc
+       &dev_attr_node_desc,
+       &dev_attr_fw_ver,
 };
 
 static void free_port_list_attributes(struct ib_device *device)