Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 369331
b: refs/heads/master
c: 97d8105
h: refs/heads/master
i:
  369329: 990de0e
  369327: 654f908
v: v3
  • Loading branch information
Rajesh Borundia authored and David S. Miller committed Apr 19, 2013
1 parent 028b946 commit a2dde7e
Show file tree
Hide file tree
Showing 5 changed files with 321 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f80bc8fe6d44f1f0ebd90d4e698189c5b9ad25e7
refs/heads/master: 97d8105cf3fb1eb84351ff4b69287ef7d25a4422
1 change: 1 addition & 0 deletions trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,7 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
if (netif_running(netdev))
qlcnic_down(adapter, netdev);

qlcnic_sriov_cleanup(adapter);
if (qlcnic_82xx_check(adapter))
qlcnic_clr_all_drv_state(adapter, 0);

Expand Down
18 changes: 18 additions & 0 deletions trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ enum qlcnic_vf_state {
QLC_BC_VF_RECV,
QLC_BC_VF_CHANNEL,
QLC_BC_VF_STATE,
QLC_BC_VF_FLR,
QLC_BC_VF_SOFT_FLR,
};

struct qlcnic_resources {
Expand Down Expand Up @@ -124,9 +126,11 @@ struct qlcnic_vf_info {
unsigned long state;
struct completion ch_free_cmpl;
struct work_struct trans_work;
struct work_struct flr_work;
/* It synchronizes commands sent from VF */
struct mutex send_cmd_lock;
struct qlcnic_bc_trans *send_cmd;
struct qlcnic_bc_trans *flr_trans;
struct qlcnic_trans_list rcv_act;
struct qlcnic_trans_list rcv_pend;
struct qlcnic_adapter *adapter;
Expand All @@ -143,6 +147,7 @@ struct qlcnic_back_channel {
u16 trans_counter;
struct workqueue_struct *bc_trans_wq;
struct workqueue_struct *bc_async_wq;
struct workqueue_struct *bc_flr_wq;
struct list_head async_list;
};

Expand All @@ -165,6 +170,9 @@ int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *, u8);
void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *, u32);
int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *, u8);
void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *);
void qlcnic_sriov_cleanup_list(struct qlcnic_trans_list *);
int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *, struct qlcnic_vf_info *,
struct qlcnic_bc_trans *);

static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter)
{
Expand All @@ -185,6 +193,10 @@ void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *, u32 *);
void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *, struct qlcnic_vf_info *);
bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *,
struct qlcnic_bc_trans *,
struct qlcnic_vf_info *);
#else
static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}
Expand All @@ -209,6 +221,12 @@ qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter, u32 *int_id)
static inline void
qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter, u32 *int_id)
{}
static inline void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf) {}
static inline bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *adapter,
struct qlcnic_bc_trans *trans,
struct qlcnic_vf_info *vf)
{ return false; }
#endif

#endif
90 changes: 85 additions & 5 deletions trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@

#define QLC_BC_MSG 0
#define QLC_BC_CFREE 1
#define QLC_BC_FLR 2
#define QLC_BC_HDR_SZ 16
#define QLC_BC_PAYLOAD_SZ (1024 - QLC_BC_HDR_SZ)

#define QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF 2048
#define QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF 512

static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *);
static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *,
struct qlcnic_cmd_args *);

Expand Down Expand Up @@ -84,6 +86,11 @@ static inline bool qlcnic_sriov_channel_free_check(u32 val)
return (val & (1 << QLC_BC_CFREE)) ? true : false;
}

static inline bool qlcnic_sriov_flr_check(u32 val)
{
return (val & (1 << QLC_BC_FLR)) ? true : false;
}

static inline u8 qlcnic_sriov_target_func_id(u32 val)
{
return (val >> 4) & 0xff;
Expand Down Expand Up @@ -192,17 +199,48 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
return err;
}

void qlcnic_sriov_cleanup_list(struct qlcnic_trans_list *t_list)
{
struct qlcnic_bc_trans *trans;
struct qlcnic_cmd_args cmd;
unsigned long flags;

spin_lock_irqsave(&t_list->lock, flags);

while (!list_empty(&t_list->wait_list)) {
trans = list_first_entry(&t_list->wait_list,
struct qlcnic_bc_trans, list);
list_del(&trans->list);
t_list->count--;
cmd.req.arg = (u32 *)trans->req_pay;
cmd.rsp.arg = (u32 *)trans->rsp_pay;
qlcnic_free_mbx_args(&cmd);
qlcnic_sriov_cleanup_transaction(trans);
}

spin_unlock_irqrestore(&t_list->lock, flags);
}

void __qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter)
{
struct qlcnic_sriov *sriov = adapter->ahw->sriov;
struct qlcnic_back_channel *bc = &sriov->bc;
struct qlcnic_vf_info *vf;
int i;

if (!qlcnic_sriov_enable_check(adapter))
return;

qlcnic_sriov_cleanup_async_list(bc);
destroy_workqueue(bc->bc_async_wq);

for (i = 0; i < sriov->num_vfs; i++) {
vf = &sriov->vf_info[i];
qlcnic_sriov_cleanup_list(&vf->rcv_pend);
cancel_work_sync(&vf->trans_work);
qlcnic_sriov_cleanup_list(&vf->rcv_act);
}

destroy_workqueue(bc->bc_trans_wq);

for (i = 0; i < sriov->num_vfs; i++)
Expand Down Expand Up @@ -651,6 +689,9 @@ static void qlcnic_sriov_schedule_bc_cmd(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf,
work_func_t func)
{
if (test_bit(QLC_BC_VF_FLR, &vf->state))
return;

INIT_WORK(&vf->trans_work, func);
queue_work(sriov->bc.bc_trans_wq, &vf->trans_work);
}
Expand Down Expand Up @@ -768,10 +809,13 @@ static int qlcnic_sriov_issue_bc_post(struct qlcnic_bc_trans *trans, u8 type)
static int __qlcnic_sriov_send_bc_msg(struct qlcnic_bc_trans *trans,
struct qlcnic_vf_info *vf, u8 type)
{
int err;
bool flag = true;
int err = -EIO;

while (flag) {
if (test_bit(QLC_BC_VF_FLR, &vf->state))
trans->trans_state = QLC_ABORT;

switch (trans->trans_state) {
case QLC_INIT:
trans->trans_state = QLC_WAIT_FOR_CHANNEL_FREE;
Expand Down Expand Up @@ -853,6 +897,9 @@ static void qlcnic_sriov_process_bc_cmd(struct work_struct *work)
struct qlcnic_cmd_args cmd;
u8 req;

if (test_bit(QLC_BC_VF_FLR, &vf->state))
return;

trans = list_first_entry(&vf->rcv_act.wait_list,
struct qlcnic_bc_trans, list);
adapter = vf->adapter;
Expand Down Expand Up @@ -906,18 +953,30 @@ static void qlcnic_sriov_handle_bc_resp(struct qlcnic_bc_hdr *hdr,
clear_bit(QLC_BC_VF_SEND, &vf->state);
}

static int qlcnic_sriov_add_act_list(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf,
struct qlcnic_bc_trans *trans)
int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf,
struct qlcnic_bc_trans *trans)
{
struct qlcnic_trans_list *t_list = &vf->rcv_act;

spin_lock(&t_list->lock);
t_list->count++;
list_add_tail(&trans->list, &t_list->wait_list);
if (t_list->count == 1)
qlcnic_sriov_schedule_bc_cmd(sriov, vf,
qlcnic_sriov_process_bc_cmd);
return 0;
}

static int qlcnic_sriov_add_act_list(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf,
struct qlcnic_bc_trans *trans)
{
struct qlcnic_trans_list *t_list = &vf->rcv_act;

spin_lock(&t_list->lock);

__qlcnic_sriov_add_act_list(sriov, vf, trans);

spin_unlock(&t_list->lock);
return 0;
}
Expand Down Expand Up @@ -1019,6 +1078,10 @@ static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov,
trans->vf = vf;
trans->trans_id = hdr->seq_id;
trans->curr_req_frag++;

if (qlcnic_sriov_soft_flr_check(adapter, trans, vf))
return;

if (trans->curr_req_frag == trans->req_hdr->num_frags) {
if (qlcnic_sriov_add_act_list(sriov, vf, trans)) {
qlcnic_free_mbx_args(&cmd);
Expand Down Expand Up @@ -1053,6 +1116,18 @@ static void qlcnic_sriov_handle_msg_event(struct qlcnic_sriov *sriov,
}
}

static void qlcnic_sriov_handle_flr_event(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf)
{
struct qlcnic_adapter *adapter = vf->adapter;

if (qlcnic_sriov_pf_check(adapter))
qlcnic_sriov_pf_handle_flr(sriov, vf);
else
dev_err(&adapter->pdev->dev,
"Invalid event to VF. VF should not get FLR event\n");
}

void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *adapter, u32 event)
{
struct qlcnic_vf_info *vf;
Expand All @@ -1073,6 +1148,11 @@ void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *adapter, u32 event)
if (qlcnic_sriov_channel_free_check(event))
complete(&vf->ch_free_cmpl);

if (qlcnic_sriov_flr_check(event)) {
qlcnic_sriov_handle_flr_event(sriov, vf);
return;
}

if (qlcnic_sriov_bc_msg_check(event))
qlcnic_sriov_handle_msg_event(sriov, vf);
}
Expand Down
Loading

0 comments on commit a2dde7e

Please sign in to comment.