Skip to content

Commit

Permalink
qlcnic: VLAN enhancement for 84XX adapters
Browse files Browse the repository at this point in the history
o Support multiple VLANs on 84xx VF devices

Signed-off-by: Manish Chopra <manish.chopra@qlogic.com>
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Manish Chopra authored and davem330 committed Dec 17, 2013
1 parent 80c0e4f commit 154d0c8
Show file tree
Hide file tree
Showing 8 changed files with 407 additions and 112 deletions.
18 changes: 16 additions & 2 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -788,9 +788,10 @@ struct qlcnic_cardrsp_tx_ctx {
#define QLCNIC_MAC_VLAN_ADD 3
#define QLCNIC_MAC_VLAN_DEL 4

struct qlcnic_mac_list_s {
struct qlcnic_mac_vlan_list {
struct list_head list;
uint8_t mac_addr[ETH_ALEN+2];
u16 vlan_id;
};

/* MAC Learn */
Expand Down Expand Up @@ -1637,7 +1638,6 @@ int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
void qlcnic_set_netdev_features(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
void qlcnic_sriov_vf_schedule_multi(struct net_device *);
void qlcnic_vf_add_mc_list(struct net_device *, u16);

/*
* QLOGIC Board information
Expand Down Expand Up @@ -2136,4 +2136,18 @@ static inline bool qlcnic_sriov_vf_check(struct qlcnic_adapter *adapter)

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;
}
#endif /* __QLCNIC_H_ */
2 changes: 1 addition & 1 deletion drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1637,7 +1637,7 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)

cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
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);
if (!err)
return err;
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,11 @@ struct qlc_83xx_idc {
char **name;
};

enum qlcnic_vlan_operations {
QLC_VLAN_ADD = 0,
QLC_VLAN_DELETE
};

/* Device States */
enum qlcnic_83xx_states {
QLC_83XX_IDC_DEV_UNKNOWN,
Expand Down
48 changes: 22 additions & 26 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct qlcnic_mac_vlan_list *cur;
struct list_head *head;
struct qlcnic_mac_list_s *cur;
int err = -EINVAL;

/* Delete MAC from the existing 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) {
err = qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
0, QLCNIC_MAC_DEL);
Expand All @@ -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)
{
struct qlcnic_mac_vlan_list *cur;
struct list_head *head;
struct qlcnic_mac_list_s *cur;

/* look up if already exists */
list_for_each(head, &adapter->mac_list) {
cur = list_entry(head, struct qlcnic_mac_list_s, list);
if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
cur = list_entry(head, struct qlcnic_mac_vlan_list, list);
if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0 &&
cur->vlan_id == vlan)
return 0;
}

cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC);
cur = kzalloc(sizeof(*cur), GFP_ATOMIC);
if (cur == NULL)
return -ENOMEM;

Expand All @@ -499,6 +500,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
return -EIO;
}

cur->vlan_id = vlan;
list_add_tail(&cur->list, &adapter->mac_list);
return 0;
}
Expand All @@ -516,8 +518,7 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
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);

if (netdev->flags & IFF_PROMISC) {
Expand All @@ -526,15 +527,11 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
} else if ((netdev->flags & IFF_ALLMULTI) ||
(netdev_mc_count(netdev) > ahw->max_mc_count)) {
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
} else if (!netdev_mc_empty(netdev) &&
!qlcnic_sriov_vf_check(adapter)) {
} else if (!netdev_mc_empty(netdev)) {
netdev_for_each_mc_addr(ha, netdev)
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
* to store all the unicast addresses then enable promiscuous mode
*/
Expand All @@ -545,14 +542,12 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
qlcnic_nic_add_mac(adapter, ha->addr, vlan);
}

if (!qlcnic_sriov_vf_check(adapter)) {
if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
!adapter->fdb_mac_learn) {
qlcnic_alloc_lb_filters_mem(adapter);
adapter->drv_mac_learn = true;
} else {
adapter->drv_mac_learn = false;
}
if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
!adapter->fdb_mac_learn) {
qlcnic_alloc_lb_filters_mem(adapter);
adapter->drv_mac_learn = 1;
} else {
adapter->drv_mac_learn = 0;
}

qlcnic_nic_set_promisc(adapter, mode);
Expand All @@ -561,16 +556,17 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
void qlcnic_set_multi(struct net_device *netdev)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct qlcnic_mac_vlan_list *cur;
struct netdev_hw_addr *ha;
struct qlcnic_mac_list_s *cur;
size_t temp;

if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
return;
if (qlcnic_sriov_vf_check(adapter)) {
if (!netdev_mc_empty(netdev)) {
netdev_for_each_mc_addr(ha, netdev) {
cur = kzalloc(sizeof(struct qlcnic_mac_list_s),
GFP_ATOMIC);
temp = sizeof(struct qlcnic_mac_vlan_list);
cur = kzalloc(temp, GFP_ATOMIC);
if (cur == NULL)
break;
memcpy(cur->mac_addr,
Expand Down Expand Up @@ -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)
{
struct qlcnic_mac_list_s *cur;
struct list_head *head = &adapter->mac_list;
struct qlcnic_mac_vlan_list *cur;

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, 0, QLCNIC_MAC_DEL);
list_del(&cur->list);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,11 @@ int qlcnic_read_mac_addr(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;

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)) {
qlcnic_sre_macaddr_change(adapter, cur->mac_addr,
0, QLCNIC_MAC_DEL);
Expand Down
12 changes: 11 additions & 1 deletion drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ struct qlcnic_vport {
u16 handle;
u16 max_tx_bw;
u16 min_tx_bw;
u16 pvid;
u8 vlan_mode;
u16 vlan;
u8 qos;
bool spoofchk;
u8 mac[6];
Expand All @@ -137,6 +137,8 @@ struct qlcnic_vf_info {
u8 pci_func;
u16 rx_ctx_id;
u16 tx_ctx_id;
u16 *sriov_vlans;
int num_vlan;
unsigned long state;
struct completion ch_free_cmpl;
struct work_struct trans_work;
Expand All @@ -149,6 +151,7 @@ struct qlcnic_vf_info {
struct qlcnic_trans_list rcv_pend;
struct qlcnic_adapter *adapter;
struct qlcnic_vport *vp;
struct mutex vlan_list_lock; /* Lock for VLAN list */
};

struct qlcnic_async_work_list {
Expand Down Expand Up @@ -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_vf_shutdown(struct pci_dev *);
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)
{
Expand Down

0 comments on commit 154d0c8

Please sign in to comment.