aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Borundia <rajesh.borundia@qlogic.com>2014-05-09 02:51:31 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-09 13:08:58 -0400
commitd747c3337484afac9953c44ea56a912869778559 (patch)
tree02a4b3c00eee7fc0e50b60ced8e170643fa0e7de
parent74b7ba1a8bc994f92cfe4716d80c17f90df5eba3 (diff)
qlcnic: Add mac learning support to SR-IOV VF.
o SR-IOV VF can be uplinked to bridge/macvtap device. Enable mac learning to support communication through embedded switch. o Learn vlan filters based on QLCNIC_VLAN_FILTERING flag. Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h12
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c12
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c16
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c51
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c14
6 files changed, 78 insertions, 28 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 7bad613becba..557b911a89f8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1019,6 +1019,8 @@ struct qlcnic_ipaddr {
1019#define QLCNIC_DEL_VXLAN_PORT 0x200000 1019#define QLCNIC_DEL_VXLAN_PORT 0x200000
1020#endif 1020#endif
1021 1021
1022#define QLCNIC_VLAN_FILTERING 0x800000
1023
1022#define QLCNIC_IS_MSI_FAMILY(adapter) \ 1024#define QLCNIC_IS_MSI_FAMILY(adapter) \
1023 ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) 1025 ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
1024#define QLCNIC_IS_TSO_CAPABLE(adapter) \ 1026#define QLCNIC_IS_TSO_CAPABLE(adapter) \
@@ -2355,6 +2357,16 @@ static inline bool qlcnic_83xx_vf_check(struct qlcnic_adapter *adapter)
2355 return (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X) ? true : false; 2357 return (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X) ? true : false;
2356} 2358}
2357 2359
2360static inline bool qlcnic_sriov_check(struct qlcnic_adapter *adapter)
2361{
2362 bool status;
2363
2364 status = (qlcnic_sriov_pf_check(adapter) ||
2365 qlcnic_sriov_vf_check(adapter)) ? true : false;
2366
2367 return status;
2368}
2369
2358static inline u32 qlcnic_get_vnic_func_count(struct qlcnic_adapter *adapter) 2370static inline u32 qlcnic_get_vnic_func_count(struct qlcnic_adapter *adapter)
2359{ 2371{
2360 if (qlcnic_84xx_check(adapter)) 2372 if (qlcnic_84xx_check(adapter))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index deb2278b48d5..e45bf09af0c9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -313,20 +313,16 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
313 u16 vlan_id = 0; 313 u16 vlan_id = 0;
314 u8 hindex, hval; 314 u8 hindex, hval;
315 315
316 if (!qlcnic_sriov_pf_check(adapter)) { 316 if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
317 if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) 317 return;
318 return; 318
319 } else { 319 if (adapter->flags & QLCNIC_VLAN_FILTERING) {
320 if (protocol == ETH_P_8021Q) { 320 if (protocol == ETH_P_8021Q) {
321 vh = (struct vlan_ethhdr *)skb->data; 321 vh = (struct vlan_ethhdr *)skb->data;
322 vlan_id = ntohs(vh->h_vlan_TCI); 322 vlan_id = ntohs(vh->h_vlan_TCI);
323 } else if (vlan_tx_tag_present(skb)) { 323 } else if (vlan_tx_tag_present(skb)) {
324 vlan_id = vlan_tx_tag_get(skb); 324 vlan_id = vlan_tx_tag_get(skb);
325 } 325 }
326
327 if (ether_addr_equal(phdr->h_source, adapter->mac_addr) &&
328 !vlan_id)
329 return;
330 } 326 }
331 327
332 memcpy(&src_addr, phdr->h_source, ETH_ALEN); 328 memcpy(&src_addr, phdr->h_source, ETH_ALEN);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 1a52a781401f..8a570fa3542b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -378,7 +378,8 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
378 if (!adapter->fdb_mac_learn) 378 if (!adapter->fdb_mac_learn)
379 return ndo_dflt_fdb_del(ndm, tb, netdev, addr); 379 return ndo_dflt_fdb_del(ndm, tb, netdev, addr);
380 380
381 if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { 381 if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
382 qlcnic_sriov_check(adapter)) {
382 if (is_unicast_ether_addr(addr)) { 383 if (is_unicast_ether_addr(addr)) {
383 err = dev_uc_del(netdev, addr); 384 err = dev_uc_del(netdev, addr);
384 if (!err) 385 if (!err)
@@ -402,7 +403,8 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
402 if (!adapter->fdb_mac_learn) 403 if (!adapter->fdb_mac_learn)
403 return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags); 404 return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags);
404 405
405 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) { 406 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) &&
407 !qlcnic_sriov_check(adapter)) {
406 pr_info("%s: FDB e-switch is not enabled\n", __func__); 408 pr_info("%s: FDB e-switch is not enabled\n", __func__);
407 return -EOPNOTSUPP; 409 return -EOPNOTSUPP;
408 } 410 }
@@ -432,7 +434,8 @@ static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,
432 if (!adapter->fdb_mac_learn) 434 if (!adapter->fdb_mac_learn)
433 return ndo_dflt_fdb_dump(skb, ncb, netdev, idx); 435 return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
434 436
435 if (adapter->flags & QLCNIC_ESWITCH_ENABLED) 437 if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
438 qlcnic_sriov_check(adapter))
436 idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx); 439 idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx);
437 440
438 return idx; 441 return idx;
@@ -2809,6 +2812,8 @@ static int qlcnic_close(struct net_device *netdev)
2809 return 0; 2812 return 0;
2810} 2813}
2811 2814
2815#define QLCNIC_VF_LB_BUCKET_SIZE 1
2816
2812void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter) 2817void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
2813{ 2818{
2814 void *head; 2819 void *head;
@@ -2824,7 +2829,10 @@ void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
2824 spin_lock_init(&adapter->mac_learn_lock); 2829 spin_lock_init(&adapter->mac_learn_lock);
2825 spin_lock_init(&adapter->rx_mac_learn_lock); 2830 spin_lock_init(&adapter->rx_mac_learn_lock);
2826 2831
2827 if (qlcnic_82xx_check(adapter)) { 2832 if (qlcnic_sriov_vf_check(adapter)) {
2833 filter_size = QLCNIC_83XX_SRIOV_VF_MAX_MAC - 1;
2834 adapter->fhash.fbucket_size = QLCNIC_VF_LB_BUCKET_SIZE;
2835 } else if (qlcnic_82xx_check(adapter)) {
2828 filter_size = QLCNIC_LB_MAX_FILTERS; 2836 filter_size = QLCNIC_LB_MAX_FILTERS;
2829 adapter->fhash.fbucket_size = QLCNIC_LB_BUCKET_SIZE; 2837 adapter->fhash.fbucket_size = QLCNIC_LB_BUCKET_SIZE;
2830 } else { 2838 } else {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
index 54159bde2bc7..335b50f7bd3e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
@@ -52,6 +52,7 @@ enum qlcnic_bc_commands {
52 QLCNIC_BC_CMD_CFG_GUEST_VLAN = 0x3, 52 QLCNIC_BC_CMD_CFG_GUEST_VLAN = 0x3,
53}; 53};
54 54
55#define QLCNIC_83XX_SRIOV_VF_MAX_MAC 2
55#define QLC_BC_CMD 1 56#define QLC_BC_CMD 1
56 57
57struct qlcnic_trans_list { 58struct qlcnic_trans_list {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index 44cd5bd03744..3b39ab2ad5e9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -199,6 +199,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
199 goto qlcnic_destroy_async_wq; 199 goto qlcnic_destroy_async_wq;
200 } 200 }
201 sriov->vf_info[i].vp = vp; 201 sriov->vf_info[i].vp = vp;
202 vp->vlan_mode = QLC_GUEST_VLAN_MODE;
202 vp->max_tx_bw = MAX_BW; 203 vp->max_tx_bw = MAX_BW;
203 vp->spoofchk = false; 204 vp->spoofchk = false;
204 random_ether_addr(vp->mac); 205 random_ether_addr(vp->mac);
@@ -517,6 +518,8 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
517{ 518{
518 int err; 519 int err;
519 520
521 adapter->flags |= QLCNIC_VLAN_FILTERING;
522 adapter->ahw->total_nic_func = 1;
520 INIT_LIST_HEAD(&adapter->vf_mc_list); 523 INIT_LIST_HEAD(&adapter->vf_mc_list);
521 if (!qlcnic_use_msi_x && !!qlcnic_use_msi) 524 if (!qlcnic_use_msi_x && !!qlcnic_use_msi)
522 dev_warn(&adapter->pdev->dev, 525 dev_warn(&adapter->pdev->dev,
@@ -772,6 +775,7 @@ static int qlcnic_sriov_prepare_bc_hdr(struct qlcnic_bc_trans *trans,
772 cmd->req.arg = (u32 *)trans->req_pay; 775 cmd->req.arg = (u32 *)trans->req_pay;
773 cmd->rsp.arg = (u32 *)trans->rsp_pay; 776 cmd->rsp.arg = (u32 *)trans->rsp_pay;
774 cmd_op = cmd->req.arg[0] & 0xff; 777 cmd_op = cmd->req.arg[0] & 0xff;
778 cmd->cmd_op = cmd_op;
775 remainder = (trans->rsp_pay_size) % (bc_pay_sz); 779 remainder = (trans->rsp_pay_size) % (bc_pay_sz);
776 num_frags = (trans->rsp_pay_size) / (bc_pay_sz); 780 num_frags = (trans->rsp_pay_size) / (bc_pay_sz);
777 if (remainder) 781 if (remainder)
@@ -1410,12 +1414,17 @@ retry:
1410 (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) { 1414 (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) {
1411 rsp = QLCNIC_RCODE_SUCCESS; 1415 rsp = QLCNIC_RCODE_SUCCESS;
1412 } else { 1416 } else {
1413 rsp = mbx_err_code; 1417 if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) {
1414 if (!rsp) 1418 rsp = QLCNIC_RCODE_SUCCESS;
1415 rsp = 1; 1419 } else {
1416 dev_err(dev, 1420 rsp = mbx_err_code;
1417 "MBX command 0x%x failed with err:0x%x for VF %d\n", 1421 if (!rsp)
1418 opcode, mbx_err_code, func); 1422 rsp = 1;
1423
1424 dev_err(dev,
1425 "MBX command 0x%x failed with err:0x%x for VF %d\n",
1426 opcode, mbx_err_code, func);
1427 }
1419 } 1428 }
1420 1429
1421err_out: 1430err_out:
@@ -1537,6 +1546,28 @@ void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
1537 } 1546 }
1538 } 1547 }
1539 1548
1549 /* configure unicast MAC address, if there is not sufficient space
1550 * to store all the unicast addresses then enable promiscuous mode
1551 */
1552 if (netdev_uc_count(netdev) > ahw->max_uc_count) {
1553 mode = VPORT_MISS_MODE_ACCEPT_ALL;
1554 } else if (!netdev_uc_empty(netdev)) {
1555 netdev_for_each_uc_addr(ha, netdev)
1556 qlcnic_vf_add_mc_list(netdev, ha->addr);
1557 }
1558
1559 if (adapter->pdev->is_virtfn) {
1560 if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
1561 !adapter->fdb_mac_learn) {
1562 qlcnic_alloc_lb_filters_mem(adapter);
1563 adapter->drv_mac_learn = 1;
1564 adapter->rx_mac_learn = true;
1565 } else {
1566 adapter->drv_mac_learn = 0;
1567 adapter->rx_mac_learn = false;
1568 }
1569 }
1570
1540 qlcnic_nic_set_promisc(adapter, mode); 1571 qlcnic_nic_set_promisc(adapter, mode);
1541} 1572}
1542 1573
@@ -1830,6 +1861,12 @@ static int qlcnic_sriov_vf_idc_unknown_state(struct qlcnic_adapter *adapter)
1830 return 0; 1861 return 0;
1831} 1862}
1832 1863
1864static void qlcnic_sriov_vf_periodic_tasks(struct qlcnic_adapter *adapter)
1865{
1866 if (adapter->fhash.fnum)
1867 qlcnic_prune_lb_filters(adapter);
1868}
1869
1833static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *work) 1870static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *work)
1834{ 1871{
1835 struct qlcnic_adapter *adapter; 1872 struct qlcnic_adapter *adapter;
@@ -1861,6 +1898,8 @@ static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *work)
1861 } 1898 }
1862 1899
1863 idc->prev_state = idc->curr_state; 1900 idc->prev_state = idc->curr_state;
1901 qlcnic_sriov_vf_periodic_tasks(adapter);
1902
1864 if (!ret && test_bit(QLC_83XX_MODULE_LOADED, &idc->status)) 1903 if (!ret && test_bit(QLC_83XX_MODULE_LOADED, &idc->status))
1865 qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, 1904 qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state,
1866 idc->delay); 1905 idc->delay);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
index 199ab7c6fbad..6d2f72f114f2 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
@@ -84,7 +84,7 @@ static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
84 info->max_tx_ques = res->num_tx_queues / max; 84 info->max_tx_ques = res->num_tx_queues / max;
85 85
86 if (qlcnic_83xx_pf_check(adapter)) 86 if (qlcnic_83xx_pf_check(adapter))
87 num_macs = 1; 87 num_macs = QLCNIC_83XX_SRIOV_VF_MAX_MAC;
88 88
89 info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters; 89 info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
90 90
@@ -338,9 +338,12 @@ static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter,
338 338
339 cmd.req.arg[1] = 0x4; 339 cmd.req.arg[1] = 0x4;
340 if (enable) { 340 if (enable) {
341 adapter->flags |= QLCNIC_VLAN_FILTERING;
341 cmd.req.arg[1] |= BIT_16; 342 cmd.req.arg[1] |= BIT_16;
342 if (qlcnic_84xx_check(adapter)) 343 if (qlcnic_84xx_check(adapter))
343 cmd.req.arg[1] |= QLC_SRIOV_ALLOW_VLAN0; 344 cmd.req.arg[1] |= QLC_SRIOV_ALLOW_VLAN0;
345 } else {
346 adapter->flags &= ~QLCNIC_VLAN_FILTERING;
344 } 347 }
345 348
346 err = qlcnic_issue_cmd(adapter, &cmd); 349 err = qlcnic_issue_cmd(adapter, &cmd);
@@ -1253,7 +1256,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
1253 struct qlcnic_vf_info *vf, 1256 struct qlcnic_vf_info *vf,
1254 struct qlcnic_cmd_args *cmd) 1257 struct qlcnic_cmd_args *cmd)
1255{ 1258{
1256 struct qlcnic_macvlan_mbx *macvlan;
1257 struct qlcnic_vport *vp = vf->vp; 1259 struct qlcnic_vport *vp = vf->vp;
1258 u8 op, new_op; 1260 u8 op, new_op;
1259 1261
@@ -1263,14 +1265,6 @@ static int qlcnic_sriov_validate_cfg_macvlan(struct qlcnic_adapter *adapter,
1263 cmd->req.arg[1] |= (vf->vp->handle << 16); 1265 cmd->req.arg[1] |= (vf->vp->handle << 16);
1264 cmd->req.arg[1] |= BIT_31; 1266 cmd->req.arg[1] |= BIT_31;
1265 1267
1266 macvlan = (struct qlcnic_macvlan_mbx *)&cmd->req.arg[2];
1267 if (!(macvlan->mac_addr0 & BIT_0)) {
1268 dev_err(&adapter->pdev->dev,
1269 "MAC address change is not allowed from VF %d",
1270 vf->pci_func);
1271 return -EINVAL;
1272 }
1273
1274 if (vp->vlan_mode == QLC_PVID_MODE) { 1268 if (vp->vlan_mode == QLC_PVID_MODE) {
1275 op = cmd->req.arg[1] & 0x7; 1269 op = cmd->req.arg[1] & 0x7;
1276 cmd->req.arg[1] &= ~0x7; 1270 cmd->req.arg[1] &= ~0x7;