net: dsa: move HWMON support to its own file
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>
Fri, 6 Jan 2017 21:42:00 +0000 (16:42 -0500)
committerDavid S. Miller <davem@davemloft.net>
Sun, 8 Jan 2017 03:37:22 +0000 (22:37 -0500)
Isolate the HWMON support in DSA in its own file. Currently only the
legacy DSA code is concerned.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/dsa/Makefile
net/dsa/dsa.c
net/dsa/dsa_priv.h
net/dsa/hwmon.c [new file with mode: 0644]

index a3380ed..560b674 100644 (file)
@@ -1,6 +1,7 @@
 # the core
 obj-$(CONFIG_NET_DSA) += dsa_core.o
 dsa_core-y += dsa.o slave.o dsa2.o
+dsa_core-$(CONFIG_NET_DSA_HWMON) += hwmon.o
 
 # tagging formats
 dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
index 3f85be0..cda787e 100644 (file)
@@ -9,9 +9,7 @@
  * (at your option) any later version.
  */
 
-#include <linux/ctype.h>
 #include <linux/device.h>
-#include <linux/hwmon.h>
 #include <linux/list.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -108,105 +106,6 @@ dsa_switch_probe(struct device *parent, struct device *host_dev, int sw_addr,
        return ret;
 }
 
-/* hwmon support ************************************************************/
-
-#ifdef CONFIG_NET_DSA_HWMON
-
-static ssize_t temp1_input_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct dsa_switch *ds = dev_get_drvdata(dev);
-       int temp, ret;
-
-       ret = ds->ops->get_temp(ds, &temp);
-       if (ret < 0)
-               return ret;
-
-       return sprintf(buf, "%d\n", temp * 1000);
-}
-static DEVICE_ATTR_RO(temp1_input);
-
-static ssize_t temp1_max_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
-{
-       struct dsa_switch *ds = dev_get_drvdata(dev);
-       int temp, ret;
-
-       ret = ds->ops->get_temp_limit(ds, &temp);
-       if (ret < 0)
-               return ret;
-
-       return sprintf(buf, "%d\n", temp * 1000);
-}
-
-static ssize_t temp1_max_store(struct device *dev,
-                              struct device_attribute *attr, const char *buf,
-                              size_t count)
-{
-       struct dsa_switch *ds = dev_get_drvdata(dev);
-       int temp, ret;
-
-       ret = kstrtoint(buf, 0, &temp);
-       if (ret < 0)
-               return ret;
-
-       ret = ds->ops->set_temp_limit(ds, DIV_ROUND_CLOSEST(temp, 1000));
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-static DEVICE_ATTR_RW(temp1_max);
-
-static ssize_t temp1_max_alarm_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       struct dsa_switch *ds = dev_get_drvdata(dev);
-       bool alarm;
-       int ret;
-
-       ret = ds->ops->get_temp_alarm(ds, &alarm);
-       if (ret < 0)
-               return ret;
-
-       return sprintf(buf, "%d\n", alarm);
-}
-static DEVICE_ATTR_RO(temp1_max_alarm);
-
-static struct attribute *dsa_hwmon_attrs[] = {
-       &dev_attr_temp1_input.attr,     /* 0 */
-       &dev_attr_temp1_max.attr,       /* 1 */
-       &dev_attr_temp1_max_alarm.attr, /* 2 */
-       NULL
-};
-
-static umode_t dsa_hwmon_attrs_visible(struct kobject *kobj,
-                                      struct attribute *attr, int index)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct dsa_switch *ds = dev_get_drvdata(dev);
-       struct dsa_switch_ops *ops = ds->ops;
-       umode_t mode = attr->mode;
-
-       if (index == 1) {
-               if (!ops->get_temp_limit)
-                       mode = 0;
-               else if (!ops->set_temp_limit)
-                       mode &= ~S_IWUSR;
-       } else if (index == 2 && !ops->get_temp_alarm) {
-               mode = 0;
-       }
-       return mode;
-}
-
-static const struct attribute_group dsa_hwmon_group = {
-       .attrs = dsa_hwmon_attrs,
-       .is_visible = dsa_hwmon_attrs_visible,
-};
-__ATTRIBUTE_GROUPS(dsa_hwmon);
-
-#endif /* CONFIG_NET_DSA_HWMON */
-
 /* basic switch operations **************************************************/
 int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev,
                      struct device_node *port_dn, int port)
@@ -415,30 +314,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
        if (ret)
                return ret;
 
-#ifdef CONFIG_NET_DSA_HWMON
-       /* If the switch provides a temperature sensor,
-        * register with hardware monitoring subsystem.
-        * Treat registration error as non-fatal and ignore it.
-        */
-       if (ops->get_temp) {
-               const char *netname = netdev_name(dst->master_netdev);
-               char hname[IFNAMSIZ + 1];
-               int i, j;
-
-               /* Create valid hwmon 'name' attribute */
-               for (i = j = 0; i < IFNAMSIZ && netname[i]; i++) {
-                       if (isalnum(netname[i]))
-                               hname[j++] = netname[i];
-               }
-               hname[j] = '\0';
-               scnprintf(ds->hwmon_name, sizeof(ds->hwmon_name), "%s_dsa%d",
-                         hname, index);
-               ds->hwmon_dev = hwmon_device_register_with_groups(NULL,
-                                       ds->hwmon_name, ds, dsa_hwmon_groups);
-               if (IS_ERR(ds->hwmon_dev))
-                       ds->hwmon_dev = NULL;
-       }
-#endif /* CONFIG_NET_DSA_HWMON */
+       dsa_hwmon_register(ds);
 
        return 0;
 }
@@ -498,10 +374,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
 {
        int port;
 
-#ifdef CONFIG_NET_DSA_HWMON
-       if (ds->hwmon_dev)
-               hwmon_device_unregister(ds->hwmon_dev);
-#endif
+       dsa_hwmon_unregister(ds);
 
        /* Destroy network devices for physical switch ports. */
        for (port = 0; port < DSA_MAX_PORTS; port++) {
index 63ae148..7e3385e 100644 (file)
@@ -56,6 +56,15 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
 int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds);
 void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds);
 
+/* hwmon.c */
+#ifdef CONFIG_NET_DSA_HWMON
+void dsa_hwmon_register(struct dsa_switch *ds);
+void dsa_hwmon_unregister(struct dsa_switch *ds);
+#else
+static inline void dsa_hwmon_register(struct dsa_switch *ds) { }
+static inline void dsa_hwmon_unregister(struct dsa_switch *ds) { }
+#endif
+
 /* slave.c */
 extern const struct dsa_device_ops notag_netdev_ops;
 void dsa_slave_mii_bus_init(struct dsa_switch *ds);
diff --git a/net/dsa/hwmon.c b/net/dsa/hwmon.c
new file mode 100644 (file)
index 0000000..3a9cdf0
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * net/dsa/hwmon.c - HWMON subsystem support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/ctype.h>
+#include <linux/hwmon.h>
+#include <net/dsa.h>
+
+#include "dsa_priv.h"
+
+static ssize_t temp1_input_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct dsa_switch *ds = dev_get_drvdata(dev);
+       int temp, ret;
+
+       ret = ds->ops->get_temp(ds, &temp);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", temp * 1000);
+}
+static DEVICE_ATTR_RO(temp1_input);
+
+static ssize_t temp1_max_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct dsa_switch *ds = dev_get_drvdata(dev);
+       int temp, ret;
+
+       ret = ds->ops->get_temp_limit(ds, &temp);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", temp * 1000);
+}
+
+static ssize_t temp1_max_store(struct device *dev,
+                              struct device_attribute *attr, const char *buf,
+                              size_t count)
+{
+       struct dsa_switch *ds = dev_get_drvdata(dev);
+       int temp, ret;
+
+       ret = kstrtoint(buf, 0, &temp);
+       if (ret < 0)
+               return ret;
+
+       ret = ds->ops->set_temp_limit(ds, DIV_ROUND_CLOSEST(temp, 1000));
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+static DEVICE_ATTR_RW(temp1_max);
+
+static ssize_t temp1_max_alarm_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct dsa_switch *ds = dev_get_drvdata(dev);
+       bool alarm;
+       int ret;
+
+       ret = ds->ops->get_temp_alarm(ds, &alarm);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", alarm);
+}
+static DEVICE_ATTR_RO(temp1_max_alarm);
+
+static struct attribute *dsa_hwmon_attrs[] = {
+       &dev_attr_temp1_input.attr,     /* 0 */
+       &dev_attr_temp1_max.attr,       /* 1 */
+       &dev_attr_temp1_max_alarm.attr, /* 2 */
+       NULL
+};
+
+static umode_t dsa_hwmon_attrs_visible(struct kobject *kobj,
+                                      struct attribute *attr, int index)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct dsa_switch *ds = dev_get_drvdata(dev);
+       struct dsa_switch_ops *ops = ds->ops;
+       umode_t mode = attr->mode;
+
+       if (index == 1) {
+               if (!ops->get_temp_limit)
+                       mode = 0;
+               else if (!ops->set_temp_limit)
+                       mode &= ~S_IWUSR;
+       } else if (index == 2 && !ops->get_temp_alarm) {
+               mode = 0;
+       }
+       return mode;
+}
+
+static const struct attribute_group dsa_hwmon_group = {
+       .attrs = dsa_hwmon_attrs,
+       .is_visible = dsa_hwmon_attrs_visible,
+};
+__ATTRIBUTE_GROUPS(dsa_hwmon);
+
+void dsa_hwmon_register(struct dsa_switch *ds)
+{
+       const char *netname = netdev_name(ds->dst->master_netdev);
+       char hname[IFNAMSIZ + 1];
+       int i, j;
+
+       /* If the switch provides temperature accessors, register with hardware
+        * monitoring subsystem. Treat registration error as non-fatal.
+        */
+       if (!ds->ops->get_temp)
+               return;
+
+       /* Create valid hwmon 'name' attribute */
+       for (i = j = 0; i < IFNAMSIZ && netname[i]; i++) {
+               if (isalnum(netname[i]))
+                       hname[j++] = netname[i];
+       }
+       hname[j] = '\0';
+       scnprintf(ds->hwmon_name, sizeof(ds->hwmon_name), "%s_dsa%d", hname,
+                 ds->index);
+       ds->hwmon_dev = hwmon_device_register_with_groups(NULL, ds->hwmon_name,
+                                                         ds, dsa_hwmon_groups);
+       if (IS_ERR(ds->hwmon_dev)) {
+               pr_warn("DSA: failed to register HWMON subsystem for switch %d\n",
+                       ds->index);
+               ds->hwmon_dev = NULL;
+       } else {
+               pr_info("DSA: registered HWMON subsystem for switch %d\n",
+                       ds->index);
+       }
+}
+
+void dsa_hwmon_unregister(struct dsa_switch *ds)
+{
+       if (ds->hwmon_dev) {
+               hwmon_device_unregister(ds->hwmon_dev);
+               ds->hwmon_dev = NULL;
+       }
+}