* [PATCH net-next 1/2] phy: marvell: Add support for temperature sensor
2017-01-11 1:03 [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs Andrew Lunn
@ 2017-01-11 1:03 ` Andrew Lunn
2017-01-11 15:09 ` Andrew Lunn
2017-01-11 1:03 ` [PATCH net-next 2/2] net: dsa: Remove hwmon support Andrew Lunn
2017-01-11 17:06 ` [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs Vivien Didelot
2 siblings, 1 reply; 12+ messages in thread
From: Andrew Lunn @ 2017-01-11 1:03 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli, Andrew Lunn
Some Marvell PHYs have an inbuilt temperature sensor. Add hwmon
support for this sensor.
There are two different variants. The simpler, older chips have a 5
degree accuracy. The newer devices have 1 degree accuracy.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/phy/marvell.c | 426 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 423 insertions(+), 3 deletions(-)
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index e269262471a4..44c247cfe660 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -17,8 +17,10 @@
*/
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/unistd.h>
+#include <linux/hwmon.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -90,6 +92,17 @@
#define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4)
#define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4))
+#define MII_88E1121_MISC_TEST 0x1a
+#define MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK 0x1f00
+#define MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT 8
+#define MII_88E1510_MISC_TEST_TEMP_IRQ_EN BIT(7)
+#define MII_88E1510_MISC_TEST_TEMP_IRQ BIT(6)
+#define MII_88E1121_MISC_TEST_TEMP_SENSOR_EN BIT(5)
+#define MII_88E1121_MISC_TEST_TEMP_MASK 0x1f
+
+#define MII_88E1510_TEMP_SENSOR 0x1b
+#define MII_88E1510_TEMP_SENSOR_MASK 0xff
+
#define MII_88E1318S_PHY_MSCR1_REG 16
#define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
@@ -172,6 +185,8 @@ static struct marvell_hw_stat marvell_hw_stats[] = {
struct marvell_priv {
u64 stats[ARRAY_SIZE(marvell_hw_stats)];
+ char *hwmon_name;
+ struct device *hwmon_dev;
};
static int marvell_ack_interrupt(struct phy_device *phydev)
@@ -1467,6 +1482,374 @@ static void marvell_get_stats(struct phy_device *phydev,
data[i] = marvell_get_stat(phydev, i);
}
+#ifdef CONFIG_HWMON
+static int m88e1121_get_temp(struct phy_device *phydev, long *temp)
+{
+ int ret;
+ int val;
+
+ *temp = 0;
+
+ mutex_lock(&phydev->lock);
+
+ ret = phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x6);
+ if (ret < 0)
+ goto error;
+
+ /* Enable temperature sensor */
+ ret = phy_read(phydev, MII_88E1121_MISC_TEST);
+ if (ret < 0)
+ goto error;
+
+ ret = phy_write(phydev, MII_88E1121_MISC_TEST,
+ ret | MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
+ if (ret < 0)
+ goto error;
+
+ /* Wait for temperature to stabilize */
+ usleep_range(10000, 12000);
+
+ val = phy_read(phydev, MII_88E1121_MISC_TEST);
+ if (val < 0) {
+ ret = val;
+ goto error;
+ }
+
+ /* Disable temperature sensor */
+ ret = phy_write(phydev, MII_88E1121_MISC_TEST,
+ ret & ~MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
+ if (ret < 0)
+ goto error;
+
+ *temp = ((val & MII_88E1121_MISC_TEST_TEMP_MASK) - 5) * 5000;
+
+error:
+ phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x0);
+ mutex_unlock(&phydev->lock);
+
+ return ret;
+}
+
+static int m88e1121_hwmon_read(struct device *dev,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel, long *temp)
+{
+ struct phy_device *phydev = dev_get_drvdata(dev);
+ int err;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ err = m88e1121_get_temp(phydev, temp);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
+static umode_t m88e1121_hwmon_is_visible(const void *data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type != hwmon_temp)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0444;
+ default:
+ return 0;
+ }
+}
+
+static u32 m88e1121_hwmon_chip_config[] = {
+ HWMON_C_REGISTER_TZ,
+ 0
+};
+
+static const struct hwmon_channel_info m88e1121_hwmon_chip = {
+ .type = hwmon_chip,
+ .config = m88e1121_hwmon_chip_config,
+};
+
+static u32 m88e1121_hwmon_temp_config[] = {
+ HWMON_T_INPUT,
+ 0
+};
+
+static const struct hwmon_channel_info m88e1121_hwmon_temp = {
+ .type = hwmon_temp,
+ .config = m88e1121_hwmon_temp_config,
+};
+
+static const struct hwmon_channel_info *m88e1121_hwmon_info[] = {
+ &m88e1121_hwmon_chip,
+ &m88e1121_hwmon_temp,
+ NULL
+};
+
+static const struct hwmon_ops m88e1121_hwmon_hwmon_ops = {
+ .is_visible = m88e1121_hwmon_is_visible,
+ .read = m88e1121_hwmon_read,
+};
+
+static const struct hwmon_chip_info m88e1121_hwmon_chip_info = {
+ .ops = &m88e1121_hwmon_hwmon_ops,
+ .info = m88e1121_hwmon_info,
+};
+
+static int m88e1510_get_temp(struct phy_device *phydev, long *temp)
+{
+ int ret;
+
+ *temp = 0;
+
+ mutex_lock(&phydev->lock);
+
+ ret = phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x6);
+ if (ret < 0)
+ goto error;
+
+ ret = phy_read(phydev, MII_88E1510_TEMP_SENSOR);
+ if (ret < 0)
+ goto error;
+
+ *temp = ((ret & MII_88E1510_TEMP_SENSOR_MASK) - 25) * 1000;
+
+error:
+ phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x0);
+ mutex_unlock(&phydev->lock);
+
+ return ret;
+}
+
+int m88e1510_get_temp_critical(struct phy_device *phydev, long *temp)
+{
+ int ret;
+
+ *temp = 0;
+
+ mutex_lock(&phydev->lock);
+
+ ret = phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x6);
+ if (ret < 0)
+ goto error;
+
+ ret = phy_read(phydev, MII_88E1121_MISC_TEST);
+ if (ret < 0)
+ goto error;
+
+ *temp = (((ret & MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK) >>
+ MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT) * 5) - 25;
+ /* convert to mC */
+ *temp *= 1000;
+
+error:
+ phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x0);
+ mutex_unlock(&phydev->lock);
+
+ return ret;
+}
+
+int m88e1510_set_temp_critical(struct phy_device *phydev, long temp)
+{
+ int ret;
+
+ mutex_lock(&phydev->lock);
+
+ ret = phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x6);
+ if (ret < 0)
+ goto error;
+
+ ret = phy_read(phydev, MII_88E1121_MISC_TEST);
+ if (ret < 0)
+ goto error;
+
+ temp = temp / 1000;
+ temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f);
+ ret = phy_write(phydev, MII_88E1121_MISC_TEST,
+ (ret & ~MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK) |
+ (temp << MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT));
+
+error:
+ phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x0);
+ mutex_unlock(&phydev->lock);
+
+ return ret;
+}
+
+int m88e1510_get_temp_alarm(struct phy_device *phydev, long *alarm)
+{
+ int ret;
+
+ *alarm = false;
+
+ mutex_lock(&phydev->lock);
+
+ ret = phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x6);
+ if (ret < 0)
+ goto error;
+
+ ret = phy_read(phydev, MII_88E1121_MISC_TEST);
+ if (ret < 0)
+ goto error;
+ *alarm = !!(ret & MII_88E1510_MISC_TEST_TEMP_IRQ);
+
+error:
+ phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 0x0);
+ mutex_unlock(&phydev->lock);
+
+ return ret;
+}
+
+static int m88e1510_hwmon_read(struct device *dev,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel, long *temp)
+{
+ struct phy_device *phydev = dev_get_drvdata(dev);
+ int err;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ err = m88e1510_get_temp(phydev, temp);
+ break;
+ case hwmon_temp_crit:
+ err = m88e1510_get_temp_critical(phydev, temp);
+ break;
+ case hwmon_temp_max_alarm:
+ err = m88e1510_get_temp_alarm(phydev, temp);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
+static int m88e1510_hwmon_write(struct device *dev,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel, long temp)
+{
+ struct phy_device *phydev = dev_get_drvdata(dev);
+ int err;
+
+ switch (attr) {
+ case hwmon_temp_crit:
+ err = m88e1510_set_temp_critical(phydev, temp);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return err;
+}
+
+static umode_t m88e1510_hwmon_is_visible(const void *data,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ if (type != hwmon_temp)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_max_alarm:
+ return 0444;
+ case hwmon_temp_crit:
+ return 0644;
+ default:
+ return 0;
+ }
+}
+
+static u32 m88e1510_hwmon_temp_config[] = {
+ HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM,
+ 0
+};
+
+static const struct hwmon_channel_info m88e1510_hwmon_temp = {
+ .type = hwmon_temp,
+ .config = m88e1510_hwmon_temp_config,
+};
+
+static const struct hwmon_channel_info *m88e1510_hwmon_info[] = {
+ &m88e1121_hwmon_chip,
+ &m88e1510_hwmon_temp,
+ NULL
+};
+
+static const struct hwmon_ops m88e1510_hwmon_hwmon_ops = {
+ .is_visible = m88e1510_hwmon_is_visible,
+ .read = m88e1510_hwmon_read,
+ .write = m88e1510_hwmon_write,
+};
+
+static const struct hwmon_chip_info m88e1510_hwmon_chip_info = {
+ .ops = &m88e1510_hwmon_hwmon_ops,
+ .info = m88e1510_hwmon_info,
+};
+
+static int marvell_hwmon_name(struct phy_device *phydev)
+{
+ struct marvell_priv *priv = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
+ const char *devname = dev_name(dev);
+ size_t len = strlen(devname);
+ int i, j;
+
+ priv->hwmon_name = devm_kzalloc(dev, len, GFP_KERNEL);
+ if (!priv->hwmon_name)
+ return -ENOMEM;
+
+ for (i = j = 0; i < len && devname[i]; i++) {
+ if (isalnum(devname[i]))
+ priv->hwmon_name[j++] = devname[i];
+ }
+
+ return 0;
+}
+
+static int marvell_hwmon_probe(struct phy_device *phydev,
+ const struct hwmon_chip_info *chip)
+{
+ struct marvell_priv *priv = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
+ int err;
+
+ err = marvell_hwmon_name(phydev);
+ if (err)
+ return err;
+
+ priv->hwmon_dev = devm_hwmon_device_register_with_info(
+ dev, priv->hwmon_name, phydev, chip, NULL);
+
+ if (IS_ERR(priv->hwmon_dev))
+ return PTR_ERR(priv->hwmon_dev);
+
+ return 0;
+}
+
+static int m88e1121_hwmon_probe(struct phy_device *phydev)
+{
+ return marvell_hwmon_probe(phydev, &m88e1121_hwmon_chip_info);
+}
+
+static int m88e1510_hwmon_probe(struct phy_device *phydev)
+{
+ return marvell_hwmon_probe(phydev, &m88e1510_hwmon_chip_info);
+}
+#else
+static int m88e1121_hwmon_probe(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int m88e1510_hwmon_probe(struct phy_device *phydev)
+{
+ return 0;
+}
+#endif
+
static int marvell_probe(struct phy_device *phydev)
{
struct marvell_priv *priv;
@@ -1480,6 +1863,39 @@ static int marvell_probe(struct phy_device *phydev)
return 0;
}
+static int m88e1121_probe(struct phy_device *phydev)
+{
+ int err;
+
+ err = marvell_probe(phydev);
+ if (err)
+ return err;
+
+ return m88e1121_hwmon_probe(phydev);
+}
+
+static int m88e1510_probe(struct phy_device *phydev)
+{
+ int err;
+
+ err = marvell_probe(phydev);
+ if (err)
+ return err;
+
+ return m88e1510_hwmon_probe(phydev);
+}
+
+static void marvell_remove(struct phy_device *phydev)
+{
+#ifdef CONFIG_HWMON
+
+ struct marvell_priv *priv = phydev->priv;
+
+ if (priv && priv->hwmon_dev)
+ hwmon_device_unregister(priv->hwmon_dev);
+#endif
+}
+
static struct phy_driver marvell_drivers[] = {
{
.phy_id = MARVELL_PHY_ID_88E1101,
@@ -1557,9 +1973,10 @@ static struct phy_driver marvell_drivers[] = {
.phy_id = MARVELL_PHY_ID_88E1121R,
.phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1121R",
+ .probe = &m88e1121_probe,
+ .remove = &marvell_remove,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
- .probe = marvell_probe,
.config_init = &m88e1121_config_init,
.config_aneg = &m88e1121_config_aneg,
.read_status = &marvell_read_status,
@@ -1670,8 +2087,10 @@ static struct phy_driver marvell_drivers[] = {
.phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1510",
.features = PHY_GBIT_FEATURES | SUPPORTED_FIBRE,
+ .probe = &m88e1510_probe,
+ .remove = &marvell_remove,
+ .features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
- .probe = marvell_probe,
.config_init = &m88e1510_config_init,
.config_aneg = &m88e1510_config_aneg,
.read_status = &marvell_read_status,
@@ -1688,9 +2107,10 @@ static struct phy_driver marvell_drivers[] = {
.phy_id = MARVELL_PHY_ID_88E1540,
.phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "Marvell 88E1540",
+ .probe = m88e1510_probe,
+ .remove = &marvell_remove,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
- .probe = marvell_probe,
.config_init = &marvell_config_init,
.config_aneg = &m88e1510_config_aneg,
.read_status = &marvell_read_status,
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH net-next 1/2] phy: marvell: Add support for temperature sensor
2017-01-11 1:03 ` [PATCH net-next 1/2] phy: marvell: Add support for temperature sensor Andrew Lunn
@ 2017-01-11 15:09 ` Andrew Lunn
2017-01-11 16:29 ` Sergei Shtylyov
0 siblings, 1 reply; 12+ messages in thread
From: Andrew Lunn @ 2017-01-11 15:09 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli
> +static int marvell_hwmon_probe(struct phy_device *phydev,
> + const struct hwmon_chip_info *chip)
> +{
> + struct marvell_priv *priv = phydev->priv;
> + struct device *dev = &phydev->mdio.dev;
> + int err;
> +
> + err = marvell_hwmon_name(phydev);
> + if (err)
> + return err;
> +
> + priv->hwmon_dev = devm_hwmon_device_register_with_info(
> + dev, priv->hwmon_name, phydev, chip, NULL);
> +
> + if (IS_ERR(priv->hwmon_dev))
> + return PTR_ERR(priv->hwmon_dev);
> +
> + return 0;
> +}
0-day has pointed out this can be simplified to just
return PTR_ERR(priv->hwmon_dev);
I will submit a v2 in a couple of days, when others have had chance to
comment.
Andrew
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH net-next 1/2] phy: marvell: Add support for temperature sensor
2017-01-11 15:09 ` Andrew Lunn
@ 2017-01-11 16:29 ` Sergei Shtylyov
0 siblings, 0 replies; 12+ messages in thread
From: Sergei Shtylyov @ 2017-01-11 16:29 UTC (permalink / raw)
To: Andrew Lunn, David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli
Hello!
On 01/11/2017 06:09 PM, Andrew Lunn wrote:
>> +static int marvell_hwmon_probe(struct phy_device *phydev,
>> + const struct hwmon_chip_info *chip)
>> +{
>> + struct marvell_priv *priv = phydev->priv;
>> + struct device *dev = &phydev->mdio.dev;
>> + int err;
>> +
>> + err = marvell_hwmon_name(phydev);
>> + if (err)
>> + return err;
>> +
>> + priv->hwmon_dev = devm_hwmon_device_register_with_info(
>> + dev, priv->hwmon_name, phydev, chip, NULL);
>> +
>> + if (IS_ERR(priv->hwmon_dev))
>> + return PTR_ERR(priv->hwmon_dev);
>> +
>> + return 0;
>> +}
>
> 0-day has pointed out this can be simplified to just
>
> return PTR_ERR(priv->hwmon_dev);
PTR_ERR_OR_ZERO() maybe?
[...]
MBR, Sergei
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH net-next 2/2] net: dsa: Remove hwmon support
2017-01-11 1:03 [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs Andrew Lunn
2017-01-11 1:03 ` [PATCH net-next 1/2] phy: marvell: Add support for temperature sensor Andrew Lunn
@ 2017-01-11 1:03 ` Andrew Lunn
2017-01-11 17:06 ` [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs Vivien Didelot
2 siblings, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2017-01-11 1:03 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Vivien Didelot, Florian Fainelli, Andrew Lunn
Only the Marvell mv88e6xxx DSA driver made use of the HWMON support in
DSA. The temperature sensor is actually in the embedded PHY, and the
PHY driver now supports it. So remove all HWMON support from DSA and
drivers.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx/chip.c | 154 ----------------------------------
drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 16 ----
include/net/dsa.h | 8 --
net/dsa/Kconfig | 11 ---
net/dsa/Makefile | 1 -
net/dsa/dsa.c | 4 -
net/dsa/dsa_priv.h | 9 --
net/dsa/hwmon.c | 147 --------------------------------
8 files changed, 350 deletions(-)
delete mode 100644 net/dsa/hwmon.c
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index eea8e0176e33..81843204b850 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)
of_node_put(chip->mdio_np);
}
-#ifdef CONFIG_NET_DSA_HWMON
-
-static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
-{
- struct mv88e6xxx_chip *chip = ds->priv;
- u16 val;
- int ret;
-
- *temp = 0;
-
- mutex_lock(&chip->reg_lock);
-
- ret = mv88e6xxx_phy_write(chip, 0x0, 0x16, 0x6);
- if (ret < 0)
- goto error;
-
- /* Enable temperature sensor */
- ret = mv88e6xxx_phy_read(chip, 0x0, 0x1a, &val);
- if (ret < 0)
- goto error;
-
- ret = mv88e6xxx_phy_write(chip, 0x0, 0x1a, val | (1 << 5));
- if (ret < 0)
- goto error;
-
- /* Wait for temperature to stabilize */
- usleep_range(10000, 12000);
-
- ret = mv88e6xxx_phy_read(chip, 0x0, 0x1a, &val);
- if (ret < 0)
- goto error;
-
- /* Disable temperature sensor */
- ret = mv88e6xxx_phy_write(chip, 0x0, 0x1a, val & ~(1 << 5));
- if (ret < 0)
- goto error;
-
- *temp = ((val & 0x1f) - 5) * 5;
-
-error:
- mv88e6xxx_phy_write(chip, 0x0, 0x16, 0x0);
- mutex_unlock(&chip->reg_lock);
- return ret;
-}
-
-static int mv88e63xx_get_temp(struct dsa_switch *ds, int *temp)
-{
- struct mv88e6xxx_chip *chip = ds->priv;
- int phy = mv88e6xxx_6320_family(chip) ? 3 : 0;
- u16 val;
- int ret;
-
- *temp = 0;
-
- mutex_lock(&chip->reg_lock);
- ret = mv88e6xxx_phy_page_read(chip, phy, 6, 27, &val);
- mutex_unlock(&chip->reg_lock);
- if (ret < 0)
- return ret;
-
- *temp = (val & 0xff) - 25;
-
- return 0;
-}
-
-static int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
-{
- struct mv88e6xxx_chip *chip = ds->priv;
-
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_TEMP))
- return -EOPNOTSUPP;
-
- if (mv88e6xxx_6320_family(chip) || mv88e6xxx_6352_family(chip))
- return mv88e63xx_get_temp(ds, temp);
-
- return mv88e61xx_get_temp(ds, temp);
-}
-
-static int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
-{
- struct mv88e6xxx_chip *chip = ds->priv;
- int phy = mv88e6xxx_6320_family(chip) ? 3 : 0;
- u16 val;
- int ret;
-
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_TEMP_LIMIT))
- return -EOPNOTSUPP;
-
- *temp = 0;
-
- mutex_lock(&chip->reg_lock);
- ret = mv88e6xxx_phy_page_read(chip, phy, 6, 26, &val);
- mutex_unlock(&chip->reg_lock);
- if (ret < 0)
- return ret;
-
- *temp = (((val >> 8) & 0x1f) * 5) - 25;
-
- return 0;
-}
-
-static int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
-{
- struct mv88e6xxx_chip *chip = ds->priv;
- int phy = mv88e6xxx_6320_family(chip) ? 3 : 0;
- u16 val;
- int err;
-
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_TEMP_LIMIT))
- return -EOPNOTSUPP;
-
- mutex_lock(&chip->reg_lock);
- err = mv88e6xxx_phy_page_read(chip, phy, 6, 26, &val);
- if (err)
- goto unlock;
- temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f);
- err = mv88e6xxx_phy_page_write(chip, phy, 6, 26,
- (val & 0xe0ff) | (temp << 8));
-unlock:
- mutex_unlock(&chip->reg_lock);
-
- return err;
-}
-
-static int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
-{
- struct mv88e6xxx_chip *chip = ds->priv;
- int phy = mv88e6xxx_6320_family(chip) ? 3 : 0;
- u16 val;
- int ret;
-
- if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_TEMP_LIMIT))
- return -EOPNOTSUPP;
-
- *alarm = false;
-
- mutex_lock(&chip->reg_lock);
- ret = mv88e6xxx_phy_page_read(chip, phy, 6, 26, &val);
- mutex_unlock(&chip->reg_lock);
- if (ret < 0)
- return ret;
-
- *alarm = !!(val & 0x40);
-
- return 0;
-}
-#endif /* CONFIG_NET_DSA_HWMON */
-
static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
{
struct mv88e6xxx_chip *chip = ds->priv;
@@ -4372,12 +4224,6 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.get_sset_count = mv88e6xxx_get_sset_count,
.set_eee = mv88e6xxx_set_eee,
.get_eee = mv88e6xxx_get_eee,
-#ifdef CONFIG_NET_DSA_HWMON
- .get_temp = mv88e6xxx_get_temp,
- .get_temp_limit = mv88e6xxx_get_temp_limit,
- .set_temp_limit = mv88e6xxx_set_temp_limit,
- .get_temp_alarm = mv88e6xxx_get_temp_alarm,
-#endif
.get_eeprom_len = mv88e6xxx_get_eeprom_len,
.get_eeprom = mv88e6xxx_get_eeprom,
.set_eeprom = mv88e6xxx_set_eeprom,
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index a224d66dafd9..994f88fd7be1 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -496,12 +496,6 @@ enum mv88e6xxx_cap {
*/
MV88E6XXX_CAP_STU,
- /* Internal temperature sensor.
- * Available from any enabled port's PHY register 26, page 6.
- */
- MV88E6XXX_CAP_TEMP,
- MV88E6XXX_CAP_TEMP_LIMIT,
-
/* VLAN Table Unit.
* The VTU is used to program 802.1Q VLANs. See GLOBAL_VTU_OP.
*/
@@ -532,8 +526,6 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_G2_POT BIT_ULL(MV88E6XXX_CAP_G2_POT)
#define MV88E6XXX_FLAG_STU BIT_ULL(MV88E6XXX_CAP_STU)
-#define MV88E6XXX_FLAG_TEMP BIT_ULL(MV88E6XXX_CAP_TEMP)
-#define MV88E6XXX_FLAG_TEMP_LIMIT BIT_ULL(MV88E6XXX_CAP_TEMP_LIMIT)
#define MV88E6XXX_FLAG_VTU BIT_ULL(MV88E6XXX_CAP_VTU)
/* Ingress Rate Limit unit */
@@ -585,7 +577,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_STU | \
- MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP | \
@@ -604,8 +595,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_2X | \
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
- MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_TEMP_LIMIT | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP | \
@@ -620,7 +609,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_STU | \
- MV88E6XXX_FLAG_TEMP | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP | \
@@ -636,8 +624,6 @@ enum mv88e6xxx_cap {
MV88E6XXX_FLAG_G2_MGMT_EN_0X | \
MV88E6XXX_FLAG_G2_POT | \
MV88E6XXX_FLAG_STU | \
- MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_TEMP_LIMIT | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP | \
@@ -650,8 +636,6 @@ struct mv88e6xxx_ops;
(MV88E6XXX_FLAG_EEE | \
MV88E6XXX_FLAG_GLOBAL2 | \
MV88E6XXX_FLAG_STU | \
- MV88E6XXX_FLAG_TEMP | \
- MV88E6XXX_FLAG_TEMP_LIMIT | \
MV88E6XXX_FLAG_VTU | \
MV88E6XXX_FLAGS_IRL | \
MV88E6XXX_FLAGS_MULTI_CHIP | \
diff --git a/include/net/dsa.h b/include/net/dsa.h
index b94d1f2ef912..904747967726 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -307,14 +307,6 @@ struct dsa_switch_ops {
int (*get_eee)(struct dsa_switch *ds, int port,
struct ethtool_eee *e);
-#ifdef CONFIG_NET_DSA_HWMON
- /* Hardware monitoring */
- int (*get_temp)(struct dsa_switch *ds, int *temp);
- int (*get_temp_limit)(struct dsa_switch *ds, int *temp);
- int (*set_temp_limit)(struct dsa_switch *ds, int temp);
- int (*get_temp_alarm)(struct dsa_switch *ds, bool *alarm);
-#endif
-
/* EEPROM access */
int (*get_eeprom_len)(struct dsa_switch *ds);
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
if NET_DSA
-config NET_DSA_HWMON
- bool "Distributed Switch Architecture HWMON support"
- default y
- depends on HWMON && !(NET_DSA=y && HWMON=m)
- ---help---
- Say Y if you want to expose thermal sensor data on switches supported
- by the Distributed Switch Architecture.
-
- Some of those switches contain thermal sensors. This data is available
- via the hwmon sysfs interface and exposes the onboard sensors.
-
# tagging formats
config NET_DSA_TAG_BRCM
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 @@
# 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
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index fd532487dfdf..4d0e5877d3bf 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)
if (ret)
return ret;
- dsa_hwmon_register(ds);
-
return 0;
}
@@ -376,8 +374,6 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
{
int port;
- dsa_hwmon_unregister(ds);
-
/* Destroy network devices for physical switch ports. */
for (port = 0; port < DSA_MAX_PORTS; port++) {
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);
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
deleted file mode 100644
index 08831a811278..000000000000
--- a/net/dsa/hwmon.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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);
- const 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;
- }
-}
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs.
2017-01-11 1:03 [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs Andrew Lunn
2017-01-11 1:03 ` [PATCH net-next 1/2] phy: marvell: Add support for temperature sensor Andrew Lunn
2017-01-11 1:03 ` [PATCH net-next 2/2] net: dsa: Remove hwmon support Andrew Lunn
@ 2017-01-11 17:06 ` Vivien Didelot
2017-01-11 17:37 ` Andrew Lunn
2 siblings, 1 reply; 12+ messages in thread
From: Vivien Didelot @ 2017-01-11 17:06 UTC (permalink / raw)
To: Andrew Lunn, David Miller
Cc: netdev, Florian Fainelli, Andrew Lunn, Guenter Roeck
Hi Andrew,
Andrew Lunn <andrew@lunn.ch> writes:
> Marvell Ethernet switches contain temperature sensors. They are inside
> the embedded PHYs. Move the code into the PHY driver, so that discrete
> PHY drivers also export there temperature sensor.
This message is not correct. The Marvell Ethernet switches contain only
one temperature sensor for the entire chip (please adjust the cover
letter and commit messages when you respin.)
The temperature and threshold are accessed through the embedded PHY
registers of any port, as long as the port is not disabled.
Even unlikely to be used, an interrupt can be generated when the
temperature exceeds a certain threshold. It should be enabled on only
one port at a time since there is only one temperature sensor.
To sum up briefly, the temperature chip is physically inside the switch
chip, but its access is via the embedded PHYs of the switch.
I'd prefer to see the temperature code in the PHY driver as well, but I
prefer we make sure that privileging the data access over the physical
representation is the correct thing to do before moving code around.
Thanks,
Vivien
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs.
2017-01-11 17:06 ` [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs Vivien Didelot
@ 2017-01-11 17:37 ` Andrew Lunn
2017-01-11 17:55 ` Florian Fainelli
2017-01-11 18:00 ` Guenter Roeck
0 siblings, 2 replies; 12+ messages in thread
From: Andrew Lunn @ 2017-01-11 17:37 UTC (permalink / raw)
To: Vivien Didelot; +Cc: David Miller, netdev, Florian Fainelli, Guenter Roeck
On Wed, Jan 11, 2017 at 12:06:11PM -0500, Vivien Didelot wrote:
> Hi Andrew,
>
> Andrew Lunn <andrew@lunn.ch> writes:
>
> > Marvell Ethernet switches contain temperature sensors. They are inside
> > the embedded PHYs. Move the code into the PHY driver, so that discrete
> > PHY drivers also export there temperature sensor.
>
> This message is not correct. The Marvell Ethernet switches contain only
> one temperature sensor for the entire chip (please adjust the cover
> letter and commit messages when you respin.)
Agreed.
> The temperature and threshold are accessed through the embedded PHY
> registers of any port, as long as the port is not disabled.
This is not correct. Each PHY has its own threshold registers. They
can be different, even if they are applied to one shared sensor. One
PHY can be in alarm state, while others are not, due to different
thresholds.
> Even unlikely to be used, an interrupt can be generated when the
> temperature exceeds a certain threshold. It should be enabled on only
> one port at a time since there is only one temperature sensor.
Actually, since each PHY can have a different threshold, it would in
theory be possible to have different PHYs generating interrupts at
different thresholds.
However, at the moment, there is no code to enable interrupts for
temperature alarms. I also don't see any need to add such code, since
there is nowhere in HWMON to actively report such an alarm condition.
There is potentially an issue sometime down the road, if we were to
enable the temperature threshold interrupt. It is not clear what
happens if two PHYs have the same threshold conditions and this
threshold is crossed. Do all PHYs trigger an interrupt? Does only one?
Do none? I would prefer investigating and solving such issues if and
when it is decided to enable the interrupt.
> To sum up briefly, the temperature chip is physically inside the switch
> chip, but its access is via the embedded PHYs of the switch.
There is one temperature sensor in the chip, which each embedded PHY
shares for reporting the current temperature. It appears that
everything but the sensor is duplicated in each embedded PHY.
Andrew
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs.
2017-01-11 17:37 ` Andrew Lunn
@ 2017-01-11 17:55 ` Florian Fainelli
2017-01-11 19:19 ` Andrew Lunn
2017-01-11 18:00 ` Guenter Roeck
1 sibling, 1 reply; 12+ messages in thread
From: Florian Fainelli @ 2017-01-11 17:55 UTC (permalink / raw)
To: Andrew Lunn, Vivien Didelot; +Cc: David Miller, netdev, Guenter Roeck
On 01/11/2017 09:37 AM, Andrew Lunn wrote:
> On Wed, Jan 11, 2017 at 12:06:11PM -0500, Vivien Didelot wrote:
>> Hi Andrew,
>>
>> Andrew Lunn <andrew@lunn.ch> writes:
>>
>>> Marvell Ethernet switches contain temperature sensors. They are inside
>>> the embedded PHYs. Move the code into the PHY driver, so that discrete
>>> PHY drivers also export there temperature sensor.
>>
>> This message is not correct. The Marvell Ethernet switches contain only
>> one temperature sensor for the entire chip (please adjust the cover
>> letter and commit messages when you respin.)
>
> Agreed.
>
>> The temperature and threshold are accessed through the embedded PHY
>> registers of any port, as long as the port is not disabled.
>
> This is not correct. Each PHY has its own threshold registers. They
> can be different, even if they are applied to one shared sensor. One
> PHY can be in alarm state, while others are not, due to different
> thresholds.
>
>> Even unlikely to be used, an interrupt can be generated when the
>> temperature exceeds a certain threshold. It should be enabled on only
>> one port at a time since there is only one temperature sensor.
>
> Actually, since each PHY can have a different threshold, it would in
> theory be possible to have different PHYs generating interrupts at
> different thresholds.
>
> However, at the moment, there is no code to enable interrupts for
> temperature alarms. I also don't see any need to add such code, since
> there is nowhere in HWMON to actively report such an alarm condition.
Are not the *_alarm attributes specifically designed to report such
things? See Documentation/hwmon/sysfs-interface
>
> There is potentially an issue sometime down the road, if we were to
> enable the temperature threshold interrupt. It is not clear what
> happens if two PHYs have the same threshold conditions and this
> threshold is crossed. Do all PHYs trigger an interrupt? Does only one?
> Do none? I would prefer investigating and solving such issues if and
> when it is decided to enable the interrupt.
>
>> To sum up briefly, the temperature chip is physically inside the switch
>> chip, but its access is via the embedded PHYs of the switch.
>
> There is one temperature sensor in the chip, which each embedded PHY
> shares for reporting the current temperature. It appears that
> everything but the sensor is duplicated in each embedded PHY.
If that is the case, should we have a way to make the HWMON attributes
be associated with the switch device while still calling into the PHY
driver to do the actual temperature readings and such? Right now, it
sounds like we will have a duplication of HWMON attributes created for
every port of the switch that is connecting to the Marvell PHY driver.
--
Florian
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs.
2017-01-11 17:37 ` Andrew Lunn
2017-01-11 17:55 ` Florian Fainelli
@ 2017-01-11 18:00 ` Guenter Roeck
2017-01-11 19:16 ` Andrew Lunn
1 sibling, 1 reply; 12+ messages in thread
From: Guenter Roeck @ 2017-01-11 18:00 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Vivien Didelot, David Miller, netdev, Florian Fainelli
On Wed, Jan 11, 2017 at 06:37:41PM +0100, Andrew Lunn wrote:
>
> However, at the moment, there is no code to enable interrupts for
> temperature alarms. I also don't see any need to add such code, since
> there is nowhere in HWMON to actively report such an alarm condition.
>
That is not entirely correct. It is not in the hwmon core, but that is
mostly because the sysfs attributes are managed in the hwmon drivers,
at least with the legacy API, and it is thus the responsibility of
hwmon drivers to implement interrupts and to alert user space.
It is on my task list to add a callback into the core, to support
generating udev and sysfs events with the new API, but so far I don't
see a need for it because no one requested it. This makes it kind
of a circular argument (not that the dsa hwmon driver supports the
new API anyway, but still).
Guenter
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs.
2017-01-11 18:00 ` Guenter Roeck
@ 2017-01-11 19:16 ` Andrew Lunn
2017-01-11 20:00 ` Guenter Roeck
0 siblings, 1 reply; 12+ messages in thread
From: Andrew Lunn @ 2017-01-11 19:16 UTC (permalink / raw)
To: Guenter Roeck; +Cc: Vivien Didelot, David Miller, netdev, Florian Fainelli
> This makes it kind
> of a circular argument (not that the dsa hwmon driver supports the
> new API anyway, but still).
Actually, the code i posted does. I didn't just move it, i re-wrote it
to use devm_hwmon_device_register_with_info().
Andrew
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] Move hwmon support out of switch and into PHYs.
2017-01-11 19:16 ` Andrew Lunn
@ 2017-01-11 20:00 ` Guenter Roeck
0 siblings, 0 replies; 12+ messages in thread
From: Guenter Roeck @ 2017-01-11 20:00 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Vivien Didelot, David Miller, netdev, Florian Fainelli
On Wed, Jan 11, 2017 at 08:16:43PM +0100, Andrew Lunn wrote:
> > This makes it kind
> > of a circular argument (not that the dsa hwmon driver supports the
> > new API anyway, but still).
>
> Actually, the code i posted does. I didn't just move it, i re-wrote it
> to use devm_hwmon_device_register_with_info().
>
Cool. Sorry, I didn't remember. Then maybe you should ask for the core
to support the necessary callback ;-).
Guenter
^ permalink raw reply [flat|nested] 12+ messages in thread