mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
132a3f2bee
commit
74b7ba1a8b
|
@ -1693,7 +1693,7 @@ 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);
|
||||||
void qlcnic_set_netdev_features(struct qlcnic_adapter *,
|
void qlcnic_set_netdev_features(struct qlcnic_adapter *,
|
||||||
struct qlcnic_esw_func_cfg *);
|
struct qlcnic_esw_func_cfg *);
|
||||||
void qlcnic_sriov_vf_schedule_multi(struct net_device *);
|
void qlcnic_sriov_vf_set_multi(struct net_device *);
|
||||||
int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8);
|
int qlcnic_is_valid_nic_func(struct qlcnic_adapter *, u8);
|
||||||
int qlcnic_get_pci_func_type(struct qlcnic_adapter *, u16, u16 *, u16 *,
|
int qlcnic_get_pci_func_type(struct qlcnic_adapter *, u16, u16 *, u16 *,
|
||||||
u16 *);
|
u16 *);
|
||||||
|
|
|
@ -567,28 +567,14 @@ static void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
|
||||||
void qlcnic_set_multi(struct net_device *netdev)
|
void qlcnic_set_multi(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_mac_vlan_list *cur;
|
|
||||||
struct netdev_hw_addr *ha;
|
|
||||||
size_t temp;
|
|
||||||
|
|
||||||
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
|
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
|
||||||
return;
|
return;
|
||||||
if (qlcnic_sriov_vf_check(adapter)) {
|
|
||||||
if (!netdev_mc_empty(netdev)) {
|
if (qlcnic_sriov_vf_check(adapter))
|
||||||
netdev_for_each_mc_addr(ha, netdev) {
|
qlcnic_sriov_vf_set_multi(netdev);
|
||||||
temp = sizeof(struct qlcnic_mac_vlan_list);
|
else
|
||||||
cur = kzalloc(temp, GFP_ATOMIC);
|
__qlcnic_set_multi(netdev, 0);
|
||||||
if (cur == NULL)
|
|
||||||
break;
|
|
||||||
memcpy(cur->mac_addr,
|
|
||||||
ha->addr, ETH_ALEN);
|
|
||||||
list_add_tail(&cur->list, &adapter->vf_mc_list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qlcnic_sriov_vf_schedule_multi(adapter->netdev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
__qlcnic_set_multi(netdev, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
|
int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
|
||||||
|
|
|
@ -1917,8 +1917,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
|
||||||
if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state))
|
if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (qlcnic_sriov_vf_check(adapter))
|
|
||||||
qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
|
|
||||||
smp_mb();
|
smp_mb();
|
||||||
netif_carrier_off(netdev);
|
netif_carrier_off(netdev);
|
||||||
adapter->ahw->linkup = 0;
|
adapter->ahw->linkup = 0;
|
||||||
|
@ -1930,6 +1928,8 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
|
||||||
qlcnic_delete_lb_filters(adapter);
|
qlcnic_delete_lb_filters(adapter);
|
||||||
|
|
||||||
qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
|
qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
|
||||||
|
if (qlcnic_sriov_vf_check(adapter))
|
||||||
|
qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc);
|
||||||
|
|
||||||
qlcnic_napi_disable(adapter);
|
qlcnic_napi_disable(adapter);
|
||||||
|
|
||||||
|
|
|
@ -151,13 +151,14 @@ struct qlcnic_vf_info {
|
||||||
struct qlcnic_trans_list rcv_pend;
|
struct qlcnic_trans_list rcv_pend;
|
||||||
struct qlcnic_adapter *adapter;
|
struct qlcnic_adapter *adapter;
|
||||||
struct qlcnic_vport *vp;
|
struct qlcnic_vport *vp;
|
||||||
struct mutex vlan_list_lock; /* Lock for VLAN list */
|
spinlock_t vlan_list_lock; /* Lock for VLAN list */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qlcnic_async_work_list {
|
struct qlcnic_async_work_list {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
struct qlcnic_cmd_args *cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qlcnic_back_channel {
|
struct qlcnic_back_channel {
|
||||||
|
|
|
@ -39,6 +39,8 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *, u8);
|
||||||
static void qlcnic_sriov_process_bc_cmd(struct work_struct *);
|
static void qlcnic_sriov_process_bc_cmd(struct work_struct *);
|
||||||
static int qlcnic_sriov_vf_shutdown(struct pci_dev *);
|
static int qlcnic_sriov_vf_shutdown(struct pci_dev *);
|
||||||
static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *);
|
static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *);
|
||||||
|
static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *,
|
||||||
|
struct qlcnic_cmd_args *);
|
||||||
|
|
||||||
static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
|
static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
|
||||||
.read_crb = qlcnic_83xx_read_crb,
|
.read_crb = qlcnic_83xx_read_crb,
|
||||||
|
@ -181,7 +183,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
|
||||||
vf->adapter = adapter;
|
vf->adapter = adapter;
|
||||||
vf->pci_func = qlcnic_sriov_virtid_fn(adapter, i);
|
vf->pci_func = qlcnic_sriov_virtid_fn(adapter, i);
|
||||||
mutex_init(&vf->send_cmd_lock);
|
mutex_init(&vf->send_cmd_lock);
|
||||||
mutex_init(&vf->vlan_list_lock);
|
spin_lock_init(&vf->vlan_list_lock);
|
||||||
INIT_LIST_HEAD(&vf->rcv_act.wait_list);
|
INIT_LIST_HEAD(&vf->rcv_act.wait_list);
|
||||||
INIT_LIST_HEAD(&vf->rcv_pend.wait_list);
|
INIT_LIST_HEAD(&vf->rcv_pend.wait_list);
|
||||||
spin_lock_init(&vf->rcv_act.lock);
|
spin_lock_init(&vf->rcv_act.lock);
|
||||||
|
@ -1356,7 +1358,7 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter,
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
|
static int __qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
|
||||||
struct qlcnic_cmd_args *cmd)
|
struct qlcnic_cmd_args *cmd)
|
||||||
{
|
{
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
@ -1428,6 +1430,16 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
|
||||||
return rsp;
|
return rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
|
||||||
|
struct qlcnic_cmd_args *cmd)
|
||||||
|
{
|
||||||
|
if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT)
|
||||||
|
return qlcnic_sriov_async_issue_cmd(adapter, cmd);
|
||||||
|
else
|
||||||
|
return __qlcnic_sriov_issue_cmd(adapter, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op)
|
static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op)
|
||||||
{
|
{
|
||||||
struct qlcnic_cmd_args cmd;
|
struct qlcnic_cmd_args cmd;
|
||||||
|
@ -1458,58 +1470,28 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_o
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qlcnic_vf_add_mc_list(struct net_device *netdev)
|
static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
|
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
|
||||||
struct qlcnic_mac_vlan_list *cur;
|
|
||||||
struct list_head *head, tmp_list;
|
|
||||||
struct qlcnic_vf_info *vf;
|
struct qlcnic_vf_info *vf;
|
||||||
u16 vlan_id;
|
u16 vlan_id;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
static const u8 bcast_addr[ETH_ALEN] = {
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
vf = &adapter->ahw->sriov->vf_info[0];
|
vf = &adapter->ahw->sriov->vf_info[0];
|
||||||
INIT_LIST_HEAD(&tmp_list);
|
|
||||||
head = &adapter->vf_mc_list;
|
|
||||||
netif_addr_lock_bh(netdev);
|
|
||||||
|
|
||||||
while (!list_empty(head)) {
|
if (!qlcnic_sriov_check_any_vlan(vf)) {
|
||||||
cur = list_entry(head->next, struct qlcnic_mac_vlan_list, list);
|
qlcnic_nic_add_mac(adapter, mac, 0);
|
||||||
list_move(&cur->list, &tmp_list);
|
} else {
|
||||||
}
|
spin_lock(&vf->vlan_list_lock);
|
||||||
|
for (i = 0; i < sriov->num_allowed_vlans; i++) {
|
||||||
netif_addr_unlock_bh(netdev);
|
vlan_id = vf->sriov_vlans[i];
|
||||||
|
if (vlan_id)
|
||||||
while (!list_empty(&tmp_list)) {
|
qlcnic_nic_add_mac(adapter, mac, vlan_id);
|
||||||
cur = list_entry((&tmp_list)->next,
|
|
||||||
struct qlcnic_mac_vlan_list, list);
|
|
||||||
if (!qlcnic_sriov_check_any_vlan(vf)) {
|
|
||||||
qlcnic_nic_add_mac(adapter, bcast_addr, 0);
|
|
||||||
qlcnic_nic_add_mac(adapter, cur->mac_addr, 0);
|
|
||||||
} else {
|
|
||||||
mutex_lock(&vf->vlan_list_lock);
|
|
||||||
for (i = 0; i < sriov->num_allowed_vlans; i++) {
|
|
||||||
vlan_id = vf->sriov_vlans[i];
|
|
||||||
if (vlan_id) {
|
|
||||||
qlcnic_nic_add_mac(adapter, bcast_addr,
|
|
||||||
vlan_id);
|
|
||||||
qlcnic_nic_add_mac(adapter,
|
|
||||||
cur->mac_addr,
|
|
||||||
vlan_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mutex_unlock(&vf->vlan_list_lock);
|
|
||||||
if (qlcnic_84xx_check(adapter)) {
|
|
||||||
qlcnic_nic_add_mac(adapter, bcast_addr, 0);
|
|
||||||
qlcnic_nic_add_mac(adapter, cur->mac_addr, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
list_del(&cur->list);
|
spin_unlock(&vf->vlan_list_lock);
|
||||||
kfree(cur);
|
if (qlcnic_84xx_check(adapter))
|
||||||
|
qlcnic_nic_add_mac(adapter, mac, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,6 +1500,7 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc)
|
||||||
struct list_head *head = &bc->async_list;
|
struct list_head *head = &bc->async_list;
|
||||||
struct qlcnic_async_work_list *entry;
|
struct qlcnic_async_work_list *entry;
|
||||||
|
|
||||||
|
flush_workqueue(bc->bc_async_wq);
|
||||||
while (!list_empty(head)) {
|
while (!list_empty(head)) {
|
||||||
entry = list_entry(head->next, struct qlcnic_async_work_list,
|
entry = list_entry(head->next, struct qlcnic_async_work_list,
|
||||||
list);
|
list);
|
||||||
|
@ -1527,10 +1510,14 @@ void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *bc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
|
void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
static const u8 bcast_addr[ETH_ALEN] = {
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||||
|
};
|
||||||
|
struct netdev_hw_addr *ha;
|
||||||
u32 mode = VPORT_MISS_MODE_DROP;
|
u32 mode = VPORT_MISS_MODE_DROP;
|
||||||
|
|
||||||
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
|
if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
|
||||||
|
@ -1542,23 +1529,27 @@ static void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
|
||||||
} else if ((netdev->flags & IFF_ALLMULTI) ||
|
} else if ((netdev->flags & IFF_ALLMULTI) ||
|
||||||
(netdev_mc_count(netdev) > ahw->max_mc_count)) {
|
(netdev_mc_count(netdev) > ahw->max_mc_count)) {
|
||||||
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
|
mode = VPORT_MISS_MODE_ACCEPT_MULTI;
|
||||||
|
} else {
|
||||||
|
qlcnic_vf_add_mc_list(netdev, bcast_addr);
|
||||||
|
if (!netdev_mc_empty(netdev)) {
|
||||||
|
netdev_for_each_mc_addr(ha, netdev)
|
||||||
|
qlcnic_vf_add_mc_list(netdev, ha->addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qlcnic_sriov_vf_check(adapter))
|
|
||||||
qlcnic_vf_add_mc_list(netdev);
|
|
||||||
|
|
||||||
qlcnic_nic_set_promisc(adapter, mode);
|
qlcnic_nic_set_promisc(adapter, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qlcnic_sriov_handle_async_multi(struct work_struct *work)
|
static void qlcnic_sriov_handle_async_issue_cmd(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct qlcnic_async_work_list *entry;
|
struct qlcnic_async_work_list *entry;
|
||||||
struct net_device *netdev;
|
struct qlcnic_adapter *adapter;
|
||||||
|
struct qlcnic_cmd_args *cmd;
|
||||||
|
|
||||||
entry = container_of(work, struct qlcnic_async_work_list, work);
|
entry = container_of(work, struct qlcnic_async_work_list, work);
|
||||||
netdev = (struct net_device *)entry->ptr;
|
adapter = entry->ptr;
|
||||||
|
cmd = entry->cmd;
|
||||||
qlcnic_sriov_vf_set_multi(netdev);
|
__qlcnic_sriov_issue_cmd(adapter, cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1588,8 +1579,9 @@ qlcnic_sriov_get_free_node_async_work(struct qlcnic_back_channel *bc)
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc,
|
static void qlcnic_sriov_schedule_async_cmd(struct qlcnic_back_channel *bc,
|
||||||
work_func_t func, void *data)
|
work_func_t func, void *data,
|
||||||
|
struct qlcnic_cmd_args *cmd)
|
||||||
{
|
{
|
||||||
struct qlcnic_async_work_list *entry = NULL;
|
struct qlcnic_async_work_list *entry = NULL;
|
||||||
|
|
||||||
|
@ -1598,21 +1590,23 @@ static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
entry->ptr = data;
|
entry->ptr = data;
|
||||||
|
entry->cmd = cmd;
|
||||||
INIT_WORK(&entry->work, func);
|
INIT_WORK(&entry->work, func);
|
||||||
queue_work(bc->bc_async_wq, &entry->work);
|
queue_work(bc->bc_async_wq, &entry->work);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qlcnic_sriov_vf_schedule_multi(struct net_device *netdev)
|
static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *adapter,
|
||||||
|
struct qlcnic_cmd_args *cmd)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
|
||||||
struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc;
|
struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc;
|
||||||
|
|
||||||
if (adapter->need_fw_reset)
|
if (adapter->need_fw_reset)
|
||||||
return;
|
return -EIO;
|
||||||
|
|
||||||
qlcnic_sriov_schedule_bc_async_work(bc, qlcnic_sriov_handle_async_multi,
|
qlcnic_sriov_schedule_async_cmd(bc, qlcnic_sriov_handle_async_issue_cmd,
|
||||||
netdev);
|
adapter, cmd);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter)
|
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,
|
||||||
if (!vf->sriov_vlans)
|
if (!vf->sriov_vlans)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
mutex_lock(&vf->vlan_list_lock);
|
spin_lock_bh(&vf->vlan_list_lock);
|
||||||
|
|
||||||
for (i = 0; i < sriov->num_allowed_vlans; i++) {
|
for (i = 0; i < sriov->num_allowed_vlans; i++) {
|
||||||
if (vf->sriov_vlans[i] == vlan_id) {
|
if (vf->sriov_vlans[i] == vlan_id) {
|
||||||
|
@ -1899,7 +1893,7 @@ static int qlcnic_sriov_check_vlan_id(struct qlcnic_sriov *sriov,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&vf->vlan_list_lock);
|
spin_unlock_bh(&vf->vlan_list_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1908,12 +1902,12 @@ static int qlcnic_sriov_validate_num_vlans(struct qlcnic_sriov *sriov,
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
mutex_lock(&vf->vlan_list_lock);
|
spin_lock_bh(&vf->vlan_list_lock);
|
||||||
|
|
||||||
if (vf->num_vlan >= sriov->num_allowed_vlans)
|
if (vf->num_vlan >= sriov->num_allowed_vlans)
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
|
||||||
mutex_unlock(&vf->vlan_list_lock);
|
spin_unlock_bh(&vf->vlan_list_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1966,7 +1960,7 @@ static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id,
|
||||||
if (!vf->sriov_vlans)
|
if (!vf->sriov_vlans)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&vf->vlan_list_lock);
|
spin_lock_bh(&vf->vlan_list_lock);
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case QLC_VLAN_ADD:
|
case QLC_VLAN_ADD:
|
||||||
|
@ -1979,7 +1973,7 @@ static void qlcnic_sriov_vlan_operation(struct qlcnic_vf_info *vf, u16 vlan_id,
|
||||||
netdev_err(adapter->netdev, "Invalid VLAN operation\n");
|
netdev_err(adapter->netdev, "Invalid VLAN operation\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&vf->vlan_list_lock);
|
spin_unlock_bh(&vf->vlan_list_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1987,6 +1981,7 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter,
|
||||||
u16 vid, u8 enable)
|
u16 vid, u8 enable)
|
||||||
{
|
{
|
||||||
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
|
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
|
||||||
|
struct net_device *netdev = adapter->netdev;
|
||||||
struct qlcnic_vf_info *vf;
|
struct qlcnic_vf_info *vf;
|
||||||
struct qlcnic_cmd_args cmd;
|
struct qlcnic_cmd_args cmd;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -2012,14 +2007,18 @@ int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *adapter,
|
||||||
dev_err(&adapter->pdev->dev,
|
dev_err(&adapter->pdev->dev,
|
||||||
"Failed to configure guest VLAN, err=%d\n", ret);
|
"Failed to configure guest VLAN, err=%d\n", ret);
|
||||||
} else {
|
} else {
|
||||||
|
netif_addr_lock_bh(netdev);
|
||||||
qlcnic_free_mac_list(adapter);
|
qlcnic_free_mac_list(adapter);
|
||||||
|
netif_addr_unlock_bh(netdev);
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_ADD);
|
qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_ADD);
|
||||||
else
|
else
|
||||||
qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_DELETE);
|
qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_DELETE);
|
||||||
|
|
||||||
qlcnic_set_multi(adapter->netdev);
|
netif_addr_lock_bh(netdev);
|
||||||
|
qlcnic_set_multi(netdev);
|
||||||
|
netif_addr_unlock_bh(netdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
qlcnic_free_mbx_args(&cmd);
|
qlcnic_free_mbx_args(&cmd);
|
||||||
|
@ -2150,11 +2149,11 @@ bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *vf)
|
||||||
{
|
{
|
||||||
bool err = false;
|
bool err = false;
|
||||||
|
|
||||||
mutex_lock(&vf->vlan_list_lock);
|
spin_lock_bh(&vf->vlan_list_lock);
|
||||||
|
|
||||||
if (vf->num_vlan)
|
if (vf->num_vlan)
|
||||||
err = true;
|
err = true;
|
||||||
|
|
||||||
mutex_unlock(&vf->vlan_list_lock);
|
spin_unlock_bh(&vf->vlan_list_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -784,7 +784,7 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
|
||||||
struct qlcnic_vf_info *vf,
|
struct qlcnic_vf_info *vf,
|
||||||
u16 vlan, u8 op)
|
u16 vlan, u8 op)
|
||||||
{
|
{
|
||||||
struct qlcnic_cmd_args cmd;
|
struct qlcnic_cmd_args *cmd;
|
||||||
struct qlcnic_macvlan_mbx mv;
|
struct qlcnic_macvlan_mbx mv;
|
||||||
struct qlcnic_vport *vp;
|
struct qlcnic_vport *vp;
|
||||||
u8 *addr;
|
u8 *addr;
|
||||||
|
@ -794,21 +794,27 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
|
||||||
|
|
||||||
vp = vf->vp;
|
vp = vf->vp;
|
||||||
|
|
||||||
if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN))
|
cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
|
||||||
|
if (!cmd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
|
||||||
|
if (err)
|
||||||
|
goto free_cmd;
|
||||||
|
|
||||||
|
cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
|
||||||
vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func);
|
vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func);
|
||||||
if (vpid < 0) {
|
if (vpid < 0) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out;
|
goto free_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vlan)
|
if (vlan)
|
||||||
op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
|
op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
|
||||||
QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL);
|
QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL);
|
||||||
|
|
||||||
cmd.req.arg[1] = op | (1 << 8) | (3 << 6);
|
cmd->req.arg[1] = op | (1 << 8) | (3 << 6);
|
||||||
cmd.req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31;
|
cmd->req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31;
|
||||||
|
|
||||||
addr = vp->mac;
|
addr = vp->mac;
|
||||||
mv.vlan = vlan;
|
mv.vlan = vlan;
|
||||||
|
@ -818,18 +824,18 @@ static int qlcnic_sriov_cfg_vf_def_mac(struct qlcnic_adapter *adapter,
|
||||||
mv.mac_addr3 = addr[3];
|
mv.mac_addr3 = addr[3];
|
||||||
mv.mac_addr4 = addr[4];
|
mv.mac_addr4 = addr[4];
|
||||||
mv.mac_addr5 = addr[5];
|
mv.mac_addr5 = addr[5];
|
||||||
buf = &cmd.req.arg[2];
|
buf = &cmd->req.arg[2];
|
||||||
memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
|
memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
|
||||||
|
|
||||||
err = qlcnic_issue_cmd(adapter, &cmd);
|
err = qlcnic_issue_cmd(adapter, cmd);
|
||||||
|
|
||||||
if (err)
|
if (!err)
|
||||||
dev_err(&adapter->pdev->dev,
|
return err;
|
||||||
"MAC-VLAN %s to CAM failed, err=%d.\n",
|
|
||||||
((op == 1) ? "add " : "delete "), err);
|
|
||||||
|
|
||||||
out:
|
free_args:
|
||||||
qlcnic_free_mbx_args(&cmd);
|
qlcnic_free_mbx_args(cmd);
|
||||||
|
free_cmd:
|
||||||
|
kfree(cmd);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,7 +857,7 @@ static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter,
|
||||||
|
|
||||||
sriov = adapter->ahw->sriov;
|
sriov = adapter->ahw->sriov;
|
||||||
|
|
||||||
mutex_lock(&vf->vlan_list_lock);
|
spin_lock_bh(&vf->vlan_list_lock);
|
||||||
if (vf->num_vlan) {
|
if (vf->num_vlan) {
|
||||||
for (i = 0; i < sriov->num_allowed_vlans; i++) {
|
for (i = 0; i < sriov->num_allowed_vlans; i++) {
|
||||||
vlan = vf->sriov_vlans[i];
|
vlan = vf->sriov_vlans[i];
|
||||||
|
@ -860,7 +866,7 @@ static void qlcnic_83xx_cfg_default_mac_vlan(struct qlcnic_adapter *adapter,
|
||||||
opcode);
|
opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&vf->vlan_list_lock);
|
spin_unlock_bh(&vf->vlan_list_lock);
|
||||||
|
|
||||||
if (vf->vp->vlan_mode != QLC_PVID_MODE) {
|
if (vf->vp->vlan_mode != QLC_PVID_MODE) {
|
||||||
if (qlcnic_83xx_pf_check(adapter) &&
|
if (qlcnic_83xx_pf_check(adapter) &&
|
||||||
|
|
Loading…
Reference in New Issue