Skip to content

Commit 97d8105

Browse files
Rajesh Borundiadavem330
authored andcommitted
qlcnic: VF FLR implementation.
o FLR from Hypervisor - When hypervisor issues a VF FLR request, adapter notifies the parent PF driver of the FLR request for PF driver to perform any cleanup on behalf of that VF. o FLR from VF Driver - VF driver may initiate a VF FLR request, if VF state needs to be cleaned up before a re-initialization. VF re-initialization during kdump is an example. o PF driver cleans up all resources allocated on behalf of a VF, on VF FLR notifications from the adapter or from the VF driver. Signed-off-by: Manish Chopra <[email protected]> Signed-off-by: Sucheta Chakraborty <[email protected]> Signed-off-by: Rajesh Borundia <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f80bc8f commit 97d8105

File tree

4 files changed

+320
-18
lines changed

4 files changed

+320
-18
lines changed

drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,6 +2112,7 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
21122112
if (netif_running(netdev))
21132113
qlcnic_down(adapter, netdev);
21142114

2115+
qlcnic_sriov_cleanup(adapter);
21152116
if (qlcnic_82xx_check(adapter))
21162117
qlcnic_clr_all_drv_state(adapter, 0);
21172118

drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ enum qlcnic_vf_state {
9191
QLC_BC_VF_RECV,
9292
QLC_BC_VF_CHANNEL,
9393
QLC_BC_VF_STATE,
94+
QLC_BC_VF_FLR,
95+
QLC_BC_VF_SOFT_FLR,
9496
};
9597

9698
struct qlcnic_resources {
@@ -124,9 +126,11 @@ struct qlcnic_vf_info {
124126
unsigned long state;
125127
struct completion ch_free_cmpl;
126128
struct work_struct trans_work;
129+
struct work_struct flr_work;
127130
/* It synchronizes commands sent from VF */
128131
struct mutex send_cmd_lock;
129132
struct qlcnic_bc_trans *send_cmd;
133+
struct qlcnic_bc_trans *flr_trans;
130134
struct qlcnic_trans_list rcv_act;
131135
struct qlcnic_trans_list rcv_pend;
132136
struct qlcnic_adapter *adapter;
@@ -143,6 +147,7 @@ struct qlcnic_back_channel {
143147
u16 trans_counter;
144148
struct workqueue_struct *bc_trans_wq;
145149
struct workqueue_struct *bc_async_wq;
150+
struct workqueue_struct *bc_flr_wq;
146151
struct list_head async_list;
147152
};
148153

@@ -165,6 +170,9 @@ int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *, u8);
165170
void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *, u32);
166171
int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *, u8);
167172
void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *);
173+
void qlcnic_sriov_cleanup_list(struct qlcnic_trans_list *);
174+
int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *, struct qlcnic_vf_info *,
175+
struct qlcnic_bc_trans *);
168176

169177
static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter)
170178
{
@@ -185,6 +193,10 @@ void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *, u32 *);
185193
void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *, u32 *);
186194
void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *, u32 *);
187195
void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *, u32 *);
196+
void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *, struct qlcnic_vf_info *);
197+
bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *,
198+
struct qlcnic_bc_trans *,
199+
struct qlcnic_vf_info *);
188200
#else
189201
static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
190202
static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}
@@ -209,6 +221,12 @@ qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter, u32 *int_id)
209221
static inline void
210222
qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter, u32 *int_id)
211223
{}
224+
static inline void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov,
225+
struct qlcnic_vf_info *vf) {}
226+
static inline bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *adapter,
227+
struct qlcnic_bc_trans *trans,
228+
struct qlcnic_vf_info *vf)
229+
{ return false; }
212230
#endif
213231

214232
#endif

drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
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 *);
2729
static 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+
8794
static 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+
195224
void __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)
768809
static 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+
10561131
void 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

Comments
 (0)