Merge branch 'qlcnic-next'
Jitendra Kalsaria says: ==================== qlcnic driver updates This patch series containes following changes - * Optimize MAC learning code. * Export board temperature using hwmon-sysfs interface. * Add support for configuring Tx interrupt coalescing parameters from VF. * Logging error messages in error path. * Restrict extended vNIC support in legacy interrupt mode and log appropriate message. Please apply this series to net-next. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4940b8cd1b
|
@ -66,6 +66,17 @@ config QLCNIC_VXLAN
|
|||
Say Y here if you want to enable hardware offload support for
|
||||
Virtual eXtensible Local Area Network (VXLAN) in the driver.
|
||||
|
||||
config QLCNIC_HWMON
|
||||
bool "QLOGIC QLCNIC 82XX and 83XX family HWMON support"
|
||||
depends on QLCNIC && HWMON
|
||||
default y
|
||||
---help---
|
||||
This configuration parameter can be used to read the
|
||||
board temperature in Converged Ethernet devices
|
||||
supported by qlcnic.
|
||||
|
||||
This data is available via the hwmon sysfs interface.
|
||||
|
||||
config QLGE
|
||||
tristate "QLogic QLGE 10Gb Ethernet Driver Support"
|
||||
depends on PCI
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
|
||||
#define _QLCNIC_LINUX_MAJOR 5
|
||||
#define _QLCNIC_LINUX_MINOR 3
|
||||
#define _QLCNIC_LINUX_SUBVERSION 57
|
||||
#define QLCNIC_LINUX_VERSIONID "5.3.57"
|
||||
#define _QLCNIC_LINUX_SUBVERSION 58
|
||||
#define QLCNIC_LINUX_VERSIONID "5.3.58"
|
||||
#define QLCNIC_DRV_IDC_VER 0x01
|
||||
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
|
||||
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
|
||||
|
@ -537,6 +537,7 @@ struct qlcnic_hardware_context {
|
|||
u8 phys_port_id[ETH_ALEN];
|
||||
u8 lb_mode;
|
||||
u16 vxlan_port;
|
||||
struct device *hwmon_dev;
|
||||
};
|
||||
|
||||
struct qlcnic_adapter_stats {
|
||||
|
@ -2361,4 +2362,18 @@ static inline u32 qlcnic_get_vnic_func_count(struct qlcnic_adapter *adapter)
|
|||
else
|
||||
return QLC_DEFAULT_VNIC_COUNT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_QLCNIC_HWMON
|
||||
void qlcnic_register_hwmon_dev(struct qlcnic_adapter *);
|
||||
void qlcnic_unregister_hwmon_dev(struct qlcnic_adapter *);
|
||||
#else
|
||||
static inline void qlcnic_register_hwmon_dev(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
static inline void qlcnic_unregister_hwmon_dev(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif /* __QLCNIC_H_ */
|
||||
|
|
|
@ -33,6 +33,7 @@ static void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *);
|
|||
#define RSS_HASHTYPE_IP_TCP 0x3
|
||||
#define QLC_83XX_FW_MBX_CMD 0
|
||||
#define QLC_SKIP_INACTIVE_PCI_REGS 7
|
||||
#define QLC_MAX_LEGACY_FUNC_SUPP 8
|
||||
|
||||
static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
|
||||
{QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
|
||||
|
@ -357,8 +358,15 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
|
|||
if (!ahw->intr_tbl)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
|
||||
if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
|
||||
if (adapter->ahw->pci_func >= QLC_MAX_LEGACY_FUNC_SUPP) {
|
||||
dev_err(&adapter->pdev->dev, "PCI function number 8 and higher are not supported with legacy interrupt, func 0x%x\n",
|
||||
ahw->pci_func);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
qlcnic_83xx_enable_legacy(adapter);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_msix; i++) {
|
||||
if (adapter->flags & QLCNIC_MSIX_ENABLED)
|
||||
|
@ -879,6 +887,9 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dev_err(&adapter->pdev->dev, "%s: Invalid mailbox command opcode 0x%x\n",
|
||||
__func__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -2181,6 +2181,8 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
|
|||
max_sds_rings = QLCNIC_MAX_SDS_RINGS;
|
||||
max_tx_rings = QLCNIC_MAX_TX_RINGS;
|
||||
} else {
|
||||
dev_err(&adapter->pdev->dev, "%s: Invalid opmode %d\n",
|
||||
__func__, ret);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
|
@ -1027,8 +1027,11 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
|
|||
u32 arg1;
|
||||
|
||||
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
|
||||
!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
|
||||
!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) {
|
||||
dev_err(&adapter->pdev->dev, "%s: Not a management function\n",
|
||||
__func__);
|
||||
return err;
|
||||
}
|
||||
|
||||
arg1 = id | (enable_mirroring ? BIT_4 : 0);
|
||||
arg1 |= pci_func << 8;
|
||||
|
@ -1318,8 +1321,12 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
|
|||
u32 arg1, arg2 = 0;
|
||||
u8 pci_func;
|
||||
|
||||
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
|
||||
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
|
||||
dev_err(&adapter->pdev->dev, "%s: Not a management function\n",
|
||||
__func__);
|
||||
return err;
|
||||
}
|
||||
|
||||
pci_func = esw_cfg->pci_func;
|
||||
index = qlcnic_is_valid_nic_func(adapter, pci_func);
|
||||
if (index < 0)
|
||||
|
@ -1363,6 +1370,8 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
|
|||
arg1 &= ~(0x0ffff << 16);
|
||||
break;
|
||||
default:
|
||||
dev_err(&adapter->pdev->dev, "%s: Invalid opmode 0x%x\n",
|
||||
__func__, esw_cfg->op_mode);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -305,7 +305,6 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
|
|||
{
|
||||
struct vlan_ethhdr *vh = (struct vlan_ethhdr *)(skb->data);
|
||||
struct ethhdr *phdr = (struct ethhdr *)(skb->data);
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
u16 protocol = ntohs(skb->protocol);
|
||||
struct qlcnic_filter *fil, *tmp_fil;
|
||||
struct hlist_head *head;
|
||||
|
@ -330,13 +329,6 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
|
|||
return;
|
||||
}
|
||||
|
||||
if (adapter->fhash.fnum >= adapter->fhash.fmax) {
|
||||
adapter->stats.mac_filter_limit_overrun++;
|
||||
netdev_info(netdev, "Can not add more than %d mac-vlan filters, configured %d\n",
|
||||
adapter->fhash.fmax, adapter->fhash.fnum);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&src_addr, phdr->h_source, ETH_ALEN);
|
||||
hval = qlcnic_mac_hash(src_addr, vlan_id);
|
||||
hindex = hval & (adapter->fhash.fbucket_size - 1);
|
||||
|
@ -353,6 +345,11 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
|
|||
}
|
||||
}
|
||||
|
||||
if (unlikely(adapter->fhash.fnum >= adapter->fhash.fmax)) {
|
||||
adapter->stats.mac_filter_limit_overrun++;
|
||||
return;
|
||||
}
|
||||
|
||||
fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
|
||||
if (!fil)
|
||||
return;
|
||||
|
@ -1216,8 +1213,7 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,
|
|||
if (!skb)
|
||||
return buffer;
|
||||
|
||||
if (adapter->drv_mac_learn &&
|
||||
(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
|
||||
if (adapter->rx_mac_learn) {
|
||||
t_vid = 0;
|
||||
is_lb_pkt = qlcnic_82xx_is_lb_pkt(sts_data0);
|
||||
qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
|
||||
|
@ -1293,8 +1289,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
|
|||
if (!skb)
|
||||
return buffer;
|
||||
|
||||
if (adapter->drv_mac_learn &&
|
||||
(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
|
||||
if (adapter->rx_mac_learn) {
|
||||
t_vid = 0;
|
||||
is_lb_pkt = qlcnic_82xx_is_lb_pkt(sts_data0);
|
||||
qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
|
||||
|
|
|
@ -1014,6 +1014,8 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
|
|||
|
||||
if (pfn >= ahw->max_vnic_func) {
|
||||
ret = QL_STATUS_INVALID_PARAM;
|
||||
dev_err(&adapter->pdev->dev, "%s: Invalid function 0x%x, max 0x%x\n",
|
||||
__func__, pfn, ahw->max_vnic_func);
|
||||
goto err_eswitch;
|
||||
}
|
||||
|
||||
|
@ -2052,6 +2054,7 @@ out:
|
|||
|
||||
static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||
int err = 0;
|
||||
|
||||
adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
|
||||
|
@ -2061,6 +2064,18 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
if (qlcnic_83xx_check(adapter)) {
|
||||
ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX_TX;
|
||||
ahw->coal.tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
|
||||
ahw->coal.tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
|
||||
ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
|
||||
ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
|
||||
} else {
|
||||
ahw->coal.type = QLCNIC_INTR_COAL_TYPE_RX;
|
||||
ahw->coal.rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
|
||||
ahw->coal.rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
|
||||
}
|
||||
|
||||
/* clear stats */
|
||||
memset(&adapter->stats, 0, sizeof(adapter->stats));
|
||||
err_out:
|
||||
|
@ -2517,9 +2532,11 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
case -ENOMEM:
|
||||
dev_err(&pdev->dev, "Adapter initialization failed. Please reboot\n");
|
||||
goto err_out_free_hw;
|
||||
case -EOPNOTSUPP:
|
||||
dev_err(&pdev->dev, "Adapter initialization failed\n");
|
||||
goto err_out_free_hw;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Adapter initialization failed. A reboot may be required to recover from this failure\n");
|
||||
dev_err(&pdev->dev, "If reboot does not help to recover from this failure, try a flash update of the adapter\n");
|
||||
dev_err(&pdev->dev, "Adapter initialization failed. Driver will load in maintenance mode to recover the adapter using the application\n");
|
||||
goto err_out_maintenance_mode;
|
||||
}
|
||||
}
|
||||
|
@ -2593,7 +2610,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
qlcnic_alloc_lb_filters_mem(adapter);
|
||||
|
||||
qlcnic_add_sysfs(adapter);
|
||||
|
||||
qlcnic_register_hwmon_dev(adapter);
|
||||
return 0;
|
||||
|
||||
err_out_disable_mbx_intr:
|
||||
|
@ -2700,6 +2717,8 @@ static void qlcnic_remove(struct pci_dev *pdev)
|
|||
|
||||
qlcnic_remove_sysfs(adapter);
|
||||
|
||||
qlcnic_unregister_hwmon_dev(adapter);
|
||||
|
||||
qlcnic_cleanup_pci_map(adapter->ahw);
|
||||
|
||||
qlcnic_release_firmware(adapter);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define QLC_VF_FLOOD_BIT BIT_16
|
||||
#define QLC_FLOOD_MODE 0x5
|
||||
#define QLC_SRIOV_ALLOW_VLAN0 BIT_19
|
||||
#define QLC_INTR_COAL_TYPE_MASK 0x7
|
||||
|
||||
static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8);
|
||||
|
||||
|
@ -1178,19 +1179,41 @@ static int qlcnic_sriov_validate_cfg_intrcoal(struct qlcnic_adapter *adapter,
|
|||
{
|
||||
struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
|
||||
u16 ctx_id, pkts, time;
|
||||
int err = -EINVAL;
|
||||
u8 type;
|
||||
|
||||
type = cmd->req.arg[1] & QLC_INTR_COAL_TYPE_MASK;
|
||||
ctx_id = cmd->req.arg[1] >> 16;
|
||||
pkts = cmd->req.arg[2] & 0xffff;
|
||||
time = cmd->req.arg[2] >> 16;
|
||||
|
||||
if (ctx_id != vf->rx_ctx_id)
|
||||
return -EINVAL;
|
||||
if (pkts > coal->rx_packets)
|
||||
return -EINVAL;
|
||||
if (time < coal->rx_time_us)
|
||||
return -EINVAL;
|
||||
switch (type) {
|
||||
case QLCNIC_INTR_COAL_TYPE_RX:
|
||||
if (ctx_id != vf->rx_ctx_id || pkts > coal->rx_packets ||
|
||||
time < coal->rx_time_us)
|
||||
goto err_label;
|
||||
break;
|
||||
case QLCNIC_INTR_COAL_TYPE_TX:
|
||||
if (ctx_id != vf->tx_ctx_id || pkts > coal->tx_packets ||
|
||||
time < coal->tx_time_us)
|
||||
goto err_label;
|
||||
break;
|
||||
default:
|
||||
netdev_err(adapter->netdev, "Invalid coalescing type 0x%x received\n",
|
||||
type);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_label:
|
||||
netdev_err(adapter->netdev, "Expected: rx_ctx_id 0x%x rx_packets 0x%x rx_time_us 0x%x tx_ctx_id 0x%x tx_packets 0x%x tx_time_us 0x%x\n",
|
||||
vf->rx_ctx_id, coal->rx_packets, coal->rx_time_us,
|
||||
vf->tx_ctx_id, coal->tx_packets, coal->tx_time_us);
|
||||
netdev_err(adapter->netdev, "Received: ctx_id 0x%x packets 0x%x time_us 0x%x type 0x%x\n",
|
||||
ctx_id, pkts, time, type);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int qlcnic_sriov_pf_cfg_intrcoal_cmd(struct qlcnic_bc_trans *tran,
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
#include <linux/sysfs.h>
|
||||
#include <linux/aer.h>
|
||||
#include <linux/log2.h>
|
||||
#ifdef CONFIG_QLCNIC_HWMON
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#endif
|
||||
|
||||
#define QLC_STATUS_UNSUPPORTED_CMD -2
|
||||
|
||||
|
@ -358,6 +362,8 @@ int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
|
|||
if (adapter->npars[i].pci_func == pci_func)
|
||||
return i;
|
||||
}
|
||||
|
||||
dev_err(&adapter->pdev->dev, "%s: Invalid nic function\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1243,6 +1249,68 @@ static struct bin_attribute bin_attr_flash = {
|
|||
.write = qlcnic_83xx_sysfs_flash_write_handler,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_QLCNIC_HWMON
|
||||
|
||||
static ssize_t qlcnic_hwmon_show_temp(struct device *dev,
|
||||
struct device_attribute *dev_attr,
|
||||
char *buf)
|
||||
{
|
||||
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
|
||||
unsigned int temperature = 0, value = 0;
|
||||
|
||||
if (qlcnic_83xx_check(adapter))
|
||||
value = QLCRDX(adapter->ahw, QLC_83XX_ASIC_TEMP);
|
||||
else if (qlcnic_82xx_check(adapter))
|
||||
value = QLC_SHARED_REG_RD32(adapter, QLCNIC_ASIC_TEMP);
|
||||
|
||||
temperature = qlcnic_get_temp_val(value);
|
||||
/* display millidegree celcius */
|
||||
temperature *= 1000;
|
||||
return sprintf(buf, "%u\n", temperature);
|
||||
}
|
||||
|
||||
/* hwmon-sysfs attributes */
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
|
||||
qlcnic_hwmon_show_temp, NULL, 1);
|
||||
|
||||
static struct attribute *qlcnic_hwmon_attrs[] = {
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
ATTRIBUTE_GROUPS(qlcnic_hwmon);
|
||||
|
||||
void qlcnic_register_hwmon_dev(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct device *dev = &adapter->pdev->dev;
|
||||
struct device *hwmon_dev;
|
||||
|
||||
/* Skip hwmon registration for a VF device */
|
||||
if (qlcnic_sriov_vf_check(adapter)) {
|
||||
adapter->ahw->hwmon_dev = NULL;
|
||||
return;
|
||||
}
|
||||
hwmon_dev = hwmon_device_register_with_groups(dev, qlcnic_driver_name,
|
||||
adapter,
|
||||
qlcnic_hwmon_groups);
|
||||
if (IS_ERR(hwmon_dev)) {
|
||||
dev_err(dev, "Cannot register with hwmon, err=%ld\n",
|
||||
PTR_ERR(hwmon_dev));
|
||||
hwmon_dev = NULL;
|
||||
}
|
||||
adapter->ahw->hwmon_dev = hwmon_dev;
|
||||
}
|
||||
|
||||
void qlcnic_unregister_hwmon_dev(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct device *hwmon_dev = adapter->ahw->hwmon_dev;
|
||||
if (hwmon_dev) {
|
||||
hwmon_device_unregister(hwmon_dev);
|
||||
adapter->ahw->hwmon_dev = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
|
||||
{
|
||||
struct device *dev = &adapter->pdev->dev;
|
||||
|
|
Loading…
Reference in New Issue