Commit 6e2842f4 authored by David S. Miller's avatar David S. Miller

Merge branch 'qlcnic'

Shahed Shaikh says:

====================
This patch series includes following changes:
* Support for spoof check configuration per VF using
  iproute2 tool.
* Set HW mask for 8300 adapter in INT-x mode to stop generating
  interrupts.
* Updated IRQ name for 8200 and 8300 Series adapter as per
  format used by other multiqueue drivers.
* Remove qlcnic_config_npars module parameter.
* Initialize trans_work and idc_aen_work at VF probe.
* Convert netsted if-else into switch-case statement.
* Change in diagnostics routine.
* Modify reset recovery path in diag mode by providing diagnostics
  routines enough time to unwind before proceeding with reset recovery.
* Implement GET_LED_STATUS command for 82xx adapter and refactor
  qlcnic_store_beacon() to split 8200 and 8300 specific calls.
* Some cleanup and log enhancements
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f2068b80 6a531b7b
......@@ -38,8 +38,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 2
#define _QLCNIC_LINUX_SUBVERSION 42
#define QLCNIC_LINUX_VERSIONID "5.2.42"
#define _QLCNIC_LINUX_SUBVERSION 43
#define QLCNIC_LINUX_VERSIONID "5.2.43"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
......@@ -303,7 +303,6 @@ extern int qlcnic_use_msi;
extern int qlcnic_use_msi_x;
extern int qlcnic_auto_fw_reset;
extern int qlcnic_load_fw_file;
extern int qlcnic_config_npars;
/* Number of status descriptors to handle per interrupt */
#define MAX_STATUS_HANDLE (64)
......@@ -443,6 +442,7 @@ struct qlcnic_hardware_context {
u16 max_mtu;
u32 msg_enable;
u16 act_pci_func;
u16 max_pci_func;
u32 capabilities;
u32 capabilities2;
......@@ -816,6 +816,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2
#define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3
#define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5
#define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7
/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1
......@@ -913,6 +914,9 @@ struct qlcnic_ipaddr {
#define QLCNIC_IS_TSO_CAPABLE(adapter) \
((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
#define QLCNIC_BEACON_EANBLE 0xC
#define QLCNIC_BEACON_DISABLE 0xD
#define QLCNIC_DEF_NUM_STS_DESC_RINGS 4
#define QLCNIC_MSIX_TBL_SPACE 8192
#define QLCNIC_PCI_REG_MSIX_TBL 0x44
......@@ -932,6 +936,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_SRIOV_ENABLE 10
#define __QLCNIC_SRIOV_CAPABLE 11
#define __QLCNIC_MBX_POLL_ENABLE 12
#define __QLCNIC_DIAG_MODE 13
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
......@@ -1543,6 +1548,7 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *);
int qlcnic_reset_npar_config(struct qlcnic_adapter *);
int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *);
void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16);
int qlcnic_get_beacon_state(struct qlcnic_adapter *, u8 *);
int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
int qlcnic_read_mac_addr(struct qlcnic_adapter *);
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
......@@ -1886,6 +1892,21 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
writel(0xfbff, adapter->tgt_mask_reg);
}
static inline int qlcnic_get_diag_lock(struct qlcnic_adapter *adapter)
{
return test_and_set_bit(__QLCNIC_DIAG_MODE, &adapter->state);
}
static inline void qlcnic_release_diag_lock(struct qlcnic_adapter *adapter)
{
clear_bit(__QLCNIC_DIAG_MODE, &adapter->state);
}
static inline int qlcnic_check_diag_status(struct qlcnic_adapter *adapter)
{
return test_bit(__QLCNIC_DIAG_MODE, &adapter->state);
}
extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops;
extern const struct ethtool_ops qlcnic_ethtool_ops;
extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
......
......@@ -312,6 +312,11 @@ inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
writel(0, adapter->tgt_mask_reg);
}
inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
{
writel(1, adapter->tgt_mask_reg);
}
/* Enable MSI-x and INT-x interrupts */
void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
struct qlcnic_host_sds_ring *sds_ring)
......@@ -458,6 +463,9 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
{
u32 num_msix;
if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
qlcnic_83xx_set_legacy_intr_mask(adapter);
qlcnic_83xx_disable_mbx_intr(adapter);
if (adapter->flags & QLCNIC_MSIX_ENABLED)
......@@ -474,7 +482,6 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
{
irq_handler_t handler;
u32 val;
char name[32];
int err = 0;
unsigned long flags = 0;
......@@ -485,9 +492,7 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
handler = qlcnic_83xx_handle_aen;
val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
snprintf(name, (IFNAMSIZ + 4),
"%s[%s]", "qlcnic", "aen");
err = request_irq(val, handler, flags, name, adapter);
err = request_irq(val, handler, flags, "qlcnic-MB", adapter);
if (err) {
dev_err(&adapter->pdev->dev,
"failed to register MBX interrupt\n");
......@@ -1588,16 +1593,24 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
struct qlcnic_hardware_context *ahw = adapter->ahw;
int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings;
QLCDB(adapter, DRV, "%s loopback test in progress\n",
mode == QLCNIC_ILB_MODE ? "internal" : "external");
if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
dev_warn(&adapter->pdev->dev,
"Loopback test not supported for non privilege function\n");
netdev_warn(netdev,
"Loopback test not supported in non privileged mode\n");
return ret;
}
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
netdev_info(netdev, "Device is resetting\n");
return -EBUSY;
}
if (qlcnic_get_diag_lock(adapter)) {
netdev_info(netdev, "Device is in diagnostics mode\n");
return -EBUSY;
}
netdev_info(netdev, "%s loopback test in progress\n",
mode == QLCNIC_ILB_MODE ? "internal" : "external");
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
max_sds_rings);
......@@ -1638,7 +1651,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
fail_diag_alloc:
adapter->max_sds_rings = max_sds_rings;
clear_bit(__QLCNIC_RESETTING, &adapter->state);
qlcnic_release_diag_lock(adapter);
return ret;
}
......@@ -2121,26 +2134,25 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
struct qlcnic_pci_info *pci_info)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct device *dev = &adapter->pdev->dev;
struct qlcnic_cmd_args cmd;
int i, err = 0, j = 0;
u32 temp;
struct qlcnic_cmd_args cmd;
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
err = qlcnic_issue_cmd(adapter, &cmd);
adapter->ahw->act_pci_func = 0;
ahw->act_pci_func = 0;
if (err == QLCNIC_RCODE_SUCCESS) {
pci_info->func_count = cmd.rsp.arg[1] & 0xFF;
dev_info(&adapter->pdev->dev,
"%s: total functions = %d\n",
__func__, pci_info->func_count);
ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF;
for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
i++;
pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
if (pci_info->type == QLCNIC_TYPE_NIC)
adapter->ahw->act_pci_func++;
ahw->act_pci_func++;
temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
pci_info->default_port = temp;
i++;
......@@ -2152,18 +2164,21 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
i++;
memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
i = i + 3;
dev_info(&adapter->pdev->dev, "%s:\n"
"\tid = %d active = %d type = %d\n"
if (ahw->op_mode == QLCNIC_MGMT_FUNC)
dev_info(dev, "id = %d active = %d type = %d\n"
"\tport = %d min bw = %d max bw = %d\n"
"\tmac_addr = %pM\n", __func__,
pci_info->id, pci_info->active, pci_info->type,
pci_info->default_port, pci_info->tx_min_bw,
"\tmac_addr = %pM\n", pci_info->id,
pci_info->active, pci_info->type,
pci_info->default_port,
pci_info->tx_min_bw,
pci_info->tx_max_bw, pci_info->mac);
}
if (ahw->op_mode == QLCNIC_MGMT_FUNC)
dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n",
ahw->max_pci_func, ahw->act_pci_func);
} else {
dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n",
err);
dev_err(dev, "Failed to get PCI Info, error = %d\n", err);
err = -EIO;
}
......@@ -3113,8 +3128,10 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
u8 val;
int ret, max_sds_rings = adapter->max_sds_rings;
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
return -EIO;
if (qlcnic_get_diag_lock(adapter)) {
netdev_info(netdev, "Device in diagnostics mode\n");
return -EBUSY;
}
ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
max_sds_rings);
......@@ -3156,7 +3173,7 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
fail_diag_irq:
adapter->max_sds_rings = max_sds_rings;
clear_bit(__QLCNIC_RESETTING, &adapter->state);
qlcnic_release_diag_lock(adapter);
return ret;
}
......
......@@ -314,6 +314,7 @@ struct qlc_83xx_idc {
u8 vnic_state;
u8 vnic_wait_limit;
u8 quiesce_req;
u8 delay_reset;
char **name;
};
......
......@@ -649,6 +649,7 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
ahw->idc.collect_dump = 0;
ahw->reset_context = 0;
adapter->tx_timeo_cnt = 0;
ahw->idc.delay_reset = 0;
clear_bit(__QLCNIC_RESETTING, &adapter->state);
}
......@@ -883,21 +884,41 @@ static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)
int ret = 0;
if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {
qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
set_bit(__QLCNIC_RESETTING, &adapter->state);
clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
qlcnic_83xx_disable_vnic_mode(adapter, 1);
if (qlcnic_check_diag_status(adapter)) {
dev_info(&adapter->pdev->dev,
"%s: Wait for diag completion\n", __func__);
adapter->ahw->idc.delay_reset = 1;
return 0;
} else {
qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
qlcnic_83xx_idc_detach_driver(adapter);
}
}
/* Check ACK from other functions */
if (qlcnic_check_diag_status(adapter)) {
dev_info(&adapter->pdev->dev,
"%s: Wait for diag completion\n", __func__);
return -1;
} else {
if (adapter->ahw->idc.delay_reset) {
qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
qlcnic_83xx_idc_detach_driver(adapter);
adapter->ahw->idc.delay_reset = 0;
}
/* Check for ACK from other functions */
ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter);
if (ret) {
dev_info(&adapter->pdev->dev,
"%s: Waiting for reset ACK\n", __func__);
return 0;
return -1;
}
}
/* Transit to INIT state and restart the HW */
......
......@@ -42,27 +42,18 @@ int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
{
u8 id;
int i, ret = -EBUSY;
int ret = -EBUSY;
u32 data = QLCNIC_MGMT_FUNC;
struct qlcnic_hardware_context *ahw = adapter->ahw;
if (qlcnic_83xx_lock_driver(adapter))
return ret;
if (qlcnic_config_npars) {
for (i = 0; i < ahw->act_pci_func; i++) {
id = adapter->npars[i].pci_func;
if (id == ahw->pci_func)
continue;
data |= qlcnic_config_npars &
QLC_83XX_SET_FUNC_OPMODE(0x3, id);
}
} else {
id = ahw->pci_func;
data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, ahw->pci_func)) |
QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC,
ahw->pci_func);
}
data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, id)) |
QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, id);
QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data);
qlcnic_83xx_unlock_driver(adapter);
......@@ -196,20 +187,24 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
else
priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
ahw->pci_func);
if (priv_level == QLCNIC_NON_PRIV_FUNC) {
switch (priv_level) {
case QLCNIC_NON_PRIV_FUNC:
ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic;
} else if (priv_level == QLCNIC_PRIV_FUNC) {
break;
case QLCNIC_PRIV_FUNC:
ahw->op_mode = QLCNIC_PRIV_FUNC;
ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry;
nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic;
} else if (priv_level == QLCNIC_MGMT_FUNC) {
break;
case QLCNIC_MGMT_FUNC:
ahw->op_mode = QLCNIC_MGMT_FUNC;
ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic;
} else {
break;
default:
dev_err(&adapter->pdev->dev, "Invalid Virtual NIC opmode\n");
return -EIO;
}
......@@ -218,8 +213,8 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
else
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
adapter->ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
return 0;
}
......@@ -37,6 +37,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
{QLCNIC_CMD_TEMP_SIZE, 4, 4},
{QLCNIC_CMD_GET_TEMP_HDR, 4, 1},
{QLCNIC_CMD_SET_DRV_VER, 4, 1},
{QLCNIC_CMD_GET_LED_STATUS, 4, 2},
};
static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw)
......@@ -884,9 +885,10 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
u8 enable_mirroring, u8 pci_func)
{
struct device *dev = &adapter->pdev->dev;
struct qlcnic_cmd_args cmd;
int err = -EIO;
u32 arg1;
struct qlcnic_cmd_args cmd;
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
......@@ -900,13 +902,11 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
err = qlcnic_issue_cmd(adapter, &cmd);
if (err != QLCNIC_RCODE_SUCCESS)
dev_err(&adapter->pdev->dev,
"Failed to configure port mirroring%d on eswitch:%d\n",
dev_err(dev, "Failed to configure port mirroring for vNIC function %d on eSwitch %d\n",
pci_func, id);
else
dev_info(&adapter->pdev->dev,
"Configured eSwitch %d for port mirroring:%d\n",
id, pci_func);
dev_info(dev, "Configured port mirroring for vNIC function %d on eSwitch %d\n",
pci_func, id);
qlcnic_free_mbx_args(&cmd);
return err;
......@@ -1121,14 +1121,13 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
return -EIO;
}
static int
__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
static int __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
u32 *arg1, u32 *arg2)
{
int err = -EIO;
struct device *dev = &adapter->pdev->dev;
struct qlcnic_cmd_args cmd;
u8 pci_func;
pci_func = (*arg1 >> 8);
u8 pci_func = *arg1 >> 8;
int err = -EIO;
qlcnic_alloc_mbx_args(&cmd, adapter,
QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
......@@ -1139,11 +1138,10 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
qlcnic_free_mbx_args(&cmd);
if (err == QLCNIC_RCODE_SUCCESS)
dev_info(&adapter->pdev->dev,
"eSwitch port config for pci func %d\n", pci_func);
dev_info(dev, "Get eSwitch port config for vNIC function %d\n",
pci_func);
else
dev_err(&adapter->pdev->dev,
"Failed to get eswitch port config for pci func %d\n",
dev_err(dev, "Failed to get eswitch port config for vNIC function %d\n",
pci_func);
return err;
}
......@@ -1157,9 +1155,10 @@ op_type = 1 for port vlan_id
int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
struct device *dev = &adapter->pdev->dev;
struct qlcnic_cmd_args cmd;
int err = -EIO, index;
u32 arg1, arg2 = 0;
struct qlcnic_cmd_args cmd;
u8 pci_func;
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
......@@ -1216,11 +1215,11 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
qlcnic_free_mbx_args(&cmd);
if (err != QLCNIC_RCODE_SUCCESS)
dev_err(&adapter->pdev->dev,
"Failed to configure eswitch pci func %d\n", pci_func);
dev_err(dev, "Failed to configure eswitch for vNIC function %d\n",
pci_func);
else
dev_info(&adapter->pdev->dev,
"Configured eSwitch for pci func %d\n", pci_func);
dev_info(dev, "Configured eSwitch for vNIC function %d\n",
pci_func);
return err;
}
......
......@@ -1503,6 +1503,21 @@ int qlcnic_82xx_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
return rv;
}
int qlcnic_get_beacon_state(struct qlcnic_adapter *adapter, u8 *h_state)
{
struct qlcnic_cmd_args cmd;
int err;
err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LED_STATUS);
if (!err) {
err = qlcnic_issue_cmd(adapter, &cmd);
if (!err)
*h_state = cmd.rsp.arg[1];
}
qlcnic_free_mbx_args(&cmd);
return err;
}
void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter)
{
void __iomem *msix_base_addr;
......
......@@ -87,6 +87,7 @@ enum qlcnic_regs {
#define QLCNIC_CMD_CONFIG_VPORT 0x32
#define QLCNIC_CMD_GET_MAC_STATS 0x37
#define QLCNIC_CMD_SET_DRV_VER 0x38
#define QLCNIC_CMD_GET_LED_STATUS 0x3C
#define QLCNIC_CMD_CONFIGURE_RSS 0x41
#define QLCNIC_CMD_CONFIG_INTR_COAL 0x43
#define QLCNIC_CMD_CONFIGURE_LED 0x44
......
......@@ -52,10 +52,6 @@ int qlcnic_load_fw_file;
MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)");
module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444);
int qlcnic_config_npars;
module_param(qlcnic_config_npars, int, 0444);
MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled)");
static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void qlcnic_remove(struct pci_dev *pdev);
static int qlcnic_open(struct net_device *netdev);
......@@ -449,6 +445,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
.ndo_set_vf_tx_rate = qlcnic_sriov_set_vf_tx_rate,
.ndo_get_vf_config = qlcnic_sriov_get_vf_config,
.ndo_set_vf_vlan = qlcnic_sriov_set_vf_vlan,
.ndo_set_vf_spoofchk = qlcnic_sriov_set_vf_spoofchk,
#endif
};
......@@ -768,7 +765,7 @@ static int
qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
{
u8 id;
int i, ret = 1;
int ret;
u32 data = QLCNIC_MGMT_FUNC;
struct qlcnic_hardware_context *ahw = adapter->ahw;
......@@ -776,20 +773,10 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
if (ret)
goto err_lock;
if (qlcnic_config_npars) {
for (i = 0; i < ahw->act_pci_func; i++) {
id = adapter->npars[i].pci_func;
if (id == ahw->pci_func)
continue;
data |= (qlcnic_config_npars &
QLC_DEV_SET_DRV(0xf, id));
}
} else {
id = ahw->pci_func;
data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE);
data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) |
(QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC,
ahw->pci_func));
}
data = (data & ~QLC_DEV_SET_DRV(0xf, id)) |
QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, id);
QLC_SHARED_REG_WR32(adapter, QLCNIC_DRV_OP_MODE, data);
qlcnic_api_unlock(adapter);
err_lock:
......@@ -875,6 +862,27 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev,
return 0;
}
static inline bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter,
int index)
{
struct pci_dev *pdev = adapter->pdev;
unsigned short subsystem_vendor;
bool ret = true;
subsystem_vendor = pdev->subsystem_vendor;
if (pdev->device == PCI_DEVICE_ID_QLOGIC_QLE824X ||
pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) {
if (qlcnic_boards[index].sub_vendor == subsystem_vendor &&
qlcnic_boards[index].sub_device == pdev->subsystem_device)
ret = true;
else
ret = false;
}
return ret;
}
static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
{
struct pci_dev *pdev = adapter->pdev;
......@@ -883,19 +891,17 @@ static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) {
if (qlcnic_boards[i].vendor == pdev->vendor &&
qlcnic_boards[i].device == pdev->device &&
qlcnic_boards[i].sub_vendor == pdev->subsystem_vendor &&
qlcnic_boards[i].sub_device == pdev->subsystem_device) {
sprintf(name, "%pM: %s" ,
adapter->mac_addr,
qlcnic_boards[i].short_name);
qlcnic_validate_subsystem_id(adapter, i)) {
found = 1;
break;
}
}
if (!found)
sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr);
else
sprintf(name, "%pM: %s" , adapter->mac_addr,
qlcnic_boards[i].short_name);
}
static void
......@@ -1395,16 +1401,23 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
for (ring = 0; ring < num_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
if (qlcnic_82xx_check(adapter) &&
(ring == (num_sds_rings - 1)))
(ring == (num_sds_rings - 1))) {
if (!(adapter->flags &
QLCNIC_MSIX_ENABLED))
snprintf(sds_ring->name,
sizeof(sds_ring->name),
"qlcnic-%s[Tx0+Rx%d]",
netdev->name, ring);
"qlcnic");
else
snprintf(sds_ring->name,
sizeof(sds_ring->name),
"qlcnic-%s[Rx%d]",
"%s-tx-0-rx-%d",
netdev->name, ring);
} else {
snprintf(sds_ring->name,
sizeof(sds_ring->name),
"%s-rx-%d",
netdev->name, ring);
}
err = request_irq(sds_ring->irq, handler, flags,
sds_ring->name, sds_ring);
if (err)
......@@ -1419,7 +1432,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
ring++) {
tx_ring = &adapter->tx_ring[ring];
snprintf(tx_ring->name, sizeof(tx_ring->name),
"qlcnic-%s[Tx%d]", netdev->name, ring);
"%s-tx-%d", netdev->name, ring);
err = request_irq(tx_ring->irq, handler, flags,
tx_ring->name, tx_ring);
if (err)
......
......@@ -129,6 +129,7 @@ struct qlcnic_vport {
u8 vlan_mode;
u16 vlan;
u8 qos;
bool spoofchk;
u8 mac[6];
};
......@@ -225,6 +226,7 @@ int qlcnic_sriov_set_vf_tx_rate(struct net_device *, int, int);
int qlcnic_sriov_get_vf_config(struct net_device *, int ,
struct ifla_vf_info *);
int qlcnic_sriov_set_vf_vlan(struct net_device *, int, u16, u8);
int qlcnic_sriov_set_vf_spoofchk(struct net_device *, int, bool);
#else
static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}
......
......@@ -35,6 +35,7 @@ static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *);
static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *);
static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *,
struct qlcnic_cmd_args *);
static void qlcnic_sriov_process_bc_cmd(struct work_struct *);
static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
.read_crb = qlcnic_83xx_read_crb,
......@@ -179,6 +180,8 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
spin_lock_init(&vf->rcv_pend.lock);
init_completion(&vf->ch_free_cmpl);
INIT_WORK(&vf->trans_work, qlcnic_sriov_process_bc_cmd);
if (qlcnic_sriov_pf_check(adapter)) {
vp = kzalloc(sizeof(struct qlcnic_vport), GFP_KERNEL);
if (!vp) {
......@@ -187,6 +190,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
}
sriov->vf_info[i].vp = vp;
vp->max_tx_bw = MAX_BW;
vp->spoofchk = true;
random_ether_addr(vp->mac);
dev_info(&adapter->pdev->dev,
"MAC Address %pM is configured for VF %d\n",
......@@ -652,6 +656,8 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac)
if (qlcnic_read_mac_addr(adapter))
dev_warn(&adapter->pdev->dev, "failed to read mac addr\n");
INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
return 0;
}
......@@ -864,7 +870,6 @@ static void qlcnic_sriov_schedule_bc_cmd(struct qlcnic_sriov *sriov,
vf->adapter->need_fw_reset)
return;
INIT_WORK(&vf->trans_work, func);
queue_work(sriov->bc.bc_trans_wq, &vf->trans_work);
}
......
......@@ -580,6 +580,7 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func)
struct qlcnic_cmd_args cmd;
struct qlcnic_vport *vp;
int err, id;
u8 *mac;
id = qlcnic_sriov_func_to_index(adapter, func);
if (id < 0)
......@@ -591,6 +592,14 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func)
return err;
cmd.req.arg[1] = 0x3 | func << 16;
if (vp->spoofchk == true) {
mac = vp->mac;
cmd.req.arg[2] |= BIT_1 | BIT_3 | BIT_8;
cmd.req.arg[4] = mac[5] | mac[4] << 8 | mac[3] << 16 |
mac[2] << 24;
cmd.req.arg[5] = mac[1] | mac[0] << 8;
}
if (vp->vlan_mode == QLC_PVID_MODE) {
cmd.req.arg[2] |= BIT_6;
cmd.req.arg[3] |= vp->vlan << 8;
......@@ -1767,6 +1776,7 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev,
memcpy(&ivi->mac, vp->mac, ETH_ALEN);
ivi->vlan = vp->vlan;
ivi->qos = vp->qos;
ivi->spoofchk = vp->spoofchk;
if (vp->max_tx_bw == MAX_BW)
ivi->tx_rate = 0;
else
......@@ -1775,3 +1785,29 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev,
ivi->vf = vf;
return 0;
}
int qlcnic_sriov_set_vf_spoofchk(struct net_device *netdev, int vf, bool chk)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_vf_info *vf_info;
struct qlcnic_vport *vp;
if (!qlcnic_sriov_pf_check(adapter))
return -EOPNOTSUPP;
if (vf >= sriov->num_vfs)
return -EINVAL;
vf_info = &sriov->vf_info[vf];
vp = vf_info->vp;
if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) {
netdev_err(netdev,
"Spoof check change failed for VF %d, as VF driver is loaded. Please unload VF driver and retry the operation\n",
vf);
return -EOPNOTSUPP;
}
vp->spoofchk = chk;
return 0;
}
......@@ -114,25 +114,16 @@ static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon,
return 0;
}
static ssize_t qlcnic_store_beacon(struct device *dev,
struct device_attribute *attr,
static int qlcnic_83xx_store_beacon(struct qlcnic_adapter *adapter,
const char *buf, size_t len)
{
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_hardware_context *ahw = adapter->ahw;
int err, max_sds_rings = adapter->max_sds_rings;
u16 beacon;
u8 b_state, b_rate;
unsigned long h_beacon;
int err;
if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
dev_warn(dev,
"LED test not supported in non privileged mode\n");
return -EOPNOTSUPP;
}
if (test_bit(__QLCNIC_RESETTING, &adapter->state))
return -EIO;
if (qlcnic_83xx_check(adapter) &&
!test_bit(__QLCNIC_RESETTING, &adapter->state)) {
if (kstrtoul(buf, 2, &h_beacon))
return -EINVAL;
......@@ -141,30 +132,33 @@ static ssize_t qlcnic_store_beacon(struct device *dev,
rtnl_lock();
if (!ahw->beacon_state) {
if (test_and_set_bit(__QLCNIC_LED_ENABLE,
&adapter->state)) {
if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
rtnl_unlock();
return -EBUSY;
}
}
if (h_beacon) {
if (h_beacon)
err = qlcnic_83xx_config_led(adapter, 1, h_beacon);
if (err)
goto beacon_err;
} else {
else
err = qlcnic_83xx_config_led(adapter, 0, !h_beacon);
if (err)
goto beacon_err;
}
/* set the current beacon state */
if (!err)
ahw->beacon_state = h_beacon;
beacon_err:
if (!ahw->beacon_state)
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
rtnl_unlock();
return len;
}
}
static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
const char *buf, size_t len)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
int err, max_sds_rings = adapter->max_sds_rings;
u16 beacon;
u8 h_beacon_state, b_state, b_rate;
if (len != sizeof(u16))
return QL_STATUS_INVALID_PARAM;
......@@ -174,16 +168,29 @@ static ssize_t qlcnic_store_beacon(struct device *dev,
if (err)
return err;
if (adapter->ahw->beacon_state == b_state)
if ((ahw->capabilities2 & QLCNIC_FW_CAPABILITY_2_BEACON)) {
err = qlcnic_get_beacon_state(adapter, &h_beacon_state);
if (!err) {
dev_info(&adapter->pdev->dev,
"Failed to get current beacon state\n");
} else {
if (h_beacon_state == QLCNIC_BEACON_DISABLE)
ahw->beacon_state = 0;
else if (h_beacon_state == QLCNIC_BEACON_EANBLE)
ahw->beacon_state = 2;
}
}
if (ahw->beacon_state == b_state)
return len;
rtnl_lock();
if (!adapter->ahw->beacon_state)
if (!ahw->beacon_state) {
if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
rtnl_unlock();
return -EBUSY;
}
}
if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
err = -EIO;
......@@ -206,14 +213,37 @@ static ssize_t qlcnic_store_beacon(struct device *dev,
if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
out:
if (!adapter->ahw->beacon_state)
out:
if (!ahw->beacon_state)
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
rtnl_unlock();
return err;
}
static ssize_t qlcnic_store_beacon(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
int err = 0;
if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
dev_warn(dev,
"LED test not supported in non privileged mode\n");
return -EOPNOTSUPP;
}
if (qlcnic_82xx_check(adapter))
err = qlcnic_82xx_store_beacon(adapter, buf, len);
else if (qlcnic_83xx_check(adapter))
err = qlcnic_83xx_store_beacon(adapter, buf, len);
else
return -EIO;
return err;
}
static ssize_t qlcnic_show_beacon(struct device *dev,
struct device_attribute *attr, char *buf)
{
......
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