Commit fe6f397c authored by David S. Miller's avatar David S. Miller

Merge branch 'qlcnic-next'

Rajesh Borundia says:

====================
qlcnic: SR-IOV and FW-dump enhancements

This patch series contain following enhancements.

* SR-IOV enhancements:
 - Allow SR-IOV VF's to probe in hypervisor. SR-IOV VF can be
   uplinked to bridge/macvtap device with this change.
 - Commands from VF are processed in process context
   as it may sleep during PF-VF communication. Earlier
   we use to process qlcnic_sriov_vf_set_multi function in
   process context but now we process individual commands.
 - As SR-IOV VF's can be uplinked to bridge/macvtap device
   support mac-learning to allow communication through
   embedded switch.

* FW-dump enhancement:
 - Support to collect RDMEM section of firmware dump using
   PEX DMA method for 82xx series adapter.

* Changes in v2:
 - Removed unnecessary cast from void pointer to something
   else and verified this issue in entire patch series as
   per David Miller's suggestion.

Please apply this series to net-next.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a3ab3c13 27a4041e
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,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 58 #define _QLCNIC_LINUX_SUBVERSION 59
#define QLCNIC_LINUX_VERSIONID "5.3.58" #define QLCNIC_LINUX_VERSIONID "5.3.59"
#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))
...@@ -1019,6 +1019,8 @@ struct qlcnic_ipaddr { ...@@ -1019,6 +1019,8 @@ struct qlcnic_ipaddr {
#define QLCNIC_DEL_VXLAN_PORT 0x200000 #define QLCNIC_DEL_VXLAN_PORT 0x200000
#endif #endif
#define QLCNIC_VLAN_FILTERING 0x800000
#define QLCNIC_IS_MSI_FAMILY(adapter) \ #define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
#define QLCNIC_IS_TSO_CAPABLE(adapter) \ #define QLCNIC_IS_TSO_CAPABLE(adapter) \
...@@ -1693,7 +1695,7 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *); ...@@ -1693,7 +1695,7 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *);
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
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_set_multi(struct net_device *);
int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8); int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8);
int qlcnic_get_pci_func_type(struct qlcnic_adapter *, u16, u16 *, u16 *, int qlcnic_get_pci_func_type(struct qlcnic_adapter *, u16, u16 *, u16 *,
u16 *); u16 *);
...@@ -2355,6 +2357,16 @@ static inline bool qlcnic_83xx_vf_check(struct qlcnic_adapter *adapter) ...@@ -2355,6 +2357,16 @@ static inline bool qlcnic_83xx_vf_check(struct qlcnic_adapter *adapter)
return (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X) ? true : false; return (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X) ? true : false;
} }
static inline bool qlcnic_sriov_check(struct qlcnic_adapter *adapter)
{
bool status;
status = (qlcnic_sriov_pf_check(adapter) ||
qlcnic_sriov_vf_check(adapter)) ? true : false;
return status;
}
static inline u32 qlcnic_get_vnic_func_count(struct qlcnic_adapter *adapter) static inline u32 qlcnic_get_vnic_func_count(struct qlcnic_adapter *adapter)
{ {
if (qlcnic_84xx_check(adapter)) if (qlcnic_84xx_check(adapter))
......
...@@ -3037,19 +3037,18 @@ void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *adapter) ...@@ -3037,19 +3037,18 @@ void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *adapter)
QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK); QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
} }
int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr, int qlcnic_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
u32 *data, u32 count) u32 *data, u32 count)
{ {
int i, j, ret = 0; int i, j, ret = 0;
u32 temp; u32 temp;
int err = 0;
/* Check alignment */ /* Check alignment */
if (addr & 0xF) if (addr & 0xF)
return -EIO; return -EIO;
mutex_lock(&adapter->ahw->mem_lock); mutex_lock(&adapter->ahw->mem_lock);
qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_HI, 0); qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_HI, 0);
for (i = 0; i < count; i++, addr += 16) { for (i = 0; i < count; i++, addr += 16) {
if (!((ADDR_IN_RANGE(addr, QLCNIC_ADDR_QDR_NET, if (!((ADDR_IN_RANGE(addr, QLCNIC_ADDR_QDR_NET,
...@@ -3060,26 +3059,16 @@ int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr, ...@@ -3060,26 +3059,16 @@ int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
return -EIO; return -EIO;
} }
qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_LO, addr); qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_LO, addr);
qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_LO, qlcnic_ind_wr(adapter, QLCNIC_MS_WRTDATA_LO, *data++);
*data++); qlcnic_ind_wr(adapter, QLCNIC_MS_WRTDATA_HI, *data++);
qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_HI, qlcnic_ind_wr(adapter, QLCNIC_MS_WRTDATA_ULO, *data++);
*data++); qlcnic_ind_wr(adapter, QLCNIC_MS_WRTDATA_UHI, *data++);
qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_ULO, qlcnic_ind_wr(adapter, QLCNIC_MS_CTRL, QLCNIC_TA_WRITE_ENABLE);
*data++); qlcnic_ind_wr(adapter, QLCNIC_MS_CTRL, QLCNIC_TA_WRITE_START);
qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_UHI,
*data++);
qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL,
QLCNIC_TA_WRITE_ENABLE);
qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL,
QLCNIC_TA_WRITE_START);
for (j = 0; j < MAX_CTL_CHECK; j++) { for (j = 0; j < MAX_CTL_CHECK; j++) {
temp = QLCRD32(adapter, QLCNIC_MS_CTRL, &err); temp = qlcnic_ind_rd(adapter, QLCNIC_MS_CTRL);
if (err == -EIO) {
mutex_unlock(&adapter->ahw->mem_lock);
return err;
}
if ((temp & TA_CTL_BUSY) == 0) if ((temp & TA_CTL_BUSY) == 0)
break; break;
......
...@@ -560,7 +560,7 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *); ...@@ -560,7 +560,7 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *);
void qlcnic_83xx_napi_enable(struct qlcnic_adapter *); void qlcnic_83xx_napi_enable(struct qlcnic_adapter *);
void qlcnic_83xx_napi_disable(struct qlcnic_adapter *); void qlcnic_83xx_napi_disable(struct qlcnic_adapter *);
int qlcnic_83xx_config_led(struct qlcnic_adapter *, u32, u32); int qlcnic_83xx_config_led(struct qlcnic_adapter *, u32, u32);
void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32); int qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32);
int qlcnic_ind_rd(struct qlcnic_adapter *, u32); int qlcnic_ind_rd(struct qlcnic_adapter *, u32);
int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *); int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *);
int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *, int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *,
...@@ -617,7 +617,6 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *, u32); ...@@ -617,7 +617,6 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *, u32);
int qlcnic_83xx_lock_driver(struct qlcnic_adapter *); int qlcnic_83xx_lock_driver(struct qlcnic_adapter *);
void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *); void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *);
int qlcnic_83xx_set_default_offload_settings(struct qlcnic_adapter *); int qlcnic_83xx_set_default_offload_settings(struct qlcnic_adapter *);
int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *, u64, u32 *, u32);
int qlcnic_83xx_idc_vnic_pf_entry(struct qlcnic_adapter *); int qlcnic_83xx_idc_vnic_pf_entry(struct qlcnic_adapter *);
int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *, int); int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *, int);
int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *); int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *);
...@@ -659,4 +658,5 @@ void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *); ...@@ -659,4 +658,5 @@ void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *);
u32 qlcnic_83xx_get_cap_size(void *, int); u32 qlcnic_83xx_get_cap_size(void *, int);
void qlcnic_83xx_set_sys_info(void *, int, u32); void qlcnic_83xx_set_sys_info(void *, int, u32);
void qlcnic_83xx_store_cap_mask(void *, u32); void qlcnic_83xx_store_cap_mask(void *, u32);
int qlcnic_ms_mem_write128(struct qlcnic_adapter *, u64, u32 *, u32);
#endif #endif
...@@ -1363,8 +1363,8 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter) ...@@ -1363,8 +1363,8 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)
return ret; return ret;
} }
/* 16 byte write to MS memory */ /* 16 byte write to MS memory */
ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache, ret = qlcnic_ms_mem_write128(adapter, dest, (u32 *)p_cache,
size / 16); size / 16);
if (ret) { if (ret) {
vfree(p_cache); vfree(p_cache);
return ret; return ret;
...@@ -1389,8 +1389,8 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) ...@@ -1389,8 +1389,8 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
p_cache = (u32 *)fw->data; p_cache = (u32 *)fw->data;
addr = (u64)dest; addr = (u64)dest;
ret = qlcnic_83xx_ms_mem_write128(adapter, addr, ret = qlcnic_ms_mem_write128(adapter, addr,
p_cache, size / 16); p_cache, size / 16);
if (ret) { if (ret) {
dev_err(&adapter->pdev->dev, "MS memory write failed\n"); dev_err(&adapter->pdev->dev, "MS memory write failed\n");
release_firmware(fw); release_firmware(fw);
...@@ -1405,8 +1405,8 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) ...@@ -1405,8 +1405,8 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
data[i] = fw->data[size + i]; data[i] = fw->data[size + i];
for (; i < 16; i++) for (; i < 16; i++)
data[i] = 0; data[i] = 0;
ret = qlcnic_83xx_ms_mem_write128(adapter, addr, ret = qlcnic_ms_mem_write128(adapter, addr,
(u32 *)data, 1); (u32 *)data, 1);
if (ret) { if (ret) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"MS memory write failed\n"); "MS memory write failed\n");
......
...@@ -373,12 +373,16 @@ int qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr) ...@@ -373,12 +373,16 @@ int qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr)
return data; return data;
} }
void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data) int qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data)
{ {
int ret = 0;
if (qlcnic_82xx_check(adapter)) if (qlcnic_82xx_check(adapter))
qlcnic_write_window_reg(addr, adapter->ahw->pci_base0, data); qlcnic_write_window_reg(addr, adapter->ahw->pci_base0, data);
else else
qlcnic_83xx_wrt_reg_indirect(adapter, addr, data); ret = qlcnic_83xx_wrt_reg_indirect(adapter, addr, data);
return ret;
} }
static int static int
...@@ -567,28 +571,14 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) ...@@ -567,28 +571,14 @@ static 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;
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 (!netdev_mc_empty(netdev)) { if (qlcnic_sriov_vf_check(adapter))
netdev_for_each_mc_addr(ha, netdev) { qlcnic_sriov_vf_set_multi(netdev);
temp = sizeof(struct qlcnic_mac_vlan_list); else
cur = kzalloc(temp, GFP_ATOMIC); __qlcnic_set_multi(netdev, 0);
if (cur == NULL)
break;
memcpy(cur->mac_addr,
ha->addr, ETH_ALEN);
list_add_tail(&cur->list, &adapter->vf_mc_list);
}
}
qlcnic_sriov_vf_schedule_multi(adapter->netdev);
return;
}
__qlcnic_set_multi(netdev, 0);
} }
int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
......
...@@ -313,20 +313,16 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter, ...@@ -313,20 +313,16 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
u16 vlan_id = 0; u16 vlan_id = 0;
u8 hindex, hval; u8 hindex, hval;
if (!qlcnic_sriov_pf_check(adapter)) { if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) return;
return;
} else { if (adapter->flags & QLCNIC_VLAN_FILTERING) {
if (protocol == ETH_P_8021Q) { if (protocol == ETH_P_8021Q) {
vh = (struct vlan_ethhdr *)skb->data; vh = (struct vlan_ethhdr *)skb->data;
vlan_id = ntohs(vh->h_vlan_TCI); vlan_id = ntohs(vh->h_vlan_TCI);
} else if (vlan_tx_tag_present(skb)) { } else if (vlan_tx_tag_present(skb)) {
vlan_id = vlan_tx_tag_get(skb); vlan_id = vlan_tx_tag_get(skb);
} }
if (ether_addr_equal(phdr->h_source, adapter->mac_addr) &&
!vlan_id)
return;
} }
memcpy(&src_addr, phdr->h_source, ETH_ALEN); memcpy(&src_addr, phdr->h_source, ETH_ALEN);
......
...@@ -378,7 +378,8 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], ...@@ -378,7 +378,8 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
if (!adapter->fdb_mac_learn) if (!adapter->fdb_mac_learn)
return ndo_dflt_fdb_del(ndm, tb, netdev, addr); return ndo_dflt_fdb_del(ndm, tb, netdev, addr);
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
qlcnic_sriov_check(adapter)) {
if (is_unicast_ether_addr(addr)) { if (is_unicast_ether_addr(addr)) {
err = dev_uc_del(netdev, addr); err = dev_uc_del(netdev, addr);
if (!err) if (!err)
...@@ -402,7 +403,8 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], ...@@ -402,7 +403,8 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
if (!adapter->fdb_mac_learn) if (!adapter->fdb_mac_learn)
return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags); return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags);
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) { if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) &&
!qlcnic_sriov_check(adapter)) {
pr_info("%s: FDB e-switch is not enabled\n", __func__); pr_info("%s: FDB e-switch is not enabled\n", __func__);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -432,7 +434,8 @@ static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb, ...@@ -432,7 +434,8 @@ static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,
if (!adapter->fdb_mac_learn) if (!adapter->fdb_mac_learn)
return ndo_dflt_fdb_dump(skb, ncb, netdev, idx); return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
qlcnic_sriov_check(adapter))
idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx); idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
return idx; return idx;
...@@ -1917,8 +1920,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) ...@@ -1917,8 +1920,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state)) if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state))
return; return;
if (qlcnic_sriov_vf_check(adapter))
qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
smp_mb(); smp_mb();
netif_carrier_off(netdev); netif_carrier_off(netdev);
adapter->ahw->linkup = 0; adapter->ahw->linkup = 0;
...@@ -1930,6 +1931,8 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) ...@@ -1930,6 +1931,8 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
qlcnic_delete_lb_filters(adapter); qlcnic_delete_lb_filters(adapter);
qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE); qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
if (qlcnic_sriov_vf_check(adapter))
qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
qlcnic_napi_disable(adapter); qlcnic_napi_disable(adapter);
...@@ -2398,9 +2401,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2398,9 +2401,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
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 */
if (pdev->is_virtfn)
return -ENODEV;
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) if (err)
return err; return err;
...@@ -2680,9 +2680,9 @@ static void qlcnic_remove(struct pci_dev *pdev) ...@@ -2680,9 +2680,9 @@ static void qlcnic_remove(struct pci_dev *pdev)
return; return;
netdev = adapter->netdev; netdev = adapter->netdev;
qlcnic_sriov_pf_disable(adapter);
qlcnic_cancel_idc_work(adapter); qlcnic_cancel_idc_work(adapter);
qlcnic_sriov_pf_disable(adapter);
ahw = adapter->ahw; ahw = adapter->ahw;
unregister_netdev(netdev); unregister_netdev(netdev);
...@@ -2812,6 +2812,8 @@ static int qlcnic_close(struct net_device *netdev) ...@@ -2812,6 +2812,8 @@ static int qlcnic_close(struct net_device *netdev)
return 0; return 0;
} }
#define QLCNIC_VF_LB_BUCKET_SIZE 1
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter) void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
{ {
void *head; void *head;
...@@ -2827,7 +2829,10 @@ void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter) ...@@ -2827,7 +2829,10 @@ void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
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);
if (qlcnic_82xx_check(adapter)) { if (qlcnic_sriov_vf_check(adapter)) {
filter_size = QLCNIC_83XX_SRIOV_VF_MAX_MAC - 1;
adapter->fhash.fbucket_size = QLCNIC_VF_LB_BUCKET_SIZE;
} else if (qlcnic_82xx_check(adapter)) {
filter_size = QLCNIC_LB_MAX_FILTERS; filter_size = QLCNIC_LB_MAX_FILTERS;
adapter->fhash.fbucket_size = QLCNIC_LB_BUCKET_SIZE; adapter->fhash.fbucket_size = QLCNIC_LB_BUCKET_SIZE;
} else { } else {
......
...@@ -238,6 +238,8 @@ void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump) ...@@ -238,6 +238,8 @@ void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)
hdr->drv_cap_mask = hdr->cap_mask; hdr->drv_cap_mask = hdr->cap_mask;
fw_dump->cap_mask = hdr->cap_mask; fw_dump->cap_mask = hdr->cap_mask;
fw_dump->use_pex_dma = (hdr->capabilities & BIT_0) ? true : false;
} }
inline u32 qlcnic_82xx_get_cap_size(void *t_hdr, int index) inline u32 qlcnic_82xx_get_cap_size(void *t_hdr, int index)
...@@ -276,6 +278,8 @@ inline void qlcnic_83xx_set_saved_state(void *t_hdr, u32 index, ...@@ -276,6 +278,8 @@ inline void qlcnic_83xx_set_saved_state(void *t_hdr, u32 index,
hdr->saved_state[index] = value; hdr->saved_state[index] = value;
} }
#define QLCNIC_TEMPLATE_VERSION (0x20001)
void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump) void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)
{ {
struct qlcnic_83xx_dump_template_hdr *hdr; struct qlcnic_83xx_dump_template_hdr *hdr;
...@@ -288,6 +292,9 @@ void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump) ...@@ -288,6 +292,9 @@ void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)
hdr->drv_cap_mask = hdr->cap_mask; hdr->drv_cap_mask = hdr->cap_mask;
fw_dump->cap_mask = hdr->cap_mask; fw_dump->cap_mask = hdr->cap_mask;
fw_dump->use_pex_dma = (fw_dump->version & 0xfffff) >=
QLCNIC_TEMPLATE_VERSION;
} }
inline u32 qlcnic_83xx_get_cap_size(void *t_hdr, int index) inline u32 qlcnic_83xx_get_cap_size(void *t_hdr, int index)
...@@ -658,29 +665,28 @@ static u32 qlcnic_read_memory_test_agent(struct qlcnic_adapter *adapter, ...@@ -658,29 +665,28 @@ static u32 qlcnic_read_memory_test_agent(struct qlcnic_adapter *adapter,
static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter, static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter,
struct __mem *mem) struct __mem *mem)
{ {
struct qlcnic_83xx_dump_template_hdr *tmpl_hdr;
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
u32 dma_no, dma_base_addr, temp_addr; u32 dma_no, dma_base_addr, temp_addr;
int i, ret, dma_sts; int i, ret, dma_sts;
void *tmpl_hdr;
tmpl_hdr = adapter->ahw->fw_dump.tmpl_hdr; tmpl_hdr = adapter->ahw->fw_dump.tmpl_hdr;
dma_no = tmpl_hdr->saved_state[QLC_83XX_DMA_ENGINE_INDEX]; dma_no = qlcnic_get_saved_state(adapter, tmpl_hdr,
QLC_83XX_DMA_ENGINE_INDEX);
dma_base_addr = QLC_DMA_REG_BASE_ADDR(dma_no); dma_base_addr = QLC_DMA_REG_BASE_ADDR(dma_no);
temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_LOW; temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_LOW;
ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr, ret = qlcnic_ind_wr(adapter, temp_addr, mem->desc_card_addr);
mem->desc_card_addr);
if (ret) if (ret)
return ret; return ret;
temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_HI; temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_HI;
ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr, 0); ret = qlcnic_ind_wr(adapter, temp_addr, 0);
if (ret) if (ret)
return ret; return ret;
temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL; temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL;
ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr, ret = qlcnic_ind_wr(adapter, temp_addr, mem->start_dma_cmd);
mem->start_dma_cmd);
if (ret) if (ret)
return ret; return ret;
...@@ -710,15 +716,16 @@ static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter, ...@@ -710,15 +716,16 @@ static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter,
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
u32 temp, dma_base_addr, size = 0, read_size = 0; u32 temp, dma_base_addr, size = 0, read_size = 0;
struct qlcnic_pex_dma_descriptor *dma_descr; struct qlcnic_pex_dma_descriptor *dma_descr;
struct qlcnic_83xx_dump_template_hdr *tmpl_hdr;
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
dma_addr_t dma_phys_addr; dma_addr_t dma_phys_addr;
void *dma_buffer; void *dma_buffer;
void *tmpl_hdr;
tmpl_hdr = fw_dump->tmpl_hdr; tmpl_hdr = fw_dump->tmpl_hdr;
/* Check if DMA engine is available */ /* Check if DMA engine is available */
temp = tmpl_hdr->saved_state[QLC_83XX_DMA_ENGINE_INDEX]; temp = qlcnic_get_saved_state(adapter, tmpl_hdr,
QLC_83XX_DMA_ENGINE_INDEX);
dma_base_addr = QLC_DMA_REG_BASE_ADDR(temp); dma_base_addr = QLC_DMA_REG_BASE_ADDR(temp);
temp = qlcnic_ind_rd(adapter, temp = qlcnic_ind_rd(adapter,
dma_base_addr + QLC_DMA_CMD_STATUS_CTRL); dma_base_addr + QLC_DMA_CMD_STATUS_CTRL);
...@@ -764,8 +771,8 @@ static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter, ...@@ -764,8 +771,8 @@ static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter,
/* Write DMA descriptor to MS memory*/ /* Write DMA descriptor to MS memory*/
temp = sizeof(struct qlcnic_pex_dma_descriptor) / 16; temp = sizeof(struct qlcnic_pex_dma_descriptor) / 16;
*ret = qlcnic_83xx_ms_mem_write128(adapter, mem->desc_card_addr, *ret = qlcnic_ms_mem_write128(adapter, mem->desc_card_addr,
(u32 *)dma_descr, temp); (u32 *)dma_descr, temp);
if (*ret) { if (*ret) {
dev_info(dev, "Failed to write DMA descriptor to MS memory at address 0x%x\n", dev_info(dev, "Failed to write DMA descriptor to MS memory at address 0x%x\n",
mem->desc_card_addr); mem->desc_card_addr);
...@@ -1141,8 +1148,6 @@ static int __qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter, ...@@ -1141,8 +1148,6 @@ static int __qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter,
return err; return err;
} }
#define QLCNIC_TEMPLATE_VERSION (0x20001)
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw; struct qlcnic_hardware_context *ahw;
...@@ -1203,12 +1208,6 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) ...@@ -1203,12 +1208,6 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
"Default minidump capture mask 0x%x\n", "Default minidump capture mask 0x%x\n",
fw_dump->cap_mask); fw_dump->cap_mask);
if (qlcnic_83xx_check(adapter) &&
(fw_dump->version & 0xfffff) >= QLCNIC_TEMPLATE_VERSION)
fw_dump->use_pex_dma = true;
else
fw_dump->use_pex_dma = false;
qlcnic_enable_fw_dump_state(adapter); qlcnic_enable_fw_dump_state(adapter);
return 0; return 0;
......
...@@ -52,6 +52,7 @@ enum qlcnic_bc_commands { ...@@ -52,6 +52,7 @@ enum qlcnic_bc_commands {
QLCNIC_BC_CMD_CFG_GUEST_VLAN = 0x3, QLCNIC_BC_CMD_CFG_GUEST_VLAN = 0x3,
}; };
#define QLCNIC_83XX_SRIOV_VF_MAX_MAC 2
#define QLC_BC_CMD 1 #define QLC_BC_CMD 1
struct qlcnic_trans_list { struct qlcnic_trans_list {
...@@ -151,13 +152,14 @@ struct qlcnic_vf_info { ...@@ -151,13 +152,14 @@ 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 */ spinlock_t vlan_list_lock; /* Lock for VLAN list */
}; };
struct qlcnic_async_work_list { struct qlcnic_async_work_list {
struct list_head list; struct list_head list;
struct work_struct work; struct work_struct work;
void *ptr; void *ptr;
struct qlcnic_cmd_args *cmd;
}; };
struct qlcnic_back_channel { struct qlcnic_back_channel {
......
...@@ -39,6 +39,8 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *, u8); ...@@ -39,6 +39,8 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *, u8);
static void qlcnic_sriov_process_bc_cmd(struct work_struct *); static void qlcnic_sriov_process_bc_cmd(struct work_struct *);
static int qlcnic_sriov_vf_shutdown(struct pci_dev *); static int qlcnic_sriov_vf_shutdown(struct pci_dev *);
static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *); static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *);
static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *,
struct qlcnic_cmd_args *);
static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
.read_crb = qlcnic_83xx_read_crb, .read_crb = qlcnic_83xx_read_crb,
...@@ -181,7 +183,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) ...@@ -181,7 +183,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); spin_lock_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);
...@@ -197,8 +199,9 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) ...@@ -197,8 +199,9 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
goto qlcnic_destroy_async_wq; goto qlcnic_destroy_async_wq;
} }
sriov->vf_info[i].vp = vp; sriov->vf_info[i].vp = vp;
vp->vlan_mode = QLC_GUEST_VLAN_MODE;
vp->max_tx_bw = MAX_BW; vp->max_tx_bw = MAX_BW;
vp->spoofchk = true; vp->spoofchk = false;
random_ether_addr(vp->mac); random_ether_addr(vp->mac);
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"MAC Address %pM is configured for VF %d\n", "MAC Address %pM is configured for VF %d\n",
...@@ -515,6 +518,8 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, ...@@ -515,6 +518,8 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
{ {
int err; int err;
adapter->flags |= QLCNIC_VLAN_FILTERING;
adapter->ahw->total_nic_func = 1;
INIT_LIST_HEAD(&adapter->vf_mc_list); INIT_LIST_HEAD(&adapter->vf_mc_list);
if (!qlcnic_use_msi_x && !!qlcnic_use_msi) if (!qlcnic_use_msi_x && !!qlcnic_use_msi)
dev_warn(&adapter->pdev->dev, dev_warn(&adapter->pdev->dev,
...@@ -770,6 +775,7 @@ static int qlcnic_sriov_prepare_bc_hdr(struct qlcnic_bc_trans *trans, ...@@ -770,6 +775,7 @@ static int qlcnic_sriov_prepare_bc_hdr(struct qlcnic_bc_trans *trans,
cmd->req.arg = (u32 *)trans->req_pay; cmd->req.arg = (u32 *)trans->req_pay;
cmd->rsp.arg = (u32 *)trans->rsp_pay; cmd->rsp.arg = (u32 *)trans->rsp_pay;
cmd_op = cmd->req.arg[0] & 0xff; cmd_op = cmd->req.arg[0] & 0xff;
cmd->cmd_op = cmd_op;
remainder = (trans->rsp_pay_size) % (bc_pay_sz); remainder = (trans->rsp_pay_size) % (bc_pay_sz);
num_frags = (trans->rsp_pay_size) / (bc_pay_sz); num_frags = (trans->rsp_pay_size) / (bc_pay_sz);
if (remainder) if (remainder)
...@@ -1356,7 +1362,7 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter, ...@@ -1356,7 +1362,7 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter,
return -EIO; return -EIO;
} }
static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, static int __qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
...@@ -1408,12 +1414,17 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, ...@@ -1408,12 +1414,17 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
(mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) { (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) {
rsp = QLCNIC_RCODE_SUCCESS; rsp = QLCNIC_RCODE_SUCCESS;
} else { } else {
rsp = mbx_err_code; if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) {
if (!rsp) rsp = QLCNIC_RCODE_SUCCESS;
rsp = 1; } else {
dev_err(dev, rsp = mbx_err_code;
"MBX command 0x%x failed with err:0x%x for VF %d\n", if (!rsp)
opcode, mbx_err_code, func); rsp = 1;
dev_err(dev,
"MBX command 0x%x failed with err:0x%x for VF %d\n",
opcode, mbx_err_code, func);
}
} }
err_out: err_out:
...@@ -1428,6 +1439,16 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, ...@@ -1428,6 +1439,16 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
return rsp; return rsp;
} }
static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd)
{
if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT)
return qlcnic_sriov_async_issue_cmd(adapter, cmd);
else
return __qlcnic_sriov_issue_cmd(adapter, cmd);
}
static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op) static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op)
{ {
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
...@@ -1458,58 +1479,28 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_o ...@@ -1458,58 +1479,28 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_o
return ret; return ret;
} }
static void qlcnic_vf_add_mc_list(struct net_device *netdev) static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac)
{ {
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_sriov *sriov = adapter->ahw->sriov; struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_mac_vlan_list *cur;
struct list_head *head, tmp_list;
struct qlcnic_vf_info *vf; struct qlcnic_vf_info *vf;
u16 vlan_id; u16 vlan_id;
int i; int i;
static const u8 bcast_addr[ETH_ALEN] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
vf = &adapter->ahw->sriov->vf_info[0]; vf = &adapter->ahw->sriov->vf_info[0];
INIT_LIST_HEAD(&tmp_list);
head = &adapter->vf_mc_list;
netif_addr_lock_bh(netdev);
while (!list_empty(head)) { if (!qlcnic_sriov_check_any_vlan(vf)) {
cur = list_entry(head->next, struct qlcnic_mac_vlan_list, list); qlcnic_nic_add_mac(adapter, mac, 0);
list_move(&cur->list, &tmp_list); } else {
} spin_lock(&vf->vlan_list_lock);
for (i = 0; i < sriov->num_allowed_vlans; i++) {
netif_addr_unlock_bh(netdev); vlan_id = vf->sriov_vlans[i];
if (vlan_id)
while (!list_empty(&tmp_list)) { qlcnic_nic_add_mac(adapter, mac, vlan_id);
cur = list_entry((&tmp_list)->next,
struct qlcnic_mac_vlan_list, list);
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); spin_unlock(&vf->vlan_list_lock);
kfree(cur); if (qlcnic_84xx_check(adapter))
qlcnic_nic_add_mac(adapter, mac, 0);
} }
} }
...@@ -1518,6 +1509,7 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc) ...@@ -1518,6 +1509,7 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc)
struct list_head *head = &bc->async_list; struct list_head *head = &bc->async_list;
struct qlcnic_async_work_list *entry; struct qlcnic_async_work_list *entry;
flush_workqueue(bc->bc_async_wq);
while (!list_empty(head)) { while (!list_empty(head)) {
entry = list_entry(head->next, struct qlcnic_async_work_list, entry = list_entry(head->next, struct qlcnic_async_work_list,
list); list);
...@@ -1527,10 +1519,14 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc) ...@@ -1527,10 +1519,14 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc)
} }
} }
static void qlcnic_sriov_vf_set_multi(struct net_device *netdev) void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
{ {
struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
static const u8 bcast_addr[ETH_ALEN] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
struct netdev_hw_addr *ha;
u32 mode = VPORT_MISS_MODE_DROP; u32 mode = VPORT_MISS_MODE_DROP;
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
...@@ -1542,23 +1538,49 @@ static void qlcnic_sriov_vf_set_multi(struct net_device *netdev) ...@@ -1542,23 +1538,49 @@ static void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
} 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 {
qlcnic_vf_add_mc_list(netdev, bcast_addr);
if (!netdev_mc_empty(netdev)) {
netdev_for_each_mc_addr(ha, netdev)
qlcnic_vf_add_mc_list(netdev, ha->addr);
}
} }
if (qlcnic_sriov_vf_check(adapter)) /* configure unicast MAC address, if there is not sufficient space
qlcnic_vf_add_mc_list(netdev); * to store all the unicast addresses then enable promiscuous mode
*/
if (netdev_uc_count(netdev) > ahw->max_uc_count) {
mode = VPORT_MISS_MODE_ACCEPT_ALL;
} else if (!netdev_uc_empty(netdev)) {
netdev_for_each_uc_addr(ha, netdev)
qlcnic_vf_add_mc_list(netdev, ha->addr);
}
if (adapter->pdev->is_virtfn) {
if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
!adapter->fdb_mac_learn) {
qlcnic_alloc_lb_filters_mem(adapter);
adapter->drv_mac_learn = 1;
adapter->rx_mac_learn = true;
} else {
adapter->drv_mac_learn = 0;
adapter->rx_mac_learn = false;
}
}
qlcnic_nic_set_promisc(adapter, mode); qlcnic_nic_set_promisc(adapter, mode);
} }
static void qlcnic_sriov_handle_async_multi(struct work_struct *work) static void qlcnic_sriov_handle_async_issue_cmd(struct work_struct *work)
{ {
struct qlcnic_async_work_list *entry; struct qlcnic_async_work_list *entry;
struct net_device *netdev; struct qlcnic_adapter *adapter;
struct qlcnic_cmd_args *cmd;
entry = container_of(work, struct qlcnic_async_work_list, work); entry = container_of(work, struct qlcnic_async_work_list, work);
netdev = (struct net_device *)entry->ptr; adapter = entry->ptr;
cmd = entry->cmd;
qlcnic_sriov_vf_set_multi(netdev); __qlcnic_sriov_issue_cmd(adapter, cmd);
return; return;
} }
...@@ -1588,8 +1610,9 @@ qlcnic_sriov_get_free_node_async_work(struct qlcnic_back_channel *bc) ...@@ -1588,8 +1610,9 @@ qlcnic_sriov_get_free_node_async_work(struct qlcnic_back_channel *bc)
return entry; return entry;
} }
static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc, static void qlcnic_sriov_schedule_async_cmd(struct qlcnic_back_channel *bc,
work_func_t func, void *data) work_func_t func, void *data,
struct qlcnic_cmd_args *cmd)
{ {
struct qlcnic_async_work_list *entry = NULL; struct qlcnic_async_work_list *entry = NULL;
...@@ -1598,21 +1621,23 @@ static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc, ...@@ -1598,21 +1621,23 @@ static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc,
return; return;
entry->ptr = data; entry->ptr = data;
entry->cmd = cmd;
INIT_WORK(&entry->work, func); INIT_WORK(&entry->work, func);
queue_work(bc->bc_async_wq, &entry->work); queue_work(bc->bc_async_wq, &entry->work);
} }
void qlcnic_sriov_vf_schedule_multi(struct net_device *netdev) static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd)
{ {
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc; struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc;
if (adapter->need_fw_reset) if (adapter->need_fw_reset)
return; return -EIO;
qlcnic_sriov_schedule_bc_async_work(bc, qlcnic_sriov_handle_async_multi, qlcnic_sriov_schedule_async_cmd(bc, qlcnic_sriov_handle_async_issue_cmd,
netdev); adapter, cmd);
return 0;
} }
static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter)
...@@ -1836,6 +1861,12 @@ static int qlcnic_sriov_vf_idc_unknown_state(struct qlcnic_adapter *adapter) ...@@ -1836,6 +1861,12 @@ static int qlcnic_sriov_vf_idc_unknown_state(struct qlcnic_adapter *adapter)
return 0; return 0;
} }
static void qlcnic_sriov_vf_periodic_tasks(struct qlcnic_adapter *adapter)
{
if (adapter->fhash.fnum)
qlcnic_prune_lb_filters(adapter);
}
static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *work) static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *work)
{ {
struct qlcnic_adapter *adapter; struct qlcnic_adapter *adapter;
...@@ -1867,6 +1898,8 @@ static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *work) ...@@ -1867,6 +1898,8 @@ static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *work)
} }
idc->prev_state = idc->curr_state; idc->prev_state = idc->curr_state;
qlcnic_sriov_vf_periodic_tasks(adapter);
if (!ret && test_bit(QLC_83XX_MODULE_LOADED, &idc->status)) if (!ret && test_bit(QLC_83XX_MODULE_LOADED, &idc->status))
qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state,
idc->delay); idc->delay);
...@@ -1890,7 +1923,7 @@ static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov, ...@@ -1890,7 +1923,7 @@ static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov,
if (!vf->sriov_vlans) if (!vf->sriov_vlans)
return err; return err;
mutex_lock(&vf->vlan_list_lock); spin_lock_bh(&vf->vlan_list_lock);
for (i = 0; i < sriov->num_allowed_vlans; i++) { for (i = 0; i < sriov->num_allowed_vlans; i++) {
if (vf->sriov_vlans[i] == vlan_id) { if (vf->sriov_vlans[i] == vlan_id) {
...@@ -1899,7 +1932,7 @@ static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov, ...@@ -1899,7 +1932,7 @@ static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov,
} }
} }
mutex_unlock(&vf->vlan_list_lock); spin_unlock_bh(&vf->vlan_list_lock);
return err; return err;
} }
...@@ -1908,12 +1941,12 @@ static int qlcnic_sriov_validate_num_vlans(struct qlcnic_sriov *sriov, ...@@ -1908,12 +1941,12 @@ static int qlcnic_sriov_validate_num_vlans(struct qlcnic_sriov *sriov,
{ {
int err = 0; int err = 0;
mutex_lock(&vf->vlan_list_lock); spin_lock_bh(&vf->vlan_list_lock);
if (vf->num_vlan >= sriov->num_allowed_vlans) if (vf->num_vlan >= sriov->num_allowed_vlans)
err = -EINVAL; err = -EINVAL;
mutex_unlock(&vf->vlan_list_lock); spin_unlock_bh(&vf->vlan_list_lock);
return err; return err;
} }
...@@ -1966,7 +1999,7 @@ static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id, ...@@ -1966,7 +1999,7 @@ static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id,
if (!vf->sriov_vlans) if (!vf->sriov_vlans)
return; return;
mutex_lock(&vf->vlan_list_lock); spin_lock_bh(&vf->vlan_list_lock);
switch (opcode) { switch (opcode) {
case QLC_VLAN_ADD: case QLC_VLAN_ADD:
...@@ -1979,7 +2012,7 @@ static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id, ...@@ -1979,7 +2012,7 @@ static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id,
netdev_err(adapter->netdev, "Invalid VLAN operation\n"); netdev_err(adapter->netdev, "Invalid VLAN operation\n");
} }
mutex_unlock(&vf->vlan_list_lock); spin_unlock_bh(&vf->vlan_list_lock);
return; return;
} }
...@@ -1987,6 +2020,7 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter, ...@@ -1987,6 +2020,7 @@ 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 net_device *netdev = adapter->netdev;
struct qlcnic_vf_info *vf; struct qlcnic_vf_info *vf;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
int ret; int ret;
...@@ -2012,14 +2046,18 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter, ...@@ -2012,14 +2046,18 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter,
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to configure guest VLAN, err=%d\n", ret); "Failed to configure guest VLAN, err=%d\n", ret);
} else { } else {
netif_addr_lock_bh(netdev);
qlcnic_free_mac_list(adapter); qlcnic_free_mac_list(adapter);
netif_addr_unlock_bh(netdev);
if (enable) if (enable)
qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_ADD); qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_ADD);
else else
qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_DELETE); qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_DELETE);
qlcnic_set_multi(adapter->netdev); netif_addr_lock_bh(netdev);
qlcnic_set_multi(netdev);
netif_addr_unlock_bh(netdev);
} }
qlcnic_free_mbx_args(&cmd); qlcnic_free_mbx_args(&cmd);
...@@ -2150,11 +2188,11 @@ bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *vf) ...@@ -2150,11 +2188,11 @@ bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *vf)
{ {
bool err = false; bool err = false;
mutex_lock(&vf->vlan_list_lock); spin_lock_bh(&vf->vlan_list_lock);
if (vf->num_vlan) if (vf->num_vlan)
err = true; err = true;
mutex_unlock(&vf->vlan_list_lock); spin_unlock_bh(&vf->vlan_list_lock);
return err; return err;
} }
...@@ -84,7 +84,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter, ...@@ -84,7 +84,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
info->max_tx_ques = res->num_tx_queues / max; info->max_tx_ques = res->num_tx_queues / max;
if (qlcnic_83xx_pf_check(adapter)) if (qlcnic_83xx_pf_check(adapter))
num_macs = 1; num_macs = QLCNIC_83XX_SRIOV_VF_MAX_MAC;
info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters; info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
...@@ -338,9 +338,12 @@ static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter, ...@@ -338,9 +338,12 @@ static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter,
cmd.req.arg[1] = 0x4; cmd.req.arg[1] = 0x4;
if (enable) { if (enable) {
adapter->flags |= QLCNIC_VLAN_FILTERING;
cmd.req.arg[1] |= BIT_16; cmd.req.arg[1] |= BIT_16;
if (qlcnic_84xx_check(adapter)) if (qlcnic_84xx_check(adapter))
cmd.req.arg[1] |= QLC_SRIOV_ALLOW_VLAN0; cmd.req.arg[1] |= QLC_SRIOV_ALLOW_VLAN0;
} else {
adapter->flags &= ~QLCNIC_VLAN_FILTERING;
} }
err = qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, &cmd);
...@@ -472,12 +475,12 @@ static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter) ...@@ -472,12 +475,12 @@ static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
return -EPERM; return -EPERM;
} }
qlcnic_sriov_pf_disable(adapter);
rtnl_lock(); rtnl_lock();
if (netif_running(netdev)) if (netif_running(netdev))
__qlcnic_down(adapter, netdev); __qlcnic_down(adapter, netdev);
qlcnic_sriov_pf_disable(adapter);
qlcnic_sriov_free_vlans(adapter); qlcnic_sriov_free_vlans(adapter);
qlcnic_sriov_pf_cleanup(adapter); qlcnic_sriov_pf_cleanup(adapter);
...@@ -596,7 +599,6 @@ static int __qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, ...@@ -596,7 +599,6 @@ static int __qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter,
qlcnic_sriov_alloc_vlans(adapter); qlcnic_sriov_alloc_vlans(adapter);
err = qlcnic_sriov_pf_enable(adapter, num_vfs);
return err; return err;
del_flr_queue: del_flr_queue:
...@@ -627,25 +629,36 @@ static int qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, int num_vfs) ...@@ -627,25 +629,36 @@ static int qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, int num_vfs)
__qlcnic_down(adapter, netdev); __qlcnic_down(adapter, netdev);
err = __qlcnic_pci_sriov_enable(adapter, num_vfs); err = __qlcnic_pci_sriov_enable(adapter, num_vfs);
if (err) { if (err)
netdev_info(netdev, "Failed to enable SR-IOV on port %d\n", goto error;
adapter->portnum);
err = -EIO; if (netif_running(netdev))
if (qlcnic_83xx_configure_opmode(adapter)) __qlcnic_up(adapter, netdev);
goto error;
} else { rtnl_unlock();
err = qlcnic_sriov_pf_enable(adapter, num_vfs);
if (!err) {
netdev_info(netdev, netdev_info(netdev,
"SR-IOV is enabled successfully on port %d\n", "SR-IOV is enabled successfully on port %d\n",
adapter->portnum); adapter->portnum);
/* Return number of vfs enabled */ /* Return number of vfs enabled */
err = num_vfs; return num_vfs;
} }
rtnl_lock();
if (netif_running(netdev)) if (netif_running(netdev))
__qlcnic_up(adapter, netdev); __qlcnic_down(adapter, netdev);
error: error:
if (!qlcnic_83xx_configure_opmode(adapter)) {
if (netif_running(netdev))
__qlcnic_up(adapter, netdev);
}
rtnl_unlock(); rtnl_unlock();
netdev_info(netdev, "Failed to enable SR-IOV on port %d\n",
adapter->portnum);
return err; return err;
} }
...@@ -774,7 +787,7 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter, ...@@ -774,7 +787,7 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
struct qlcnic_vf_info *vf, struct qlcnic_vf_info *vf,
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; struct qlcnic_vport *vp;
u8 *addr; u8 *addr;
...@@ -784,21 +797,27 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter, ...@@ -784,21 +797,27 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
vp = vf->vp; vp = vf->vp;
if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN)) cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
if (!cmd)
return -ENOMEM; return -ENOMEM;
err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
if (err)
goto free_cmd;
cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_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 free_args;
} }
if (vlan) if (vlan)
op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ? 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[1] = op | (1 << 8) | (3 << 6); cmd->req.arg[1] = op | (1 << 8) | (3 << 6);
cmd.req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31; cmd->req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31;
addr = vp->mac; addr = vp->mac;
mv.vlan = vlan; mv.vlan = vlan;
...@@ -808,18 +827,18 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter, ...@@ -808,18 +827,18 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
mv.mac_addr3 = addr[3]; mv.mac_addr3 = addr[3];
mv.mac_addr4 = addr[4]; mv.mac_addr4 = addr[4];
mv.mac_addr5 = addr[5]; mv.mac_addr5 = addr[5];
buf = &cmd.req.arg[2]; buf = &cmd->req.arg[2];
memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx)); memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
err = qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, cmd);
if (err) if (!err)
dev_err(&adapter->pdev->dev, return err;
"MAC-VLAN %s to CAM failed, err=%d.\n",
((op == 1) ? "add " : "delete "), err);
out: free_args:
qlcnic_free_mbx_args(&cmd); qlcnic_free_mbx_args(cmd);
free_cmd:
kfree(cmd);
return err; return err;
} }
...@@ -841,7 +860,7 @@ static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter, ...@@ -841,7 +860,7 @@ static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter,
sriov = adapter->ahw->sriov; sriov = adapter->ahw->sriov;
mutex_lock(&vf->vlan_list_lock); spin_lock_bh(&vf->vlan_list_lock);
if (vf->num_vlan) { if (vf->num_vlan) {
for (i = 0; i < sriov->num_allowed_vlans; i++) { for (i = 0; i < sriov->num_allowed_vlans; i++) {
vlan = vf->sriov_vlans[i]; vlan = vf->sriov_vlans[i];
...@@ -850,7 +869,7 @@ static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter, ...@@ -850,7 +869,7 @@ static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter,
opcode); opcode);
} }
} }
mutex_unlock(&vf->vlan_list_lock); spin_unlock_bh(&vf->vlan_list_lock);
if (vf->vp->vlan_mode != QLC_PVID_MODE) { if (vf->vp->vlan_mode != QLC_PVID_MODE) {
if (qlcnic_83xx_pf_check(adapter) && if (qlcnic_83xx_pf_check(adapter) &&
...@@ -1237,7 +1256,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter, ...@@ -1237,7 +1256,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(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_macvlan_mbx *macvlan;
struct qlcnic_vport *vp = vf->vp; struct qlcnic_vport *vp = vf->vp;
u8 op, new_op; u8 op, new_op;
...@@ -1247,14 +1265,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter, ...@@ -1247,14 +1265,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
cmd->req.arg[1] |= (vf->vp->handle << 16); cmd->req.arg[1] |= (vf->vp->handle << 16);
cmd->req.arg[1] |= BIT_31; cmd->req.arg[1] |= BIT_31;
macvlan = (struct qlcnic_macvlan_mbx *)&cmd->req.arg[2];
if (!(macvlan->mac_addr0 & BIT_0)) {
dev_err(&adapter->pdev->dev,
"MAC address change is not allowed from VF %d",
vf->pci_func);
return -EINVAL;
}
if (vp->vlan_mode == QLC_PVID_MODE) { if (vp->vlan_mode == QLC_PVID_MODE) {
op = cmd->req.arg[1] & 0x7; op = cmd->req.arg[1] & 0x7;
cmd->req.arg[1] &= ~0x7; cmd->req.arg[1] &= ~0x7;
......
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