Skip to content

Commit 91b7282

Browse files
Rajesh Borundiadavem330
authored andcommitted
qlcnic: Support VLAN id config.
o Add support for VLAN id configuration per VF using iproute2 tool. o VLAN id's 1-4094 are treated as PVID by the PF and Guest VLAN tagging is not allowed by default. o PVID is disabled when the VLAN id is set to 0 o Guest VLAN tagging is allowed when the VLAN id is set to 4095. o Only one Guest VLAN id is supported. o VLAN id can be changed only when the VF driver is not loaded. Signed-off-by: Manish Chopra <[email protected]> Signed-off-by: Sucheta Chakraborty <[email protected]> Signed-off-by: Rajesh Borundia <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4000e7a commit 91b7282

File tree

8 files changed

+492
-29
lines changed

8 files changed

+492
-29
lines changed

drivers/net/ethernet/qlogic/qlcnic/qlcnic.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,8 @@ struct qlcnic_adapter {
979979
u8 reset_ctx_cnt;
980980

981981
u16 is_up;
982-
u16 pvid;
982+
u16 rx_pvid;
983+
u16 tx_pvid;
983984

984985
u32 irq;
985986
u32 heartbeat;
@@ -1445,10 +1446,10 @@ void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
14451446
struct qlcnic_host_rds_ring *rds_ring, u8 ring_id);
14461447
int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max);
14471448
void qlcnic_set_multi(struct net_device *netdev);
1448-
void __qlcnic_set_multi(struct net_device *netdev);
1449-
int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *);
1449+
void __qlcnic_set_multi(struct net_device *, u16);
1450+
int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *, u16);
14501451
int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *);
1451-
void qlcnic_free_mac_list(struct qlcnic_adapter *adapter);
1452+
void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter);
14521453

14531454
int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
14541455
int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *);
@@ -1530,7 +1531,7 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
15301531
int qlcnic_read_mac_addr(struct qlcnic_adapter *);
15311532
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
15321533
void qlcnic_sriov_vf_schedule_multi(struct net_device *);
1533-
void qlcnic_vf_add_mc_list(struct net_device *);
1534+
void qlcnic_vf_add_mc_list(struct net_device *, u16);
15341535

15351536
/*
15361537
* QLOGIC Board information
@@ -1606,6 +1607,7 @@ struct qlcnic_hardware_ops {
16061607
int (*config_promisc_mode) (struct qlcnic_adapter *, u32);
16071608
void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, u16);
16081609
int (*get_board_info) (struct qlcnic_adapter *);
1610+
void (*free_mac_list) (struct qlcnic_adapter *);
16091611
};
16101612

16111613
extern struct qlcnic_nic_template qlcnic_vf_ops;
@@ -1815,6 +1817,11 @@ static inline int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
18151817
return adapter->ahw->hw_ops->get_board_info(adapter);
18161818
}
18171819

1820+
static inline void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
1821+
{
1822+
return adapter->ahw->hw_ops->free_mac_list(adapter);
1823+
}
1824+
18181825
static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter,
18191826
u32 key)
18201827
{

drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
172172
.config_promisc_mode = qlcnic_83xx_nic_set_promisc,
173173
.change_l2_filter = qlcnic_83xx_change_l2_filter,
174174
.get_board_info = qlcnic_83xx_get_port_info,
175+
.free_mac_list = qlcnic_82xx_free_mac_list,
175176
};
176177

177178
static struct qlcnic_nic_template qlcnic_83xx_ops = {
@@ -1797,6 +1798,10 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
17971798
if (err)
17981799
return err;
17991800

1801+
if (vlan_id)
1802+
op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
1803+
QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL;
1804+
18001805
cmd.req.arg[1] = op | (1 << 8);
18011806
qlcnic_83xx_set_interface_id_macaddr(adapter, &temp);
18021807
cmd.req.arg[1] |= temp;

drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr)
468468
return err;
469469
}
470470

471-
int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
471+
int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
472472
{
473473
struct list_head *head;
474474
struct qlcnic_mac_list_s *cur;
@@ -487,7 +487,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
487487
memcpy(cur->mac_addr, addr, ETH_ALEN);
488488

489489
if (qlcnic_sre_macaddr_change(adapter,
490-
cur->mac_addr, 0, QLCNIC_MAC_ADD)) {
490+
cur->mac_addr, vlan, QLCNIC_MAC_ADD)) {
491491
kfree(cur);
492492
return -EIO;
493493
}
@@ -496,7 +496,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr)
496496
return 0;
497497
}
498498

499-
void __qlcnic_set_multi(struct net_device *netdev)
499+
void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
500500
{
501501
struct qlcnic_adapter *adapter = netdev_priv(netdev);
502502
struct netdev_hw_addr *ha;
@@ -509,8 +509,8 @@ void __qlcnic_set_multi(struct net_device *netdev)
509509
return;
510510

511511
if (!qlcnic_sriov_vf_check(adapter))
512-
qlcnic_nic_add_mac(adapter, adapter->mac_addr);
513-
qlcnic_nic_add_mac(adapter, bcast_addr);
512+
qlcnic_nic_add_mac(adapter, adapter->mac_addr, vlan);
513+
qlcnic_nic_add_mac(adapter, bcast_addr, vlan);
514514

515515
if (netdev->flags & IFF_PROMISC) {
516516
if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
@@ -526,12 +526,12 @@ void __qlcnic_set_multi(struct net_device *netdev)
526526

527527
if (!netdev_mc_empty(netdev) && !qlcnic_sriov_vf_check(adapter)) {
528528
netdev_for_each_mc_addr(ha, netdev) {
529-
qlcnic_nic_add_mac(adapter, ha->addr);
529+
qlcnic_nic_add_mac(adapter, ha->addr, vlan);
530530
}
531531
}
532532

533533
if (qlcnic_sriov_vf_check(adapter))
534-
qlcnic_vf_add_mc_list(netdev);
534+
qlcnic_vf_add_mc_list(netdev, vlan);
535535

536536
send_fw_cmd:
537537
if (!qlcnic_sriov_vf_check(adapter)) {
@@ -570,7 +570,7 @@ void qlcnic_set_multi(struct net_device *netdev)
570570
qlcnic_sriov_vf_schedule_multi(adapter->netdev);
571571
return;
572572
}
573-
__qlcnic_set_multi(netdev);
573+
__qlcnic_set_multi(netdev, 0);
574574
}
575575

576576
int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
@@ -592,7 +592,7 @@ int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
592592
(struct cmd_desc_type0 *)&req, 1);
593593
}
594594

595-
void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
595+
void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter)
596596
{
597597
struct qlcnic_mac_list_s *cur;
598598
struct list_head *head = &adapter->mac_list;

drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,14 +344,14 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
344344
flags = FLAGS_VLAN_OOB;
345345
vlan_tci = vlan_tx_tag_get(skb);
346346
}
347-
if (unlikely(adapter->pvid)) {
347+
if (unlikely(adapter->tx_pvid)) {
348348
if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
349349
return -EIO;
350350
if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
351351
goto set_flags;
352352

353353
flags = FLAGS_VLAN_OOB;
354-
vlan_tci = adapter->pvid;
354+
vlan_tci = adapter->tx_pvid;
355355
}
356356
set_flags:
357357
qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
@@ -980,10 +980,10 @@ static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter,
980980
memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
981981
skb_pull(skb, VLAN_HLEN);
982982
}
983-
if (!adapter->pvid)
983+
if (!adapter->rx_pvid)
984984
return 0;
985985

986-
if (*vlan_tag == adapter->pvid) {
986+
if (*vlan_tag == adapter->rx_pvid) {
987987
/* Outer vlan tag. Packet should follow non-vlan path */
988988
*vlan_tag = 0xffff;
989989
return 0;

drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
290290
return err;
291291

292292
if (is_unicast_ether_addr(addr))
293-
err = qlcnic_nic_add_mac(adapter, addr);
293+
err = qlcnic_nic_add_mac(adapter, addr, 0);
294294
else if (is_multicast_ether_addr(addr))
295295
err = dev_mc_add_excl(netdev, addr);
296296
else
@@ -345,6 +345,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
345345
.ndo_set_vf_mac = qlcnic_sriov_set_vf_mac,
346346
.ndo_set_vf_tx_rate = qlcnic_sriov_set_vf_tx_rate,
347347
.ndo_get_vf_config = qlcnic_sriov_get_vf_config,
348+
.ndo_set_vf_vlan = qlcnic_sriov_set_vf_vlan,
348349
#endif
349350
};
350351

@@ -404,6 +405,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
404405
.config_promisc_mode = qlcnic_82xx_nic_set_promisc,
405406
.change_l2_filter = qlcnic_82xx_change_filter,
406407
.get_board_info = qlcnic_82xx_get_board_info,
408+
.free_mac_list = qlcnic_82xx_free_mac_list,
407409
};
408410

409411
int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
@@ -900,16 +902,31 @@ void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
900902
else
901903
adapter->flags |= QLCNIC_TAGGING_ENABLED;
902904

903-
if (esw_cfg->vlan_id)
904-
adapter->pvid = esw_cfg->vlan_id;
905-
else
906-
adapter->pvid = 0;
905+
if (esw_cfg->vlan_id) {
906+
adapter->rx_pvid = esw_cfg->vlan_id;
907+
adapter->tx_pvid = esw_cfg->vlan_id;
908+
} else {
909+
adapter->rx_pvid = 0;
910+
adapter->tx_pvid = 0;
911+
}
907912
}
908913

909914
static int
910915
qlcnic_vlan_rx_add(struct net_device *netdev, __be16 proto, u16 vid)
911916
{
912917
struct qlcnic_adapter *adapter = netdev_priv(netdev);
918+
int err;
919+
920+
if (qlcnic_sriov_vf_check(adapter)) {
921+
err = qlcnic_sriov_cfg_vf_guest_vlan(adapter, vid, 1);
922+
if (err) {
923+
netdev_err(netdev,
924+
"Cannot add VLAN filter for VLAN id %d, err=%d",
925+
vid, err);
926+
return err;
927+
}
928+
}
929+
913930
set_bit(vid, adapter->vlans);
914931
return 0;
915932
}
@@ -918,6 +935,17 @@ static int
918935
qlcnic_vlan_rx_del(struct net_device *netdev, __be16 proto, u16 vid)
919936
{
920937
struct qlcnic_adapter *adapter = netdev_priv(netdev);
938+
int err;
939+
940+
if (qlcnic_sriov_vf_check(adapter)) {
941+
err = qlcnic_sriov_cfg_vf_guest_vlan(adapter, vid, 0);
942+
if (err) {
943+
netdev_err(netdev,
944+
"Cannot delete VLAN filter for VLAN id %d, err=%d",
945+
vid, err);
946+
return err;
947+
}
948+
}
921949

922950
qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
923951
clear_bit(vid, adapter->vlans);
@@ -1736,6 +1764,9 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
17361764
if (qlcnic_vlan_tx_check(adapter))
17371765
netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX);
17381766

1767+
if (qlcnic_sriov_vf_check(adapter))
1768+
netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
1769+
17391770
if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
17401771
netdev->features |= NETIF_F_LRO;
17411772

drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ struct qlcnic_bc_hdr {
4848
enum qlcnic_bc_commands {
4949
QLCNIC_BC_CMD_CHANNEL_INIT = 0x0,
5050
QLCNIC_BC_CMD_CHANNEL_TERM = 0x1,
51+
QLCNIC_BC_CMD_GET_ACL = 0x2,
52+
QLCNIC_BC_CMD_CFG_GUEST_VLAN = 0x3,
5153
};
5254

5355
#define QLC_BC_CMD 1
@@ -95,6 +97,12 @@ enum qlcnic_vf_state {
9597
QLC_BC_VF_SOFT_FLR,
9698
};
9799

100+
enum qlcnic_vlan_mode {
101+
QLC_NO_VLAN_MODE = 0,
102+
QLC_PVID_MODE,
103+
QLC_GUEST_VLAN_MODE,
104+
};
105+
98106
struct qlcnic_resources {
99107
u16 num_tx_mac_filters;
100108
u16 num_rx_ucast_mac_filters;
@@ -118,6 +126,9 @@ struct qlcnic_vport {
118126
u16 handle;
119127
u16 max_tx_bw;
120128
u16 min_tx_bw;
129+
u8 vlan_mode;
130+
u16 vlan;
131+
u8 qos;
121132
u8 mac[6];
122133
};
123134

@@ -156,6 +167,11 @@ struct qlcnic_back_channel {
156167
struct qlcnic_sriov {
157168
u16 vp_handle;
158169
u8 num_vfs;
170+
u8 any_vlan;
171+
u8 vlan_mode;
172+
u16 num_allowed_vlans;
173+
u16 *allowed_vlans;
174+
u16 vlan;
159175
struct qlcnic_resources ff_max;
160176
struct qlcnic_back_channel bc;
161177
struct qlcnic_vf_info *vf_info;
@@ -177,6 +193,7 @@ int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *, struct qlcnic_vf_info *,
177193
struct qlcnic_bc_trans *);
178194
int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *,
179195
struct qlcnic_info *, u16);
196+
int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8);
180197

181198
static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter)
182199
{
@@ -207,6 +224,7 @@ int qlcnic_sriov_set_vf_mac(struct net_device *, int, u8 *);
207224
int qlcnic_sriov_set_vf_tx_rate(struct net_device *, int, int);
208225
int qlcnic_sriov_get_vf_config(struct net_device *, int ,
209226
struct ifla_vf_info *);
227+
int qlcnic_sriov_set_vf_vlan(struct net_device *, int, u16, u8);
210228
#else
211229
static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
212230
static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}

0 commit comments

Comments
 (0)