Skip to content

Commit

Permalink
eth: fbnic: Add hardware monitoring support via HWMON interface
Browse files Browse the repository at this point in the history
This patch adds support for hardware monitoring to the fbnic driver,
allowing for temperature and voltage sensor data to be exposed to
userspace via the HWMON interface. The driver registers a HWMON device
and provides callbacks for reading sensor data, enabling system
admins to monitor the health and operating conditions of fbnic.

Signed-off-by: Sanman Pradhan <sanmanpradhan@meta.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Link: https://patch.msgid.link/20241014152709.2123811-1-sanman.p211993@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
sanmanpradhanmeta authored and Paolo Abeni committed Oct 17, 2024
1 parent e60fa8e commit d85ebad
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/meta/fbnic/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fbnic-y := fbnic_devlink.o \
fbnic_ethtool.o \
fbnic_fw.o \
fbnic_hw_stats.o \
fbnic_hwmon.o \
fbnic_irq.o \
fbnic_mac.o \
fbnic_netdev.o \
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/meta/fbnic/fbnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
struct fbnic_dev {
struct device *dev;
struct net_device *netdev;
struct device *hwmon;

u32 __iomem *uc_addr0;
u32 __iomem *uc_addr4;
Expand All @@ -31,6 +32,7 @@ struct fbnic_dev {

struct fbnic_fw_mbx mbx[FBNIC_IPC_MBX_INDICES];
struct fbnic_fw_cap fw_cap;
struct fbnic_fw_completion *cmpl_data;
/* Lock protecting Tx Mailbox queue to prevent possible races */
spinlock_t fw_tx_lock;

Expand Down Expand Up @@ -138,6 +140,9 @@ void fbnic_devlink_unregister(struct fbnic_dev *fbd);
int fbnic_fw_enable_mbx(struct fbnic_dev *fbd);
void fbnic_fw_disable_mbx(struct fbnic_dev *fbd);

void fbnic_hwmon_register(struct fbnic_dev *fbd);
void fbnic_hwmon_unregister(struct fbnic_dev *fbd);

int fbnic_pcs_irq_enable(struct fbnic_dev *fbd);
void fbnic_pcs_irq_disable(struct fbnic_dev *fbd);

Expand Down
7 changes: 7 additions & 0 deletions drivers/net/ethernet/meta/fbnic/fbnic_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ struct fbnic_fw_cap {
u8 link_fec;
};

struct fbnic_fw_completion {
struct {
s32 millivolts;
s32 millidegrees;
} tsene;
};

void fbnic_mbx_init(struct fbnic_dev *fbd);
void fbnic_mbx_clean(struct fbnic_dev *fbd);
void fbnic_mbx_poll(struct fbnic_dev *fbd);
Expand Down
81 changes: 81 additions & 0 deletions drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) Meta Platforms, Inc. and affiliates. */

#include <linux/hwmon.h>

#include "fbnic.h"
#include "fbnic_mac.h"

static int fbnic_hwmon_sensor_id(enum hwmon_sensor_types type)
{
if (type == hwmon_temp)
return FBNIC_SENSOR_TEMP;
if (type == hwmon_in)
return FBNIC_SENSOR_VOLTAGE;

return -EOPNOTSUPP;
}

static umode_t fbnic_hwmon_is_visible(const void *drvdata,
enum hwmon_sensor_types type,
u32 attr, int channel)
{
if (type == hwmon_temp && attr == hwmon_temp_input)
return 0444;
if (type == hwmon_in && attr == hwmon_in_input)
return 0444;

return 0;
}

static int fbnic_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct fbnic_dev *fbd = dev_get_drvdata(dev);
const struct fbnic_mac *mac = fbd->mac;
int id;

id = fbnic_hwmon_sensor_id(type);
return id < 0 ? id : mac->get_sensor(fbd, id, val);
}

static const struct hwmon_ops fbnic_hwmon_ops = {
.is_visible = fbnic_hwmon_is_visible,
.read = fbnic_hwmon_read,
};

static const struct hwmon_channel_info *fbnic_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
HWMON_CHANNEL_INFO(in, HWMON_I_INPUT),
NULL
};

static const struct hwmon_chip_info fbnic_chip_info = {
.ops = &fbnic_hwmon_ops,
.info = fbnic_hwmon_info,
};

void fbnic_hwmon_register(struct fbnic_dev *fbd)
{
if (!IS_REACHABLE(CONFIG_HWMON))
return;

fbd->hwmon = hwmon_device_register_with_info(fbd->dev, "fbnic",
fbd, &fbnic_chip_info,
NULL);
if (IS_ERR(fbd->hwmon)) {
dev_notice(fbd->dev,
"Failed to register hwmon device %pe\n",
fbd->hwmon);
fbd->hwmon = NULL;
}
}

void fbnic_hwmon_unregister(struct fbnic_dev *fbd)
{
if (!IS_REACHABLE(CONFIG_HWMON) || !fbd->hwmon)
return;

hwmon_device_unregister(fbd->hwmon);
fbd->hwmon = NULL;
}
22 changes: 22 additions & 0 deletions drivers/net/ethernet/meta/fbnic/fbnic_mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,27 @@ fbnic_mac_get_eth_mac_stats(struct fbnic_dev *fbd, bool reset,
MAC_STAT_TX_BROADCAST);
}

static int fbnic_mac_get_sensor_asic(struct fbnic_dev *fbd, int id, long *val)
{
struct fbnic_fw_completion fw_cmpl;
s32 *sensor;

switch (id) {
case FBNIC_SENSOR_TEMP:
sensor = &fw_cmpl.tsene.millidegrees;
break;
case FBNIC_SENSOR_VOLTAGE:
sensor = &fw_cmpl.tsene.millivolts;
break;
default:
return -EINVAL;
}

*val = *sensor;

return 0;
}

static const struct fbnic_mac fbnic_mac_asic = {
.init_regs = fbnic_mac_init_regs,
.pcs_enable = fbnic_pcs_enable_asic,
Expand All @@ -695,6 +716,7 @@ static const struct fbnic_mac fbnic_mac_asic = {
.get_eth_mac_stats = fbnic_mac_get_eth_mac_stats,
.link_down = fbnic_mac_link_down_asic,
.link_up = fbnic_mac_link_up_asic,
.get_sensor = fbnic_mac_get_sensor_asic,
};

/**
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/ethernet/meta/fbnic/fbnic_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ enum {
#define FBNIC_LINK_MODE_PAM4 (FBNIC_LINK_50R1)
#define FBNIC_LINK_MODE_MASK (FBNIC_LINK_AUTO - 1)

enum fbnic_sensor_id {
FBNIC_SENSOR_TEMP, /* Temp in millidegrees Centigrade */
FBNIC_SENSOR_VOLTAGE, /* Voltage in millivolts */
};

/* This structure defines the interface hooks for the MAC. The MAC hooks
* will be configured as a const struct provided with a set of function
* pointers.
Expand Down Expand Up @@ -83,6 +88,8 @@ struct fbnic_mac {

void (*link_down)(struct fbnic_dev *fbd);
void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);

int (*get_sensor)(struct fbnic_dev *fbd, int id, long *val);
};

int fbnic_mac_init(struct fbnic_dev *fbd);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/meta/fbnic/fbnic_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

fbnic_devlink_register(fbd);

fbnic_hwmon_register(fbd);

if (!fbd->dsn) {
dev_warn(&pdev->dev, "Reading serial number failed\n");
goto init_failure_mode;
Expand Down Expand Up @@ -352,6 +354,7 @@ static void fbnic_remove(struct pci_dev *pdev)
fbnic_netdev_free(fbd);
}

fbnic_hwmon_unregister(fbd);
fbnic_devlink_unregister(fbd);
fbnic_fw_disable_mbx(fbd);
fbnic_free_irqs(fbd);
Expand Down

0 comments on commit d85ebad

Please sign in to comment.