diff options
author | Rajesh Borundia <rajesh.borundia@qlogic.com> | 2014-05-09 02:51:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-09 13:08:57 -0400 |
commit | 74b7ba1a8bc994f92cfe4716d80c17f90df5eba3 (patch) | |
tree | ce5979d71d3c242a0d4d77920dce787f0663f363 | |
parent | 132a3f2bee7600366244097658c4c89ac99a8981 (diff) |
qlcnic: Add support to process commands in atomic context
o Commands from VF may sleep during PF-VF communication.
Earlier we use to process qlcnic_sriov_vf_set_multi
function in process context. Now individual commands
that are called in atomic context are processed in
process context without waiting for completion of
command.
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.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 24 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 137 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 36 |
6 files changed, 99 insertions, 107 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 09fe9c276f1c..7bad613becba 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -1693,7 +1693,7 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *); | |||
1693 | int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); | 1693 | int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); |
1694 | void qlcnic_set_netdev_features(struct qlcnic_adapter *, | 1694 | void qlcnic_set_netdev_features(struct qlcnic_adapter *, |
1695 | struct qlcnic_esw_func_cfg *); | 1695 | struct qlcnic_esw_func_cfg *); |
1696 | void qlcnic_sriov_vf_schedule_multi(struct net_device *); | 1696 | void qlcnic_sriov_vf_set_multi(struct net_device *); |
1697 | int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8); | 1697 | int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8); |
1698 | int qlcnic_get_pci_func_type(struct qlcnic_adapter *, u16, u16 *, u16 *, | 1698 | int qlcnic_get_pci_func_type(struct qlcnic_adapter *, u16, u16 *, u16 *, |
1699 | u16 *); | 1699 | u16 *); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 9f3adf4e70b5..e5352b70314a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
@@ -567,28 +567,14 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) | |||
567 | void qlcnic_set_multi(struct net_device *netdev) | 567 | void qlcnic_set_multi(struct net_device *netdev) |
568 | { | 568 | { |
569 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 569 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
570 | struct qlcnic_mac_vlan_list *cur; | ||
571 | struct netdev_hw_addr *ha; | ||
572 | size_t temp; | ||
573 | 570 | ||
574 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) | 571 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) |
575 | return; | 572 | return; |
576 | if (qlcnic_sriov_vf_check(adapter)) { | 573 | |
577 | if (!netdev_mc_empty(netdev)) { | 574 | if (qlcnic_sriov_vf_check(adapter)) |
578 | netdev_for_each_mc_addr(ha, netdev) { | 575 | qlcnic_sriov_vf_set_multi(netdev); |
579 | temp = sizeof(struct qlcnic_mac_vlan_list); | 576 | else |
580 | cur = kzalloc(temp, GFP_ATOMIC); | 577 | __qlcnic_set_multi(netdev, 0); |
581 | if (cur == NULL) | ||
582 | break; | ||
583 | memcpy(cur->mac_addr, | ||
584 | ha->addr, ETH_ALEN); | ||
585 | list_add_tail(&cur->list, &adapter->vf_mc_list); | ||
586 | } | ||
587 | } | ||
588 | qlcnic_sriov_vf_schedule_multi(adapter->netdev); | ||
589 | return; | ||
590 | } | ||
591 | __qlcnic_set_multi(netdev, 0); | ||
592 | } | 578 | } |
593 | 579 | ||
594 | int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) | 580 | int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 28ebe1ba5a0b..1a52a781401f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -1917,8 +1917,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1917 | if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state)) | 1917 | if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state)) |
1918 | return; | 1918 | return; |
1919 | 1919 | ||
1920 | if (qlcnic_sriov_vf_check(adapter)) | ||
1921 | qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc); | ||
1922 | smp_mb(); | 1920 | smp_mb(); |
1923 | netif_carrier_off(netdev); | 1921 | netif_carrier_off(netdev); |
1924 | adapter->ahw->linkup = 0; | 1922 | adapter->ahw->linkup = 0; |
@@ -1930,6 +1928,8 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1930 | qlcnic_delete_lb_filters(adapter); | 1928 | qlcnic_delete_lb_filters(adapter); |
1931 | 1929 | ||
1932 | qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE); | 1930 | qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE); |
1931 | if (qlcnic_sriov_vf_check(adapter)) | ||
1932 | qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc); | ||
1933 | 1933 | ||
1934 | qlcnic_napi_disable(adapter); | 1934 | qlcnic_napi_disable(adapter); |
1935 | 1935 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h index 396bd1fd1d27..54159bde2bc7 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | |||
@@ -151,13 +151,14 @@ struct qlcnic_vf_info { | |||
151 | struct qlcnic_trans_list rcv_pend; | 151 | struct qlcnic_trans_list rcv_pend; |
152 | struct qlcnic_adapter *adapter; | 152 | struct qlcnic_adapter *adapter; |
153 | struct qlcnic_vport *vp; | 153 | struct qlcnic_vport *vp; |
154 | struct mutex vlan_list_lock; /* Lock for VLAN list */ | 154 | spinlock_t vlan_list_lock; /* Lock for VLAN list */ |
155 | }; | 155 | }; |
156 | 156 | ||
157 | struct qlcnic_async_work_list { | 157 | struct qlcnic_async_work_list { |
158 | struct list_head list; | 158 | struct list_head list; |
159 | struct work_struct work; | 159 | struct work_struct work; |
160 | void *ptr; | 160 | void *ptr; |
161 | struct qlcnic_cmd_args *cmd; | ||
161 | }; | 162 | }; |
162 | 163 | ||
163 | struct qlcnic_back_channel { | 164 | struct qlcnic_back_channel { |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 4eccc2b74f67..44cd5bd03744 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | |||
@@ -39,6 +39,8 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *, u8); | |||
39 | static void qlcnic_sriov_process_bc_cmd(struct work_struct *); | 39 | static void qlcnic_sriov_process_bc_cmd(struct work_struct *); |
40 | static int qlcnic_sriov_vf_shutdown(struct pci_dev *); | 40 | static int qlcnic_sriov_vf_shutdown(struct pci_dev *); |
41 | static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *); | 41 | static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *); |
42 | static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *, | ||
43 | struct qlcnic_cmd_args *); | ||
42 | 44 | ||
43 | static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { | 45 | static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { |
44 | .read_crb = qlcnic_83xx_read_crb, | 46 | .read_crb = qlcnic_83xx_read_crb, |
@@ -181,7 +183,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) | |||
181 | vf->adapter = adapter; | 183 | vf->adapter = adapter; |
182 | vf->pci_func = qlcnic_sriov_virtid_fn(adapter, i); | 184 | vf->pci_func = qlcnic_sriov_virtid_fn(adapter, i); |
183 | mutex_init(&vf->send_cmd_lock); | 185 | mutex_init(&vf->send_cmd_lock); |
184 | mutex_init(&vf->vlan_list_lock); | 186 | spin_lock_init(&vf->vlan_list_lock); |
185 | INIT_LIST_HEAD(&vf->rcv_act.wait_list); | 187 | INIT_LIST_HEAD(&vf->rcv_act.wait_list); |
186 | INIT_LIST_HEAD(&vf->rcv_pend.wait_list); | 188 | INIT_LIST_HEAD(&vf->rcv_pend.wait_list); |
187 | spin_lock_init(&vf->rcv_act.lock); | 189 | spin_lock_init(&vf->rcv_act.lock); |
@@ -1356,7 +1358,7 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter, | |||
1356 | return -EIO; | 1358 | return -EIO; |
1357 | } | 1359 | } |
1358 | 1360 | ||
1359 | static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, | 1361 | static int __qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, |
1360 | struct qlcnic_cmd_args *cmd) | 1362 | struct qlcnic_cmd_args *cmd) |
1361 | { | 1363 | { |
1362 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 1364 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
@@ -1428,6 +1430,16 @@ cleanup_transaction: | |||
1428 | return rsp; | 1430 | return rsp; |
1429 | } | 1431 | } |
1430 | 1432 | ||
1433 | |||
1434 | static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, | ||
1435 | struct qlcnic_cmd_args *cmd) | ||
1436 | { | ||
1437 | if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) | ||
1438 | return qlcnic_sriov_async_issue_cmd(adapter, cmd); | ||
1439 | else | ||
1440 | return __qlcnic_sriov_issue_cmd(adapter, cmd); | ||
1441 | } | ||
1442 | |||
1431 | static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op) | 1443 | static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op) |
1432 | { | 1444 | { |
1433 | struct qlcnic_cmd_args cmd; | 1445 | struct qlcnic_cmd_args cmd; |
@@ -1458,58 +1470,28 @@ out: | |||
1458 | return ret; | 1470 | return ret; |
1459 | } | 1471 | } |
1460 | 1472 | ||
1461 | static void qlcnic_vf_add_mc_list(struct net_device *netdev) | 1473 | static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac) |
1462 | { | 1474 | { |
1463 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1475 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1464 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; | 1476 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
1465 | struct qlcnic_mac_vlan_list *cur; | ||
1466 | struct list_head *head, tmp_list; | ||
1467 | struct qlcnic_vf_info *vf; | 1477 | struct qlcnic_vf_info *vf; |
1468 | u16 vlan_id; | 1478 | u16 vlan_id; |
1469 | int i; | 1479 | int i; |
1470 | 1480 | ||
1471 | static const u8 bcast_addr[ETH_ALEN] = { | ||
1472 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
1473 | }; | ||
1474 | |||
1475 | vf = &adapter->ahw->sriov->vf_info[0]; | 1481 | vf = &adapter->ahw->sriov->vf_info[0]; |
1476 | INIT_LIST_HEAD(&tmp_list); | ||
1477 | head = &adapter->vf_mc_list; | ||
1478 | netif_addr_lock_bh(netdev); | ||
1479 | |||
1480 | while (!list_empty(head)) { | ||
1481 | cur = list_entry(head->next, struct qlcnic_mac_vlan_list, list); | ||
1482 | list_move(&cur->list, &tmp_list); | ||
1483 | } | ||
1484 | |||
1485 | netif_addr_unlock_bh(netdev); | ||
1486 | 1482 | ||
1487 | while (!list_empty(&tmp_list)) { | 1483 | if (!qlcnic_sriov_check_any_vlan(vf)) { |
1488 | cur = list_entry((&tmp_list)->next, | 1484 | qlcnic_nic_add_mac(adapter, mac, 0); |
1489 | struct qlcnic_mac_vlan_list, list); | 1485 | } else { |
1490 | if (!qlcnic_sriov_check_any_vlan(vf)) { | 1486 | spin_lock(&vf->vlan_list_lock); |
1491 | qlcnic_nic_add_mac(adapter, bcast_addr, 0); | 1487 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
1492 | qlcnic_nic_add_mac(adapter, cur->mac_addr, 0); | 1488 | vlan_id = vf->sriov_vlans[i]; |
1493 | } else { | 1489 | if (vlan_id) |
1494 | mutex_lock(&vf->vlan_list_lock); | 1490 | qlcnic_nic_add_mac(adapter, mac, vlan_id); |
1495 | for (i = 0; i < sriov->num_allowed_vlans; i++) { | ||
1496 | vlan_id = vf->sriov_vlans[i]; | ||
1497 | if (vlan_id) { | ||
1498 | qlcnic_nic_add_mac(adapter, bcast_addr, | ||
1499 | vlan_id); | ||
1500 | qlcnic_nic_add_mac(adapter, | ||
1501 | cur->mac_addr, | ||
1502 | vlan_id); | ||
1503 | } | ||
1504 | } | ||
1505 | mutex_unlock(&vf->vlan_list_lock); | ||
1506 | if (qlcnic_84xx_check(adapter)) { | ||
1507 | qlcnic_nic_add_mac(adapter, bcast_addr, 0); | ||
1508 | qlcnic_nic_add_mac(adapter, cur->mac_addr, 0); | ||
1509 | } | ||
1510 | } | 1491 | } |
1511 | list_del(&cur->list); | 1492 | spin_unlock(&vf->vlan_list_lock); |
1512 | kfree(cur); | 1493 | if (qlcnic_84xx_check(adapter)) |
1494 | qlcnic_nic_add_mac(adapter, mac, 0); | ||
1513 | } | 1495 | } |
1514 | } | 1496 | } |
1515 | 1497 | ||
@@ -1518,6 +1500,7 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc) | |||
1518 | struct list_head *head = &bc->async_list; | 1500 | struct list_head *head = &bc->async_list; |
1519 | struct qlcnic_async_work_list *entry; | 1501 | struct qlcnic_async_work_list *entry; |
1520 | 1502 | ||
1503 | flush_workqueue(bc->bc_async_wq); | ||
1521 | while (!list_empty(head)) { | 1504 | while (!list_empty(head)) { |
1522 | entry = list_entry(head->next, struct qlcnic_async_work_list, | 1505 | entry = list_entry(head->next, struct qlcnic_async_work_list, |
1523 | list); | 1506 | list); |
@@ -1527,10 +1510,14 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc) | |||
1527 | } | 1510 | } |
1528 | } | 1511 | } |
1529 | 1512 | ||
1530 | static void qlcnic_sriov_vf_set_multi(struct net_device *netdev) | 1513 | void qlcnic_sriov_vf_set_multi(struct net_device *netdev) |
1531 | { | 1514 | { |
1532 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1515 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1533 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 1516 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1517 | static const u8 bcast_addr[ETH_ALEN] = { | ||
1518 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
1519 | }; | ||
1520 | struct netdev_hw_addr *ha; | ||
1534 | u32 mode = VPORT_MISS_MODE_DROP; | 1521 | u32 mode = VPORT_MISS_MODE_DROP; |
1535 | 1522 | ||
1536 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) | 1523 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) |
@@ -1542,23 +1529,27 @@ static void qlcnic_sriov_vf_set_multi(struct net_device *netdev) | |||
1542 | } else if ((netdev->flags & IFF_ALLMULTI) || | 1529 | } else if ((netdev->flags & IFF_ALLMULTI) || |
1543 | (netdev_mc_count(netdev) > ahw->max_mc_count)) { | 1530 | (netdev_mc_count(netdev) > ahw->max_mc_count)) { |
1544 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; | 1531 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; |
1532 | } else { | ||
1533 | qlcnic_vf_add_mc_list(netdev, bcast_addr); | ||
1534 | if (!netdev_mc_empty(netdev)) { | ||
1535 | netdev_for_each_mc_addr(ha, netdev) | ||
1536 | qlcnic_vf_add_mc_list(netdev, ha->addr); | ||
1537 | } | ||
1545 | } | 1538 | } |
1546 | 1539 | ||
1547 | if (qlcnic_sriov_vf_check(adapter)) | ||
1548 | qlcnic_vf_add_mc_list(netdev); | ||
1549 | |||
1550 | qlcnic_nic_set_promisc(adapter, mode); | 1540 | qlcnic_nic_set_promisc(adapter, mode); |
1551 | } | 1541 | } |
1552 | 1542 | ||
1553 | static void qlcnic_sriov_handle_async_multi(struct work_struct *work) | 1543 | static void qlcnic_sriov_handle_async_issue_cmd(struct work_struct *work) |
1554 | { | 1544 | { |
1555 | struct qlcnic_async_work_list *entry; | 1545 | struct qlcnic_async_work_list *entry; |
1556 | struct net_device *netdev; | 1546 | struct qlcnic_adapter *adapter; |
1547 | struct qlcnic_cmd_args *cmd; | ||
1557 | 1548 | ||
1558 | entry = container_of(work, struct qlcnic_async_work_list, work); | 1549 | entry = container_of(work, struct qlcnic_async_work_list, work); |
1559 | netdev = (struct net_device *)entry->ptr; | 1550 | adapter = entry->ptr; |
1560 | 1551 | cmd = entry->cmd; | |
1561 | qlcnic_sriov_vf_set_multi(netdev); | 1552 | __qlcnic_sriov_issue_cmd(adapter, cmd); |
1562 | return; | 1553 | return; |
1563 | } | 1554 | } |
1564 | 1555 | ||
@@ -1588,8 +1579,9 @@ qlcnic_sriov_get_free_node_async_work(struct qlcnic_back_channel *bc) | |||
1588 | return entry; | 1579 | return entry; |
1589 | } | 1580 | } |
1590 | 1581 | ||
1591 | static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc, | 1582 | static void qlcnic_sriov_schedule_async_cmd(struct qlcnic_back_channel *bc, |
1592 | work_func_t func, void *data) | 1583 | work_func_t func, void *data, |
1584 | struct qlcnic_cmd_args *cmd) | ||
1593 | { | 1585 | { |
1594 | struct qlcnic_async_work_list *entry = NULL; | 1586 | struct qlcnic_async_work_list *entry = NULL; |
1595 | 1587 | ||
@@ -1598,21 +1590,23 @@ static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc, | |||
1598 | return; | 1590 | return; |
1599 | 1591 | ||
1600 | entry->ptr = data; | 1592 | entry->ptr = data; |
1593 | entry->cmd = cmd; | ||
1601 | INIT_WORK(&entry->work, func); | 1594 | INIT_WORK(&entry->work, func); |
1602 | queue_work(bc->bc_async_wq, &entry->work); | 1595 | queue_work(bc->bc_async_wq, &entry->work); |
1603 | } | 1596 | } |
1604 | 1597 | ||
1605 | void qlcnic_sriov_vf_schedule_multi(struct net_device *netdev) | 1598 | static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *adapter, |
1599 | struct qlcnic_cmd_args *cmd) | ||
1606 | { | 1600 | { |
1607 | 1601 | ||
1608 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1609 | struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc; | 1602 | struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc; |
1610 | 1603 | ||
1611 | if (adapter->need_fw_reset) | 1604 | if (adapter->need_fw_reset) |
1612 | return; | 1605 | return -EIO; |
1613 | 1606 | ||
1614 | qlcnic_sriov_schedule_bc_async_work(bc, qlcnic_sriov_handle_async_multi, | 1607 | qlcnic_sriov_schedule_async_cmd(bc, qlcnic_sriov_handle_async_issue_cmd, |
1615 | netdev); | 1608 | adapter, cmd); |
1609 | return 0; | ||
1616 | } | 1610 | } |
1617 | 1611 | ||
1618 | static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) | 1612 | static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) |
@@ -1890,7 +1884,7 @@ static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov, | |||
1890 | if (!vf->sriov_vlans) | 1884 | if (!vf->sriov_vlans) |
1891 | return err; | 1885 | return err; |
1892 | 1886 | ||
1893 | mutex_lock(&vf->vlan_list_lock); | 1887 | spin_lock_bh(&vf->vlan_list_lock); |
1894 | 1888 | ||
1895 | for (i = 0; i < sriov->num_allowed_vlans; i++) { | 1889 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
1896 | if (vf->sriov_vlans[i] == vlan_id) { | 1890 | if (vf->sriov_vlans[i] == vlan_id) { |
@@ -1899,7 +1893,7 @@ static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov, | |||
1899 | } | 1893 | } |
1900 | } | 1894 | } |
1901 | 1895 | ||
1902 | mutex_unlock(&vf->vlan_list_lock); | 1896 | spin_unlock_bh(&vf->vlan_list_lock); |
1903 | return err; | 1897 | return err; |
1904 | } | 1898 | } |
1905 | 1899 | ||
@@ -1908,12 +1902,12 @@ static int qlcnic_sriov_validate_num_vlans(struct qlcnic_sriov *sriov, | |||
1908 | { | 1902 | { |
1909 | int err = 0; | 1903 | int err = 0; |
1910 | 1904 | ||
1911 | mutex_lock(&vf->vlan_list_lock); | 1905 | spin_lock_bh(&vf->vlan_list_lock); |
1912 | 1906 | ||
1913 | if (vf->num_vlan >= sriov->num_allowed_vlans) | 1907 | if (vf->num_vlan >= sriov->num_allowed_vlans) |
1914 | err = -EINVAL; | 1908 | err = -EINVAL; |
1915 | 1909 | ||
1916 | mutex_unlock(&vf->vlan_list_lock); | 1910 | spin_unlock_bh(&vf->vlan_list_lock); |
1917 | return err; | 1911 | return err; |
1918 | } | 1912 | } |
1919 | 1913 | ||
@@ -1966,7 +1960,7 @@ static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id, | |||
1966 | if (!vf->sriov_vlans) | 1960 | if (!vf->sriov_vlans) |
1967 | return; | 1961 | return; |
1968 | 1962 | ||
1969 | mutex_lock(&vf->vlan_list_lock); | 1963 | spin_lock_bh(&vf->vlan_list_lock); |
1970 | 1964 | ||
1971 | switch (opcode) { | 1965 | switch (opcode) { |
1972 | case QLC_VLAN_ADD: | 1966 | case QLC_VLAN_ADD: |
@@ -1979,7 +1973,7 @@ static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id, | |||
1979 | netdev_err(adapter->netdev, "Invalid VLAN operation\n"); | 1973 | netdev_err(adapter->netdev, "Invalid VLAN operation\n"); |
1980 | } | 1974 | } |
1981 | 1975 | ||
1982 | mutex_unlock(&vf->vlan_list_lock); | 1976 | spin_unlock_bh(&vf->vlan_list_lock); |
1983 | return; | 1977 | return; |
1984 | } | 1978 | } |
1985 | 1979 | ||
@@ -1987,6 +1981,7 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter, | |||
1987 | u16 vid, u8 enable) | 1981 | u16 vid, u8 enable) |
1988 | { | 1982 | { |
1989 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; | 1983 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
1984 | struct net_device *netdev = adapter->netdev; | ||
1990 | struct qlcnic_vf_info *vf; | 1985 | struct qlcnic_vf_info *vf; |
1991 | struct qlcnic_cmd_args cmd; | 1986 | struct qlcnic_cmd_args cmd; |
1992 | int ret; | 1987 | int ret; |
@@ -2012,14 +2007,18 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter, | |||
2012 | dev_err(&adapter->pdev->dev, | 2007 | dev_err(&adapter->pdev->dev, |
2013 | "Failed to configure guest VLAN, err=%d\n", ret); | 2008 | "Failed to configure guest VLAN, err=%d\n", ret); |
2014 | } else { | 2009 | } else { |
2010 | netif_addr_lock_bh(netdev); | ||
2015 | qlcnic_free_mac_list(adapter); | 2011 | qlcnic_free_mac_list(adapter); |
2012 | netif_addr_unlock_bh(netdev); | ||
2016 | 2013 | ||
2017 | if (enable) | 2014 | if (enable) |
2018 | qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_ADD); | 2015 | qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_ADD); |
2019 | else | 2016 | else |
2020 | qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_DELETE); | 2017 | qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_DELETE); |
2021 | 2018 | ||
2022 | qlcnic_set_multi(adapter->netdev); | 2019 | netif_addr_lock_bh(netdev); |
2020 | qlcnic_set_multi(netdev); | ||
2021 | netif_addr_unlock_bh(netdev); | ||
2023 | } | 2022 | } |
2024 | 2023 | ||
2025 | qlcnic_free_mbx_args(&cmd); | 2024 | qlcnic_free_mbx_args(&cmd); |
@@ -2150,11 +2149,11 @@ bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *vf) | |||
2150 | { | 2149 | { |
2151 | bool err = false; | 2150 | bool err = false; |
2152 | 2151 | ||
2153 | mutex_lock(&vf->vlan_list_lock); | 2152 | spin_lock_bh(&vf->vlan_list_lock); |
2154 | 2153 | ||
2155 | if (vf->num_vlan) | 2154 | if (vf->num_vlan) |
2156 | err = true; | 2155 | err = true; |
2157 | 2156 | ||
2158 | mutex_unlock(&vf->vlan_list_lock); | 2157 | spin_unlock_bh(&vf->vlan_list_lock); |
2159 | return err; | 2158 | return err; |
2160 | } | 2159 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index df409086e4d3..199ab7c6fbad 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | |||
@@ -784,7 +784,7 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter, | |||
784 | struct qlcnic_vf_info *vf, | 784 | struct qlcnic_vf_info *vf, |
785 | u16 vlan, u8 op) | 785 | u16 vlan, u8 op) |
786 | { | 786 | { |
787 | struct qlcnic_cmd_args cmd; | 787 | struct qlcnic_cmd_args *cmd; |
788 | struct qlcnic_macvlan_mbx mv; | 788 | struct qlcnic_macvlan_mbx mv; |
789 | struct qlcnic_vport *vp; | 789 | struct qlcnic_vport *vp; |
790 | u8 *addr; | 790 | u8 *addr; |
@@ -794,21 +794,27 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter, | |||
794 | 794 | ||
795 | vp = vf->vp; | 795 | vp = vf->vp; |
796 | 796 | ||
797 | if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN)) | 797 | cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); |
798 | if (!cmd) | ||
798 | return -ENOMEM; | 799 | return -ENOMEM; |
799 | 800 | ||
801 | err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN); | ||
802 | if (err) | ||
803 | goto free_cmd; | ||
804 | |||
805 | cmd->type = QLC_83XX_MBX_CMD_NO_WAIT; | ||
800 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func); | 806 | vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func); |
801 | if (vpid < 0) { | 807 | if (vpid < 0) { |
802 | err = -EINVAL; | 808 | err = -EINVAL; |
803 | goto out; | 809 | goto free_args; |
804 | } | 810 | } |
805 | 811 | ||
806 | if (vlan) | 812 | if (vlan) |
807 | op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ? | 813 | op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ? |
808 | QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL); | 814 | QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL); |
809 | 815 | ||
810 | cmd.req.arg[1] = op | (1 << 8) | (3 << 6); | 816 | cmd->req.arg[1] = op | (1 << 8) | (3 << 6); |
811 | cmd.req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31; | 817 | cmd->req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31; |
812 | 818 | ||
813 | addr = vp->mac; | 819 | addr = vp->mac; |
814 | mv.vlan = vlan; | 820 | mv.vlan = vlan; |
@@ -818,18 +824,18 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter, | |||
818 | mv.mac_addr3 = addr[3]; | 824 | mv.mac_addr3 = addr[3]; |
819 | mv.mac_addr4 = addr[4]; | 825 | mv.mac_addr4 = addr[4]; |
820 | mv.mac_addr5 = addr[5]; | 826 | mv.mac_addr5 = addr[5]; |
821 | buf = &cmd.req.arg[2]; | 827 | buf = &cmd->req.arg[2]; |
822 | memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx)); | 828 | memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx)); |
823 | 829 | ||
824 | err = qlcnic_issue_cmd(adapter, &cmd); | 830 | err = qlcnic_issue_cmd(adapter, cmd); |
825 | 831 | ||
826 | if (err) | 832 | if (!err) |
827 | dev_err(&adapter->pdev->dev, | 833 | return err; |
828 | "MAC-VLAN %s to CAM failed, err=%d.\n", | ||
829 | ((op == 1) ? "add " : "delete "), err); | ||
830 | 834 | ||
831 | out: | 835 | free_args: |
832 | qlcnic_free_mbx_args(&cmd); | 836 | qlcnic_free_mbx_args(cmd); |
837 | free_cmd: | ||
838 | kfree(cmd); | ||
833 | return err; | 839 | return err; |
834 | } | 840 | } |
835 | 841 | ||
@@ -851,7 +857,7 @@ static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter, | |||
851 | 857 | ||
852 | sriov = adapter->ahw->sriov; | 858 | sriov = adapter->ahw->sriov; |
853 | 859 | ||
854 | mutex_lock(&vf->vlan_list_lock); | 860 | spin_lock_bh(&vf->vlan_list_lock); |
855 | if (vf->num_vlan) { | 861 | if (vf->num_vlan) { |
856 | for (i = 0; i < sriov->num_allowed_vlans; i++) { | 862 | for (i = 0; i < sriov->num_allowed_vlans; i++) { |
857 | vlan = vf->sriov_vlans[i]; | 863 | vlan = vf->sriov_vlans[i]; |
@@ -860,7 +866,7 @@ static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter, | |||
860 | opcode); | 866 | opcode); |
861 | } | 867 | } |
862 | } | 868 | } |
863 | mutex_unlock(&vf->vlan_list_lock); | 869 | spin_unlock_bh(&vf->vlan_list_lock); |
864 | 870 | ||
865 | if (vf->vp->vlan_mode != QLC_PVID_MODE) { | 871 | if (vf->vp->vlan_mode != QLC_PVID_MODE) { |
866 | if (qlcnic_83xx_pf_check(adapter) && | 872 | if (qlcnic_83xx_pf_check(adapter) && |