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