1818
1919#define QLC_BC_MSG 0
2020#define QLC_BC_CFREE 1
21+ #define QLC_BC_FLR 2
2122#define QLC_BC_HDR_SZ 16
2223#define QLC_BC_PAYLOAD_SZ (1024 - QLC_BC_HDR_SZ)
2324
2425#define QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF 2048
2526#define QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF 512
2627
28+ static void qlcnic_sriov_cleanup_transaction (struct qlcnic_bc_trans * );
2729static int qlcnic_sriov_vf_mbx_op (struct qlcnic_adapter * ,
2830 struct qlcnic_cmd_args * );
2931
@@ -84,6 +86,11 @@ static inline bool qlcnic_sriov_channel_free_check(u32 val)
8486 return (val & (1 << QLC_BC_CFREE )) ? true : false;
8587}
8688
89+ static inline bool qlcnic_sriov_flr_check (u32 val )
90+ {
91+ return (val & (1 << QLC_BC_FLR )) ? true : false;
92+ }
93+
8794static inline u8 qlcnic_sriov_target_func_id (u32 val )
8895{
8996 return (val >> 4 ) & 0xff ;
@@ -192,17 +199,48 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
192199 return err ;
193200}
194201
202+ void qlcnic_sriov_cleanup_list (struct qlcnic_trans_list * t_list )
203+ {
204+ struct qlcnic_bc_trans * trans ;
205+ struct qlcnic_cmd_args cmd ;
206+ unsigned long flags ;
207+
208+ spin_lock_irqsave (& t_list -> lock , flags );
209+
210+ while (!list_empty (& t_list -> wait_list )) {
211+ trans = list_first_entry (& t_list -> wait_list ,
212+ struct qlcnic_bc_trans , list );
213+ list_del (& trans -> list );
214+ t_list -> count -- ;
215+ cmd .req .arg = (u32 * )trans -> req_pay ;
216+ cmd .rsp .arg = (u32 * )trans -> rsp_pay ;
217+ qlcnic_free_mbx_args (& cmd );
218+ qlcnic_sriov_cleanup_transaction (trans );
219+ }
220+
221+ spin_unlock_irqrestore (& t_list -> lock , flags );
222+ }
223+
195224void __qlcnic_sriov_cleanup (struct qlcnic_adapter * adapter )
196225{
197226 struct qlcnic_sriov * sriov = adapter -> ahw -> sriov ;
198227 struct qlcnic_back_channel * bc = & sriov -> bc ;
228+ struct qlcnic_vf_info * vf ;
199229 int i ;
200230
201231 if (!qlcnic_sriov_enable_check (adapter ))
202232 return ;
203233
204234 qlcnic_sriov_cleanup_async_list (bc );
205235 destroy_workqueue (bc -> bc_async_wq );
236+
237+ for (i = 0 ; i < sriov -> num_vfs ; i ++ ) {
238+ vf = & sriov -> vf_info [i ];
239+ qlcnic_sriov_cleanup_list (& vf -> rcv_pend );
240+ cancel_work_sync (& vf -> trans_work );
241+ qlcnic_sriov_cleanup_list (& vf -> rcv_act );
242+ }
243+
206244 destroy_workqueue (bc -> bc_trans_wq );
207245
208246 for (i = 0 ; i < sriov -> num_vfs ; i ++ )
@@ -651,6 +689,9 @@ static void qlcnic_sriov_schedule_bc_cmd(struct qlcnic_sriov *sriov,
651689 struct qlcnic_vf_info * vf ,
652690 work_func_t func )
653691{
692+ if (test_bit (QLC_BC_VF_FLR , & vf -> state ))
693+ return ;
694+
654695 INIT_WORK (& vf -> trans_work , func );
655696 queue_work (sriov -> bc .bc_trans_wq , & vf -> trans_work );
656697}
@@ -768,10 +809,13 @@ static int qlcnic_sriov_issue_bc_post(struct qlcnic_bc_trans *trans, u8 type)
768809static int __qlcnic_sriov_send_bc_msg (struct qlcnic_bc_trans * trans ,
769810 struct qlcnic_vf_info * vf , u8 type )
770811{
771- int err ;
772812 bool flag = true;
813+ int err = - EIO ;
773814
774815 while (flag ) {
816+ if (test_bit (QLC_BC_VF_FLR , & vf -> state ))
817+ trans -> trans_state = QLC_ABORT ;
818+
775819 switch (trans -> trans_state ) {
776820 case QLC_INIT :
777821 trans -> trans_state = QLC_WAIT_FOR_CHANNEL_FREE ;
@@ -853,6 +897,9 @@ static void qlcnic_sriov_process_bc_cmd(struct work_struct *work)
853897 struct qlcnic_cmd_args cmd ;
854898 u8 req ;
855899
900+ if (test_bit (QLC_BC_VF_FLR , & vf -> state ))
901+ return ;
902+
856903 trans = list_first_entry (& vf -> rcv_act .wait_list ,
857904 struct qlcnic_bc_trans , list );
858905 adapter = vf -> adapter ;
@@ -906,18 +953,30 @@ static void qlcnic_sriov_handle_bc_resp(struct qlcnic_bc_hdr *hdr,
906953 clear_bit (QLC_BC_VF_SEND , & vf -> state );
907954}
908955
909- static int qlcnic_sriov_add_act_list (struct qlcnic_sriov * sriov ,
910- struct qlcnic_vf_info * vf ,
911- struct qlcnic_bc_trans * trans )
956+ int __qlcnic_sriov_add_act_list (struct qlcnic_sriov * sriov ,
957+ struct qlcnic_vf_info * vf ,
958+ struct qlcnic_bc_trans * trans )
912959{
913960 struct qlcnic_trans_list * t_list = & vf -> rcv_act ;
914961
915- spin_lock (& t_list -> lock );
916962 t_list -> count ++ ;
917963 list_add_tail (& trans -> list , & t_list -> wait_list );
918964 if (t_list -> count == 1 )
919965 qlcnic_sriov_schedule_bc_cmd (sriov , vf ,
920966 qlcnic_sriov_process_bc_cmd );
967+ return 0 ;
968+ }
969+
970+ static int qlcnic_sriov_add_act_list (struct qlcnic_sriov * sriov ,
971+ struct qlcnic_vf_info * vf ,
972+ struct qlcnic_bc_trans * trans )
973+ {
974+ struct qlcnic_trans_list * t_list = & vf -> rcv_act ;
975+
976+ spin_lock (& t_list -> lock );
977+
978+ __qlcnic_sriov_add_act_list (sriov , vf , trans );
979+
921980 spin_unlock (& t_list -> lock );
922981 return 0 ;
923982}
@@ -1019,6 +1078,10 @@ static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov,
10191078 trans -> vf = vf ;
10201079 trans -> trans_id = hdr -> seq_id ;
10211080 trans -> curr_req_frag ++ ;
1081+
1082+ if (qlcnic_sriov_soft_flr_check (adapter , trans , vf ))
1083+ return ;
1084+
10221085 if (trans -> curr_req_frag == trans -> req_hdr -> num_frags ) {
10231086 if (qlcnic_sriov_add_act_list (sriov , vf , trans )) {
10241087 qlcnic_free_mbx_args (& cmd );
@@ -1053,6 +1116,18 @@ static void qlcnic_sriov_handle_msg_event(struct qlcnic_sriov *sriov,
10531116 }
10541117}
10551118
1119+ static void qlcnic_sriov_handle_flr_event (struct qlcnic_sriov * sriov ,
1120+ struct qlcnic_vf_info * vf )
1121+ {
1122+ struct qlcnic_adapter * adapter = vf -> adapter ;
1123+
1124+ if (qlcnic_sriov_pf_check (adapter ))
1125+ qlcnic_sriov_pf_handle_flr (sriov , vf );
1126+ else
1127+ dev_err (& adapter -> pdev -> dev ,
1128+ "Invalid event to VF. VF should not get FLR event\n" );
1129+ }
1130+
10561131void qlcnic_sriov_handle_bc_event (struct qlcnic_adapter * adapter , u32 event )
10571132{
10581133 struct qlcnic_vf_info * vf ;
@@ -1073,6 +1148,11 @@ void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *adapter, u32 event)
10731148 if (qlcnic_sriov_channel_free_check (event ))
10741149 complete (& vf -> ch_free_cmpl );
10751150
1151+ if (qlcnic_sriov_flr_check (event )) {
1152+ qlcnic_sriov_handle_flr_event (sriov , vf );
1153+ return ;
1154+ }
1155+
10761156 if (qlcnic_sriov_bc_msg_check (event ))
10771157 qlcnic_sriov_handle_msg_event (sriov , vf );
10781158}
0 commit comments