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

Merge branch 'qlcnic'

Shahed Shaikh says:

====================
This series includes following changes:
o SRIOV and VLAN filtering related enhancements which includes
   - Do MAC learning for PF
   - Restrict VF from configuring any VLAN mode
   - Enable flooding on PF
   - Turn on promiscuous mode for PF

o Bug fix in qlcnic_sriov_cleanup() introduced by commit
  154d0c81("qlcnic: VLAN enhancement for 84XX adapters")

o Beaconing support for 83xx and 84xx series adapters

o Allow 82xx adapter to perform IPv6 LRO even if destination IP address is not
  programmed.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2315dc91 db5ee75d
...@@ -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 53 #define _QLCNIC_LINUX_SUBVERSION 54
#define QLCNIC_LINUX_VERSIONID "5.3.53" #define QLCNIC_LINUX_VERSIONID "5.3.54"
#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))
...@@ -970,6 +970,9 @@ struct qlcnic_ipaddr { ...@@ -970,6 +970,9 @@ struct qlcnic_ipaddr {
#define QLCNIC_BEACON_EANBLE 0xC #define QLCNIC_BEACON_EANBLE 0xC
#define QLCNIC_BEACON_DISABLE 0xD #define QLCNIC_BEACON_DISABLE 0xD
#define QLCNIC_BEACON_ON 2
#define QLCNIC_BEACON_OFF 0
#define QLCNIC_MSIX_TBL_SPACE 8192 #define QLCNIC_MSIX_TBL_SPACE 8192
#define QLCNIC_PCI_REG_MSIX_TBL 0x44 #define QLCNIC_PCI_REG_MSIX_TBL 0x44
#define QLCNIC_MSIX_TBL_PGSIZE 4096 #define QLCNIC_MSIX_TBL_PGSIZE 4096
...@@ -1079,6 +1082,7 @@ struct qlcnic_adapter { ...@@ -1079,6 +1082,7 @@ struct qlcnic_adapter {
u64 dev_rst_time; u64 dev_rst_time;
bool drv_mac_learn; bool drv_mac_learn;
bool fdb_mac_learn; bool fdb_mac_learn;
u8 rx_mac_learn;
unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
u8 flash_mfg_id; u8 flash_mfg_id;
struct qlcnic_npar_info *npars; struct qlcnic_npar_info *npars;
...@@ -1640,7 +1644,6 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *); ...@@ -1640,7 +1644,6 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *);
int qlcnic_reset_npar_config(struct qlcnic_adapter *); int qlcnic_reset_npar_config(struct qlcnic_adapter *);
int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *); int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *);
void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16); void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16);
int qlcnic_get_beacon_state(struct qlcnic_adapter *, u8 *);
int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter); int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
int qlcnic_read_mac_addr(struct qlcnic_adapter *); int qlcnic_read_mac_addr(struct qlcnic_adapter *);
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
...@@ -1767,6 +1770,7 @@ struct qlcnic_hardware_ops { ...@@ -1767,6 +1770,7 @@ struct qlcnic_hardware_ops {
pci_channel_state_t); pci_channel_state_t);
pci_ers_result_t (*io_slot_reset) (struct pci_dev *); pci_ers_result_t (*io_slot_reset) (struct pci_dev *);
void (*io_resume) (struct pci_dev *); void (*io_resume) (struct pci_dev *);
void (*get_beacon_state)(struct qlcnic_adapter *);
}; };
extern struct qlcnic_nic_template qlcnic_vf_ops; extern struct qlcnic_nic_template qlcnic_vf_ops;
...@@ -1993,6 +1997,11 @@ static inline void qlcnic_set_mac_filter_count(struct qlcnic_adapter *adapter) ...@@ -1993,6 +1997,11 @@ static inline void qlcnic_set_mac_filter_count(struct qlcnic_adapter *adapter)
adapter->ahw->hw_ops->set_mac_filter_count(adapter); adapter->ahw->hw_ops->set_mac_filter_count(adapter);
} }
static inline void qlcnic_get_beacon_state(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->get_beacon_state(adapter);
}
static inline void qlcnic_read_phys_port_id(struct qlcnic_adapter *adapter) static inline void qlcnic_read_phys_port_id(struct qlcnic_adapter *adapter)
{ {
if (adapter->ahw->hw_ops->read_phys_port_id) if (adapter->ahw->hw_ops->read_phys_port_id)
......
...@@ -181,7 +181,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { ...@@ -181,7 +181,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
.io_error_detected = qlcnic_83xx_io_error_detected, .io_error_detected = qlcnic_83xx_io_error_detected,
.io_slot_reset = qlcnic_83xx_io_slot_reset, .io_slot_reset = qlcnic_83xx_io_slot_reset,
.io_resume = qlcnic_83xx_io_resume, .io_resume = qlcnic_83xx_io_resume,
.get_beacon_state = qlcnic_83xx_get_beacon_state,
}; };
static struct qlcnic_nic_template qlcnic_83xx_ops = { static struct qlcnic_nic_template qlcnic_83xx_ops = {
...@@ -1388,6 +1388,33 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev, ...@@ -1388,6 +1388,33 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
netif_device_attach(netdev); netif_device_attach(netdev);
} }
void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *adapter)
{
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_cmd_args cmd;
u8 beacon_state;
int err = 0;
err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LED_CONFIG);
if (!err) {
err = qlcnic_issue_cmd(adapter, &cmd);
if (!err) {
beacon_state = cmd.rsp.arg[4];
if (beacon_state == QLCNIC_BEACON_DISABLE)
ahw->beacon_state = QLC_83XX_BEACON_OFF;
else if (beacon_state == QLC_83XX_ENABLE_BEACON)
ahw->beacon_state = QLC_83XX_BEACON_ON;
}
} else {
netdev_err(adapter->netdev, "Get beacon state failed, err=%d\n",
err);
}
qlcnic_free_mbx_args(&cmd);
return;
}
int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state, int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
u32 beacon) u32 beacon)
{ {
...@@ -1591,7 +1618,9 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter, ...@@ -1591,7 +1618,9 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
u32 *interface_id) u32 *interface_id)
{ {
if (qlcnic_sriov_pf_check(adapter)) { if (qlcnic_sriov_pf_check(adapter)) {
qlcnic_alloc_lb_filters_mem(adapter);
qlcnic_pf_set_interface_id_promisc(adapter, interface_id); qlcnic_pf_set_interface_id_promisc(adapter, interface_id);
adapter->rx_mac_learn = 1;
} else { } else {
if (!qlcnic_sriov_vf_check(adapter)) if (!qlcnic_sriov_vf_check(adapter))
*interface_id = adapter->recv_ctx->context_id << 16; *interface_id = adapter->recv_ctx->context_id << 16;
...@@ -1618,6 +1647,10 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) ...@@ -1618,6 +1647,10 @@ 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);
if (qlcnic_84xx_check(adapter) && qlcnic_sriov_pf_check(adapter))
mode = VPORT_MISS_MODE_ACCEPT_ALL;
cmd->req.arg[1] = mode | temp; cmd->req.arg[1] = mode | temp;
err = qlcnic_issue_cmd(adapter, cmd); err = qlcnic_issue_cmd(adapter, cmd);
if (!err) if (!err)
......
...@@ -381,6 +381,8 @@ enum qlcnic_83xx_states { ...@@ -381,6 +381,8 @@ enum qlcnic_83xx_states {
/* LED configuration settings */ /* LED configuration settings */
#define QLC_83XX_ENABLE_BEACON 0xe #define QLC_83XX_ENABLE_BEACON 0xe
#define QLC_83XX_BEACON_ON 1
#define QLC_83XX_BEACON_OFF 0
#define QLC_83XX_LED_RATE 0xff #define QLC_83XX_LED_RATE 0xff
#define QLC_83XX_LED_ACT (1 << 10) #define QLC_83XX_LED_ACT (1 << 10)
#define QLC_83XX_LED_MOD (0 << 13) #define QLC_83XX_LED_MOD (0 << 13)
...@@ -559,6 +561,7 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *); ...@@ -559,6 +561,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_83xx_get_beacon_state(struct qlcnic_adapter *);
void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32); void 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 *);
......
...@@ -2214,6 +2214,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) ...@@ -2214,6 +2214,7 @@ 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;
int err = 0; int err = 0;
adapter->rx_mac_learn = 0;
ahw->msix_supported = !!qlcnic_use_msi_x; ahw->msix_supported = !!qlcnic_use_msi_x;
qlcnic_83xx_init_rings(adapter); qlcnic_83xx_init_rings(adapter);
......
...@@ -224,10 +224,14 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) ...@@ -224,10 +224,14 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
return -EIO; return -EIO;
} }
if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) {
adapter->flags |= QLCNIC_ESWITCH_ENABLED; adapter->flags |= QLCNIC_ESWITCH_ENABLED;
else if (adapter->drv_mac_learn)
adapter->rx_mac_learn = 1;
} else {
adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
adapter->rx_mac_learn = 0;
}
ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO; ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
......
...@@ -546,8 +546,11 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) ...@@ -546,8 +546,11 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
!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 = 1;
if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
adapter->rx_mac_learn = 1;
} else { } else {
adapter->drv_mac_learn = 0; adapter->drv_mac_learn = 0;
adapter->rx_mac_learn = 0;
} }
qlcnic_nic_set_promisc(adapter, mode); qlcnic_nic_set_promisc(adapter, mode);
...@@ -779,8 +782,8 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter) ...@@ -779,8 +782,8 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
"Could not send interrupt coalescing parameters\n"); "Could not send interrupt coalescing parameters\n");
} }
#define QLCNIC_ENABLE_IPV4_LRO 1 #define QLCNIC_ENABLE_IPV4_LRO BIT_0
#define QLCNIC_ENABLE_IPV6_LRO 2 #define QLCNIC_ENABLE_IPV6_LRO (BIT_1 | BIT_9)
int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable) int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
{ {
...@@ -1530,19 +1533,34 @@ int qlcnic_82xx_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) ...@@ -1530,19 +1533,34 @@ int qlcnic_82xx_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
return rv; return rv;
} }
int qlcnic_get_beacon_state(struct qlcnic_adapter *adapter, u8 *h_state) void qlcnic_82xx_get_beacon_state(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_hardware_context *ahw = adapter->ahw;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
int err; u8 beacon_state;
int err = 0;
err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LED_STATUS); if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) {
if (!err) { err = qlcnic_alloc_mbx_args(&cmd, adapter,
err = qlcnic_issue_cmd(adapter, &cmd); QLCNIC_CMD_GET_LED_STATUS);
if (!err) if (!err) {
*h_state = cmd.rsp.arg[1]; err = qlcnic_issue_cmd(adapter, &cmd);
if (err) {
netdev_err(adapter->netdev,
"Failed to get current beacon state, err=%d\n",
err);
} else {
beacon_state = cmd.rsp.arg[1];
if (beacon_state == QLCNIC_BEACON_DISABLE)
ahw->beacon_state = QLCNIC_BEACON_OFF;
else if (beacon_state == QLCNIC_BEACON_EANBLE)
ahw->beacon_state = QLCNIC_BEACON_ON;
}
}
qlcnic_free_mbx_args(&cmd);
} }
qlcnic_free_mbx_args(&cmd);
return err; return;
} }
void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter) void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter)
......
...@@ -169,6 +169,7 @@ int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int); ...@@ -169,6 +169,7 @@ int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int);
int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32); int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32);
int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
struct net_device *netdev); struct net_device *netdev);
void qlcnic_82xx_get_beacon_state(struct qlcnic_adapter *);
void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter,
u64 *uaddr, u16 vlan_id); u64 *uaddr, u16 vlan_id);
void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter); void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter);
......
...@@ -156,9 +156,9 @@ static inline void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter, ...@@ -156,9 +156,9 @@ static inline void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter,
writel(1, tx_ring->crb_intr_mask); writel(1, tx_ring->crb_intr_mask);
} }
static inline u8 qlcnic_mac_hash(u64 mac) static inline u8 qlcnic_mac_hash(u64 mac, u16 vlan)
{ {
return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff)); return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff) ^ (vlan & 0xff));
} }
static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter, static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter,
...@@ -221,8 +221,11 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb, ...@@ -221,8 +221,11 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb,
u8 hindex, op; u8 hindex, op;
int ret; int ret;
if (!qlcnic_sriov_pf_check(adapter) || (vlan_id == 0xffff))
vlan_id = 0;
memcpy(&src_addr, phdr->h_source, ETH_ALEN); memcpy(&src_addr, phdr->h_source, ETH_ALEN);
hindex = qlcnic_mac_hash(src_addr) & hindex = qlcnic_mac_hash(src_addr, vlan_id) &
(adapter->fhash.fbucket_size - 1); (adapter->fhash.fbucket_size - 1);
if (loopback_pkt) { if (loopback_pkt) {
...@@ -322,27 +325,43 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter, ...@@ -322,27 +325,43 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
struct cmd_desc_type0 *first_desc, struct cmd_desc_type0 *first_desc,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct vlan_ethhdr *vh = (struct vlan_ethhdr *)(skb->data);
struct ethhdr *phdr = (struct ethhdr *)(skb->data);
struct net_device *netdev = adapter->netdev;
u16 protocol = ntohs(skb->protocol);
struct qlcnic_filter *fil, *tmp_fil; struct qlcnic_filter *fil, *tmp_fil;
struct hlist_node *n;
struct hlist_head *head; struct hlist_head *head;
struct net_device *netdev = adapter->netdev; struct hlist_node *n;
struct ethhdr *phdr = (struct ethhdr *)(skb->data);
u64 src_addr = 0; u64 src_addr = 0;
u16 vlan_id = 0; u16 vlan_id = 0;
u8 hindex; u8 hindex, hval;
if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) if (!qlcnic_sriov_pf_check(adapter)) {
return; if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
return;
} else {
if (protocol == ETH_P_8021Q) {
vh = (struct vlan_ethhdr *)skb->data;
vlan_id = ntohs(vh->h_vlan_TCI);
} else if (vlan_tx_tag_present(skb)) {
vlan_id = vlan_tx_tag_get(skb);
}
if (ether_addr_equal(phdr->h_source, adapter->mac_addr) &&
!vlan_id)
return;
}
if (adapter->fhash.fnum >= adapter->fhash.fmax) { if (adapter->fhash.fnum >= adapter->fhash.fmax) {
adapter->stats.mac_filter_limit_overrun++; adapter->stats.mac_filter_limit_overrun++;
netdev_info(netdev, "Can not add more than %d mac addresses\n", netdev_info(netdev, "Can not add more than %d mac-vlan filters, configured %d\n",
adapter->fhash.fmax); adapter->fhash.fmax, adapter->fhash.fnum);
return; return;
} }
memcpy(&src_addr, phdr->h_source, ETH_ALEN); memcpy(&src_addr, phdr->h_source, ETH_ALEN);
hindex = qlcnic_mac_hash(src_addr) & (adapter->fhash.fbucket_size - 1); hval = qlcnic_mac_hash(src_addr, vlan_id);
hindex = hval & (adapter->fhash.fbucket_size - 1);
head = &(adapter->fhash.fhead[hindex]); head = &(adapter->fhash.fhead[hindex]);
hlist_for_each_entry_safe(tmp_fil, n, head, fnode) { hlist_for_each_entry_safe(tmp_fil, n, head, fnode) {
...@@ -1599,7 +1618,8 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter, ...@@ -1599,7 +1618,8 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
struct sk_buff *skb; struct sk_buff *skb;
struct qlcnic_host_rds_ring *rds_ring; struct qlcnic_host_rds_ring *rds_ring;
int index, length, cksum, is_lb_pkt; int index, length, cksum, is_lb_pkt;
u16 vid = 0xffff, t_vid; u16 vid = 0xffff;
int err;
if (unlikely(ring >= adapter->max_rds_rings)) if (unlikely(ring >= adapter->max_rds_rings))
return NULL; return NULL;
...@@ -1617,19 +1637,19 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter, ...@@ -1617,19 +1637,19 @@ qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter,
if (!skb) if (!skb)
return buffer; return buffer;
if (adapter->drv_mac_learn &&
(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
t_vid = 0;
is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
}
if (length > rds_ring->skb_size) if (length > rds_ring->skb_size)
skb_put(skb, rds_ring->skb_size); skb_put(skb, rds_ring->skb_size);
else else
skb_put(skb, length); skb_put(skb, length);
if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { err = qlcnic_check_rx_tagging(adapter, skb, &vid);
if (adapter->rx_mac_learn) {
is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0);
qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
}
if (unlikely(err)) {
adapter->stats.rxdropped++; adapter->stats.rxdropped++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
return buffer; return buffer;
...@@ -1664,7 +1684,8 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter, ...@@ -1664,7 +1684,8 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
int l2_hdr_offset, l4_hdr_offset; int l2_hdr_offset, l4_hdr_offset;
int index, is_lb_pkt; int index, is_lb_pkt;
u16 lro_length, length, data_offset, gso_size; u16 lro_length, length, data_offset, gso_size;
u16 vid = 0xffff, t_vid; u16 vid = 0xffff;
int err;
if (unlikely(ring > adapter->max_rds_rings)) if (unlikely(ring > adapter->max_rds_rings))
return NULL; return NULL;
...@@ -1686,12 +1707,6 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter, ...@@ -1686,12 +1707,6 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
if (!skb) if (!skb)
return buffer; return buffer;
if (adapter->drv_mac_learn &&
(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
t_vid = 0;
is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, t_vid);
}
if (qlcnic_83xx_is_tstamp(sts_data[1])) if (qlcnic_83xx_is_tstamp(sts_data[1]))
data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE; data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE;
else else
...@@ -1700,7 +1715,14 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter, ...@@ -1700,7 +1715,14 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,
skb_put(skb, lro_length + data_offset); skb_put(skb, lro_length + data_offset);
skb_pull(skb, l2_hdr_offset); skb_pull(skb, l2_hdr_offset);
if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { err = qlcnic_check_rx_tagging(adapter, skb, &vid);
if (adapter->rx_mac_learn) {
is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1);
qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, vid);
}
if (unlikely(err)) {
adapter->stats.rxdropped++; adapter->stats.rxdropped++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
return buffer; return buffer;
......
...@@ -546,6 +546,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { ...@@ -546,6 +546,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
.io_error_detected = qlcnic_82xx_io_error_detected, .io_error_detected = qlcnic_82xx_io_error_detected,
.io_slot_reset = qlcnic_82xx_io_slot_reset, .io_slot_reset = qlcnic_82xx_io_slot_reset,
.io_resume = qlcnic_82xx_io_resume, .io_resume = qlcnic_82xx_io_resume,
.get_beacon_state = qlcnic_82xx_get_beacon_state,
}; };
static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter) static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
......
...@@ -277,9 +277,7 @@ static void qlcnic_sriov_vf_cleanup(struct qlcnic_adapter *adapter) ...@@ -277,9 +277,7 @@ 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 (!test_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state))
if (!sriov)
return; return;
qlcnic_sriov_free_vlans(adapter); qlcnic_sriov_free_vlans(adapter);
......
...@@ -9,9 +9,14 @@ ...@@ -9,9 +9,14 @@
#include "qlcnic.h" #include "qlcnic.h"
#include <linux/types.h> #include <linux/types.h>
#define QLCNIC_SRIOV_VF_MAX_MAC 8 #define QLCNIC_SRIOV_VF_MAX_MAC 7
#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
#define QLC_MAC_OPCODE_MASK 0x7
#define QLC_MAC_STAR_ADD 6
#define QLC_MAC_STAR_DEL 7
#define QLC_VF_FLOOD_BIT BIT_16
#define QLC_FLOOD_MODE 0x5
static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8); static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8);
...@@ -344,6 +349,28 @@ static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter, ...@@ -344,6 +349,28 @@ static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter,
return err; return err;
} }
/* On configuring VF flood bit, PFD will receive traffic from all VFs */
static int qlcnic_sriov_pf_cfg_flood(struct qlcnic_adapter *adapter)
{
struct qlcnic_cmd_args cmd;
int err;
err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
if (err)
return err;
cmd.req.arg[1] = QLC_FLOOD_MODE | QLC_VF_FLOOD_BIT;
err = qlcnic_issue_cmd(adapter, &cmd);
if (err)
dev_err(&adapter->pdev->dev,
"Failed to configure VF Flood bit on PF, err=%d\n",
err);
qlcnic_free_mbx_args(&cmd);
return err;
}
static int qlcnic_sriov_pf_cfg_eswitch(struct qlcnic_adapter *adapter, static int qlcnic_sriov_pf_cfg_eswitch(struct qlcnic_adapter *adapter,
u8 func, u8 enable) u8 func, u8 enable)
{ {
...@@ -471,6 +498,12 @@ static int qlcnic_sriov_pf_init(struct qlcnic_adapter *adapter) ...@@ -471,6 +498,12 @@ static int qlcnic_sriov_pf_init(struct qlcnic_adapter *adapter)
if (err) if (err)
return err; return err;
if (qlcnic_84xx_check(adapter)) {
err = qlcnic_sriov_pf_cfg_flood(adapter);
if (err)
goto disable_vlan_filtering;
}
err = qlcnic_sriov_pf_cfg_eswitch(adapter, func, 1); err = qlcnic_sriov_pf_cfg_eswitch(adapter, func, 1);
if (err) if (err)
goto disable_vlan_filtering; goto disable_vlan_filtering;
...@@ -1173,6 +1206,13 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter, ...@@ -1173,6 +1206,13 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
struct qlcnic_vport *vp = vf->vp; struct qlcnic_vport *vp = vf->vp;
u8 op, new_op; u8 op, new_op;
if (((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_ADD) ||
((cmd->req.arg[1] & QLC_MAC_OPCODE_MASK) == QLC_MAC_STAR_DEL)) {
netdev_err(adapter->netdev, "MAC + any VLAN filter not allowed from VF %d\n",
vf->pci_func);
return -EINVAL;
}
if (!(cmd->req.arg[1] & BIT_8)) if (!(cmd->req.arg[1] & BIT_8))
return -EINVAL; return -EINVAL;
......
...@@ -126,6 +126,8 @@ static int qlcnic_83xx_store_beacon(struct qlcnic_adapter *adapter, ...@@ -126,6 +126,8 @@ static int qlcnic_83xx_store_beacon(struct qlcnic_adapter *adapter,
if (kstrtoul(buf, 2, &h_beacon)) if (kstrtoul(buf, 2, &h_beacon))
return -EINVAL; return -EINVAL;
qlcnic_get_beacon_state(adapter);
if (ahw->beacon_state == h_beacon) if (ahw->beacon_state == h_beacon)
return len; return len;
...@@ -157,7 +159,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter, ...@@ -157,7 +159,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
int err, drv_sds_rings = adapter->drv_sds_rings; int err, drv_sds_rings = adapter->drv_sds_rings;
u16 beacon; u16 beacon;
u8 h_beacon_state, b_state, b_rate; u8 b_state, b_rate;
if (len != sizeof(u16)) if (len != sizeof(u16))
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
...@@ -167,18 +169,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter, ...@@ -167,18 +169,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
if (err) if (err)
return err; return err;
if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) { qlcnic_get_beacon_state(adapter);
err = qlcnic_get_beacon_state(adapter, &h_beacon_state);
if (err) {
netdev_err(adapter->netdev,
"Failed to get current beacon state\n");
} else {
if (h_beacon_state == QLCNIC_BEACON_DISABLE)
ahw->beacon_state = 0;
else if (h_beacon_state == QLCNIC_BEACON_EANBLE)
ahw->beacon_state = 2;
}
}
if (ahw->beacon_state == b_state) if (ahw->beacon_state == b_state)
return len; return len;
......
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