Commit 5c509a2e authored by David S. Miller's avatar David S. Miller

Merge branch 'qlcnic'

Manish Chopra says:

====================
qlcnic: Refactoring and enhancements

This patch series includes follwing changes

* Refactor DCBX code. Do not allow DCBX operations for VFs
* Issue INIT_NIC mailbox command only once
* Refactor initialize nic code path
* Allow configuration for single TX/RX queue
* VLAN enhancement for 84xx adapters
* Support for 16 virtual NIC functions for 84XX series adapters

Please apply to net-next
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents baf9573e c100bb22
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
#define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 3 #define _QLCNIC_LINUX_MINOR 3
#define _QLCNIC_LINUX_SUBVERSION 52 #define _QLCNIC_LINUX_SUBVERSION 53
#define QLCNIC_LINUX_VERSIONID "5.3.52" #define QLCNIC_LINUX_VERSIONID "5.3.53"
#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))
...@@ -115,6 +115,10 @@ enum qlcnic_queue_type { ...@@ -115,6 +115,10 @@ enum qlcnic_queue_type {
#define QLCNIC_VNIC_MODE 0xFF #define QLCNIC_VNIC_MODE 0xFF
#define QLCNIC_DEFAULT_MODE 0x0 #define QLCNIC_DEFAULT_MODE 0x0
/* Virtual NIC function count */
#define QLC_DEFAULT_VNIC_COUNT 8
#define QLC_84XX_VNIC_COUNT 16
/* /*
* Following are the states of the Phantom. Phantom will set them and * Following are the states of the Phantom. Phantom will set them and
* Host will read to check if the fields are correct. * Host will read to check if the fields are correct.
...@@ -374,7 +378,7 @@ struct qlcnic_rx_buffer { ...@@ -374,7 +378,7 @@ struct qlcnic_rx_buffer {
#define QLCNIC_INTR_DEFAULT 0x04 #define QLCNIC_INTR_DEFAULT 0x04
#define QLCNIC_CONFIG_INTR_COALESCE 3 #define QLCNIC_CONFIG_INTR_COALESCE 3
#define QLCNIC_DEV_INFO_SIZE 1 #define QLCNIC_DEV_INFO_SIZE 2
struct qlcnic_nic_intr_coalesce { struct qlcnic_nic_intr_coalesce {
u8 type; u8 type;
...@@ -462,8 +466,10 @@ struct qlcnic_hardware_context { ...@@ -462,8 +466,10 @@ struct qlcnic_hardware_context {
u16 max_rx_ques; u16 max_rx_ques;
u16 max_mtu; u16 max_mtu;
u32 msg_enable; u32 msg_enable;
u16 act_pci_func; u16 total_nic_func;
u16 max_pci_func; u16 max_pci_func;
u32 max_vnic_func;
u32 total_pci_func;
u32 capabilities; u32 capabilities;
u32 extra_capability[3]; u32 extra_capability[3];
...@@ -788,9 +794,10 @@ struct qlcnic_cardrsp_tx_ctx { ...@@ -788,9 +794,10 @@ struct qlcnic_cardrsp_tx_ctx {
#define QLCNIC_MAC_VLAN_ADD 3 #define QLCNIC_MAC_VLAN_ADD 3
#define QLCNIC_MAC_VLAN_DEL 4 #define QLCNIC_MAC_VLAN_DEL 4
struct qlcnic_mac_list_s { struct qlcnic_mac_vlan_list {
struct list_head list; struct list_head list;
uint8_t mac_addr[ETH_ALEN+2]; uint8_t mac_addr[ETH_ALEN+2];
u16 vlan_id;
}; };
/* MAC Learn */ /* MAC Learn */
...@@ -856,7 +863,7 @@ struct qlcnic_mac_list_s { ...@@ -856,7 +863,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3
#define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5 #define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5
#define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7
#define QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG BIT_8 #define QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG BIT_9
/* module types */ /* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1 #define LINKEVENT_MODULE_NOT_PRESENT 1
...@@ -1637,7 +1644,9 @@ int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); ...@@ -1637,7 +1644,9 @@ int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
void qlcnic_set_netdev_features(struct qlcnic_adapter *, void qlcnic_set_netdev_features(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *); struct qlcnic_esw_func_cfg *);
void qlcnic_sriov_vf_schedule_multi(struct net_device *); void qlcnic_sriov_vf_schedule_multi(struct net_device *);
void qlcnic_vf_add_mc_list(struct net_device *, u16); int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8);
int qlcnic_get_pci_func_type(struct qlcnic_adapter *, u16, u16 *, u16 *,
u16 *);
/* /*
* QLOGIC Board information * QLOGIC Board information
...@@ -2136,4 +2145,26 @@ static inline bool qlcnic_sriov_vf_check(struct qlcnic_adapter *adapter) ...@@ -2136,4 +2145,26 @@ static inline bool qlcnic_sriov_vf_check(struct qlcnic_adapter *adapter)
return status; return status;
} }
static inline bool qlcnic_83xx_pf_check(struct qlcnic_adapter *adapter)
{
unsigned short device = adapter->pdev->device;
return (device == PCI_DEVICE_ID_QLOGIC_QLE834X) ? true : false;
}
static inline bool qlcnic_83xx_vf_check(struct qlcnic_adapter *adapter)
{
unsigned short device = adapter->pdev->device;
return (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X) ? true : false;
}
static inline u32 qlcnic_get_vnic_func_count(struct qlcnic_adapter *adapter)
{
if (qlcnic_84xx_check(adapter))
return QLC_84XX_VNIC_COUNT;
else
return QLC_DEFAULT_VNIC_COUNT;
}
#endif /* __QLCNIC_H_ */ #endif /* __QLCNIC_H_ */
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define RSS_HASHTYPE_IP_TCP 0x3 #define RSS_HASHTYPE_IP_TCP 0x3
#define QLC_83XX_FW_MBX_CMD 0 #define QLC_83XX_FW_MBX_CMD 0
#define QLC_SKIP_INACTIVE_PCI_REGS 7
static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
{QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1}, {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
...@@ -34,7 +35,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { ...@@ -34,7 +35,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
{QLCNIC_CMD_READ_MAX_MTU, 4, 2}, {QLCNIC_CMD_READ_MAX_MTU, 4, 2},
{QLCNIC_CMD_READ_MAX_LRO, 4, 2}, {QLCNIC_CMD_READ_MAX_LRO, 4, 2},
{QLCNIC_CMD_MAC_ADDRESS, 4, 3}, {QLCNIC_CMD_MAC_ADDRESS, 4, 3},
{QLCNIC_CMD_GET_PCI_INFO, 1, 66}, {QLCNIC_CMD_GET_PCI_INFO, 1, 129},
{QLCNIC_CMD_GET_NIC_INFO, 2, 19}, {QLCNIC_CMD_GET_NIC_INFO, 2, 19},
{QLCNIC_CMD_SET_NIC_INFO, 32, 1}, {QLCNIC_CMD_SET_NIC_INFO, 32, 1},
{QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3}, {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
...@@ -68,7 +69,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { ...@@ -68,7 +69,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
{QLCNIC_CMD_CONFIG_VPORT, 4, 4}, {QLCNIC_CMD_CONFIG_VPORT, 4, 4},
{QLCNIC_CMD_BC_EVENT_SETUP, 2, 1}, {QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
{QLCNIC_CMD_DCB_QUERY_CAP, 1, 2}, {QLCNIC_CMD_DCB_QUERY_CAP, 1, 2},
{QLCNIC_CMD_DCB_QUERY_PARAM, 2, 50}, {QLCNIC_CMD_DCB_QUERY_PARAM, 1, 50},
}; };
const u32 qlcnic_83xx_ext_reg_tbl[] = { const u32 qlcnic_83xx_ext_reg_tbl[] = {
...@@ -289,6 +290,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter) ...@@ -289,6 +290,7 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
if (qlcnic_sriov_vf_check(adapter)) if (qlcnic_sriov_vf_check(adapter))
return -EINVAL; return -EINVAL;
num_msix = 1; num_msix = 1;
adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
} }
/* setup interrupt mapping table for fw */ /* setup interrupt mapping table for fw */
ahw->intr_tbl = vzalloc(num_msix * ahw->intr_tbl = vzalloc(num_msix *
...@@ -636,7 +638,7 @@ int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter) ...@@ -636,7 +638,7 @@ int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter) void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
u16 act_pci_fn = ahw->act_pci_func; u16 act_pci_fn = ahw->total_nic_func;
u16 count; u16 count;
ahw->max_mc_count = QLC_83XX_MAX_MC_COUNT; ahw->max_mc_count = QLC_83XX_MAX_MC_COUNT;
...@@ -1518,8 +1520,7 @@ int qlcnic_83xx_set_led(struct net_device *netdev, ...@@ -1518,8 +1520,7 @@ int qlcnic_83xx_set_led(struct net_device *netdev,
return err; return err;
} }
void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter, void qlcnic_83xx_initialize_nic(struct qlcnic_adapter *adapter, int enable)
int enable)
{ {
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
int status; int status;
...@@ -1527,21 +1528,21 @@ void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter, ...@@ -1527,21 +1528,21 @@ void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
if (qlcnic_sriov_vf_check(adapter)) if (qlcnic_sriov_vf_check(adapter))
return; return;
if (enable) { if (enable)
status = qlcnic_alloc_mbx_args(&cmd, adapter, status = qlcnic_alloc_mbx_args(&cmd, adapter,
QLCNIC_CMD_INIT_NIC_FUNC); QLCNIC_CMD_INIT_NIC_FUNC);
if (status) else
return;
cmd.req.arg[1] = BIT_0 | BIT_31;
} else {
status = qlcnic_alloc_mbx_args(&cmd, adapter, status = qlcnic_alloc_mbx_args(&cmd, adapter,
QLCNIC_CMD_STOP_NIC_FUNC); QLCNIC_CMD_STOP_NIC_FUNC);
if (status)
return;
cmd.req.arg[1] = BIT_0 | BIT_31; if (status)
} return;
cmd.req.arg[1] = QLC_REGISTER_LB_IDC | QLC_INIT_FW_RESOURCES;
if (adapter->dcb)
cmd.req.arg[1] |= QLC_REGISTER_DCB_AEN;
status = qlcnic_issue_cmd(adapter, &cmd); status = qlcnic_issue_cmd(adapter, &cmd);
if (status) if (status)
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
...@@ -1637,7 +1638,7 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) ...@@ -1637,7 +1638,7 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
cmd->type = QLC_83XX_MBX_CMD_NO_WAIT; cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
qlcnic_83xx_set_interface_id_promisc(adapter, &temp); qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
cmd->req.arg[1] = (mode ? 1 : 0) | temp; cmd->req.arg[1] = mode | temp;
err = qlcnic_issue_cmd(adapter, cmd); err = qlcnic_issue_cmd(adapter, cmd);
if (!err) if (!err)
return err; return err;
...@@ -2293,11 +2294,37 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter, ...@@ -2293,11 +2294,37 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
return err; return err;
} }
int qlcnic_get_pci_func_type(struct qlcnic_adapter *adapter, u16 type,
u16 *nic, u16 *fcoe, u16 *iscsi)
{
struct device *dev = &adapter->pdev->dev;
int err = 0;
switch (type) {
case QLCNIC_TYPE_NIC:
(*nic)++;
break;
case QLCNIC_TYPE_FCOE:
(*fcoe)++;
break;
case QLCNIC_TYPE_ISCSI:
(*iscsi)++;
break;
default:
dev_err(dev, "%s: Unknown PCI type[%x]\n",
__func__, type);
err = -EIO;
}
return err;
}
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 qlcnic_hardware_context *ahw = adapter->ahw;
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
u16 nic = 0, fcoe = 0, iscsi = 0;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
int i, err = 0, j = 0; int i, err = 0, j = 0;
u32 temp; u32 temp;
...@@ -2308,16 +2335,20 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, ...@@ -2308,16 +2335,20 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
err = qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, &cmd);
ahw->act_pci_func = 0; ahw->total_nic_func = 0;
if (err == QLCNIC_RCODE_SUCCESS) { if (err == QLCNIC_RCODE_SUCCESS) {
ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF; ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF;
for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) { for (i = 2, j = 0; j < ahw->max_vnic_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++;
if (!pci_info->active) {
i += QLC_SKIP_INACTIVE_PCI_REGS;
continue;
}
pci_info->type = cmd.rsp.arg[i] & 0xFFFF; pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
if (pci_info->type == QLCNIC_TYPE_NIC) err = qlcnic_get_pci_func_type(adapter, pci_info->type,
ahw->act_pci_func++; &nic, &fcoe, &iscsi);
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++;
...@@ -2335,6 +2366,13 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, ...@@ -2335,6 +2366,13 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
err = -EIO; err = -EIO;
} }
ahw->total_nic_func = nic;
ahw->total_pci_func = nic + fcoe + iscsi;
if (ahw->total_nic_func == 0 || ahw->total_pci_func == 0) {
dev_err(dev, "%s: Invalid function count: total nic func[%x], total pci func[%x]\n",
__func__, ahw->total_nic_func, ahw->total_pci_func);
err = -EIO;
}
qlcnic_free_mbx_args(&cmd); qlcnic_free_mbx_args(&cmd);
return err; return err;
......
...@@ -324,6 +324,11 @@ struct qlc_83xx_idc { ...@@ -324,6 +324,11 @@ struct qlc_83xx_idc {
char **name; char **name;
}; };
enum qlcnic_vlan_operations {
QLC_VLAN_ADD = 0,
QLC_VLAN_DELETE
};
/* Device States */ /* Device States */
enum qlcnic_83xx_states { enum qlcnic_83xx_states {
QLC_83XX_IDC_DEV_UNKNOWN, QLC_83XX_IDC_DEV_UNKNOWN,
...@@ -518,6 +523,11 @@ enum qlc_83xx_ext_regs { ...@@ -518,6 +523,11 @@ enum qlc_83xx_ext_regs {
QLC_83XX_ASIC_TEMP, QLC_83XX_ASIC_TEMP,
}; };
/* Initialize/Stop NIC command bit definitions */
#define QLC_REGISTER_DCB_AEN BIT_1
#define QLC_REGISTER_LB_IDC BIT_0
#define QLC_INIT_FW_RESOURCES BIT_31
/* 83xx funcitons */ /* 83xx funcitons */
int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *); int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *); int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
...@@ -542,7 +552,7 @@ int qlcnic_83xx_config_intr_coalesce(struct qlcnic_adapter *); ...@@ -542,7 +552,7 @@ int qlcnic_83xx_config_intr_coalesce(struct qlcnic_adapter *);
void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, u16); void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, u16);
int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *); int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int); void qlcnic_83xx_initialize_nic(struct qlcnic_adapter *, int);
int qlcnic_83xx_napi_add(struct qlcnic_adapter *, struct net_device *); int qlcnic_83xx_napi_add(struct qlcnic_adapter *, struct net_device *);
void qlcnic_83xx_napi_del(struct qlcnic_adapter *); void qlcnic_83xx_napi_del(struct qlcnic_adapter *);
......
...@@ -614,8 +614,7 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) ...@@ -614,8 +614,7 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox); qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);
qlcnic_83xx_enable_mbx_interrupt(adapter); qlcnic_83xx_enable_mbx_interrupt(adapter);
/* register for NIC IDC AEN Events */ qlcnic_83xx_initialize_nic(adapter, 1);
qlcnic_83xx_register_nic_idc_func(adapter, 1);
err = qlcnic_sriov_pf_reinit(adapter); err = qlcnic_sriov_pf_reinit(adapter);
if (err) if (err)
...@@ -2198,7 +2197,6 @@ static void qlcnic_83xx_init_rings(struct qlcnic_adapter *adapter) ...@@ -2198,7 +2197,6 @@ static void qlcnic_83xx_init_rings(struct qlcnic_adapter *adapter)
int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_dcb *dcb;
int err = 0; int err = 0;
ahw->msix_supported = !!qlcnic_use_msi_x; ahw->msix_supported = !!qlcnic_use_msi_x;
...@@ -2250,8 +2248,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) ...@@ -2250,8 +2248,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);
/* register for NIC IDC AEN Events */ qlcnic_83xx_initialize_nic(adapter, 1);
qlcnic_83xx_register_nic_idc_func(adapter, 1);
/* Configure default, SR-IOV or Virtual NIC mode of operation */ /* Configure default, SR-IOV or Virtual NIC mode of operation */
err = qlcnic_83xx_configure_opmode(adapter); err = qlcnic_83xx_configure_opmode(adapter);
...@@ -2264,11 +2261,6 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) ...@@ -2264,11 +2261,6 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
if (err) if (err)
goto disable_mbx_intr; goto disable_mbx_intr;
dcb = adapter->dcb;
if (dcb && qlcnic_dcb_attach(dcb))
qlcnic_clear_dcb_ops(dcb);
/* Periodically monitor device status */ /* Periodically monitor device status */
qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work); qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);
return 0; return 0;
...@@ -2299,7 +2291,7 @@ void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter) ...@@ -2299,7 +2291,7 @@ void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter)
qlcnic_83xx_disable_vnic_mode(adapter, 1); qlcnic_83xx_disable_vnic_mode(adapter, 1);
qlcnic_83xx_idc_detach_driver(adapter); qlcnic_83xx_idc_detach_driver(adapter);
qlcnic_83xx_register_nic_idc_func(adapter, 0); qlcnic_83xx_initialize_nic(adapter, 0);
cancel_delayed_work_sync(&adapter->idc_aen_work); cancel_delayed_work_sync(&adapter->idc_aen_work);
} }
......
...@@ -107,7 +107,7 @@ static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter) ...@@ -107,7 +107,7 @@ static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter)
npar = adapter->npars; npar = adapter->npars;
for (i = 0; i < ahw->act_pci_func; i++, npar++) { for (i = 0; i < ahw->total_nic_func; i++, npar++) {
dev_info(dev, "id:%d active:%d type:%d port:%d min_bw:%d max_bw:%d mac_addr:%pM\n", dev_info(dev, "id:%d active:%d type:%d port:%d min_bw:%d max_bw:%d mac_addr:%pM\n",
npar->pci_func, npar->active, npar->type, npar->pci_func, npar->active, npar->type,
npar->phy_port, npar->min_bw, npar->max_bw, npar->phy_port, npar->min_bw, npar->max_bw,
...@@ -115,7 +115,7 @@ static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter) ...@@ -115,7 +115,7 @@ static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter)
} }
dev_info(dev, "Max functions = %d, active functions = %d\n", dev_info(dev, "Max functions = %d, active functions = %d\n",
ahw->max_pci_func, ahw->act_pci_func); ahw->max_pci_func, ahw->total_nic_func);
if (qlcnic_83xx_set_vnic_opmode(adapter)) if (qlcnic_83xx_set_vnic_opmode(adapter))
return err; return err;
......
...@@ -91,18 +91,6 @@ void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd) ...@@ -91,18 +91,6 @@ void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd)
cmd->rsp.arg = NULL; cmd->rsp.arg = NULL;
} }
static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
{
int i;
for (i = 0; i < adapter->ahw->act_pci_func; i++) {
if (adapter->npars[i].pci_func == pci_func)
return i;
}
return -1;
}
static u32 static u32
qlcnic_poll_rsp(struct qlcnic_adapter *adapter) qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
{ {
...@@ -966,13 +954,15 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter, ...@@ -966,13 +954,15 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
struct qlcnic_pci_info *pci_info) struct qlcnic_pci_info *pci_info)
{ {
int err = 0, i; struct qlcnic_hardware_context *ahw = adapter->ahw;
size_t npar_size = sizeof(struct qlcnic_pci_info_le);
size_t pci_size = npar_size * ahw->max_vnic_func;
u16 nic = 0, fcoe = 0, iscsi = 0;
struct qlcnic_pci_info_le *npar;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
dma_addr_t pci_info_dma_t; dma_addr_t pci_info_dma_t;
struct qlcnic_pci_info_le *npar;
void *pci_info_addr; void *pci_info_addr;
size_t npar_size = sizeof(struct qlcnic_pci_info_le); int err = 0, i;
size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
pci_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, pci_size, pci_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, pci_size,
&pci_info_dma_t, GFP_KERNEL); &pci_info_dma_t, GFP_KERNEL);
...@@ -989,14 +979,16 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, ...@@ -989,14 +979,16 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
cmd.req.arg[3] = pci_size; cmd.req.arg[3] = pci_size;
err = qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, &cmd);
adapter->ahw->act_pci_func = 0; ahw->total_nic_func = 0;
if (err == QLCNIC_RCODE_SUCCESS) { if (err == QLCNIC_RCODE_SUCCESS) {
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) { for (i = 0; i < ahw->max_vnic_func; i++, npar++, pci_info++) {
pci_info->id = le16_to_cpu(npar->id); pci_info->id = le16_to_cpu(npar->id);
pci_info->active = le16_to_cpu(npar->active); pci_info->active = le16_to_cpu(npar->active);
if (!pci_info->active)
continue;
pci_info->type = le16_to_cpu(npar->type); pci_info->type = le16_to_cpu(npar->type);
if (pci_info->type == QLCNIC_TYPE_NIC) err = qlcnic_get_pci_func_type(adapter, pci_info->type,
adapter->ahw->act_pci_func++; &nic, &fcoe, &iscsi);
pci_info->default_port = pci_info->default_port =
le16_to_cpu(npar->default_port); le16_to_cpu(npar->default_port);
pci_info->tx_min_bw = pci_info->tx_min_bw =
...@@ -1011,6 +1003,14 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, ...@@ -1011,6 +1003,14 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
err = -EIO; err = -EIO;
} }
ahw->total_nic_func = nic;
ahw->total_pci_func = nic + fcoe + iscsi;
if (ahw->total_nic_func == 0 || ahw->total_pci_func == 0) {
dev_err(&adapter->pdev->dev,
"%s: Invalid function count: total nic func[%x], total pci func[%x]\n",
__func__, ahw->total_nic_func, ahw->total_pci_func);
err = -EIO;
}
qlcnic_free_mbx_args(&cmd); qlcnic_free_mbx_args(&cmd);
out_free_dma: out_free_dma:
dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr, dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
...@@ -1203,7 +1203,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, ...@@ -1203,7 +1203,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL; esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
esw_stats->context_id = eswitch; esw_stats->context_id = eswitch;
for (i = 0; i < adapter->ahw->act_pci_func; i++) { for (i = 0; i < adapter->ahw->total_nic_func; i++) {
if (adapter->npars[i].phy_port != eswitch) if (adapter->npars[i].phy_port != eswitch)
continue; continue;
...@@ -1236,15 +1236,16 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, ...@@ -1236,15 +1236,16 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
const u8 port, const u8 rx_tx) const u8 port, const u8 rx_tx)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_cmd_args cmd;
int err; int err;
u32 arg1; u32 arg1;
struct qlcnic_cmd_args cmd;
if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) if (ahw->op_mode != QLCNIC_MGMT_FUNC)
return -EIO; return -EIO;
if (func_esw == QLCNIC_STATS_PORT) { if (func_esw == QLCNIC_STATS_PORT) {
if (port >= QLCNIC_MAX_PCI_FUNC) if (port >= ahw->max_vnic_func)
goto err_ret; goto err_ret;
} else if (func_esw == QLCNIC_STATS_ESWITCH) { } else if (func_esw == QLCNIC_STATS_ESWITCH) {
if (port >= QLCNIC_NIU_MAX_XG_PORTS) if (port >= QLCNIC_NIU_MAX_XG_PORTS)
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#define QLC_DCB_GET_MAP(V) (1 << V) #define QLC_DCB_GET_MAP(V) (1 << V)
#define QLC_DCB_AEN_BIT 0x2
#define QLC_DCB_FW_VER 0x2 #define QLC_DCB_FW_VER 0x2
#define QLC_DCB_MAX_TC 0x8 #define QLC_DCB_MAX_TC 0x8
#define QLC_DCB_MAX_APP 0x8 #define QLC_DCB_MAX_APP 0x8
...@@ -71,7 +70,6 @@ static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *, void *); ...@@ -71,7 +70,6 @@ static void qlcnic_82xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *); static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_dcb *);
static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8); static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_dcb *, char *, u8);
static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *); static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *);
static int qlcnic_83xx_dcb_register_aen(struct qlcnic_dcb *, bool);
static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *, void *); static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *, void *);
struct qlcnic_dcb_capability { struct qlcnic_dcb_capability {
...@@ -179,7 +177,6 @@ static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = { ...@@ -179,7 +177,6 @@ static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = {
.get_hw_capability = qlcnic_83xx_dcb_get_hw_capability, .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability,
.query_cee_param = qlcnic_83xx_dcb_query_cee_param, .query_cee_param = qlcnic_83xx_dcb_query_cee_param,
.get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg, .get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg,
.register_aen = qlcnic_83xx_dcb_register_aen,
.aen_handler = qlcnic_83xx_dcb_aen_handler, .aen_handler = qlcnic_83xx_dcb_aen_handler,
}; };
...@@ -260,6 +257,9 @@ int qlcnic_register_dcb(struct qlcnic_adapter *adapter) ...@@ -260,6 +257,9 @@ int qlcnic_register_dcb(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_dcb *dcb; struct qlcnic_dcb *dcb;
if (qlcnic_sriov_vf_check(adapter))
return 0;
dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC); dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC);
if (!dcb) if (!dcb)
return -ENOMEM; return -ENOMEM;
...@@ -280,7 +280,6 @@ static void __qlcnic_dcb_free(struct qlcnic_dcb *dcb) ...@@ -280,7 +280,6 @@ static void __qlcnic_dcb_free(struct qlcnic_dcb *dcb)
return; return;
adapter = dcb->adapter; adapter = dcb->adapter;
qlcnic_dcb_register_aen(dcb, 0);
while (test_bit(QLCNIC_DCB_AEN_MODE, &dcb->state)) while (test_bit(QLCNIC_DCB_AEN_MODE, &dcb->state))
usleep_range(10000, 11000); usleep_range(10000, 11000);
...@@ -304,7 +303,6 @@ static void __qlcnic_dcb_get_info(struct qlcnic_dcb *dcb) ...@@ -304,7 +303,6 @@ static void __qlcnic_dcb_get_info(struct qlcnic_dcb *dcb)
{ {
qlcnic_dcb_get_hw_capability(dcb); qlcnic_dcb_get_hw_capability(dcb);
qlcnic_dcb_get_cee_cfg(dcb); qlcnic_dcb_get_cee_cfg(dcb);
qlcnic_dcb_register_aen(dcb, 1);
} }
static int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb) static int __qlcnic_dcb_attach(struct qlcnic_dcb *dcb)
...@@ -642,29 +640,6 @@ static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb) ...@@ -642,29 +640,6 @@ static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
return err; return err;
} }
static int qlcnic_83xx_dcb_register_aen(struct qlcnic_dcb *dcb, bool flag)
{
u8 val = (flag ? QLCNIC_CMD_INIT_NIC_FUNC : QLCNIC_CMD_STOP_NIC_FUNC);
struct qlcnic_adapter *adapter = dcb->adapter;
struct qlcnic_cmd_args cmd;
int err;
err = qlcnic_alloc_mbx_args(&cmd, adapter, val);
if (err)
return err;
cmd.req.arg[1] = QLC_DCB_AEN_BIT;
err = qlcnic_issue_cmd(adapter, &cmd);
if (err)
dev_err(&adapter->pdev->dev, "Failed to %s DCBX AEN, err %d\n",
(flag ? "register" : "unregister"), err);
qlcnic_free_mbx_args(&cmd);
return err;
}
static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data) static void qlcnic_83xx_dcb_aen_handler(struct qlcnic_dcb *dcb, void *data)
{ {
u32 *val = data; u32 *val = data;
......
...@@ -25,7 +25,6 @@ struct qlcnic_dcb_ops { ...@@ -25,7 +25,6 @@ struct qlcnic_dcb_ops {
int (*get_hw_capability) (struct qlcnic_dcb *); int (*get_hw_capability) (struct qlcnic_dcb *);
int (*query_cee_param) (struct qlcnic_dcb *, char *, u8); int (*query_cee_param) (struct qlcnic_dcb *, char *, u8);
void (*init_dcbnl_ops) (struct qlcnic_dcb *); void (*init_dcbnl_ops) (struct qlcnic_dcb *);
int (*register_aen) (struct qlcnic_dcb *, bool);
void (*aen_handler) (struct qlcnic_dcb *, void *); void (*aen_handler) (struct qlcnic_dcb *, void *);
int (*get_cee_cfg) (struct qlcnic_dcb *); int (*get_cee_cfg) (struct qlcnic_dcb *);
void (*get_info) (struct qlcnic_dcb *); void (*get_info) (struct qlcnic_dcb *);
...@@ -103,13 +102,6 @@ static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_dcb *dcb) ...@@ -103,13 +102,6 @@ static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
return 0; return 0;
} }
static inline void
qlcnic_dcb_register_aen(struct qlcnic_dcb *dcb, u8 flag)
{
if (dcb && dcb->ops->register_aen)
dcb->ops->register_aen(dcb, flag);
}
static inline void qlcnic_dcb_aen_handler(struct qlcnic_dcb *dcb, void *msg) static inline void qlcnic_dcb_aen_handler(struct qlcnic_dcb *dcb, void *msg)
{ {
if (dcb && dcb->ops->aen_handler) if (dcb && dcb->ops->aen_handler)
...@@ -121,4 +113,10 @@ static inline void qlcnic_dcb_init_dcbnl_ops(struct qlcnic_dcb *dcb) ...@@ -121,4 +113,10 @@ static inline void qlcnic_dcb_init_dcbnl_ops(struct qlcnic_dcb *dcb)
if (dcb && dcb->ops->init_dcbnl_ops) if (dcb && dcb->ops->init_dcbnl_ops)
dcb->ops->init_dcbnl_ops(dcb); dcb->ops->init_dcbnl_ops(dcb);
} }
static inline void qlcnic_dcb_enable(struct qlcnic_dcb *dcb)
{
if (dcb && qlcnic_dcb_attach(dcb))
qlcnic_clear_dcb_ops(dcb);
}
#endif #endif
...@@ -221,7 +221,7 @@ static const u32 ext_diag_registers[] = { ...@@ -221,7 +221,7 @@ static const u32 ext_diag_registers[] = {
-1 -1
}; };
#define QLCNIC_MGMT_API_VERSION 2 #define QLCNIC_MGMT_API_VERSION 3
#define QLCNIC_ETHTOOL_REGS_VER 4 #define QLCNIC_ETHTOOL_REGS_VER 4
static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter) static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter)
...@@ -519,6 +519,9 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) ...@@ -519,6 +519,9 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff)); regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
regs_buff[1] = QLCNIC_MGMT_API_VERSION; regs_buff[1] = QLCNIC_MGMT_API_VERSION;
if (adapter->ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
regs_buff[2] = adapter->ahw->max_vnic_func;
if (qlcnic_82xx_check(adapter)) if (qlcnic_82xx_check(adapter))
i = qlcnic_82xx_get_registers(adapter, regs_buff); i = qlcnic_82xx_get_registers(adapter, regs_buff);
else else
......
...@@ -698,7 +698,6 @@ struct qlcnic_legacy_intr_set { ...@@ -698,7 +698,6 @@ struct qlcnic_legacy_intr_set {
}; };
#define QLCNIC_MSIX_BASE 0x132110 #define QLCNIC_MSIX_BASE 0x132110
#define QLCNIC_MAX_PCI_FUNC 8
#define QLCNIC_MAX_VLAN_FILTERS 64 #define QLCNIC_MAX_VLAN_FILTERS 64
#define FLASH_ROM_WINDOW 0x42110030 #define FLASH_ROM_WINDOW 0x42110030
......
...@@ -455,13 +455,13 @@ int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, ...@@ -455,13 +455,13 @@ int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr) int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr)
{ {
struct qlcnic_mac_vlan_list *cur;
struct list_head *head; struct list_head *head;
struct qlcnic_mac_list_s *cur;
int err = -EINVAL; int err = -EINVAL;
/* Delete MAC from the existing list */ /* Delete MAC from the existing list */
list_for_each(head, &adapter->mac_list) { list_for_each(head, &adapter->mac_list) {
cur = list_entry(head, struct qlcnic_mac_list_s, list); cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
err = qlcnic_sre_macaddr_change(adapter, cur->mac_addr, err = qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
0, QLCNIC_MAC_DEL); 0, QLCNIC_MAC_DEL);
...@@ -477,17 +477,18 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr) ...@@ -477,17 +477,18 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr)
int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan) int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
{ {
struct qlcnic_mac_vlan_list *cur;
struct list_head *head; struct list_head *head;
struct qlcnic_mac_list_s *cur;
/* look up if already exists */ /* look up if already exists */
list_for_each(head, &adapter->mac_list) { list_for_each(head, &adapter->mac_list) {
cur = list_entry(head, struct qlcnic_mac_list_s, list); cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0 &&
cur->vlan_id == vlan)
return 0; return 0;
} }
cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC); cur = kzalloc(sizeof(*cur), GFP_ATOMIC);
if (cur == NULL) if (cur == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -499,6 +500,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan) ...@@ -499,6 +500,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
return -EIO; return -EIO;
} }
cur->vlan_id = vlan;
list_add_tail(&cur->list, &adapter->mac_list); list_add_tail(&cur->list, &adapter->mac_list);
return 0; return 0;
} }
...@@ -516,8 +518,7 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) ...@@ -516,8 +518,7 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
return; return;
if (!qlcnic_sriov_vf_check(adapter)) qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan);
qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan);
qlcnic_nic_add_mac(adapter, bcast_addr, vlan); qlcnic_nic_add_mac(adapter, bcast_addr, vlan);
if (netdev->flags & IFF_PROMISC) { if (netdev->flags & IFF_PROMISC) {
...@@ -526,15 +527,11 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) ...@@ -526,15 +527,11 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
} else if ((netdev->flags & IFF_ALLMULTI) || } else if ((netdev->flags & IFF_ALLMULTI) ||
(netdev_mc_count(netdev) > ahw->max_mc_count)) { (netdev_mc_count(netdev) > ahw->max_mc_count)) {
mode = VPORT_MISS_MODE_ACCEPT_MULTI; mode = VPORT_MISS_MODE_ACCEPT_MULTI;
} else if (!netdev_mc_empty(netdev) && } else if (!netdev_mc_empty(netdev)) {
!qlcnic_sriov_vf_check(adapter)) {
netdev_for_each_mc_addr(ha, netdev) netdev_for_each_mc_addr(ha, netdev)
qlcnic_nic_add_mac(adapter, ha->addr, vlan); qlcnic_nic_add_mac(adapter, ha->addr, vlan);
} }
if (qlcnic_sriov_vf_check(adapter))
qlcnic_vf_add_mc_list(netdev, vlan);
/* configure unicast MAC address, if there is not sufficient space /* configure unicast MAC address, if there is not sufficient space
* to store all the unicast addresses then enable promiscuous mode * to store all the unicast addresses then enable promiscuous mode
*/ */
...@@ -545,14 +542,12 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) ...@@ -545,14 +542,12 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
qlcnic_nic_add_mac(adapter, ha->addr, vlan); qlcnic_nic_add_mac(adapter, ha->addr, vlan);
} }
if (!qlcnic_sriov_vf_check(adapter)) { if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
if (mode == VPORT_MISS_MODE_ACCEPT_ALL && !adapter->fdb_mac_learn) {
!adapter->fdb_mac_learn) { qlcnic_alloc_lb_filters_mem(adapter);
qlcnic_alloc_lb_filters_mem(adapter); adapter->drv_mac_learn = 1;
adapter->drv_mac_learn = true; } else {
} else { adapter->drv_mac_learn = 0;
adapter->drv_mac_learn = false;
}
} }
qlcnic_nic_set_promisc(adapter, mode); qlcnic_nic_set_promisc(adapter, mode);
...@@ -561,16 +556,17 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) ...@@ -561,16 +556,17 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
void qlcnic_set_multi(struct net_device *netdev) void qlcnic_set_multi(struct net_device *netdev)
{ {
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_mac_vlan_list *cur;
struct netdev_hw_addr *ha; struct netdev_hw_addr *ha;
struct qlcnic_mac_list_s *cur; size_t temp;
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
return; return;
if (qlcnic_sriov_vf_check(adapter)) { if (qlcnic_sriov_vf_check(adapter)) {
if (!netdev_mc_empty(netdev)) { if (!netdev_mc_empty(netdev)) {
netdev_for_each_mc_addr(ha, netdev) { netdev_for_each_mc_addr(ha, netdev) {
cur = kzalloc(sizeof(struct qlcnic_mac_list_s), temp = sizeof(struct qlcnic_mac_vlan_list);
GFP_ATOMIC); cur = kzalloc(temp, GFP_ATOMIC);
if (cur == NULL) if (cur == NULL)
break; break;
memcpy(cur->mac_addr, memcpy(cur->mac_addr,
...@@ -605,11 +601,11 @@ int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) ...@@ -605,11 +601,11 @@ int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter) void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_mac_list_s *cur;
struct list_head *head = &adapter->mac_list; struct list_head *head = &adapter->mac_list;
struct qlcnic_mac_vlan_list *cur;
while (!list_empty(head)) { while (!list_empty(head)) {
cur = list_entry(head->next, struct qlcnic_mac_list_s, list); cur = list_entry(head->next, struct qlcnic_mac_vlan_list, list);
qlcnic_sre_macaddr_change(adapter, qlcnic_sre_macaddr_change(adapter,
cur->mac_addr, 0, QLCNIC_MAC_DEL); cur->mac_addr, 0, QLCNIC_MAC_DEL);
list_del(&cur->list); list_del(&cur->list);
......
...@@ -1466,8 +1466,7 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, ...@@ -1466,8 +1466,7 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
for (ring = 0; ring < adapter->drv_sds_rings; ring++) { for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring]; sds_ring = &recv_ctx->sds_rings[ring];
if (qlcnic_check_multi_tx(adapter) && if (qlcnic_check_multi_tx(adapter) &&
!adapter->ahw->diag_test && !adapter->ahw->diag_test) {
(adapter->drv_tx_rings > QLCNIC_SINGLE_RING)) {
netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll, netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
NAPI_POLL_WEIGHT); NAPI_POLL_WEIGHT);
} else { } else {
...@@ -1540,8 +1539,7 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter) ...@@ -1540,8 +1539,7 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
if (qlcnic_check_multi_tx(adapter) && if (qlcnic_check_multi_tx(adapter) &&
(adapter->flags & QLCNIC_MSIX_ENABLED) && (adapter->flags & QLCNIC_MSIX_ENABLED) &&
!adapter->ahw->diag_test && !adapter->ahw->diag_test) {
(adapter->drv_tx_rings > QLCNIC_SINGLE_RING)) {
for (ring = 0; ring < adapter->drv_tx_rings; ring++) { for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
tx_ring = &adapter->tx_ring[ring]; tx_ring = &adapter->tx_ring[ring];
napi_enable(&tx_ring->napi); napi_enable(&tx_ring->napi);
......
...@@ -308,11 +308,11 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) ...@@ -308,11 +308,11 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter) static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_mac_list_s *cur; struct qlcnic_mac_vlan_list *cur;
struct list_head *head; struct list_head *head;
list_for_each(head, &adapter->mac_list) { list_for_each(head, &adapter->mac_list) {
cur = list_entry(head, struct qlcnic_mac_list_s, list); cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
if (!memcmp(adapter->mac_addr, cur->mac_addr, ETH_ALEN)) { if (!memcmp(adapter->mac_addr, cur->mac_addr, ETH_ALEN)) {
qlcnic_sre_macaddr_change(adapter, cur->mac_addr, qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
0, QLCNIC_MAC_DEL); 0, QLCNIC_MAC_DEL);
...@@ -646,8 +646,7 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) ...@@ -646,8 +646,7 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
} else { } else {
adapter->ahw->num_msix = num_msix; adapter->ahw->num_msix = num_msix;
if (qlcnic_check_multi_tx(adapter) && if (qlcnic_check_multi_tx(adapter) &&
!adapter->ahw->diag_test && !adapter->ahw->diag_test)
(adapter->drv_tx_rings > 1))
drv_sds_rings = num_msix - drv_tx_rings; drv_sds_rings = num_msix - drv_tx_rings;
else else
drv_sds_rings = num_msix; drv_sds_rings = num_msix;
...@@ -800,25 +799,26 @@ static void qlcnic_cleanup_pci_map(struct qlcnic_hardware_context *ahw) ...@@ -800,25 +799,26 @@ static void qlcnic_cleanup_pci_map(struct qlcnic_hardware_context *ahw)
static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter) static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_pci_info *pci_info; struct qlcnic_pci_info *pci_info;
int ret; int ret;
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) { if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
switch (adapter->ahw->port_type) { switch (ahw->port_type) {
case QLCNIC_GBE: case QLCNIC_GBE:
adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_GBE_PORTS; ahw->total_nic_func = QLCNIC_NIU_MAX_GBE_PORTS;
break; break;
case QLCNIC_XGBE: case QLCNIC_XGBE:
adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_XG_PORTS; ahw->total_nic_func = QLCNIC_NIU_MAX_XG_PORTS;
break; break;
} }
return 0; return 0;
} }
if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) if (ahw->op_mode == QLCNIC_MGMT_FUNC)
return 0; return 0;
pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); pci_info = kcalloc(ahw->max_vnic_func, sizeof(*pci_info), GFP_KERNEL);
if (!pci_info) if (!pci_info)
return -ENOMEM; return -ENOMEM;
...@@ -846,12 +846,13 @@ static bool qlcnic_port_eswitch_cfg_capability(struct qlcnic_adapter *adapter) ...@@ -846,12 +846,13 @@ static bool qlcnic_port_eswitch_cfg_capability(struct qlcnic_adapter *adapter)
int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_pci_info *pci_info; struct qlcnic_pci_info *pci_info;
int i, id = 0, ret = 0, j = 0; int i, id = 0, ret = 0, j = 0;
u16 act_pci_func; u16 act_pci_func;
u8 pfn; u8 pfn;
pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); pci_info = kcalloc(ahw->max_vnic_func, sizeof(*pci_info), GFP_KERNEL);
if (!pci_info) if (!pci_info)
return -ENOMEM; return -ENOMEM;
...@@ -859,7 +860,7 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) ...@@ -859,7 +860,7 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
if (ret) if (ret)
goto err_pci_info; goto err_pci_info;
act_pci_func = adapter->ahw->act_pci_func; act_pci_func = ahw->total_nic_func;
adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) * adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
act_pci_func, GFP_KERNEL); act_pci_func, GFP_KERNEL);
...@@ -875,10 +876,10 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) ...@@ -875,10 +876,10 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
goto err_npars; goto err_npars;
} }
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { for (i = 0; i < ahw->max_vnic_func; i++) {
pfn = pci_info[i].id; pfn = pci_info[i].id;
if (pfn >= QLCNIC_MAX_PCI_FUNC) { if (pfn >= ahw->max_vnic_func) {
ret = QL_STATUS_INVALID_PARAM; ret = QL_STATUS_INVALID_PARAM;
goto err_eswitch; goto err_eswitch;
} }
...@@ -1345,7 +1346,7 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) ...@@ -1345,7 +1346,7 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset) if (adapter->need_fw_reset)
return 0; return 0;
for (i = 0; i < adapter->ahw->act_pci_func; i++) { for (i = 0; i < adapter->ahw->total_nic_func; i++) {
if (!adapter->npars[i].eswitch_status) if (!adapter->npars[i].eswitch_status)
continue; continue;
...@@ -1408,7 +1409,7 @@ int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) ...@@ -1408,7 +1409,7 @@ int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
return 0; return 0;
/* Set the NPAR config data after FW reset */ /* Set the NPAR config data after FW reset */
for (i = 0; i < adapter->ahw->act_pci_func; i++) { for (i = 0; i < adapter->ahw->total_nic_func; i++) {
npar = &adapter->npars[i]; npar = &adapter->npars[i];
pci_func = npar->pci_func; pci_func = npar->pci_func;
if (!adapter->npars[i].eswitch_status) if (!adapter->npars[i].eswitch_status)
...@@ -2037,7 +2038,7 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter) ...@@ -2037,7 +2038,7 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter)
void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter) void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
u16 act_pci_fn = ahw->act_pci_func; u16 act_pci_fn = ahw->total_nic_func;
u16 count; u16 count;
ahw->max_mc_count = QLCNIC_MAX_MC_COUNT; ahw->max_mc_count = QLCNIC_MAX_MC_COUNT;
...@@ -2212,7 +2213,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2212,7 +2213,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct qlcnic_hardware_context *ahw; struct qlcnic_hardware_context *ahw;
int err, pci_using_dac = -1; int err, pci_using_dac = -1;
char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */ char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */
struct qlcnic_dcb *dcb;
if (pdev->is_virtfn) if (pdev->is_virtfn)
return -ENODEV; return -ENODEV;
...@@ -2290,7 +2290,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2290,7 +2290,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_wq; goto err_out_free_wq;
adapter->dev_rst_time = jiffies; adapter->dev_rst_time = jiffies;
adapter->ahw->revision_id = pdev->revision; ahw->revision_id = pdev->revision;
ahw->max_vnic_func = qlcnic_get_vnic_func_count(adapter);
if (qlcnic_mac_learn == FDB_MAC_LEARN) if (qlcnic_mac_learn == FDB_MAC_LEARN)
adapter->fdb_mac_learn = true; adapter->fdb_mac_learn = true;
else if (qlcnic_mac_learn == DRV_MAC_LEARN) else if (qlcnic_mac_learn == DRV_MAC_LEARN)
...@@ -2335,10 +2336,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2335,10 +2336,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->flags |= QLCNIC_NEED_FLR; adapter->flags |= QLCNIC_NEED_FLR;
dcb = adapter->dcb;
if (dcb && qlcnic_dcb_attach(dcb))
qlcnic_clear_dcb_ops(dcb);
} else if (qlcnic_83xx_check(adapter)) { } else if (qlcnic_83xx_check(adapter)) {
qlcnic_83xx_check_vf(adapter, ent); qlcnic_83xx_check_vf(adapter, ent);
adapter->portnum = adapter->ahw->pci_func; adapter->portnum = adapter->ahw->pci_func;
...@@ -2367,6 +2364,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2367,6 +2364,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_hw; goto err_out_free_hw;
} }
qlcnic_dcb_enable(adapter->dcb);
if (qlcnic_read_mac_addr(adapter)) if (qlcnic_read_mac_addr(adapter))
dev_warn(&pdev->dev, "failed to read mac addr\n"); dev_warn(&pdev->dev, "failed to read mac addr\n");
...@@ -2500,13 +2499,11 @@ static void qlcnic_remove(struct pci_dev *pdev) ...@@ -2500,13 +2499,11 @@ static void qlcnic_remove(struct pci_dev *pdev)
qlcnic_cancel_idc_work(adapter); qlcnic_cancel_idc_work(adapter);
ahw = adapter->ahw; ahw = adapter->ahw;
qlcnic_dcb_free(adapter->dcb);
unregister_netdev(netdev); unregister_netdev(netdev);
qlcnic_sriov_cleanup(adapter); qlcnic_sriov_cleanup(adapter);
if (qlcnic_83xx_check(adapter)) { if (qlcnic_83xx_check(adapter)) {
qlcnic_83xx_register_nic_idc_func(adapter, 0); qlcnic_83xx_initialize_nic(adapter, 0);
cancel_delayed_work_sync(&adapter->idc_aen_work); cancel_delayed_work_sync(&adapter->idc_aen_work);
qlcnic_83xx_free_mbx_intr(adapter); qlcnic_83xx_free_mbx_intr(adapter);
qlcnic_83xx_detach_mailbox_work(adapter); qlcnic_83xx_detach_mailbox_work(adapter);
...@@ -2514,6 +2511,8 @@ static void qlcnic_remove(struct pci_dev *pdev) ...@@ -2514,6 +2511,8 @@ static void qlcnic_remove(struct pci_dev *pdev)
kfree(ahw->fw_info); kfree(ahw->fw_info);
} }
qlcnic_dcb_free(adapter->dcb);
qlcnic_detach(adapter); qlcnic_detach(adapter);
if (adapter->npars != NULL) if (adapter->npars != NULL)
...@@ -2642,7 +2641,7 @@ void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter) ...@@ -2642,7 +2641,7 @@ void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
if (adapter->fhash.fmax && adapter->fhash.fhead) if (adapter->fhash.fmax && adapter->fhash.fhead)
return; return;
act_pci_func = adapter->ahw->act_pci_func; act_pci_func = adapter->ahw->total_nic_func;
spin_lock_init(&adapter->mac_learn_lock); spin_lock_init(&adapter->mac_learn_lock);
spin_lock_init(&adapter->rx_mac_learn_lock); spin_lock_init(&adapter->rx_mac_learn_lock);
...@@ -3725,12 +3724,6 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt, ...@@ -3725,12 +3724,6 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt,
return -EINVAL; return -EINVAL;
} }
if (ring_cnt < 2) {
netdev_err(netdev,
"%s rings value should not be lower than 2\n", buf);
return -EINVAL;
}
if (!is_power_of_2(ring_cnt)) { if (!is_power_of_2(ring_cnt)) {
netdev_err(netdev, "%s rings value should be a power of 2\n", netdev_err(netdev, "%s rings value should be a power of 2\n",
buf); buf);
...@@ -3788,8 +3781,7 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt) ...@@ -3788,8 +3781,7 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter, u8 rx_cnt, u8 tx_cnt)
} }
if (qlcnic_83xx_check(adapter)) { if (qlcnic_83xx_check(adapter)) {
/* register for NIC IDC AEN Events */ qlcnic_83xx_initialize_nic(adapter, 1);
qlcnic_83xx_register_nic_idc_func(adapter, 1);
err = qlcnic_83xx_setup_mbx_intr(adapter); err = qlcnic_83xx_setup_mbx_intr(adapter);
qlcnic_83xx_disable_mbx_poll(adapter); qlcnic_83xx_disable_mbx_poll(adapter);
if (err) { if (err) {
......
...@@ -126,8 +126,8 @@ struct qlcnic_vport { ...@@ -126,8 +126,8 @@ struct qlcnic_vport {
u16 handle; u16 handle;
u16 max_tx_bw; u16 max_tx_bw;
u16 min_tx_bw; u16 min_tx_bw;
u16 pvid;
u8 vlan_mode; u8 vlan_mode;
u16 vlan;
u8 qos; u8 qos;
bool spoofchk; bool spoofchk;
u8 mac[6]; u8 mac[6];
...@@ -137,6 +137,8 @@ struct qlcnic_vf_info { ...@@ -137,6 +137,8 @@ struct qlcnic_vf_info {
u8 pci_func; u8 pci_func;
u16 rx_ctx_id; u16 rx_ctx_id;
u16 tx_ctx_id; u16 tx_ctx_id;
u16 *sriov_vlans;
int num_vlan;
unsigned long state; unsigned long state;
struct completion ch_free_cmpl; struct completion ch_free_cmpl;
struct work_struct trans_work; struct work_struct trans_work;
...@@ -149,6 +151,7 @@ struct qlcnic_vf_info { ...@@ -149,6 +151,7 @@ struct qlcnic_vf_info {
struct qlcnic_trans_list rcv_pend; struct qlcnic_trans_list rcv_pend;
struct qlcnic_adapter *adapter; struct qlcnic_adapter *adapter;
struct qlcnic_vport *vp; struct qlcnic_vport *vp;
struct mutex vlan_list_lock; /* Lock for VLAN list */
}; };
struct qlcnic_async_work_list { struct qlcnic_async_work_list {
...@@ -197,6 +200,13 @@ int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *, ...@@ -197,6 +200,13 @@ int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *,
int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8); int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8);
int qlcnic_sriov_vf_shutdown(struct pci_dev *); int qlcnic_sriov_vf_shutdown(struct pci_dev *);
int qlcnic_sriov_vf_resume(struct qlcnic_adapter *); int qlcnic_sriov_vf_resume(struct qlcnic_adapter *);
void qlcnic_sriov_free_vlans(struct qlcnic_adapter *);
void qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *);
bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *);
void qlcnic_sriov_del_vlan_id(struct qlcnic_sriov *,
struct qlcnic_vf_info *, u16);
void qlcnic_sriov_add_vlan_id(struct qlcnic_sriov *,
struct qlcnic_vf_info *, u16);
static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter) static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter)
{ {
......
...@@ -176,6 +176,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) ...@@ -176,6 +176,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
vf->adapter = adapter; vf->adapter = adapter;
vf->pci_func = qlcnic_sriov_virtid_fn(adapter, i); vf->pci_func = qlcnic_sriov_virtid_fn(adapter, i);
mutex_init(&vf->send_cmd_lock); mutex_init(&vf->send_cmd_lock);
mutex_init(&vf->vlan_list_lock);
INIT_LIST_HEAD(&vf->rcv_act.wait_list); INIT_LIST_HEAD(&vf->rcv_act.wait_list);
INIT_LIST_HEAD(&vf->rcv_pend.wait_list); INIT_LIST_HEAD(&vf->rcv_pend.wait_list);
spin_lock_init(&vf->rcv_act.lock); spin_lock_init(&vf->rcv_act.lock);
...@@ -276,6 +277,13 @@ static void qlcnic_sriov_vf_cleanup(struct qlcnic_adapter *adapter) ...@@ -276,6 +277,13 @@ static void qlcnic_sriov_vf_cleanup(struct qlcnic_adapter *adapter)
void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter) void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
if (!sriov)
return;
qlcnic_sriov_free_vlans(adapter);
if (qlcnic_sriov_pf_check(adapter)) if (qlcnic_sriov_pf_check(adapter))
qlcnic_sriov_pf_cleanup(adapter); qlcnic_sriov_pf_cleanup(adapter);
...@@ -416,10 +424,15 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter, ...@@ -416,10 +424,15 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter,
return 0; return 0;
sriov->any_vlan = cmd->rsp.arg[2] & 0xf; sriov->any_vlan = cmd->rsp.arg[2] & 0xf;
sriov->num_allowed_vlans = cmd->rsp.arg[2] >> 16;
dev_info(&adapter->pdev->dev, "Number of allowed Guest VLANs = %d\n",
sriov->num_allowed_vlans);
qlcnic_sriov_alloc_vlans(adapter);
if (!sriov->any_vlan) if (!sriov->any_vlan)
return 0; return 0;
sriov->num_allowed_vlans = cmd->rsp.arg[2] >> 16;
num_vlans = sriov->num_allowed_vlans; num_vlans = sriov->num_allowed_vlans;
sriov->allowed_vlans = kzalloc(sizeof(u16) * num_vlans, GFP_KERNEL); sriov->allowed_vlans = kzalloc(sizeof(u16) * num_vlans, GFP_KERNEL);
if (!sriov->allowed_vlans) if (!sriov->allowed_vlans)
...@@ -473,6 +486,8 @@ static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) ...@@ -473,6 +486,8 @@ static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter)
if (err) if (err)
return err; return err;
ahw->max_mc_count = nic_info.max_rx_mcast_mac_filters;
err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func); err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func);
if (err) if (err)
return -EIO; return -EIO;
...@@ -500,7 +515,6 @@ static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) ...@@ -500,7 +515,6 @@ static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter)
static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
int pci_using_dac) int pci_using_dac)
{ {
struct qlcnic_dcb *dcb;
int err; int err;
INIT_LIST_HEAD(&adapter->vf_mc_list); INIT_LIST_HEAD(&adapter->vf_mc_list);
...@@ -538,11 +552,6 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, ...@@ -538,11 +552,6 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
if (err) if (err)
goto err_out_send_channel_term; goto err_out_send_channel_term;
dcb = adapter->dcb;
if (dcb && qlcnic_dcb_attach(dcb))
qlcnic_clear_dcb_ops(dcb);
err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac); err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac);
if (err) if (err)
goto err_out_send_channel_term; goto err_out_send_channel_term;
...@@ -1447,18 +1456,27 @@ int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op) ...@@ -1447,18 +1456,27 @@ int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op)
return ret; return ret;
} }
void qlcnic_vf_add_mc_list(struct net_device *netdev, u16 vlan) static void qlcnic_vf_add_mc_list(struct net_device *netdev)
{ {
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_mac_list_s *cur; struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_mac_vlan_list *cur;
struct list_head *head, tmp_list; struct list_head *head, tmp_list;
struct qlcnic_vf_info *vf;
u16 vlan_id;
int i;
static const u8 bcast_addr[ETH_ALEN] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
vf = &adapter->ahw->sriov->vf_info[0];
INIT_LIST_HEAD(&tmp_list); INIT_LIST_HEAD(&tmp_list);
head = &adapter->vf_mc_list; head = &adapter->vf_mc_list;
netif_addr_lock_bh(netdev); netif_addr_lock_bh(netdev);
while (!list_empty(head)) { while (!list_empty(head)) {
cur = list_entry(head->next, struct qlcnic_mac_list_s, list); cur = list_entry(head->next, struct qlcnic_mac_vlan_list, list);
list_move(&cur->list, &tmp_list); list_move(&cur->list, &tmp_list);
} }
...@@ -1466,8 +1484,28 @@ void qlcnic_vf_add_mc_list(struct net_device *netdev, u16 vlan) ...@@ -1466,8 +1484,28 @@ void qlcnic_vf_add_mc_list(struct net_device *netdev, u16 vlan)
while (!list_empty(&tmp_list)) { while (!list_empty(&tmp_list)) {
cur = list_entry((&tmp_list)->next, cur = list_entry((&tmp_list)->next,
struct qlcnic_mac_list_s, list); struct qlcnic_mac_vlan_list, list);
qlcnic_nic_add_mac(adapter, cur->mac_addr, vlan); if (!qlcnic_sriov_check_any_vlan(vf)) {
qlcnic_nic_add_mac(adapter, bcast_addr, 0);
qlcnic_nic_add_mac(adapter, cur->mac_addr, 0);
} else {
mutex_lock(&vf->vlan_list_lock);
for (i = 0; i < sriov->num_allowed_vlans; i++) {
vlan_id = vf->sriov_vlans[i];
if (vlan_id) {
qlcnic_nic_add_mac(adapter, bcast_addr,
vlan_id);
qlcnic_nic_add_mac(adapter,
cur->mac_addr,
vlan_id);
}
}
mutex_unlock(&vf->vlan_list_lock);
if (qlcnic_84xx_check(adapter)) {
qlcnic_nic_add_mac(adapter, bcast_addr, 0);
qlcnic_nic_add_mac(adapter, cur->mac_addr, 0);
}
}
list_del(&cur->list); list_del(&cur->list);
kfree(cur); kfree(cur);
} }
...@@ -1490,13 +1528,24 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc) ...@@ -1490,13 +1528,24 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc)
static void qlcnic_sriov_vf_set_multi(struct net_device *netdev) static void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
{ {
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
u16 vlan; struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 mode = VPORT_MISS_MODE_DROP;
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
return; return;
vlan = adapter->ahw->sriov->vlan; if (netdev->flags & IFF_PROMISC) {
__qlcnic_set_multi(netdev, vlan); if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
mode = VPORT_MISS_MODE_ACCEPT_ALL;
} else if ((netdev->flags & IFF_ALLMULTI) ||
(netdev_mc_count(netdev) > ahw->max_mc_count)) {
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
}
if (qlcnic_sriov_vf_check(adapter))
qlcnic_vf_add_mc_list(netdev);
qlcnic_nic_set_promisc(adapter, mode);
} }
static void qlcnic_sriov_handle_async_multi(struct work_struct *work) static void qlcnic_sriov_handle_async_multi(struct work_struct *work)
...@@ -1584,8 +1633,6 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) ...@@ -1584,8 +1633,6 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter)
if (err) if (err)
goto err_out_term_channel; goto err_out_term_channel;
qlcnic_dcb_get_info(adapter->dcb);
return 0; return 0;
err_out_term_channel: err_out_term_channel:
...@@ -1833,18 +1880,60 @@ static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *adapter) ...@@ -1833,18 +1880,60 @@ static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *adapter)
cancel_delayed_work_sync(&adapter->fw_work); cancel_delayed_work_sync(&adapter->fw_work);
} }
static int qlcnic_sriov_validate_vlan_cfg(struct qlcnic_sriov *sriov, static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf, u16 vlan_id)
{
int i, err = -EINVAL;
if (!vf->sriov_vlans)
return err;
mutex_lock(&vf->vlan_list_lock);
for (i = 0; i < sriov->num_allowed_vlans; i++) {
if (vf->sriov_vlans[i] == vlan_id) {
err = 0;
break;
}
}
mutex_unlock(&vf->vlan_list_lock);
return err;
}
static int qlcnic_sriov_validate_num_vlans(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf)
{
int err = 0;
mutex_lock(&vf->vlan_list_lock);
if (vf->num_vlan >= sriov->num_allowed_vlans)
err = -EINVAL;
mutex_unlock(&vf->vlan_list_lock);
return err;
}
static int qlcnic_sriov_validate_vlan_cfg(struct qlcnic_adapter *adapter,
u16 vid, u8 enable) u16 vid, u8 enable)
{ {
u16 vlan = sriov->vlan; struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_vf_info *vf;
bool vlan_exist;
u8 allowed = 0; u8 allowed = 0;
int i; int i;
vf = &adapter->ahw->sriov->vf_info[0];
vlan_exist = qlcnic_sriov_check_any_vlan(vf);
if (sriov->vlan_mode != QLC_GUEST_VLAN_MODE) if (sriov->vlan_mode != QLC_GUEST_VLAN_MODE)
return -EINVAL; return -EINVAL;
if (enable) { if (enable) {
if (vlan) if (qlcnic_83xx_vf_check(adapter) && vlan_exist)
return -EINVAL;
if (qlcnic_sriov_validate_num_vlans(sriov, vf))
return -EINVAL; return -EINVAL;
if (sriov->any_vlan) { if (sriov->any_vlan) {
...@@ -1857,24 +1946,54 @@ static int qlcnic_sriov_validate_vlan_cfg(struct qlcnic_sriov *sriov, ...@@ -1857,24 +1946,54 @@ static int qlcnic_sriov_validate_vlan_cfg(struct qlcnic_sriov *sriov,
return -EINVAL; return -EINVAL;
} }
} else { } else {
if (!vlan || vlan != vid) if (!vlan_exist || qlcnic_sriov_check_vlan_id(sriov, vf, vid))
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id,
enum qlcnic_vlan_operations opcode)
{
struct qlcnic_adapter *adapter = vf->adapter;
struct qlcnic_sriov *sriov;
sriov = adapter->ahw->sriov;
if (!vf->sriov_vlans)
return;
mutex_lock(&vf->vlan_list_lock);
switch (opcode) {
case QLC_VLAN_ADD:
qlcnic_sriov_add_vlan_id(sriov, vf, vlan_id);
break;
case QLC_VLAN_DELETE:
qlcnic_sriov_del_vlan_id(sriov, vf, vlan_id);
break;
default:
netdev_err(adapter->netdev, "Invalid VLAN operation\n");
}
mutex_unlock(&vf->vlan_list_lock);
return;
}
int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter, int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter,
u16 vid, u8 enable) u16 vid, u8 enable)
{ {
struct qlcnic_sriov *sriov = adapter->ahw->sriov; struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_vf_info *vf;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
int ret; int ret;
if (vid == 0) if (vid == 0)
return 0; return 0;
ret = qlcnic_sriov_validate_vlan_cfg(sriov, vid, enable); vf = &adapter->ahw->sriov->vf_info[0];
ret = qlcnic_sriov_validate_vlan_cfg(adapter, vid, enable);
if (ret) if (ret)
return ret; return ret;
...@@ -1894,11 +2013,11 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter, ...@@ -1894,11 +2013,11 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter,
qlcnic_free_mac_list(adapter); qlcnic_free_mac_list(adapter);
if (enable) if (enable)
sriov->vlan = vid; qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_ADD);
else else
sriov->vlan = 0; qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_DELETE);
qlcnic_sriov_vf_set_multi(adapter->netdev); qlcnic_set_multi(adapter->netdev);
} }
qlcnic_free_mbx_args(&cmd); qlcnic_free_mbx_args(&cmd);
...@@ -1908,20 +2027,18 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter, ...@@ -1908,20 +2027,18 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter,
static void qlcnic_sriov_vf_free_mac_list(struct qlcnic_adapter *adapter) static void qlcnic_sriov_vf_free_mac_list(struct qlcnic_adapter *adapter)
{ {
struct list_head *head = &adapter->mac_list; struct list_head *head = &adapter->mac_list;
struct qlcnic_mac_list_s *cur; struct qlcnic_mac_vlan_list *cur;
u16 vlan;
vlan = adapter->ahw->sriov->vlan;
while (!list_empty(head)) { while (!list_empty(head)) {
cur = list_entry(head->next, struct qlcnic_mac_list_s, list); cur = list_entry(head->next, struct qlcnic_mac_vlan_list, list);
qlcnic_sre_macaddr_change(adapter, cur->mac_addr, qlcnic_sre_macaddr_change(adapter, cur->mac_addr, cur->vlan_id,
vlan, QLCNIC_MAC_DEL); QLCNIC_MAC_DEL);
list_del(&cur->list); list_del(&cur->list);
kfree(cur); kfree(cur);
} }
} }
int qlcnic_sriov_vf_shutdown(struct pci_dev *pdev) int qlcnic_sriov_vf_shutdown(struct pci_dev *pdev)
{ {
struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
...@@ -1972,3 +2089,70 @@ int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter) ...@@ -1972,3 +2089,70 @@ int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter)
idc->delay); idc->delay);
return err; return err;
} }
void qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter)
{
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_vf_info *vf;
int i;
for (i = 0; i < sriov->num_vfs; i++) {
vf = &sriov->vf_info[i];
vf->sriov_vlans = kcalloc(sriov->num_allowed_vlans,
sizeof(*vf->sriov_vlans), GFP_KERNEL);
}
}
void qlcnic_sriov_free_vlans(struct qlcnic_adapter *adapter)
{
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_vf_info *vf;
int i;
for (i = 0; i < sriov->num_vfs; i++) {
vf = &sriov->vf_info[i];
kfree(vf->sriov_vlans);
vf->sriov_vlans = NULL;
}
}
void qlcnic_sriov_add_vlan_id(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf, u16 vlan_id)
{
int i;
for (i = 0; i < sriov->num_allowed_vlans; i++) {
if (!vf->sriov_vlans[i]) {
vf->sriov_vlans[i] = vlan_id;
vf->num_vlan++;
return;
}
}
}
void qlcnic_sriov_del_vlan_id(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf, u16 vlan_id)
{
int i;
for (i = 0; i < sriov->num_allowed_vlans; i++) {
if (vf->sriov_vlans[i] == vlan_id) {
vf->sriov_vlans[i] = 0;
vf->num_vlan--;
return;
}
}
}
bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *vf)
{
bool err = false;
mutex_lock(&vf->vlan_list_lock);
if (vf->num_vlan)
err = true;
mutex_unlock(&vf->vlan_list_lock);
return err;
}
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "qlcnic.h" #include "qlcnic.h"
#include <linux/types.h> #include <linux/types.h>
#define QLCNIC_SRIOV_VF_MAX_MAC 1 #define QLCNIC_SRIOV_VF_MAX_MAC 8
#define QLC_VF_MIN_TX_RATE 100 #define QLC_VF_MIN_TX_RATE 100
#define QLC_VF_MAX_TX_RATE 9999 #define QLC_VF_MAX_TX_RATE 9999
...@@ -64,9 +64,10 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter, ...@@ -64,9 +64,10 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
{ {
struct qlcnic_sriov *sriov = adapter->ahw->sriov; struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_resources *res = &sriov->ff_max; struct qlcnic_resources *res = &sriov->ff_max;
u32 temp, num_vf_macs, num_vfs, max; u16 num_macs = sriov->num_allowed_vlans + 1;
int ret = -EIO, vpid, id; int ret = -EIO, vpid, id;
struct qlcnic_vport *vp; struct qlcnic_vport *vp;
u32 num_vfs, max, temp;
vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func); vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func);
if (vpid < 0) if (vpid < 0)
...@@ -76,16 +77,21 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter, ...@@ -76,16 +77,21 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
max = num_vfs + 1; max = num_vfs + 1;
info->bit_offsets = 0xffff; info->bit_offsets = 0xffff;
info->max_tx_ques = res->num_tx_queues / max; info->max_tx_ques = res->num_tx_queues / max;
info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
num_vf_macs = QLCNIC_SRIOV_VF_MAX_MAC; if (qlcnic_83xx_pf_check(adapter))
num_macs = 1;
if (adapter->ahw->pci_func == func) { if (adapter->ahw->pci_func == func) {
temp = res->num_rx_mcast_mac_filters - (num_vfs * num_vf_macs);
info->max_rx_ucast_mac_filters = temp;
temp = res->num_tx_mac_filters - (num_vfs * num_vf_macs);
info->max_tx_mac_filters = temp;
info->min_tx_bw = 0; info->min_tx_bw = 0;
info->max_tx_bw = MAX_BW; info->max_tx_bw = MAX_BW;
temp = res->num_rx_ucast_mac_filters - num_macs * num_vfs;
info->max_rx_ucast_mac_filters = temp;
temp = res->num_tx_mac_filters - num_macs * num_vfs;
info->max_tx_mac_filters = temp;
temp = num_macs * num_vfs * QLCNIC_SRIOV_VF_MAX_MAC;
temp = res->num_rx_mcast_mac_filters - temp;
info->max_rx_mcast_mac_filters = temp;
} else { } else {
id = qlcnic_sriov_func_to_index(adapter, func); id = qlcnic_sriov_func_to_index(adapter, func);
if (id < 0) if (id < 0)
...@@ -93,8 +99,10 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter, ...@@ -93,8 +99,10 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
vp = sriov->vf_info[id].vp; vp = sriov->vf_info[id].vp;
info->min_tx_bw = vp->min_tx_bw; info->min_tx_bw = vp->min_tx_bw;
info->max_tx_bw = vp->max_tx_bw; info->max_tx_bw = vp->max_tx_bw;
info->max_rx_ucast_mac_filters = num_vf_macs; info->max_rx_ucast_mac_filters = num_macs;
info->max_tx_mac_filters = num_vf_macs; info->max_tx_mac_filters = num_macs;
temp = num_macs * QLCNIC_SRIOV_VF_MAX_MAC;
info->max_rx_mcast_mac_filters = temp;
} }
info->max_rx_ip_addr = res->num_destip / max; info->max_rx_ip_addr = res->num_destip / max;
...@@ -132,6 +140,25 @@ static void qlcnic_sriov_pf_set_ff_max_res(struct qlcnic_adapter *adapter, ...@@ -132,6 +140,25 @@ static void qlcnic_sriov_pf_set_ff_max_res(struct qlcnic_adapter *adapter,
ff_max->max_local_ipv6_addrs = info->max_local_ipv6_addrs; ff_max->max_local_ipv6_addrs = info->max_local_ipv6_addrs;
} }
static void qlcnic_sriov_set_vf_max_vlan(struct qlcnic_adapter *adapter,
struct qlcnic_info *npar_info)
{
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
int temp, total_fn;
temp = npar_info->max_rx_mcast_mac_filters;
total_fn = sriov->num_vfs + 1;
temp = temp / (QLCNIC_SRIOV_VF_MAX_MAC * total_fn);
sriov->num_allowed_vlans = temp - 1;
if (qlcnic_83xx_pf_check(adapter))
sriov->num_allowed_vlans = 1;
netdev_info(adapter->netdev, "Max Guest VLANs supported per VF = %d\n",
sriov->num_allowed_vlans);
}
static int qlcnic_sriov_get_pf_info(struct qlcnic_adapter *adapter, static int qlcnic_sriov_get_pf_info(struct qlcnic_adapter *adapter,
struct qlcnic_info *npar_info) struct qlcnic_info *npar_info)
{ {
...@@ -165,6 +192,7 @@ static int qlcnic_sriov_get_pf_info(struct qlcnic_adapter *adapter, ...@@ -165,6 +192,7 @@ static int qlcnic_sriov_get_pf_info(struct qlcnic_adapter *adapter,
npar_info->max_local_ipv6_addrs = LSW(cmd.rsp.arg[8]); npar_info->max_local_ipv6_addrs = LSW(cmd.rsp.arg[8]);
npar_info->max_remote_ipv6_addrs = MSW(cmd.rsp.arg[8]); npar_info->max_remote_ipv6_addrs = MSW(cmd.rsp.arg[8]);
qlcnic_sriov_set_vf_max_vlan(adapter, npar_info);
qlcnic_sriov_pf_set_ff_max_res(adapter, npar_info); qlcnic_sriov_pf_set_ff_max_res(adapter, npar_info);
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"\n\ttotal_pf: %d,\n" "\n\ttotal_pf: %d,\n"
...@@ -403,6 +431,8 @@ static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter) ...@@ -403,6 +431,8 @@ static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
qlcnic_sriov_pf_disable(adapter); qlcnic_sriov_pf_disable(adapter);
qlcnic_sriov_free_vlans(adapter);
qlcnic_sriov_pf_cleanup(adapter); qlcnic_sriov_pf_cleanup(adapter);
/* After disabling SRIOV re-init the driver in default mode /* After disabling SRIOV re-init the driver in default mode
...@@ -511,6 +541,8 @@ static int __qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, ...@@ -511,6 +541,8 @@ static int __qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter,
if (err) if (err)
goto del_flr_queue; goto del_flr_queue;
qlcnic_sriov_alloc_vlans(adapter);
err = qlcnic_sriov_pf_enable(adapter, num_vfs); err = qlcnic_sriov_pf_enable(adapter, num_vfs);
return err; return err;
...@@ -608,7 +640,7 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func) ...@@ -608,7 +640,7 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func)
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->pvid << 8;
} }
err = qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, &cmd);
...@@ -643,10 +675,13 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans, ...@@ -643,10 +675,13 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans,
struct qlcnic_vf_info *vf = trans->vf; struct qlcnic_vf_info *vf = trans->vf;
struct qlcnic_vport *vp = vf->vp; struct qlcnic_vport *vp = vf->vp;
struct qlcnic_adapter *adapter; struct qlcnic_adapter *adapter;
struct qlcnic_sriov *sriov;
u16 func = vf->pci_func; u16 func = vf->pci_func;
size_t size;
int err; int err;
adapter = vf->adapter; adapter = vf->adapter;
sriov = adapter->ahw->sriov;
if (trans->req_hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) { if (trans->req_hdr->cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) {
err = qlcnic_sriov_pf_config_vport(adapter, 1, func); err = qlcnic_sriov_pf_config_vport(adapter, 1, func);
...@@ -656,8 +691,12 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans, ...@@ -656,8 +691,12 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans,
qlcnic_sriov_pf_config_vport(adapter, 0, func); qlcnic_sriov_pf_config_vport(adapter, 0, func);
} }
} else { } else {
if (vp->vlan_mode == QLC_GUEST_VLAN_MODE) if (vp->vlan_mode == QLC_GUEST_VLAN_MODE) {
vp->vlan = 0; size = sizeof(*vf->sriov_vlans);
size = size * sriov->num_allowed_vlans;
memset(vf->sriov_vlans, 0, size);
}
err = qlcnic_sriov_pf_config_vport(adapter, 0, func); err = qlcnic_sriov_pf_config_vport(adapter, 0, func);
} }
...@@ -679,20 +718,23 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans, ...@@ -679,20 +718,23 @@ static int qlcnic_sriov_pf_channel_cfg_cmd(struct qlcnic_bc_trans *trans,
} }
static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter, static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
struct qlcnic_vport *vp, struct qlcnic_vf_info *vf,
u16 func, u16 vlan, u8 op) u16 vlan, u8 op)
{ {
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
struct qlcnic_macvlan_mbx mv; struct qlcnic_macvlan_mbx mv;
struct qlcnic_vport *vp;
u8 *addr; u8 *addr;
int err; int err;
u32 *buf; u32 *buf;
int vpid; int vpid;
vp = vf->vp;
if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN)) if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN))
return -ENOMEM; return -ENOMEM;
vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func); vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func);
if (vpid < 0) { if (vpid < 0) {
err = -EINVAL; err = -EINVAL;
goto out; goto out;
...@@ -736,6 +778,35 @@ static int qlcnic_sriov_validate_create_rx_ctx(struct qlcnic_cmd_args *cmd) ...@@ -736,6 +778,35 @@ static int qlcnic_sriov_validate_create_rx_ctx(struct qlcnic_cmd_args *cmd)
return 0; return 0;
} }
static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter,
struct qlcnic_vf_info *vf,
int opcode)
{
struct qlcnic_sriov *sriov;
u16 vlan;
int i;
sriov = adapter->ahw->sriov;
mutex_lock(&vf->vlan_list_lock);
if (vf->num_vlan) {
for (i = 0; i < sriov->num_allowed_vlans; i++) {
vlan = vf->sriov_vlans[i];
if (vlan)
qlcnic_sriov_cfg_vf_def_mac(adapter, vf, vlan,
opcode);
}
}
mutex_unlock(&vf->vlan_list_lock);
if (vf->vp->vlan_mode != QLC_PVID_MODE) {
if (qlcnic_83xx_pf_check(adapter) &&
qlcnic_sriov_check_any_vlan(vf))
return;
qlcnic_sriov_cfg_vf_def_mac(adapter, vf, 0, opcode);
}
}
static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran, static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran,
struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
...@@ -743,7 +814,6 @@ static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran, ...@@ -743,7 +814,6 @@ static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran,
struct qlcnic_adapter *adapter = vf->adapter; struct qlcnic_adapter *adapter = vf->adapter;
struct qlcnic_rcv_mbx_out *mbx_out; struct qlcnic_rcv_mbx_out *mbx_out;
int err; int err;
u16 vlan;
err = qlcnic_sriov_validate_create_rx_ctx(cmd); err = qlcnic_sriov_validate_create_rx_ctx(cmd);
if (err) { if (err) {
...@@ -754,12 +824,10 @@ static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran, ...@@ -754,12 +824,10 @@ static int qlcnic_sriov_pf_create_rx_ctx_cmd(struct qlcnic_bc_trans *tran,
cmd->req.arg[6] = vf->vp->handle; cmd->req.arg[6] = vf->vp->handle;
err = qlcnic_issue_cmd(adapter, cmd); err = qlcnic_issue_cmd(adapter, cmd);
vlan = vf->vp->vlan;
if (!err) { if (!err) {
mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd->rsp.arg[1]; mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd->rsp.arg[1];
vf->rx_ctx_id = mbx_out->ctx_id; vf->rx_ctx_id = mbx_out->ctx_id;
qlcnic_sriov_cfg_vf_def_mac(adapter, vf->vp, vf->pci_func, qlcnic_83xx_cfg_default_mac_vlan(adapter, vf, QLCNIC_MAC_ADD);
vlan, QLCNIC_MAC_ADD);
} else { } else {
vf->rx_ctx_id = 0; vf->rx_ctx_id = 0;
} }
...@@ -843,7 +911,6 @@ static int qlcnic_sriov_pf_del_rx_ctx_cmd(struct qlcnic_bc_trans *trans, ...@@ -843,7 +911,6 @@ static int qlcnic_sriov_pf_del_rx_ctx_cmd(struct qlcnic_bc_trans *trans,
struct qlcnic_vf_info *vf = trans->vf; struct qlcnic_vf_info *vf = trans->vf;
struct qlcnic_adapter *adapter = vf->adapter; struct qlcnic_adapter *adapter = vf->adapter;
int err; int err;
u16 vlan;
err = qlcnic_sriov_validate_del_rx_ctx(vf, cmd); err = qlcnic_sriov_validate_del_rx_ctx(vf, cmd);
if (err) { if (err) {
...@@ -851,9 +918,7 @@ static int qlcnic_sriov_pf_del_rx_ctx_cmd(struct qlcnic_bc_trans *trans, ...@@ -851,9 +918,7 @@ static int qlcnic_sriov_pf_del_rx_ctx_cmd(struct qlcnic_bc_trans *trans,
return err; return err;
} }
vlan = vf->vp->vlan; qlcnic_83xx_cfg_default_mac_vlan(adapter, vf, QLCNIC_MAC_DEL);
qlcnic_sriov_cfg_vf_def_mac(adapter, vf->vp, vf->pci_func,
vlan, QLCNIC_MAC_DEL);
cmd->req.arg[1] |= vf->vp->handle << 16; cmd->req.arg[1] |= vf->vp->handle << 16;
err = qlcnic_issue_cmd(adapter, cmd); err = qlcnic_issue_cmd(adapter, cmd);
...@@ -1120,7 +1185,7 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter, ...@@ -1120,7 +1185,7 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
cmd->req.arg[1] &= ~0x7; cmd->req.arg[1] &= ~0x7;
new_op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ? new_op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL; QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL;
cmd->req.arg[3] |= vp->vlan << 16; cmd->req.arg[3] |= vp->pvid << 16;
cmd->req.arg[1] |= new_op; cmd->req.arg[1] |= new_op;
} }
...@@ -1190,8 +1255,10 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans, ...@@ -1190,8 +1255,10 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans,
struct qlcnic_vport *vp = vf->vp; struct qlcnic_vport *vp = vf->vp;
u8 cmd_op, mode = vp->vlan_mode; u8 cmd_op, mode = vp->vlan_mode;
struct qlcnic_adapter *adapter; struct qlcnic_adapter *adapter;
struct qlcnic_sriov *sriov;
adapter = vf->adapter; adapter = vf->adapter;
sriov = adapter->ahw->sriov;
cmd_op = trans->req_hdr->cmd_op; cmd_op = trans->req_hdr->cmd_op;
cmd->rsp.arg[0] |= 1 << 25; cmd->rsp.arg[0] |= 1 << 25;
...@@ -1205,10 +1272,10 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans, ...@@ -1205,10 +1272,10 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans,
switch (mode) { switch (mode) {
case QLC_GUEST_VLAN_MODE: case QLC_GUEST_VLAN_MODE:
cmd->rsp.arg[1] = mode | 1 << 8; cmd->rsp.arg[1] = mode | 1 << 8;
cmd->rsp.arg[2] = 1 << 16; cmd->rsp.arg[2] = sriov->num_allowed_vlans << 16;
break; break;
case QLC_PVID_MODE: case QLC_PVID_MODE:
cmd->rsp.arg[1] = mode | 1 << 8 | vp->vlan << 16; cmd->rsp.arg[1] = mode | 1 << 8 | vp->pvid << 16;
break; break;
} }
...@@ -1216,24 +1283,27 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans, ...@@ -1216,24 +1283,27 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans,
} }
static int qlcnic_sriov_pf_del_guest_vlan(struct qlcnic_adapter *adapter, static int qlcnic_sriov_pf_del_guest_vlan(struct qlcnic_adapter *adapter,
struct qlcnic_vf_info *vf) struct qlcnic_vf_info *vf,
struct qlcnic_cmd_args *cmd)
{ {
struct qlcnic_vport *vp = vf->vp; struct qlcnic_sriov *sriov = adapter->ahw->sriov;
u16 vlan;
if (!vp->vlan) if (!qlcnic_sriov_check_any_vlan(vf))
return -EINVAL; return -EINVAL;
vlan = cmd->req.arg[1] >> 16;
if (!vf->rx_ctx_id) { if (!vf->rx_ctx_id) {
vp->vlan = 0; qlcnic_sriov_del_vlan_id(sriov, vf, vlan);
return 0; return 0;
} }
qlcnic_sriov_cfg_vf_def_mac(adapter, vp, vf->pci_func, qlcnic_sriov_cfg_vf_def_mac(adapter, vf, vlan, QLCNIC_MAC_DEL);
vp->vlan, QLCNIC_MAC_DEL); qlcnic_sriov_del_vlan_id(sriov, vf, vlan);
vp->vlan = 0;
qlcnic_sriov_cfg_vf_def_mac(adapter, vp, vf->pci_func, if (qlcnic_83xx_pf_check(adapter))
0, QLCNIC_MAC_ADD); qlcnic_sriov_cfg_vf_def_mac(adapter, vf,
0, QLCNIC_MAC_ADD);
return 0; return 0;
} }
...@@ -1241,32 +1311,37 @@ static int qlcnic_sriov_pf_add_guest_vlan(struct qlcnic_adapter *adapter, ...@@ -1241,32 +1311,37 @@ static int qlcnic_sriov_pf_add_guest_vlan(struct qlcnic_adapter *adapter,
struct qlcnic_vf_info *vf, struct qlcnic_vf_info *vf,
struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
struct qlcnic_vport *vp = vf->vp; struct qlcnic_sriov *sriov = adapter->ahw->sriov;
int err = -EIO; int err = -EIO;
u16 vlan;
if (vp->vlan) if (qlcnic_83xx_pf_check(adapter) && qlcnic_sriov_check_any_vlan(vf))
return err; return err;
vlan = cmd->req.arg[1] >> 16;
if (!vf->rx_ctx_id) { if (!vf->rx_ctx_id) {
vp->vlan = cmd->req.arg[1] >> 16; qlcnic_sriov_add_vlan_id(sriov, vf, vlan);
return 0; return 0;
} }
err = qlcnic_sriov_cfg_vf_def_mac(adapter, vp, vf->pci_func, if (qlcnic_83xx_pf_check(adapter)) {
0, QLCNIC_MAC_DEL); err = qlcnic_sriov_cfg_vf_def_mac(adapter, vf, 0,
if (err) QLCNIC_MAC_DEL);
return err; if (err)
return err;
}
vp->vlan = cmd->req.arg[1] >> 16; err = qlcnic_sriov_cfg_vf_def_mac(adapter, vf, vlan, QLCNIC_MAC_ADD);
err = qlcnic_sriov_cfg_vf_def_mac(adapter, vp, vf->pci_func,
vp->vlan, QLCNIC_MAC_ADD);
if (err) { if (err) {
qlcnic_sriov_cfg_vf_def_mac(adapter, vp, vf->pci_func, if (qlcnic_83xx_pf_check(adapter))
0, QLCNIC_MAC_ADD); qlcnic_sriov_cfg_vf_def_mac(adapter, vf, 0,
vp->vlan = 0; QLCNIC_MAC_ADD);
return err;
} }
qlcnic_sriov_add_vlan_id(sriov, vf, vlan);
return err; return err;
} }
...@@ -1289,7 +1364,7 @@ static int qlcnic_sriov_pf_cfg_guest_vlan_cmd(struct qlcnic_bc_trans *tran, ...@@ -1289,7 +1364,7 @@ static int qlcnic_sriov_pf_cfg_guest_vlan_cmd(struct qlcnic_bc_trans *tran,
if (op) if (op)
err = qlcnic_sriov_pf_add_guest_vlan(adapter, vf, cmd); err = qlcnic_sriov_pf_add_guest_vlan(adapter, vf, cmd);
else else
err = qlcnic_sriov_pf_del_guest_vlan(adapter, vf); err = qlcnic_sriov_pf_del_guest_vlan(adapter, vf, cmd);
cmd->rsp.arg[0] |= err ? 2 << 25 : 1 << 25; cmd->rsp.arg[0] |= err ? 2 << 25 : 1 << 25;
return err; return err;
...@@ -1299,8 +1374,6 @@ static const int qlcnic_pf_passthru_supp_cmds[] = { ...@@ -1299,8 +1374,6 @@ static const int qlcnic_pf_passthru_supp_cmds[] = {
QLCNIC_CMD_GET_STATISTICS, QLCNIC_CMD_GET_STATISTICS,
QLCNIC_CMD_GET_PORT_CONFIG, QLCNIC_CMD_GET_PORT_CONFIG,
QLCNIC_CMD_GET_LINK_STATUS, QLCNIC_CMD_GET_LINK_STATUS,
QLCNIC_CMD_DCB_QUERY_CAP,
QLCNIC_CMD_DCB_QUERY_PARAM,
QLCNIC_CMD_INIT_NIC_FUNC, QLCNIC_CMD_INIT_NIC_FUNC,
QLCNIC_CMD_STOP_NIC_FUNC, QLCNIC_CMD_STOP_NIC_FUNC,
}; };
...@@ -1596,7 +1669,8 @@ void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov, ...@@ -1596,7 +1669,8 @@ void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov,
} }
if (vp->vlan_mode == QLC_GUEST_VLAN_MODE) if (vp->vlan_mode == QLC_GUEST_VLAN_MODE)
vp->vlan = 0; memset(vf->sriov_vlans, 0,
sizeof(*vf->sriov_vlans) * sriov->num_allowed_vlans);
qlcnic_sriov_schedule_flr(sriov, vf, qlcnic_sriov_pf_process_flr); qlcnic_sriov_schedule_flr(sriov, vf, qlcnic_sriov_pf_process_flr);
netdev_info(dev, "FLR received for PCI func %d\n", vf->pci_func); netdev_info(dev, "FLR received for PCI func %d\n", vf->pci_func);
...@@ -1766,20 +1840,22 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf, ...@@ -1766,20 +1840,22 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
memset(vf_info->sriov_vlans, 0,
sizeof(*vf_info->sriov_vlans) * sriov->num_allowed_vlans);
switch (vlan) { switch (vlan) {
case 4095: case 4095:
vp->vlan = 0;
vp->vlan_mode = QLC_GUEST_VLAN_MODE; vp->vlan_mode = QLC_GUEST_VLAN_MODE;
break; break;
case 0: case 0:
vp->vlan_mode = QLC_NO_VLAN_MODE; vp->vlan_mode = QLC_NO_VLAN_MODE;
vp->vlan = 0;
vp->qos = 0; vp->qos = 0;
break; break;
default: default:
vp->vlan_mode = QLC_PVID_MODE; vp->vlan_mode = QLC_PVID_MODE;
vp->vlan = vlan; qlcnic_sriov_add_vlan_id(sriov, vf_info, vlan);
vp->qos = qos; vp->qos = qos;
vp->pvid = vlan;
} }
netdev_info(netdev, "Setting VLAN %d, QoS %d, for VF %d\n", netdev_info(netdev, "Setting VLAN %d, QoS %d, for VF %d\n",
...@@ -1794,7 +1870,7 @@ static __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, ...@@ -1794,7 +1870,7 @@ static __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter,
switch (vp->vlan_mode) { switch (vp->vlan_mode) {
case QLC_PVID_MODE: case QLC_PVID_MODE:
vlan = vp->vlan; vlan = vp->pvid;
break; break;
case QLC_GUEST_VLAN_MODE: case QLC_GUEST_VLAN_MODE:
vlan = MAX_VLAN_ID; vlan = MAX_VLAN_ID;
......
...@@ -360,10 +360,28 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, ...@@ -360,10 +360,28 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
return size; return size;
} }
static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func) static u32 qlcnic_get_pci_func_count(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
u32 count = 0;
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
return ahw->total_nic_func;
if (ahw->total_pci_func <= QLC_DEFAULT_VNIC_COUNT)
count = QLC_DEFAULT_VNIC_COUNT;
else
count = ahw->max_vnic_func;
return count;
}
int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
{
u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
int i; int i;
for (i = 0; i < adapter->ahw->act_pci_func; i++) {
for (i = 0; i < pci_func_count; i++) {
if (adapter->npars[i].pci_func == pci_func) if (adapter->npars[i].pci_func == pci_func)
return i; return i;
} }
...@@ -382,7 +400,6 @@ static int validate_pm_config(struct qlcnic_adapter *adapter, ...@@ -382,7 +400,6 @@ static int validate_pm_config(struct qlcnic_adapter *adapter,
src_pci_func = pm_cfg[i].pci_func; src_pci_func = pm_cfg[i].pci_func;
dest_pci_func = pm_cfg[i].dest_npar; dest_pci_func = pm_cfg[i].dest_npar;
src_index = qlcnic_is_valid_nic_func(adapter, src_pci_func); src_index = qlcnic_is_valid_nic_func(adapter, src_pci_func);
if (src_index < 0) if (src_index < 0)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
...@@ -439,6 +456,8 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp, ...@@ -439,6 +456,8 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
pci_func = pm_cfg[i].pci_func; pci_func = pm_cfg[i].pci_func;
index = qlcnic_is_valid_nic_func(adapter, pci_func); index = qlcnic_is_valid_nic_func(adapter, pci_func);
if (index < 0)
return QL_STATUS_INVALID_PARAM;
id = adapter->npars[index].phy_port; id = adapter->npars[index].phy_port;
adapter->npars[index].enable_pm = !!pm_cfg[i].action; adapter->npars[index].enable_pm = !!pm_cfg[i].action;
adapter->npars[index].dest_npar = id; adapter->npars[index].dest_npar = id;
...@@ -455,17 +474,19 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, ...@@ -455,17 +474,19 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC]; u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
int i; struct qlcnic_pm_func_cfg *pm_cfg;
int i, pm_cfg_size;
u8 pci_func; u8 pci_func;
if (size != sizeof(pm_cfg)) pm_cfg_size = pci_func_count * sizeof(*pm_cfg);
if (size != pm_cfg_size)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
memset(&pm_cfg, 0, memset(buf, 0, pm_cfg_size);
sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC); pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { for (i = 0; i < pci_func_count; i++) {
pci_func = adapter->npars[i].pci_func; pci_func = adapter->npars[i].pci_func;
if (!adapter->npars[i].active) if (!adapter->npars[i].active)
continue; continue;
...@@ -477,26 +498,26 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, ...@@ -477,26 +498,26 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
pm_cfg[pci_func].dest_npar = 0; pm_cfg[pci_func].dest_npar = 0;
pm_cfg[pci_func].pci_func = i; pm_cfg[pci_func].pci_func = i;
} }
memcpy(buf, &pm_cfg, size);
return size; return size;
} }
static int validate_esw_config(struct qlcnic_adapter *adapter, static int validate_esw_config(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg, int count) struct qlcnic_esw_func_cfg *esw_cfg, int count)
{ {
u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
struct qlcnic_hardware_context *ahw = adapter->ahw;
int i, ret;
u32 op_mode; u32 op_mode;
u8 pci_func; u8 pci_func;
int i, ret;
if (qlcnic_82xx_check(adapter)) if (qlcnic_82xx_check(adapter))
op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE); op_mode = readl(ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
else else
op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); op_mode = QLCRDX(ahw, QLC_83XX_DRV_OP_MODE);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func; pci_func = esw_cfg[i].pci_func;
if (pci_func >= QLCNIC_MAX_PCI_FUNC) if (pci_func >= pci_func_count)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
...@@ -600,6 +621,8 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file, ...@@ -600,6 +621,8 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func; pci_func = esw_cfg[i].pci_func;
index = qlcnic_is_valid_nic_func(adapter, pci_func); index = qlcnic_is_valid_nic_func(adapter, pci_func);
if (index < 0)
return QL_STATUS_INVALID_PARAM;
npar = &adapter->npars[index]; npar = &adapter->npars[index];
switch (esw_cfg[i].op_mode) { switch (esw_cfg[i].op_mode) {
case QLCNIC_PORT_DEFAULTS: case QLCNIC_PORT_DEFAULTS:
...@@ -629,16 +652,19 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, ...@@ -629,16 +652,19 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
struct qlcnic_esw_func_cfg *esw_cfg;
size_t esw_cfg_size;
u8 i, pci_func; u8 i, pci_func;
if (size != sizeof(esw_cfg)) esw_cfg_size = pci_func_count * sizeof(*esw_cfg);
if (size != esw_cfg_size)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
memset(&esw_cfg, 0, memset(buf, 0, esw_cfg_size);
sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC); esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { for (i = 0; i < pci_func_count; i++) {
pci_func = adapter->npars[i].pci_func; pci_func = adapter->npars[i].pci_func;
if (!adapter->npars[i].active) if (!adapter->npars[i].active)
continue; continue;
...@@ -650,9 +676,6 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, ...@@ -650,9 +676,6 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
} }
memcpy(buf, &esw_cfg, size);
return size; return size;
} }
...@@ -711,6 +734,8 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file, ...@@ -711,6 +734,8 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
if (ret) if (ret)
return ret; return ret;
index = qlcnic_is_valid_nic_func(adapter, pci_func); index = qlcnic_is_valid_nic_func(adapter, pci_func);
if (index < 0)
return QL_STATUS_INVALID_PARAM;
adapter->npars[index].min_bw = nic_info.min_tx_bw; adapter->npars[index].min_bw = nic_info.min_tx_bw;
adapter->npars[index].max_bw = nic_info.max_tx_bw; adapter->npars[index].max_bw = nic_info.max_tx_bw;
} }
...@@ -726,27 +751,28 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, ...@@ -726,27 +751,28 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
struct qlcnic_npar_func_cfg *np_cfg;
struct qlcnic_info nic_info; struct qlcnic_info nic_info;
struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC]; size_t np_cfg_size;
int i, ret; int i, ret;
if (size != sizeof(np_cfg)) np_cfg_size = pci_func_count * sizeof(*np_cfg);
if (size != np_cfg_size)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
memset(&nic_info, 0, sizeof(struct qlcnic_info)); memset(&nic_info, 0, sizeof(struct qlcnic_info));
memset(&np_cfg, 0, memset(buf, 0, np_cfg_size);
sizeof(struct qlcnic_npar_func_cfg) * QLCNIC_MAX_PCI_FUNC); np_cfg = (struct qlcnic_npar_func_cfg *)buf;
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { for (i = 0; i < pci_func_count; i++) {
if (qlcnic_is_valid_nic_func(adapter, i) < 0) if (qlcnic_is_valid_nic_func(adapter, i) < 0)
continue; continue;
ret = qlcnic_get_nic_info(adapter, &nic_info, i); ret = qlcnic_get_nic_info(adapter, &nic_info, i);
if (ret) if (ret)
return ret; return ret;
if (!adapter->npars[i].eswitch_status) if (!adapter->npars[i].eswitch_status)
continue; continue;
np_cfg[i].pci_func = i; np_cfg[i].pci_func = i;
np_cfg[i].op_mode = (u8)nic_info.op_mode; np_cfg[i].op_mode = (u8)nic_info.op_mode;
np_cfg[i].port_num = nic_info.phys_port; np_cfg[i].port_num = nic_info.phys_port;
...@@ -756,8 +782,6 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, ...@@ -756,8 +782,6 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
np_cfg[i].max_tx_queues = nic_info.max_tx_ques; np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
np_cfg[i].max_rx_queues = nic_info.max_rx_ques; np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
} }
memcpy(buf, &np_cfg, size);
return size; return size;
} }
...@@ -769,6 +793,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file, ...@@ -769,6 +793,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
struct qlcnic_esw_statistics port_stats; struct qlcnic_esw_statistics port_stats;
int ret; int ret;
...@@ -778,7 +803,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file, ...@@ -778,7 +803,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
if (size != sizeof(struct qlcnic_esw_statistics)) if (size != sizeof(struct qlcnic_esw_statistics))
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
if (offset >= QLCNIC_MAX_PCI_FUNC) if (offset >= pci_func_count)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
memset(&port_stats, 0, size); memset(&port_stats, 0, size);
...@@ -869,12 +894,13 @@ static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file, ...@@ -869,12 +894,13 @@ static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
int ret; int ret;
if (qlcnic_83xx_check(adapter)) if (qlcnic_83xx_check(adapter))
return QLC_STATUS_UNSUPPORTED_CMD; return QLC_STATUS_UNSUPPORTED_CMD;
if (offset >= QLCNIC_MAX_PCI_FUNC) if (offset >= pci_func_count)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
...@@ -898,27 +924,32 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file, ...@@ -898,27 +924,32 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC]; u32 pci_func_count = qlcnic_get_pci_func_count(adapter);
struct qlcnic_pci_func_cfg *pci_cfg;
struct qlcnic_pci_info *pci_info; struct qlcnic_pci_info *pci_info;
size_t pci_info_sz, pci_cfg_sz;
int i, ret; int i, ret;
if (size != sizeof(pci_cfg)) pci_cfg_sz = pci_func_count * sizeof(*pci_cfg);
if (size != pci_cfg_sz)
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); pci_info_sz = pci_func_count * sizeof(*pci_info);
pci_info = vmalloc(pci_info_sz);
if (!pci_info) if (!pci_info)
return -ENOMEM; return -ENOMEM;
memset(pci_info, 0, pci_info_sz);
memset(buf, 0, pci_cfg_sz);
pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
ret = qlcnic_get_pci_info(adapter, pci_info); ret = qlcnic_get_pci_info(adapter, pci_info);
if (ret) { if (ret) {
kfree(pci_info); vfree(pci_info);
return ret; return ret;
} }
memset(&pci_cfg, 0, for (i = 0; i < pci_func_count; i++) {
sizeof(struct qlcnic_pci_func_cfg) * QLCNIC_MAX_PCI_FUNC);
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
pci_cfg[i].pci_func = pci_info[i].id; pci_cfg[i].pci_func = pci_info[i].id;
pci_cfg[i].func_type = pci_info[i].type; pci_cfg[i].func_type = pci_info[i].type;
pci_cfg[i].port_num = pci_info[i].default_port; pci_cfg[i].port_num = pci_info[i].default_port;
...@@ -927,8 +958,7 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file, ...@@ -927,8 +958,7 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
} }
memcpy(buf, &pci_cfg, size); vfree(pci_info);
kfree(pci_info);
return size; return size;
} }
......
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