|
44 | 44 | #include <linux/prefetch.h>
|
45 | 45 | #include <linux/dma-mapping.h>
|
46 | 46 | #include <linux/firmware.h>
|
| 47 | +#if IS_ENABLED(CONFIG_HWMON) |
| 48 | +#include <linux/hwmon.h> |
| 49 | +#include <linux/hwmon-sysfs.h> |
| 50 | +#endif |
47 | 51 |
|
48 | 52 | #include <net/checksum.h>
|
49 | 53 | #include <net/ip.h>
|
@@ -9481,6 +9485,110 @@ static int tg3_init_hw(struct tg3 *tp, int reset_phy)
|
9481 | 9485 | return tg3_reset_hw(tp, reset_phy);
|
9482 | 9486 | }
|
9483 | 9487 |
|
| 9488 | +#if IS_ENABLED(CONFIG_HWMON) |
| 9489 | +static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir) |
| 9490 | +{ |
| 9491 | + int i; |
| 9492 | + |
| 9493 | + for (i = 0; i < TG3_SD_NUM_RECS; i++, ocir++) { |
| 9494 | + u32 off = i * TG3_OCIR_LEN, len = TG3_OCIR_LEN; |
| 9495 | + |
| 9496 | + tg3_ape_scratchpad_read(tp, (u32 *) ocir, off, len); |
| 9497 | + off += len; |
| 9498 | + |
| 9499 | + if (ocir->signature != TG3_OCIR_SIG_MAGIC || |
| 9500 | + !(ocir->version_flags & TG3_OCIR_FLAG_ACTIVE)) |
| 9501 | + memset(ocir, 0, TG3_OCIR_LEN); |
| 9502 | + } |
| 9503 | +} |
| 9504 | + |
| 9505 | +/* sysfs attributes for hwmon */ |
| 9506 | +static ssize_t tg3_show_temp(struct device *dev, |
| 9507 | + struct device_attribute *devattr, char *buf) |
| 9508 | +{ |
| 9509 | + struct pci_dev *pdev = to_pci_dev(dev); |
| 9510 | + struct net_device *netdev = pci_get_drvdata(pdev); |
| 9511 | + struct tg3 *tp = netdev_priv(netdev); |
| 9512 | + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 9513 | + u32 temperature; |
| 9514 | + |
| 9515 | + spin_lock_bh(&tp->lock); |
| 9516 | + tg3_ape_scratchpad_read(tp, &temperature, attr->index, |
| 9517 | + sizeof(temperature)); |
| 9518 | + spin_unlock_bh(&tp->lock); |
| 9519 | + return sprintf(buf, "%u\n", temperature); |
| 9520 | +} |
| 9521 | + |
| 9522 | + |
| 9523 | +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tg3_show_temp, NULL, |
| 9524 | + TG3_TEMP_SENSOR_OFFSET); |
| 9525 | +static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, tg3_show_temp, NULL, |
| 9526 | + TG3_TEMP_CAUTION_OFFSET); |
| 9527 | +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, tg3_show_temp, NULL, |
| 9528 | + TG3_TEMP_MAX_OFFSET); |
| 9529 | + |
| 9530 | +static struct attribute *tg3_attributes[] = { |
| 9531 | + &sensor_dev_attr_temp1_input.dev_attr.attr, |
| 9532 | + &sensor_dev_attr_temp1_crit.dev_attr.attr, |
| 9533 | + &sensor_dev_attr_temp1_max.dev_attr.attr, |
| 9534 | + NULL |
| 9535 | +}; |
| 9536 | + |
| 9537 | +static const struct attribute_group tg3_group = { |
| 9538 | + .attrs = tg3_attributes, |
| 9539 | +}; |
| 9540 | + |
| 9541 | +#endif |
| 9542 | + |
| 9543 | +static void tg3_hwmon_close(struct tg3 *tp) |
| 9544 | +{ |
| 9545 | +#if IS_ENABLED(CONFIG_HWMON) |
| 9546 | + if (tp->hwmon_dev) { |
| 9547 | + hwmon_device_unregister(tp->hwmon_dev); |
| 9548 | + tp->hwmon_dev = NULL; |
| 9549 | + sysfs_remove_group(&tp->pdev->dev.kobj, &tg3_group); |
| 9550 | + } |
| 9551 | +#endif |
| 9552 | +} |
| 9553 | + |
| 9554 | +static void tg3_hwmon_open(struct tg3 *tp) |
| 9555 | +{ |
| 9556 | +#if IS_ENABLED(CONFIG_HWMON) |
| 9557 | + int i, err; |
| 9558 | + u32 size = 0; |
| 9559 | + struct pci_dev *pdev = tp->pdev; |
| 9560 | + struct tg3_ocir ocirs[TG3_SD_NUM_RECS]; |
| 9561 | + |
| 9562 | + tg3_sd_scan_scratchpad(tp, ocirs); |
| 9563 | + |
| 9564 | + for (i = 0; i < TG3_SD_NUM_RECS; i++) { |
| 9565 | + if (!ocirs[i].src_data_length) |
| 9566 | + continue; |
| 9567 | + |
| 9568 | + size += ocirs[i].src_hdr_length; |
| 9569 | + size += ocirs[i].src_data_length; |
| 9570 | + } |
| 9571 | + |
| 9572 | + if (!size) |
| 9573 | + return; |
| 9574 | + |
| 9575 | + /* Register hwmon sysfs hooks */ |
| 9576 | + err = sysfs_create_group(&pdev->dev.kobj, &tg3_group); |
| 9577 | + if (err) { |
| 9578 | + dev_err(&pdev->dev, "Cannot create sysfs group, aborting\n"); |
| 9579 | + return; |
| 9580 | + } |
| 9581 | + |
| 9582 | + tp->hwmon_dev = hwmon_device_register(&pdev->dev); |
| 9583 | + if (IS_ERR(tp->hwmon_dev)) { |
| 9584 | + tp->hwmon_dev = NULL; |
| 9585 | + dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n"); |
| 9586 | + sysfs_remove_group(&pdev->dev.kobj, &tg3_group); |
| 9587 | + } |
| 9588 | +#endif |
| 9589 | +} |
| 9590 | + |
| 9591 | + |
9484 | 9592 | #define TG3_STAT_ADD32(PSTAT, REG) \
|
9485 | 9593 | do { u32 __val = tr32(REG); \
|
9486 | 9594 | (PSTAT)->low += __val; \
|
@@ -10189,6 +10297,8 @@ static int tg3_open(struct net_device *dev)
|
10189 | 10297 |
|
10190 | 10298 | tg3_phy_start(tp);
|
10191 | 10299 |
|
| 10300 | + tg3_hwmon_open(tp); |
| 10301 | + |
10192 | 10302 | tg3_full_lock(tp, 0);
|
10193 | 10303 |
|
10194 | 10304 | tg3_timer_start(tp);
|
@@ -10238,6 +10348,8 @@ static int tg3_close(struct net_device *dev)
|
10238 | 10348 |
|
10239 | 10349 | tg3_timer_stop(tp);
|
10240 | 10350 |
|
| 10351 | + tg3_hwmon_close(tp); |
| 10352 | + |
10241 | 10353 | tg3_phy_stop(tp);
|
10242 | 10354 |
|
10243 | 10355 | tg3_full_lock(tp, 1);
|
|
0 commit comments