2929#define QLC_83XX_VF_RESET_FAIL_THRESH 8
3030#define QLC_BC_CMD_MAX_RETRY_CNT 5
3131
32+ static void qlcnic_sriov_handle_async_issue_cmd (struct work_struct * work );
3233static void qlcnic_sriov_vf_free_mac_list (struct qlcnic_adapter * );
3334static int qlcnic_sriov_alloc_bc_mbx_args (struct qlcnic_cmd_args * , u32 );
3435static void qlcnic_sriov_vf_poll_dev_state (struct work_struct * );
@@ -177,7 +178,10 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
177178 }
178179
179180 bc -> bc_async_wq = wq ;
180- INIT_LIST_HEAD (& bc -> async_list );
181+ INIT_LIST_HEAD (& bc -> async_cmd_list );
182+ INIT_WORK (& bc -> vf_async_work , qlcnic_sriov_handle_async_issue_cmd );
183+ spin_lock_init (& bc -> queue_lock );
184+ bc -> adapter = adapter ;
181185
182186 for (i = 0 ; i < num_vfs ; i ++ ) {
183187 vf = & sriov -> vf_info [i ];
@@ -1517,17 +1521,21 @@ static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac,
15171521
15181522void qlcnic_sriov_cleanup_async_list (struct qlcnic_back_channel * bc )
15191523{
1520- struct list_head * head = & bc -> async_list ;
1521- struct qlcnic_async_work_list * entry ;
1524+ struct list_head * head = & bc -> async_cmd_list ;
1525+ struct qlcnic_async_cmd * entry ;
15221526
15231527 flush_workqueue (bc -> bc_async_wq );
1528+ cancel_work_sync (& bc -> vf_async_work );
1529+
1530+ spin_lock (& bc -> queue_lock );
15241531 while (!list_empty (head )) {
1525- entry = list_entry (head -> next , struct qlcnic_async_work_list ,
1532+ entry = list_entry (head -> next , struct qlcnic_async_cmd ,
15261533 list );
1527- cancel_work_sync (& entry -> work );
15281534 list_del (& entry -> list );
1535+ kfree (entry -> cmd );
15291536 kfree (entry );
15301537 }
1538+ spin_unlock (& bc -> queue_lock );
15311539}
15321540
15331541void qlcnic_sriov_vf_set_multi (struct net_device * netdev )
@@ -1587,57 +1595,64 @@ void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
15871595
15881596static void qlcnic_sriov_handle_async_issue_cmd (struct work_struct * work )
15891597{
1590- struct qlcnic_async_work_list * entry ;
1591- struct qlcnic_adapter * adapter ;
1598+ struct qlcnic_async_cmd * entry , * tmp ;
1599+ struct qlcnic_back_channel * bc ;
15921600 struct qlcnic_cmd_args * cmd ;
1601+ struct list_head * head ;
1602+ LIST_HEAD (del_list );
1603+
1604+ bc = container_of (work , struct qlcnic_back_channel , vf_async_work );
1605+ head = & bc -> async_cmd_list ;
1606+
1607+ spin_lock (& bc -> queue_lock );
1608+ list_splice_init (head , & del_list );
1609+ spin_unlock (& bc -> queue_lock );
1610+
1611+ list_for_each_entry_safe (entry , tmp , & del_list , list ) {
1612+ list_del (& entry -> list );
1613+ cmd = entry -> cmd ;
1614+ __qlcnic_sriov_issue_cmd (bc -> adapter , cmd );
1615+ kfree (entry );
1616+ }
1617+
1618+ if (!list_empty (head ))
1619+ queue_work (bc -> bc_async_wq , & bc -> vf_async_work );
15931620
1594- entry = container_of (work , struct qlcnic_async_work_list , work );
1595- adapter = entry -> ptr ;
1596- cmd = entry -> cmd ;
1597- __qlcnic_sriov_issue_cmd (adapter , cmd );
15981621 return ;
15991622}
16001623
1601- static struct qlcnic_async_work_list *
1602- qlcnic_sriov_get_free_node_async_work (struct qlcnic_back_channel * bc )
1624+ static struct qlcnic_async_cmd *
1625+ qlcnic_sriov_alloc_async_cmd (struct qlcnic_back_channel * bc ,
1626+ struct qlcnic_cmd_args * cmd )
16031627{
1604- struct list_head * node ;
1605- struct qlcnic_async_work_list * entry = NULL ;
1606- u8 empty = 0 ;
1628+ struct qlcnic_async_cmd * entry = NULL ;
16071629
1608- list_for_each (node , & bc -> async_list ) {
1609- entry = list_entry (node , struct qlcnic_async_work_list , list );
1610- if (!work_pending (& entry -> work )) {
1611- empty = 1 ;
1612- break ;
1613- }
1614- }
1630+ entry = kzalloc (sizeof (* entry ), GFP_ATOMIC );
1631+ if (!entry )
1632+ return NULL ;
16151633
1616- if (!empty ) {
1617- entry = kzalloc (sizeof (struct qlcnic_async_work_list ),
1618- GFP_ATOMIC );
1619- if (entry == NULL )
1620- return NULL ;
1621- list_add_tail (& entry -> list , & bc -> async_list );
1622- }
1634+ entry -> cmd = cmd ;
1635+
1636+ spin_lock (& bc -> queue_lock );
1637+ list_add_tail (& entry -> list , & bc -> async_cmd_list );
1638+ spin_unlock (& bc -> queue_lock );
16231639
16241640 return entry ;
16251641}
16261642
16271643static void qlcnic_sriov_schedule_async_cmd (struct qlcnic_back_channel * bc ,
1628- work_func_t func , void * data ,
16291644 struct qlcnic_cmd_args * cmd )
16301645{
1631- struct qlcnic_async_work_list * entry = NULL ;
1646+ struct qlcnic_async_cmd * entry = NULL ;
16321647
1633- entry = qlcnic_sriov_get_free_node_async_work (bc );
1634- if (!entry )
1648+ entry = qlcnic_sriov_alloc_async_cmd (bc , cmd );
1649+ if (!entry ) {
1650+ qlcnic_free_mbx_args (cmd );
1651+ kfree (cmd );
16351652 return ;
1653+ }
16361654
1637- entry -> ptr = data ;
1638- entry -> cmd = cmd ;
1639- INIT_WORK (& entry -> work , func );
1640- queue_work (bc -> bc_async_wq , & entry -> work );
1655+ queue_work (bc -> bc_async_wq , & bc -> vf_async_work );
16411656}
16421657
16431658static int qlcnic_sriov_async_issue_cmd (struct qlcnic_adapter * adapter ,
@@ -1649,8 +1664,8 @@ static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *adapter,
16491664 if (adapter -> need_fw_reset )
16501665 return - EIO ;
16511666
1652- qlcnic_sriov_schedule_async_cmd (bc , qlcnic_sriov_handle_async_issue_cmd ,
1653- adapter , cmd );
1667+ qlcnic_sriov_schedule_async_cmd (bc , cmd );
1668+
16541669 return 0 ;
16551670}
16561671
0 commit comments