Skip to content

Commit 89e6f19

Browse files
sanmanp2111993kuba-moo
authored andcommitted
eth: fbnic: hwmon: Add support for reading temperature and voltage sensors
Add support for reading temperature and voltage sensor data from firmware by implementing a new TSENE message type and response parsing. This adds message handler infrastructure to transmit sensor read requests and parse responses. The sensor data will be exposed through the driver's hwmon interface. Signed-off-by: Sanman Pradhan <[email protected]> Reviewed-by: Michal Swiatkowski <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 378e5cc commit 89e6f19

File tree

4 files changed

+179
-4
lines changed

4 files changed

+179
-4
lines changed

drivers/net/ethernet/meta/fbnic/fbnic_fw.c

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ static void fbnic_mbx_process_tx_msgs(struct fbnic_dev *fbd)
228228
tx_mbx->head = head;
229229
}
230230

231-
static __maybe_unused int fbnic_mbx_map_req_w_cmpl(struct fbnic_dev *fbd,
232-
struct fbnic_tlv_msg *msg,
233-
struct fbnic_fw_completion *cmpl_data)
231+
static int fbnic_mbx_map_req_w_cmpl(struct fbnic_dev *fbd,
232+
struct fbnic_tlv_msg *msg,
233+
struct fbnic_fw_completion *cmpl_data)
234234
{
235235
unsigned long flags;
236236
int err;
@@ -269,7 +269,7 @@ static void fbnic_fw_release_cmpl_data(struct kref *kref)
269269
kfree(cmpl_data);
270270
}
271271

272-
static __maybe_unused struct fbnic_fw_completion *
272+
static struct fbnic_fw_completion *
273273
fbnic_fw_get_cmpl_by_type(struct fbnic_dev *fbd, u32 msg_type)
274274
{
275275
struct fbnic_fw_completion *cmpl_data = NULL;
@@ -708,13 +708,94 @@ void fbnic_fw_check_heartbeat(struct fbnic_dev *fbd)
708708
dev_warn(fbd->dev, "Failed to send heartbeat message\n");
709709
}
710710

711+
/**
712+
* fbnic_fw_xmit_tsene_read_msg - Create and transmit a sensor read request
713+
* @fbd: FBNIC device structure
714+
* @cmpl_data: Completion data structure to store sensor response
715+
*
716+
* Asks the firmware to provide an update with the latest sensor data.
717+
* The response will contain temperature and voltage readings.
718+
*
719+
* Return: 0 on success, negative error value on failure
720+
*/
721+
int fbnic_fw_xmit_tsene_read_msg(struct fbnic_dev *fbd,
722+
struct fbnic_fw_completion *cmpl_data)
723+
{
724+
struct fbnic_tlv_msg *msg;
725+
int err;
726+
727+
if (!fbnic_fw_present(fbd))
728+
return -ENODEV;
729+
730+
msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_TSENE_READ_REQ);
731+
if (!msg)
732+
return -ENOMEM;
733+
734+
err = fbnic_mbx_map_req_w_cmpl(fbd, msg, cmpl_data);
735+
if (err)
736+
goto free_message;
737+
738+
return 0;
739+
740+
free_message:
741+
free_page((unsigned long)msg);
742+
return err;
743+
}
744+
745+
static const struct fbnic_tlv_index fbnic_tsene_read_resp_index[] = {
746+
FBNIC_TLV_ATTR_S32(FBNIC_TSENE_THERM),
747+
FBNIC_TLV_ATTR_S32(FBNIC_TSENE_VOLT),
748+
FBNIC_TLV_ATTR_S32(FBNIC_TSENE_ERROR),
749+
FBNIC_TLV_ATTR_LAST
750+
};
751+
752+
static int fbnic_fw_parse_tsene_read_resp(void *opaque,
753+
struct fbnic_tlv_msg **results)
754+
{
755+
struct fbnic_fw_completion *cmpl_data;
756+
struct fbnic_dev *fbd = opaque;
757+
int err = 0;
758+
759+
/* Verify we have a completion pointer to provide with data */
760+
cmpl_data = fbnic_fw_get_cmpl_by_type(fbd,
761+
FBNIC_TLV_MSG_ID_TSENE_READ_RESP);
762+
if (!cmpl_data)
763+
return -EINVAL;
764+
765+
if (results[FBNIC_TSENE_ERROR]) {
766+
err = fbnic_tlv_attr_get_unsigned(results[FBNIC_TSENE_ERROR]);
767+
if (err)
768+
goto exit_complete;
769+
}
770+
771+
if (!results[FBNIC_TSENE_THERM] || !results[FBNIC_TSENE_VOLT]) {
772+
err = -EINVAL;
773+
goto exit_complete;
774+
}
775+
776+
cmpl_data->u.tsene.millidegrees =
777+
fbnic_tlv_attr_get_signed(results[FBNIC_TSENE_THERM]);
778+
cmpl_data->u.tsene.millivolts =
779+
fbnic_tlv_attr_get_signed(results[FBNIC_TSENE_VOLT]);
780+
781+
exit_complete:
782+
cmpl_data->result = err;
783+
complete(&cmpl_data->done);
784+
fbnic_fw_put_cmpl(cmpl_data);
785+
786+
return err;
787+
}
788+
711789
static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {
712790
FBNIC_TLV_PARSER(FW_CAP_RESP, fbnic_fw_cap_resp_index,
713791
fbnic_fw_parse_cap_resp),
714792
FBNIC_TLV_PARSER(OWNERSHIP_RESP, fbnic_ownership_resp_index,
715793
fbnic_fw_parse_ownership_resp),
716794
FBNIC_TLV_PARSER(HEARTBEAT_RESP, fbnic_heartbeat_resp_index,
717795
fbnic_fw_parse_heartbeat_resp),
796+
FBNIC_TLV_PARSER(TSENE_READ_RESP,
797+
fbnic_tsene_read_resp_index,
798+
fbnic_fw_parse_tsene_read_resp),
718799
FBNIC_TLV_MSG_ERROR
719800
};
720801

drivers/net/ethernet/meta/fbnic/fbnic_fw.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ struct fbnic_fw_completion {
5050
struct kref ref_count;
5151
int result;
5252
union {
53+
struct {
54+
s32 millivolts;
55+
s32 millidegrees;
56+
} tsene;
5357
} u;
5458
};
5559

@@ -61,6 +65,8 @@ void fbnic_mbx_flush_tx(struct fbnic_dev *fbd);
6165
int fbnic_fw_xmit_ownership_msg(struct fbnic_dev *fbd, bool take_ownership);
6266
int fbnic_fw_init_heartbeat(struct fbnic_dev *fbd, bool poll);
6367
void fbnic_fw_check_heartbeat(struct fbnic_dev *fbd);
68+
int fbnic_fw_xmit_tsene_read_msg(struct fbnic_dev *fbd,
69+
struct fbnic_fw_completion *cmpl_data);
6470
void fbnic_fw_init_cmpl(struct fbnic_fw_completion *cmpl_data,
6571
u32 msg_type);
6672
void fbnic_fw_clear_compl(struct fbnic_dev *fbd);
@@ -89,6 +95,8 @@ enum {
8995
FBNIC_TLV_MSG_ID_OWNERSHIP_RESP = 0x13,
9096
FBNIC_TLV_MSG_ID_HEARTBEAT_REQ = 0x14,
9197
FBNIC_TLV_MSG_ID_HEARTBEAT_RESP = 0x15,
98+
FBNIC_TLV_MSG_ID_TSENE_READ_REQ = 0x3C,
99+
FBNIC_TLV_MSG_ID_TSENE_READ_RESP = 0x3D,
92100
};
93101

94102
#define FBNIC_FW_CAP_RESP_VERSION_MAJOR CSR_GENMASK(31, 24)
@@ -130,6 +138,13 @@ enum {
130138
FBNIC_FW_LINK_FEC_BASER = 3,
131139
};
132140

141+
enum {
142+
FBNIC_TSENE_THERM = 0x0,
143+
FBNIC_TSENE_VOLT = 0x1,
144+
FBNIC_TSENE_ERROR = 0x2,
145+
FBNIC_TSENE_MSG_MAX
146+
};
147+
133148
enum {
134149
FBNIC_FW_OWNERSHIP_FLAG = 0x0,
135150
FBNIC_FW_OWNERSHIP_MSG_MAX

drivers/net/ethernet/meta/fbnic/fbnic_mac.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,77 @@ fbnic_mac_get_eth_mac_stats(struct fbnic_dev *fbd, bool reset,
686686
MAC_STAT_TX_BROADCAST);
687687
}
688688

689+
static int fbnic_mac_get_sensor_asic(struct fbnic_dev *fbd, int id,
690+
long *val)
691+
{
692+
struct fbnic_fw_completion *fw_cmpl;
693+
int err = 0, retries = 5;
694+
s32 *sensor;
695+
696+
fw_cmpl = kzalloc(sizeof(*fw_cmpl), GFP_KERNEL);
697+
if (!fw_cmpl)
698+
return -ENOMEM;
699+
700+
/* Initialize completion and queue it for FW to process */
701+
fbnic_fw_init_cmpl(fw_cmpl, FBNIC_TLV_MSG_ID_TSENE_READ_RESP);
702+
703+
switch (id) {
704+
case FBNIC_SENSOR_TEMP:
705+
sensor = &fw_cmpl->u.tsene.millidegrees;
706+
break;
707+
case FBNIC_SENSOR_VOLTAGE:
708+
sensor = &fw_cmpl->u.tsene.millivolts;
709+
break;
710+
default:
711+
err = -EINVAL;
712+
goto exit_free;
713+
}
714+
715+
err = fbnic_fw_xmit_tsene_read_msg(fbd, fw_cmpl);
716+
if (err) {
717+
dev_err(fbd->dev,
718+
"Failed to transmit TSENE read msg, err %d\n",
719+
err);
720+
goto exit_free;
721+
}
722+
723+
/* Allow 2 seconds for reply, resend and try up to 5 times */
724+
while (!wait_for_completion_timeout(&fw_cmpl->done, 2 * HZ)) {
725+
retries--;
726+
727+
if (retries == 0) {
728+
dev_err(fbd->dev,
729+
"Timed out waiting for TSENE read\n");
730+
err = -ETIMEDOUT;
731+
goto exit_cleanup;
732+
}
733+
734+
err = fbnic_fw_xmit_tsene_read_msg(fbd, NULL);
735+
if (err) {
736+
dev_err(fbd->dev,
737+
"Failed to transmit TSENE read msg, err %d\n",
738+
err);
739+
goto exit_cleanup;
740+
}
741+
}
742+
743+
/* Handle error returned by firmware */
744+
if (fw_cmpl->result) {
745+
err = fw_cmpl->result;
746+
dev_err(fbd->dev, "%s: Firmware returned error %d\n",
747+
__func__, err);
748+
goto exit_cleanup;
749+
}
750+
751+
*val = *sensor;
752+
exit_cleanup:
753+
fbnic_fw_clear_compl(fbd);
754+
exit_free:
755+
fbnic_fw_put_cmpl(fw_cmpl);
756+
757+
return err;
758+
}
759+
689760
static const struct fbnic_mac fbnic_mac_asic = {
690761
.init_regs = fbnic_mac_init_regs,
691762
.pcs_enable = fbnic_pcs_enable_asic,
@@ -695,6 +766,7 @@ static const struct fbnic_mac fbnic_mac_asic = {
695766
.get_eth_mac_stats = fbnic_mac_get_eth_mac_stats,
696767
.link_down = fbnic_mac_link_down_asic,
697768
.link_up = fbnic_mac_link_up_asic,
769+
.get_sensor = fbnic_mac_get_sensor_asic,
698770
};
699771

700772
/**

drivers/net/ethernet/meta/fbnic/fbnic_mac.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ enum {
4747
#define FBNIC_LINK_MODE_PAM4 (FBNIC_LINK_50R1)
4848
#define FBNIC_LINK_MODE_MASK (FBNIC_LINK_AUTO - 1)
4949

50+
enum fbnic_sensor_id {
51+
FBNIC_SENSOR_TEMP, /* Temp in millidegrees Centigrade */
52+
FBNIC_SENSOR_VOLTAGE, /* Voltage in millivolts */
53+
};
54+
5055
/* This structure defines the interface hooks for the MAC. The MAC hooks
5156
* will be configured as a const struct provided with a set of function
5257
* pointers.
@@ -83,6 +88,8 @@ struct fbnic_mac {
8388

8489
void (*link_down)(struct fbnic_dev *fbd);
8590
void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);
91+
92+
int (*get_sensor)(struct fbnic_dev *fbd, int id, long *val);
8693
};
8794

8895
int fbnic_mac_init(struct fbnic_dev *fbd);

0 commit comments

Comments
 (0)