Commit 20767b23 authored by David S. Miller's avatar David S. Miller

Merge branch 'bnxt_en-hwmon-SRIOV'

Michael Chan says:

====================
bnxt_en: hwmon and SRIOV updates

The first 7 patches are v2 of the hwmon patches posted about 6 weeks ago
on Aug 14.  The last 2 patches are SRIOV related updates.

Link to v1 hwmon patches:
https://lore.kernel.org/netdev/20230815045658.80494-11-michael.chan@broadcom.com/
====================
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 20f7cce7 cbdbf0aa
...@@ -4,3 +4,4 @@ obj-$(CONFIG_BNXT) += bnxt_en.o ...@@ -4,3 +4,4 @@ obj-$(CONFIG_BNXT) += bnxt_en.o
bnxt_en-y := bnxt.o bnxt_hwrm.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o bnxt_coredump.o bnxt_en-y := bnxt.o bnxt_hwrm.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o bnxt_coredump.o
bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o
bnxt_en-$(CONFIG_DEBUG_FS) += bnxt_debugfs.o bnxt_en-$(CONFIG_DEBUG_FS) += bnxt_debugfs.o
bnxt_en-$(CONFIG_BNXT_HWMON) += bnxt_hwmon.o
...@@ -52,8 +52,6 @@ ...@@ -52,8 +52,6 @@
#include <linux/cpu_rmap.h> #include <linux/cpu_rmap.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <net/page_pool/helpers.h> #include <net/page_pool/helpers.h>
#include <linux/align.h> #include <linux/align.h>
#include <net/netdev_queues.h> #include <net/netdev_queues.h>
...@@ -71,6 +69,7 @@ ...@@ -71,6 +69,7 @@
#include "bnxt_tc.h" #include "bnxt_tc.h"
#include "bnxt_devlink.h" #include "bnxt_devlink.h"
#include "bnxt_debugfs.h" #include "bnxt_debugfs.h"
#include "bnxt_hwmon.h"
#define BNXT_TX_TIMEOUT (5 * HZ) #define BNXT_TX_TIMEOUT (5 * HZ)
#define BNXT_DEF_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_HW | \ #define BNXT_DEF_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_HW | \
...@@ -2130,6 +2129,24 @@ static u16 bnxt_agg_ring_id_to_grp_idx(struct bnxt *bp, u16 ring_id) ...@@ -2130,6 +2129,24 @@ static u16 bnxt_agg_ring_id_to_grp_idx(struct bnxt *bp, u16 ring_id)
return INVALID_HW_RING_ID; return INVALID_HW_RING_ID;
} }
#define BNXT_EVENT_THERMAL_CURRENT_TEMP(data2) \
((data2) & \
ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_MASK)
#define BNXT_EVENT_THERMAL_THRESHOLD_TEMP(data2) \
(((data2) & \
ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_THRESHOLD_TEMP_MASK) >>\
ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_THRESHOLD_TEMP_SFT)
#define EVENT_DATA1_THERMAL_THRESHOLD_TYPE(data1) \
((data1) & \
ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_MASK)
#define EVENT_DATA1_THERMAL_THRESHOLD_DIR_INCREASING(data1) \
(((data1) & \
ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR) ==\
ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR_INCREASING)
static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2) static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2)
{ {
u32 err_type = BNXT_EVENT_ERROR_REPORT_TYPE(data1); u32 err_type = BNXT_EVENT_ERROR_REPORT_TYPE(data1);
...@@ -2145,6 +2162,40 @@ static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2) ...@@ -2145,6 +2162,40 @@ static void bnxt_event_error_report(struct bnxt *bp, u32 data1, u32 data2)
case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD: case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD:
netdev_warn(bp->dev, "One or more MMIO doorbells dropped by the device!\n"); netdev_warn(bp->dev, "One or more MMIO doorbells dropped by the device!\n");
break; break;
case ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_THERMAL_THRESHOLD: {
u32 type = EVENT_DATA1_THERMAL_THRESHOLD_TYPE(data1);
char *threshold_type;
char *dir_str;
switch (type) {
case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_WARN:
threshold_type = "warning";
break;
case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_CRITICAL:
threshold_type = "critical";
break;
case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_FATAL:
threshold_type = "fatal";
break;
case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_SHUTDOWN:
threshold_type = "shutdown";
break;
default:
netdev_err(bp->dev, "Unknown Thermal threshold type event\n");
return;
}
if (EVENT_DATA1_THERMAL_THRESHOLD_DIR_INCREASING(data1))
dir_str = "above";
else
dir_str = "below";
netdev_warn(bp->dev, "Chip temperature has gone %s the %s thermal threshold!\n",
dir_str, threshold_type);
netdev_warn(bp->dev, "Temperature (In Celsius), Current: %lu, threshold: %lu\n",
BNXT_EVENT_THERMAL_CURRENT_TEMP(data2),
BNXT_EVENT_THERMAL_THRESHOLD_TEMP(data2));
bnxt_hwmon_notify_event(bp, type);
break;
}
default: default:
netdev_err(bp->dev, "FW reported unknown error type %u\n", netdev_err(bp->dev, "FW reported unknown error type %u\n",
err_type); err_type);
...@@ -7699,6 +7750,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp) ...@@ -7699,6 +7750,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
bp->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF; bp->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF;
if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED)) if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED))
bp->fw_cap |= BNXT_FW_CAP_LIVEPATCH; bp->fw_cap |= BNXT_FW_CAP_LIVEPATCH;
if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_DFLT_VLAN_TPID_PCP_SUPPORTED))
bp->fw_cap |= BNXT_FW_CAP_DFLT_VLAN_TPID_PCP;
flags_ext2 = le32_to_cpu(resp->flags_ext2); flags_ext2 = le32_to_cpu(resp->flags_ext2);
if (flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_RX_ALL_PKTS_TIMESTAMPS_SUPPORTED) if (flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_RX_ALL_PKTS_TIMESTAMPS_SUPPORTED)
...@@ -10250,79 +10303,6 @@ static void bnxt_get_wol_settings(struct bnxt *bp) ...@@ -10250,79 +10303,6 @@ static void bnxt_get_wol_settings(struct bnxt *bp)
} while (handle && handle != 0xffff); } while (handle && handle != 0xffff);
} }
#ifdef CONFIG_BNXT_HWMON
static ssize_t bnxt_show_temp(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct hwrm_temp_monitor_query_output *resp;
struct hwrm_temp_monitor_query_input *req;
struct bnxt *bp = dev_get_drvdata(dev);
u32 len = 0;
int rc;
rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
if (rc)
return rc;
resp = hwrm_req_hold(bp, req);
rc = hwrm_req_send(bp, req);
if (!rc)
len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
hwrm_req_drop(bp, req);
if (rc)
return rc;
return len;
}
static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
static struct attribute *bnxt_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL
};
ATTRIBUTE_GROUPS(bnxt);
static void bnxt_hwmon_close(struct bnxt *bp)
{
if (bp->hwmon_dev) {
hwmon_device_unregister(bp->hwmon_dev);
bp->hwmon_dev = NULL;
}
}
static void bnxt_hwmon_open(struct bnxt *bp)
{
struct hwrm_temp_monitor_query_input *req;
struct pci_dev *pdev = bp->pdev;
int rc;
rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
if (!rc)
rc = hwrm_req_send_silent(bp, req);
if (rc == -EACCES || rc == -EOPNOTSUPP) {
bnxt_hwmon_close(bp);
return;
}
if (bp->hwmon_dev)
return;
bp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
DRV_MODULE_NAME, bp,
bnxt_groups);
if (IS_ERR(bp->hwmon_dev)) {
bp->hwmon_dev = NULL;
dev_warn(&pdev->dev, "Cannot register hwmon device\n");
}
}
#else
static void bnxt_hwmon_close(struct bnxt *bp)
{
}
static void bnxt_hwmon_open(struct bnxt *bp)
{
}
#endif
static bool bnxt_eee_config_ok(struct bnxt *bp) static bool bnxt_eee_config_ok(struct bnxt *bp)
{ {
struct ethtool_eee *eee = &bp->eee; struct ethtool_eee *eee = &bp->eee;
...@@ -10651,7 +10631,6 @@ static int bnxt_open(struct net_device *dev) ...@@ -10651,7 +10631,6 @@ static int bnxt_open(struct net_device *dev)
bnxt_reenable_sriov(bp); bnxt_reenable_sriov(bp);
} }
} }
bnxt_hwmon_open(bp);
} }
return rc; return rc;
...@@ -10736,7 +10715,6 @@ static int bnxt_close(struct net_device *dev) ...@@ -10736,7 +10715,6 @@ static int bnxt_close(struct net_device *dev)
{ {
struct bnxt *bp = netdev_priv(dev); struct bnxt *bp = netdev_priv(dev);
bnxt_hwmon_close(bp);
bnxt_close_nic(bp, true, true); bnxt_close_nic(bp, true, true);
bnxt_hwrm_shutdown_link(bp); bnxt_hwrm_shutdown_link(bp);
bnxt_hwrm_if_change(bp, false); bnxt_hwrm_if_change(bp, false);
...@@ -12237,6 +12215,20 @@ static void bnxt_init_dflt_coal(struct bnxt *bp) ...@@ -12237,6 +12215,20 @@ static void bnxt_init_dflt_coal(struct bnxt *bp)
bp->stats_coal_ticks = BNXT_DEF_STATS_COAL_TICKS; bp->stats_coal_ticks = BNXT_DEF_STATS_COAL_TICKS;
} }
/* FW that pre-reserves 1 VNIC per function */
static bool bnxt_fw_pre_resv_vnics(struct bnxt *bp)
{
u16 fw_maj = BNXT_FW_MAJ(bp), fw_bld = BNXT_FW_BLD(bp);
if (!(bp->flags & BNXT_FLAG_CHIP_P5) &&
(fw_maj > 218 || (fw_maj == 218 && fw_bld >= 18)))
return true;
if ((bp->flags & BNXT_FLAG_CHIP_P5) &&
(fw_maj > 216 || (fw_maj == 216 && fw_bld >= 172)))
return true;
return false;
}
static int bnxt_fw_init_one_p1(struct bnxt *bp) static int bnxt_fw_init_one_p1(struct bnxt *bp)
{ {
int rc; int rc;
...@@ -12293,6 +12285,9 @@ static int bnxt_fw_init_one_p2(struct bnxt *bp) ...@@ -12293,6 +12285,9 @@ static int bnxt_fw_init_one_p2(struct bnxt *bp)
if (rc) if (rc)
return -ENODEV; return -ENODEV;
if (bnxt_fw_pre_resv_vnics(bp))
bp->fw_cap |= BNXT_FW_CAP_PRE_RESV_VNICS;
bnxt_hwrm_func_qcfg(bp); bnxt_hwrm_func_qcfg(bp);
bnxt_hwrm_vnic_qcaps(bp); bnxt_hwrm_vnic_qcaps(bp);
bnxt_hwrm_port_led_qcaps(bp); bnxt_hwrm_port_led_qcaps(bp);
...@@ -12300,6 +12295,7 @@ static int bnxt_fw_init_one_p2(struct bnxt *bp) ...@@ -12300,6 +12295,7 @@ static int bnxt_fw_init_one_p2(struct bnxt *bp)
if (bp->fw_cap & BNXT_FW_CAP_PTP) if (bp->fw_cap & BNXT_FW_CAP_PTP)
__bnxt_hwrm_ptp_qcfg(bp); __bnxt_hwrm_ptp_qcfg(bp);
bnxt_dcb_init(bp); bnxt_dcb_init(bp);
bnxt_hwmon_init(bp);
return 0; return 0;
} }
...@@ -13205,6 +13201,7 @@ static void bnxt_remove_one(struct pci_dev *pdev) ...@@ -13205,6 +13201,7 @@ static void bnxt_remove_one(struct pci_dev *pdev)
bnxt_clear_int_mode(bp); bnxt_clear_int_mode(bp);
bnxt_hwrm_func_drv_unrgtr(bp); bnxt_hwrm_func_drv_unrgtr(bp);
bnxt_free_hwrm_resources(bp); bnxt_free_hwrm_resources(bp);
bnxt_hwmon_uninit(bp);
bnxt_ethtool_free(bp); bnxt_ethtool_free(bp);
bnxt_dcb_free(bp); bnxt_dcb_free(bp);
kfree(bp->ptp_cfg); kfree(bp->ptp_cfg);
...@@ -13801,6 +13798,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -13801,6 +13798,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
init_err_pci_clean: init_err_pci_clean:
bnxt_hwrm_func_drv_unrgtr(bp); bnxt_hwrm_func_drv_unrgtr(bp);
bnxt_free_hwrm_resources(bp); bnxt_free_hwrm_resources(bp);
bnxt_hwmon_uninit(bp);
bnxt_ethtool_free(bp); bnxt_ethtool_free(bp);
bnxt_ptp_clear(bp); bnxt_ptp_clear(bp);
kfree(bp->ptp_cfg); kfree(bp->ptp_cfg);
......
...@@ -1135,7 +1135,6 @@ struct bnxt_vf_info { ...@@ -1135,7 +1135,6 @@ struct bnxt_vf_info {
u16 vlan; u16 vlan;
u16 func_qcfg_flags; u16 func_qcfg_flags;
u32 flags; u32 flags;
#define BNXT_VF_QOS 0x1
#define BNXT_VF_SPOOFCHK 0x2 #define BNXT_VF_SPOOFCHK 0x2
#define BNXT_VF_LINK_FORCED 0x4 #define BNXT_VF_LINK_FORCED 0x4
#define BNXT_VF_LINK_UP 0x8 #define BNXT_VF_LINK_UP 0x8
...@@ -2013,6 +2012,9 @@ struct bnxt { ...@@ -2013,6 +2012,9 @@ struct bnxt {
#define BNXT_FW_CAP_RING_MONITOR BIT_ULL(30) #define BNXT_FW_CAP_RING_MONITOR BIT_ULL(30)
#define BNXT_FW_CAP_DBG_QCAPS BIT_ULL(31) #define BNXT_FW_CAP_DBG_QCAPS BIT_ULL(31)
#define BNXT_FW_CAP_PTP BIT_ULL(32) #define BNXT_FW_CAP_PTP BIT_ULL(32)
#define BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED BIT_ULL(33)
#define BNXT_FW_CAP_DFLT_VLAN_TPID_PCP BIT_ULL(34)
#define BNXT_FW_CAP_PRE_RESV_VNICS BIT_ULL(35)
u32 fw_dbg_cap; u32 fw_dbg_cap;
...@@ -2053,6 +2055,7 @@ struct bnxt { ...@@ -2053,6 +2055,7 @@ struct bnxt {
#define BNXT_FW_VER_CODE(maj, min, bld, rsv) \ #define BNXT_FW_VER_CODE(maj, min, bld, rsv) \
((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv)) ((u64)(maj) << 48 | (u64)(min) << 32 | (u64)(bld) << 16 | (rsv))
#define BNXT_FW_MAJ(bp) ((bp)->fw_ver_code >> 48) #define BNXT_FW_MAJ(bp) ((bp)->fw_ver_code >> 48)
#define BNXT_FW_BLD(bp) (((bp)->fw_ver_code >> 16) & 0xffff)
u16 vxlan_fw_dst_port_id; u16 vxlan_fw_dst_port_id;
u16 nge_fw_dst_port_id; u16 nge_fw_dst_port_id;
...@@ -2185,7 +2188,13 @@ struct bnxt { ...@@ -2185,7 +2188,13 @@ struct bnxt {
struct bnxt_tc_info *tc_info; struct bnxt_tc_info *tc_info;
struct list_head tc_indr_block_list; struct list_head tc_indr_block_list;
struct dentry *debugfs_pdev; struct dentry *debugfs_pdev;
#ifdef CONFIG_BNXT_HWMON
struct device *hwmon_dev; struct device *hwmon_dev;
u8 warn_thresh_temp;
u8 crit_thresh_temp;
u8 fatal_thresh_temp;
u8 shutdown_thresh_temp;
#endif
enum board_idx board_idx; enum board_idx board_idx;
}; };
......
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2023 Broadcom Limited
*
* 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.
*/
#include <linux/dev_printk.h>
#include <linux/errno.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/pci.h>
#include "bnxt_hsi.h"
#include "bnxt.h"
#include "bnxt_hwrm.h"
#include "bnxt_hwmon.h"
void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type)
{
u32 attr;
if (!bp->hwmon_dev)
return;
switch (type) {
case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_WARN:
attr = hwmon_temp_max_alarm;
break;
case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_CRITICAL:
attr = hwmon_temp_crit_alarm;
break;
case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_FATAL:
case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_SHUTDOWN:
attr = hwmon_temp_emergency_alarm;
break;
default:
return;
}
hwmon_notify_event(&bp->pdev->dev, hwmon_temp, attr, 0);
}
static int bnxt_hwrm_temp_query(struct bnxt *bp, u8 *temp)
{
struct hwrm_temp_monitor_query_output *resp;
struct hwrm_temp_monitor_query_input *req;
int rc;
rc = hwrm_req_init(bp, req, HWRM_TEMP_MONITOR_QUERY);
if (rc)
return rc;
resp = hwrm_req_hold(bp, req);
rc = hwrm_req_send_silent(bp, req);
if (rc)
goto drop_req;
if (temp) {
*temp = resp->temp;
} else if (resp->flags &
TEMP_MONITOR_QUERY_RESP_FLAGS_THRESHOLD_VALUES_AVAILABLE) {
bp->fw_cap |= BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED;
bp->warn_thresh_temp = resp->warn_threshold;
bp->crit_thresh_temp = resp->critical_threshold;
bp->fatal_thresh_temp = resp->fatal_threshold;
bp->shutdown_thresh_temp = resp->shutdown_threshold;
}
drop_req:
hwrm_req_drop(bp, req);
return rc;
}
static umode_t bnxt_hwmon_is_visible(const void *_data, enum hwmon_sensor_types type,
u32 attr, int channel)
{
const struct bnxt *bp = _data;
if (type != hwmon_temp)
return 0;
switch (attr) {
case hwmon_temp_input:
return 0444;
case hwmon_temp_max:
case hwmon_temp_crit:
case hwmon_temp_emergency:
case hwmon_temp_max_alarm:
case hwmon_temp_crit_alarm:
case hwmon_temp_emergency_alarm:
if (!(bp->fw_cap & BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED))
return 0;
return 0444;
default:
return 0;
}
}
static int bnxt_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
int channel, long *val)
{
struct bnxt *bp = dev_get_drvdata(dev);
u8 temp = 0;
int rc;
switch (attr) {
case hwmon_temp_input:
rc = bnxt_hwrm_temp_query(bp, &temp);
if (!rc)
*val = temp * 1000;
return rc;
case hwmon_temp_max:
*val = bp->warn_thresh_temp * 1000;
return 0;
case hwmon_temp_crit:
*val = bp->crit_thresh_temp * 1000;
return 0;
case hwmon_temp_emergency:
*val = bp->fatal_thresh_temp * 1000;
return 0;
case hwmon_temp_max_alarm:
rc = bnxt_hwrm_temp_query(bp, &temp);
if (!rc)
*val = temp >= bp->warn_thresh_temp;
return rc;
case hwmon_temp_crit_alarm:
rc = bnxt_hwrm_temp_query(bp, &temp);
if (!rc)
*val = temp >= bp->crit_thresh_temp;
return rc;
case hwmon_temp_emergency_alarm:
rc = bnxt_hwrm_temp_query(bp, &temp);
if (!rc)
*val = temp >= bp->fatal_thresh_temp;
return rc;
default:
return -EOPNOTSUPP;
}
}
static const struct hwmon_channel_info *bnxt_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
HWMON_T_EMERGENCY | HWMON_T_MAX_ALARM |
HWMON_T_CRIT_ALARM | HWMON_T_EMERGENCY_ALARM),
NULL
};
static const struct hwmon_ops bnxt_hwmon_ops = {
.is_visible = bnxt_hwmon_is_visible,
.read = bnxt_hwmon_read,
};
static const struct hwmon_chip_info bnxt_hwmon_chip_info = {
.ops = &bnxt_hwmon_ops,
.info = bnxt_hwmon_info,
};
static ssize_t temp1_shutdown_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct bnxt *bp = dev_get_drvdata(dev);
return sysfs_emit(buf, "%u\n", bp->shutdown_thresh_temp * 1000);
}
static ssize_t temp1_shutdown_alarm_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct bnxt *bp = dev_get_drvdata(dev);
u8 temp;
int rc;
rc = bnxt_hwrm_temp_query(bp, &temp);
if (rc)
return -EIO;
return sysfs_emit(buf, "%u\n", temp >= bp->shutdown_thresh_temp);
}
static DEVICE_ATTR_RO(temp1_shutdown);
static DEVICE_ATTR_RO(temp1_shutdown_alarm);
static struct attribute *bnxt_temp_extra_attrs[] = {
&dev_attr_temp1_shutdown.attr,
&dev_attr_temp1_shutdown_alarm.attr,
NULL,
};
static umode_t bnxt_temp_extra_attrs_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
struct device *dev = kobj_to_dev(kobj);
struct bnxt *bp = dev_get_drvdata(dev);
/* Shutdown temperature setting in NVM is optional */
if (!(bp->fw_cap & BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED) ||
!bp->shutdown_thresh_temp)
return 0;
return attr->mode;
}
static const struct attribute_group bnxt_temp_extra_group = {
.attrs = bnxt_temp_extra_attrs,
.is_visible = bnxt_temp_extra_attrs_visible,
};
__ATTRIBUTE_GROUPS(bnxt_temp_extra);
void bnxt_hwmon_uninit(struct bnxt *bp)
{
if (bp->hwmon_dev) {
hwmon_device_unregister(bp->hwmon_dev);
bp->hwmon_dev = NULL;
}
}
void bnxt_hwmon_init(struct bnxt *bp)
{
struct pci_dev *pdev = bp->pdev;
int rc;
/* temp1_xxx is only sensor, ensure not registered if it will fail */
rc = bnxt_hwrm_temp_query(bp, NULL);
if (rc == -EACCES || rc == -EOPNOTSUPP) {
bnxt_hwmon_uninit(bp);
return;
}
if (bp->hwmon_dev)
return;
bp->hwmon_dev = hwmon_device_register_with_info(&pdev->dev,
DRV_MODULE_NAME, bp,
&bnxt_hwmon_chip_info,
bnxt_temp_extra_groups);
if (IS_ERR(bp->hwmon_dev)) {
bp->hwmon_dev = NULL;
dev_warn(&pdev->dev, "Cannot register hwmon device\n");
}
}
/* Broadcom NetXtreme-C/E network driver.
*
* Copyright (c) 2023 Broadcom Limited
*
* 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.
*/
#ifndef BNXT_HWMON_H
#define BNXT_HWMON_H
#ifdef CONFIG_BNXT_HWMON
void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type);
void bnxt_hwmon_uninit(struct bnxt *bp);
void bnxt_hwmon_init(struct bnxt *bp);
#else
static inline void bnxt_hwmon_notify_event(struct bnxt *bp, u32 type)
{
}
static inline void bnxt_hwmon_uninit(struct bnxt *bp)
{
}
static inline void bnxt_hwmon_init(struct bnxt *bp)
{
}
#endif
#endif
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <net/dcbnl.h>
#include "bnxt_hsi.h" #include "bnxt_hsi.h"
#include "bnxt.h" #include "bnxt.h"
#include "bnxt_hwrm.h" #include "bnxt_hwrm.h"
...@@ -196,11 +197,8 @@ int bnxt_get_vf_config(struct net_device *dev, int vf_id, ...@@ -196,11 +197,8 @@ int bnxt_get_vf_config(struct net_device *dev, int vf_id,
memcpy(&ivi->mac, vf->vf_mac_addr, ETH_ALEN); memcpy(&ivi->mac, vf->vf_mac_addr, ETH_ALEN);
ivi->max_tx_rate = vf->max_tx_rate; ivi->max_tx_rate = vf->max_tx_rate;
ivi->min_tx_rate = vf->min_tx_rate; ivi->min_tx_rate = vf->min_tx_rate;
ivi->vlan = vf->vlan; ivi->vlan = vf->vlan & VLAN_VID_MASK;
if (vf->flags & BNXT_VF_QOS) ivi->qos = vf->vlan >> VLAN_PRIO_SHIFT;
ivi->qos = vf->vlan >> VLAN_PRIO_SHIFT;
else
ivi->qos = 0;
ivi->spoofchk = !!(vf->flags & BNXT_VF_SPOOFCHK); ivi->spoofchk = !!(vf->flags & BNXT_VF_SPOOFCHK);
ivi->trusted = bnxt_is_trusted_vf(bp, vf); ivi->trusted = bnxt_is_trusted_vf(bp, vf);
if (!(vf->flags & BNXT_VF_LINK_FORCED)) if (!(vf->flags & BNXT_VF_LINK_FORCED))
...@@ -256,21 +254,21 @@ int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos, ...@@ -256,21 +254,21 @@ int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos,
if (bp->hwrm_spec_code < 0x10201) if (bp->hwrm_spec_code < 0x10201)
return -ENOTSUPP; return -ENOTSUPP;
if (vlan_proto != htons(ETH_P_8021Q)) if (vlan_proto != htons(ETH_P_8021Q) &&
(vlan_proto != htons(ETH_P_8021AD) ||
!(bp->fw_cap & BNXT_FW_CAP_DFLT_VLAN_TPID_PCP)))
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
rc = bnxt_vf_ndo_prep(bp, vf_id); rc = bnxt_vf_ndo_prep(bp, vf_id);
if (rc) if (rc)
return rc; return rc;
/* TODO: needed to implement proper handling of user priority, if (vlan_id >= VLAN_N_VID || qos >= IEEE_8021Q_MAX_PRIORITIES ||
* currently fail the command if there is valid priority (!vlan_id && qos))
*/
if (vlan_id > 4095 || qos)
return -EINVAL; return -EINVAL;
vf = &bp->pf.vf[vf_id]; vf = &bp->pf.vf[vf_id];
vlan_tag = vlan_id; vlan_tag = vlan_id | (u16)qos << VLAN_PRIO_SHIFT;
if (vlan_tag == vf->vlan) if (vlan_tag == vf->vlan)
return 0; return 0;
...@@ -279,6 +277,10 @@ int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos, ...@@ -279,6 +277,10 @@ int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos,
req->fid = cpu_to_le16(vf->fw_fid); req->fid = cpu_to_le16(vf->fw_fid);
req->dflt_vlan = cpu_to_le16(vlan_tag); req->dflt_vlan = cpu_to_le16(vlan_tag);
req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN); req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN);
if (bp->fw_cap & BNXT_FW_CAP_DFLT_VLAN_TPID_PCP) {
req->enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_TPID);
req->tpid = vlan_proto;
}
rc = hwrm_req_send(bp, req); rc = hwrm_req_send(bp, req);
if (!rc) if (!rc)
vf->vlan = vlan_tag; vf->vlan = vlan_tag;
...@@ -550,7 +552,6 @@ static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs, bool reset) ...@@ -550,7 +552,6 @@ static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs, bool reset)
vf_rx_rings = hw_resc->max_rx_rings - bp->rx_nr_rings; vf_rx_rings = hw_resc->max_rx_rings - bp->rx_nr_rings;
vf_tx_rings = hw_resc->max_tx_rings - bp->tx_nr_rings; vf_tx_rings = hw_resc->max_tx_rings - bp->tx_nr_rings;
vf_vnics = hw_resc->max_vnics - bp->nr_vnics; vf_vnics = hw_resc->max_vnics - bp->nr_vnics;
vf_vnics = min_t(u16, vf_vnics, vf_rx_rings);
vf_rss = hw_resc->max_rsscos_ctxs - bp->rsscos_nr_ctxs; vf_rss = hw_resc->max_rsscos_ctxs - bp->rsscos_nr_ctxs;
req->min_rsscos_ctx = cpu_to_le16(BNXT_VF_MIN_RSS_CTX); req->min_rsscos_ctx = cpu_to_le16(BNXT_VF_MIN_RSS_CTX);
...@@ -572,11 +573,20 @@ static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs, bool reset) ...@@ -572,11 +573,20 @@ static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs, bool reset)
vf_cp_rings /= num_vfs; vf_cp_rings /= num_vfs;
vf_tx_rings /= num_vfs; vf_tx_rings /= num_vfs;
vf_rx_rings /= num_vfs; vf_rx_rings /= num_vfs;
vf_vnics /= num_vfs; if ((bp->fw_cap & BNXT_FW_CAP_PRE_RESV_VNICS) &&
vf_vnics >= pf->max_vfs) {
/* Take into account that FW has pre-reserved 1 VNIC for
* each pf->max_vfs.
*/
vf_vnics = (vf_vnics - pf->max_vfs + num_vfs) / num_vfs;
} else {
vf_vnics /= num_vfs;
}
vf_stat_ctx /= num_vfs; vf_stat_ctx /= num_vfs;
vf_ring_grps /= num_vfs; vf_ring_grps /= num_vfs;
vf_rss /= num_vfs; vf_rss /= num_vfs;
vf_vnics = min_t(u16, vf_vnics, vf_rx_rings);
req->min_cmpl_rings = cpu_to_le16(vf_cp_rings); req->min_cmpl_rings = cpu_to_le16(vf_cp_rings);
req->min_tx_rings = cpu_to_le16(vf_tx_rings); req->min_tx_rings = cpu_to_le16(vf_tx_rings);
req->min_rx_rings = cpu_to_le16(vf_rx_rings); req->min_rx_rings = cpu_to_le16(vf_rx_rings);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment