summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2017-01-19 19:37:50 -0500
committerDavid S. Miller <davem@davemloft.net>2017-01-20 14:42:51 -0500
commitcf1a56a4cf196a2922e66e9a8e0bf80d324c5548 (patch)
tree967b905290303ecf4280089f82fe018ce8b081fe
parent0b04680fdae464ee51409b8cb36005f6ef8bd689 (diff)
net: dsa: Remove hwmon support
Only the Marvell mv88e6xxx DSA driver made use of the HWMON support in DSA. The temperature sensor registers are actually in the embedded PHYs, and the PHY driver now supports it. So remove all HWMON support from DSA and drivers. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c154
-rw-r--r--drivers/net/dsa/mv88e6xxx/mv88e6xxx.h16
-rw-r--r--include/net/dsa.h8
-rw-r--r--net/dsa/Kconfig11
-rw-r--r--net/dsa/Makefile1
-rw-r--r--net/dsa/dsa.c4
-rw-r--r--net/dsa/dsa_priv.h9
-rw-r--r--net/dsa/hwmon.c147
8 files changed, 0 insertions, 350 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 987b2dbbd35a..c7e08e13bb54 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -2964,154 +2964,6 @@ static void mv88e6xxx_mdio_unregister(struct mv88e6xxx_chip *chip)
2964 of_node_put(chip->mdio_np); 2964 of_node_put(chip->mdio_np);
2965} 2965}
2966 2966
2967#ifdef CONFIG_NET_DSA_HWMON
2968
2969static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
2970{
2971 struct mv88e6xxx_chip *chip = ds->priv;
2972 u16 val;
2973 int ret;
2974
2975 *temp = 0;
2976
2977 mutex_lock(&chip->reg_lock);
2978
2979 ret = mv88e6xxx_phy_write(chip, 0x0, 0x16, 0x6);
2980 if (ret < 0)
2981 goto error;
2982
2983 /* Enable temperature sensor */
2984 ret = mv88e6xxx_phy_read(chip, 0x0, 0x1a, &val);
2985 if (ret < 0)
2986 goto error;
2987
2988 ret = mv88e6xxx_phy_write(chip, 0x0, 0x1a, val | (1 << 5));
2989 if (ret < 0)
2990 goto error;
2991
2992 /* Wait for temperature to stabilize */
2993 usleep_range(10000, 12000);
2994
2995 ret = mv88e6xxx_phy_read(chip, 0x0, 0x1a, &val);
2996 if (ret < 0)
2997 goto error;
2998
2999 /* Disable temperature sensor */
3000 ret = mv88e6xxx_phy_write(chip, 0x0, 0x1a, val & ~(1 << 5));
3001 if (ret < 0)
3002 goto error;
3003
3004 *temp = ((val & 0x1f) - 5) * 5;
3005
3006error:
3007 mv88e6xxx_phy_write(chip, 0x0, 0x16, 0x0);
3008 mutex_unlock(&chip->reg_lock);
3009 return ret;
3010}
3011
3012static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp)
3013{
3014 struct mv88e6xxx_chip *chip = ds->priv;
3015 int phy = mv88e6xxx_6320_family(chip) ? 3 : 0;
3016 u16 val;
3017 int ret;
3018
3019 *temp = 0;
3020
3021 mutex_lock(&chip->reg_lock);
3022 ret = mv88e6xxx_phy_page_read(chip, phy, 6, 27, &val);
3023 mutex_unlock(&chip->reg_lock);
3024 if (ret < 0)
3025 return ret;
3026
3027 *temp = (val & 0xff) - 25;
3028
3029 return 0;
3030}
3031
3032static int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
3033{
3034 struct mv88e6xxx_chip *chip = ds->priv;
3035
3036 if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_TEMP))
3037 return -EOPNOTSUPP;
3038
3039 if (mv88e6xxx_6320_family(chip) || mv88e6xxx_6352_family(chip))
3040 return mv88e63xx_get_temp(ds, temp);
3041
3042 return mv88e61xx_get_temp(ds, temp);
3043}
3044
3045static int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
3046{
3047 struct mv88e6xxx_chip *chip = ds->priv;
3048 int phy = mv88e6xxx_6320_family(chip) ? 3 : 0;
3049 u16 val;
3050 int ret;
3051
3052 if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_TEMP_LIMIT))
3053 return -EOPNOTSUPP;
3054
3055 *temp = 0;
3056
3057 mutex_lock(&chip->reg_lock);
3058 ret = mv88e6xxx_phy_page_read(chip, phy, 6, 26, &val);
3059 mutex_unlock(&chip->reg_lock);
3060 if (ret < 0)
3061 return ret;
3062
3063 *temp = (((val >> 8) & 0x1f) * 5) - 25;
3064
3065 return 0;
3066}
3067
3068static int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
3069{
3070 struct mv88e6xxx_chip *chip = ds->priv;
3071 int phy = mv88e6xxx_6320_family(chip) ? 3 : 0;
3072 u16 val;
3073 int err;
3074
3075 if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_TEMP_LIMIT))
3076 return -EOPNOTSUPP;
3077
3078 mutex_lock(&chip->reg_lock);
3079 err = mv88e6xxx_phy_page_read(chip, phy, 6, 26, &val);
3080 if (err)
3081 goto unlock;
3082 temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f);
3083 err = mv88e6xxx_phy_page_write(chip, phy, 6, 26,
3084 (val & 0xe0ff) | (temp << 8));
3085unlock:
3086 mutex_unlock(&chip->reg_lock);
3087
3088 return err;
3089}
3090
3091static int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
3092{
3093 struct mv88e6xxx_chip *chip = ds->priv;
3094 int phy = mv88e6xxx_6320_family(chip) ? 3 : 0;
3095 u16 val;
3096 int ret;
3097
3098 if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_TEMP_LIMIT))
3099 return -EOPNOTSUPP;
3100
3101 *alarm = false;
3102
3103 mutex_lock(&chip->reg_lock);
3104 ret = mv88e6xxx_phy_page_read(chip, phy, 6, 26, &val);
3105 mutex_unlock(&chip->reg_lock);
3106 if (ret < 0)
3107 return ret;
3108
3109 *alarm = !!(val & 0x40);
3110
3111 return 0;
3112}
3113#endif /* CONFIG_NET_DSA_HWMON */
3114
3115static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds) 2967static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
3116{ 2968{
3117 struct mv88e6xxx_chip *chip = ds->priv; 2969 struct mv88e6xxx_chip *chip = ds->priv;
@@ -4386,12 +4238,6 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
4386 .get_sset_count = mv88e6xxx_get_sset_count, 4238 .get_sset_count = mv88e6xxx_get_sset_count,
4387 .set_eee = mv88e6xxx_set_eee, 4239 .set_eee = mv88e6xxx_set_eee,
4388 .get_eee = mv88e6xxx_get_eee, 4240 .get_eee = mv88e6xxx_get_eee,
4389#ifdef CONFIG_NET_DSA_HWMON
4390 .get_temp = mv88e6xxx_get_temp,
4391 .get_temp_limit = mv88e6xxx_get_temp_limit,
4392 .set_temp_limit = mv88e6xxx_set_temp_limit,
4393 .get_temp_alarm = mv88e6xxx_get_temp_alarm,
4394#endif
4395 .get_eeprom_len = mv88e6xxx_get_eeprom_len, 4241 .get_eeprom_len = mv88e6xxx_get_eeprom_len,
4396 .get_eeprom = mv88e6xxx_get_eeprom, 4242 .get_eeprom = mv88e6xxx_get_eeprom,
4397 .set_eeprom = mv88e6xxx_set_eeprom, 4243 .set_eeprom = mv88e6xxx_set_eeprom,
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 466cfdadb7bd..ce8b43b14e96 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -497,12 +497,6 @@ enum mv88e6xxx_cap {
497 */ 497 */
498 MV88E6XXX_CAP_STU, 498 MV88E6XXX_CAP_STU,
499 499
500 /* Internal temperature sensor.
501 * Available from any enabled port's PHY register 26, page 6.
502 */
503 MV88E6XXX_CAP_TEMP,
504 MV88E6XXX_CAP_TEMP_LIMIT,
505
506 /* VLAN Table Unit. 500 /* VLAN Table Unit.
507 * The VTU is used to program 802.1Q VLANs. See GLOBAL_VTU_OP. 501 * The VTU is used to program 802.1Q VLANs. See GLOBAL_VTU_OP.
508 */ 502 */
@@ -533,8 +527,6 @@ enum mv88e6xxx_cap {
533#define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT) 527#define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT)
534 528
535#define MV88E6XXX_FLAG_STU BIT_ULL(MV88E6XXX_CAP_STU) 529#define MV88E6XXX_FLAG_STU BIT_ULL(MV88E6XXX_CAP_STU)
536#define MV88E6XXX_FLAG_TEMP BIT_ULL(MV88E6XXX_CAP_TEMP)
537#define MV88E6XXX_FLAG_TEMP_LIMIT BIT_ULL(MV88E6XXX_CAP_TEMP_LIMIT)
538#define MV88E6XXX_FLAG_VTU BIT_ULL(MV88E6XXX_CAP_VTU) 530#define MV88E6XXX_FLAG_VTU BIT_ULL(MV88E6XXX_CAP_VTU)
539 531
540/* Ingress Rate Limit unit */ 532/* Ingress Rate Limit unit */
@@ -586,7 +578,6 @@ enum mv88e6xxx_cap {
586 MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 578 MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
587 MV88E6XXX_FLAG_G2_POT | \ 579 MV88E6XXX_FLAG_G2_POT | \
588 MV88E6XXX_FLAG_STU | \ 580 MV88E6XXX_FLAG_STU | \
589 MV88E6XXX_FLAG_TEMP | \
590 MV88E6XXX_FLAG_VTU | \ 581 MV88E6XXX_FLAG_VTU | \
591 MV88E6XXX_FLAGS_IRL | \ 582 MV88E6XXX_FLAGS_IRL | \
592 MV88E6XXX_FLAGS_MULTI_CHIP | \ 583 MV88E6XXX_FLAGS_MULTI_CHIP | \
@@ -605,8 +596,6 @@ enum mv88e6xxx_cap {
605 MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ 596 MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
606 MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 597 MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
607 MV88E6XXX_FLAG_G2_POT | \ 598 MV88E6XXX_FLAG_G2_POT | \
608 MV88E6XXX_FLAG_TEMP | \
609 MV88E6XXX_FLAG_TEMP_LIMIT | \
610 MV88E6XXX_FLAG_VTU | \ 599 MV88E6XXX_FLAG_VTU | \
611 MV88E6XXX_FLAGS_IRL | \ 600 MV88E6XXX_FLAGS_IRL | \
612 MV88E6XXX_FLAGS_MULTI_CHIP | \ 601 MV88E6XXX_FLAGS_MULTI_CHIP | \
@@ -621,7 +610,6 @@ enum mv88e6xxx_cap {
621 MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 610 MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
622 MV88E6XXX_FLAG_G2_POT | \ 611 MV88E6XXX_FLAG_G2_POT | \
623 MV88E6XXX_FLAG_STU | \ 612 MV88E6XXX_FLAG_STU | \
624 MV88E6XXX_FLAG_TEMP | \
625 MV88E6XXX_FLAG_VTU | \ 613 MV88E6XXX_FLAG_VTU | \
626 MV88E6XXX_FLAGS_IRL | \ 614 MV88E6XXX_FLAGS_IRL | \
627 MV88E6XXX_FLAGS_MULTI_CHIP | \ 615 MV88E6XXX_FLAGS_MULTI_CHIP | \
@@ -637,8 +625,6 @@ enum mv88e6xxx_cap {
637 MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ 625 MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
638 MV88E6XXX_FLAG_G2_POT | \ 626 MV88E6XXX_FLAG_G2_POT | \
639 MV88E6XXX_FLAG_STU | \ 627 MV88E6XXX_FLAG_STU | \
640 MV88E6XXX_FLAG_TEMP | \
641 MV88E6XXX_FLAG_TEMP_LIMIT | \
642 MV88E6XXX_FLAG_VTU | \ 628 MV88E6XXX_FLAG_VTU | \
643 MV88E6XXX_FLAGS_IRL | \ 629 MV88E6XXX_FLAGS_IRL | \
644 MV88E6XXX_FLAGS_MULTI_CHIP | \ 630 MV88E6XXX_FLAGS_MULTI_CHIP | \
@@ -651,8 +637,6 @@ struct mv88e6xxx_ops;
651 (MV88E6XXX_FLAG_EEE | \ 637 (MV88E6XXX_FLAG_EEE | \
652 MV88E6XXX_FLAG_GLOBAL2 | \ 638 MV88E6XXX_FLAG_GLOBAL2 | \
653 MV88E6XXX_FLAG_STU | \ 639 MV88E6XXX_FLAG_STU | \
654 MV88E6XXX_FLAG_TEMP | \
655 MV88E6XXX_FLAG_TEMP_LIMIT | \
656 MV88E6XXX_FLAG_VTU | \ 640 MV88E6XXX_FLAG_VTU | \
657 MV88E6XXX_FLAGS_IRL | \ 641 MV88E6XXX_FLAGS_IRL | \
658 MV88E6XXX_FLAGS_MULTI_CHIP | \ 642 MV88E6XXX_FLAGS_MULTI_CHIP | \
diff --git a/include/net/dsa.h b/include/net/dsa.h
index c72ed7af2a2a..9d6cd923c48c 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -307,14 +307,6 @@ struct dsa_switch_ops {
307 int (*get_eee)(struct dsa_switch *ds, int port, 307 int (*get_eee)(struct dsa_switch *ds, int port,
308 struct ethtool_eee *e); 308 struct ethtool_eee *e);
309 309
310#ifdef CONFIG_NET_DSA_HWMON
311 /* Hardware monitoring */
312 int (*get_temp)(struct dsa_switch *ds, int *temp);
313 int (*get_temp_limit)(struct dsa_switch *ds, int *temp);
314 int (*set_temp_limit)(struct dsa_switch *ds, int temp);
315 int (*get_temp_alarm)(struct dsa_switch *ds, bool *alarm);
316#endif
317
318 /* EEPROM access */ 310 /* EEPROM access */
319 int (*get_eeprom_len)(struct dsa_switch *ds); 311 int (*get_eeprom_len)(struct dsa_switch *ds);
320 int (*get_eeprom)(struct dsa_switch *ds, 312 int (*get_eeprom)(struct dsa_switch *ds,
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 39bb5b3a82f2..9649238eef40 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -15,17 +15,6 @@ config NET_DSA
15 15
16if NET_DSA 16if NET_DSA
17 17
18config NET_DSA_HWMON
19 bool "Distributed Switch Architecture HWMON support"
20 default y
21 depends on HWMON && !(NET_DSA=y && HWMON=m)
22 ---help---
23 Say Y if you want to expose thermal sensor data on switches supported
24 by the Distributed Switch Architecture.
25
26 Some of those switches contain thermal sensors. This data is available
27 via the hwmon sysfs interface and exposes the onboard sensors.
28
29# tagging formats 18# tagging formats
30config NET_DSA_TAG_BRCM 19config NET_DSA_TAG_BRCM
31 bool 20 bool
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 560b6747c276..a3380ed0e0be 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -1,7 +1,6 @@
1# the core 1# the core
2obj-$(CONFIG_NET_DSA) += dsa_core.o 2obj-$(CONFIG_NET_DSA) += dsa_core.o
3dsa_core-y += dsa.o slave.o dsa2.o 3dsa_core-y += dsa.o slave.o dsa2.o
4dsa_core-$(CONFIG_NET_DSA_HWMON) += hwmon.o
5 4
6# tagging formats 5# tagging formats
7dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o 6dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 91f96e1bd2ec..77cb78767f1d 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -316,8 +316,6 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
316 if (ret) 316 if (ret)
317 return ret; 317 return ret;
318 318
319 dsa_hwmon_register(ds);
320
321 return 0; 319 return 0;
322} 320}
323 321
@@ -376,8 +374,6 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
376{ 374{
377 int port; 375 int port;
378 376
379 dsa_hwmon_unregister(ds);
380
381 /* Destroy network devices for physical switch ports. */ 377 /* Destroy network devices for physical switch ports. */
382 for (port = 0; port < DSA_MAX_PORTS; port++) { 378 for (port = 0; port < DSA_MAX_PORTS; port++) {
383 if (!(ds->enabled_port_mask & (1 << port))) 379 if (!(ds->enabled_port_mask & (1 << port)))
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 7e3385ec73f4..63ae1484abae 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -56,15 +56,6 @@ const struct dsa_device_ops *dsa_resolve_tag_protocol(int tag_protocol);
56int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds); 56int dsa_cpu_port_ethtool_setup(struct dsa_switch *ds);
57void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds); 57void dsa_cpu_port_ethtool_restore(struct dsa_switch *ds);
58 58
59/* hwmon.c */
60#ifdef CONFIG_NET_DSA_HWMON
61void dsa_hwmon_register(struct dsa_switch *ds);
62void dsa_hwmon_unregister(struct dsa_switch *ds);
63#else
64static inline void dsa_hwmon_register(struct dsa_switch *ds) { }
65static inline void dsa_hwmon_unregister(struct dsa_switch *ds) { }
66#endif
67
68/* slave.c */ 59/* slave.c */
69extern const struct dsa_device_ops notag_netdev_ops; 60extern const struct dsa_device_ops notag_netdev_ops;
70void dsa_slave_mii_bus_init(struct dsa_switch *ds); 61void dsa_slave_mii_bus_init(struct dsa_switch *ds);
diff --git a/net/dsa/hwmon.c b/net/dsa/hwmon.c
deleted file mode 100644
index 08831a811278..000000000000
--- a/net/dsa/hwmon.c
+++ /dev/null
@@ -1,147 +0,0 @@
1/*
2 * net/dsa/hwmon.c - HWMON subsystem support
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include <linux/ctype.h>
11#include <linux/hwmon.h>
12#include <net/dsa.h>
13
14#include "dsa_priv.h"
15
16static ssize_t temp1_input_show(struct device *dev,
17 struct device_attribute *attr, char *buf)
18{
19 struct dsa_switch *ds = dev_get_drvdata(dev);
20 int temp, ret;
21
22 ret = ds->ops->get_temp(ds, &temp);
23 if (ret < 0)
24 return ret;
25
26 return sprintf(buf, "%d\n", temp * 1000);
27}
28static DEVICE_ATTR_RO(temp1_input);
29
30static ssize_t temp1_max_show(struct device *dev,
31 struct device_attribute *attr, char *buf)
32{
33 struct dsa_switch *ds = dev_get_drvdata(dev);
34 int temp, ret;
35
36 ret = ds->ops->get_temp_limit(ds, &temp);
37 if (ret < 0)
38 return ret;
39
40 return sprintf(buf, "%d\n", temp * 1000);
41}
42
43static ssize_t temp1_max_store(struct device *dev,
44 struct device_attribute *attr, const char *buf,
45 size_t count)
46{
47 struct dsa_switch *ds = dev_get_drvdata(dev);
48 int temp, ret;
49
50 ret = kstrtoint(buf, 0, &temp);
51 if (ret < 0)
52 return ret;
53
54 ret = ds->ops->set_temp_limit(ds, DIV_ROUND_CLOSEST(temp, 1000));
55 if (ret < 0)
56 return ret;
57
58 return count;
59}
60static DEVICE_ATTR_RW(temp1_max);
61
62static ssize_t temp1_max_alarm_show(struct device *dev,
63 struct device_attribute *attr, char *buf)
64{
65 struct dsa_switch *ds = dev_get_drvdata(dev);
66 bool alarm;
67 int ret;
68
69 ret = ds->ops->get_temp_alarm(ds, &alarm);
70 if (ret < 0)
71 return ret;
72
73 return sprintf(buf, "%d\n", alarm);
74}
75static DEVICE_ATTR_RO(temp1_max_alarm);
76
77static struct attribute *dsa_hwmon_attrs[] = {
78 &dev_attr_temp1_input.attr, /* 0 */
79 &dev_attr_temp1_max.attr, /* 1 */
80 &dev_attr_temp1_max_alarm.attr, /* 2 */
81 NULL
82};
83
84static umode_t dsa_hwmon_attrs_visible(struct kobject *kobj,
85 struct attribute *attr, int index)
86{
87 struct device *dev = container_of(kobj, struct device, kobj);
88 struct dsa_switch *ds = dev_get_drvdata(dev);
89 const struct dsa_switch_ops *ops = ds->ops;
90 umode_t mode = attr->mode;
91
92 if (index == 1) {
93 if (!ops->get_temp_limit)
94 mode = 0;
95 else if (!ops->set_temp_limit)
96 mode &= ~S_IWUSR;
97 } else if (index == 2 && !ops->get_temp_alarm) {
98 mode = 0;
99 }
100 return mode;
101}
102
103static const struct attribute_group dsa_hwmon_group = {
104 .attrs = dsa_hwmon_attrs,
105 .is_visible = dsa_hwmon_attrs_visible,
106};
107__ATTRIBUTE_GROUPS(dsa_hwmon);
108
109void dsa_hwmon_register(struct dsa_switch *ds)
110{
111 const char *netname = netdev_name(ds->dst->master_netdev);
112 char hname[IFNAMSIZ + 1];
113 int i, j;
114
115 /* If the switch provides temperature accessors, register with hardware
116 * monitoring subsystem. Treat registration error as non-fatal.
117 */
118 if (!ds->ops->get_temp)
119 return;
120
121 /* Create valid hwmon 'name' attribute */
122 for (i = j = 0; i < IFNAMSIZ && netname[i]; i++) {
123 if (isalnum(netname[i]))
124 hname[j++] = netname[i];
125 }
126 hname[j] = '\0';
127 scnprintf(ds->hwmon_name, sizeof(ds->hwmon_name), "%s_dsa%d", hname,
128 ds->index);
129 ds->hwmon_dev = hwmon_device_register_with_groups(NULL, ds->hwmon_name,
130 ds, dsa_hwmon_groups);
131 if (IS_ERR(ds->hwmon_dev)) {
132 pr_warn("DSA: failed to register HWMON subsystem for switch %d\n",
133 ds->index);
134 ds->hwmon_dev = NULL;
135 } else {
136 pr_info("DSA: registered HWMON subsystem for switch %d\n",
137 ds->index);
138 }
139}
140
141void dsa_hwmon_unregister(struct dsa_switch *ds)
142{
143 if (ds->hwmon_dev) {
144 hwmon_device_unregister(ds->hwmon_dev);
145 ds->hwmon_dev = NULL;
146 }
147}