Skip to content

Commit

Permalink
bnx2x: Support of PF driver of a VF close request
Browse files Browse the repository at this point in the history
The 'close' command is the opposite of an init request. Here the
queues of the VF are closed (if any are opened) and released.
This flow applies the 'q_teardown' flow on all the queues.
The VF state is changed by this request.
Interrupts are disabled for the VF when closed.

Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ariel Elior authored and David S. Miller committed Jan 2, 2013
1 parent 463a68a commit 99e9d21
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
97 changes: 97 additions & 0 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ enum bnx2x_vfop_mcast_state {
BNX2X_VFOP_MCAST_CHK_DONE
};

enum bnx2x_vfop_close_state {
BNX2X_VFOP_CLOSE_QUEUES,
BNX2X_VFOP_CLOSE_HW
};

enum bnx2x_vfop_rxmode_state {
BNX2X_VFOP_RXMODE_CONFIG,
BNX2X_VFOP_RXMODE_DONE
Expand Down Expand Up @@ -2300,6 +2305,28 @@ static void bnx2x_vf_qtbl_set_q(struct bnx2x *bp, u8 abs_vfid, u8 qid,
REG_WR(bp, reg, val);
}

static void bnx2x_vf_clr_qtbl(struct bnx2x *bp, struct bnx2x_virtf *vf)
{
int i;

for_each_vfq(vf, i)
bnx2x_vf_qtbl_set_q(bp, vf->abs_vfid,
vfq_qzone_id(vf, vfq_get(vf, i)), false);
}

static void bnx2x_vf_igu_disable(struct bnx2x *bp, struct bnx2x_virtf *vf)
{
u32 val;

/* clear the VF configuration - pretend */
bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf->abs_vfid));
val = REG_RD(bp, IGU_REG_VF_CONFIGURATION);
val &= ~(IGU_VF_CONF_MSI_MSIX_EN | IGU_VF_CONF_SINGLE_ISR_EN |
IGU_VF_CONF_FUNC_EN | IGU_VF_CONF_PARENT_MASK);
REG_WR(bp, IGU_REG_VF_CONFIGURATION, val);
bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
}

u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf)
{
return min_t(u8, min_t(u8, vf_sb_count(vf), BNX2X_CIDS_PER_VF),
Expand Down Expand Up @@ -2469,6 +2496,76 @@ int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf *vf, dma_addr_t *sb_map)
return 0;
}

/* VFOP close (teardown the queues, delete mcasts and close HW) */
static void bnx2x_vfop_close(struct bnx2x *bp, struct bnx2x_virtf *vf)
{
struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf);
struct bnx2x_vfop_args_qx *qx = &vfop->args.qx;
enum bnx2x_vfop_close_state state = vfop->state;
struct bnx2x_vfop_cmd cmd = {
.done = bnx2x_vfop_close,
.block = false,
};

if (vfop->rc < 0)
goto op_err;

DP(BNX2X_MSG_IOV, "vf[%d] STATE: %d\n", vf->abs_vfid, state);

switch (state) {
case BNX2X_VFOP_CLOSE_QUEUES:

if (++(qx->qid) < vf_rxq_count(vf)) {
vfop->rc = bnx2x_vfop_qdown_cmd(bp, vf, &cmd, qx->qid);
if (vfop->rc)
goto op_err;
return;
}

/* remove multicasts */
vfop->state = BNX2X_VFOP_CLOSE_HW;
vfop->rc = bnx2x_vfop_mcast_cmd(bp, vf, &cmd, NULL, 0, false);
if (vfop->rc)
goto op_err;
return;

case BNX2X_VFOP_CLOSE_HW:

/* disable the interrupts */
DP(BNX2X_MSG_IOV, "disabling igu\n");
bnx2x_vf_igu_disable(bp, vf);

/* disable the VF */
DP(BNX2X_MSG_IOV, "clearing qtbl\n");
bnx2x_vf_clr_qtbl(bp, vf);

goto op_done;
default:
bnx2x_vfop_default(state);
}
op_err:
BNX2X_ERR("VF[%d] CLOSE error: rc %d\n", vf->abs_vfid, vfop->rc);
op_done:
vf->state = VF_ACQUIRED;
DP(BNX2X_MSG_IOV, "set state to acquired\n");
bnx2x_vfop_end(bp, vf, vfop);
}

int bnx2x_vfop_close_cmd(struct bnx2x *bp,
struct bnx2x_virtf *vf,
struct bnx2x_vfop_cmd *cmd)
{
struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
if (vfop) {
vfop->args.qx.qid = -1; /* loop */
bnx2x_vfop_opset(BNX2X_VFOP_CLOSE_QUEUES,
bnx2x_vfop_close, cmd->done);
return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_close,
cmd->block);
}
return -ENOMEM;
}

void bnx2x_lock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
enum channel_tlvs tlv)
{
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,10 @@ int bnx2x_vfop_rxmode_cmd(struct bnx2x *bp,
struct bnx2x_vfop_cmd *cmd,
int qid, unsigned long accept_flags);

int bnx2x_vfop_close_cmd(struct bnx2x *bp,
struct bnx2x_virtf *vf,
struct bnx2x_vfop_cmd *cmd);

int bnx2x_vf_idx_by_abs_fid(struct bnx2x *bp, u16 abs_vfid);
u8 bnx2x_vf_max_queue_cnt(struct bnx2x *bp, struct bnx2x_virtf *vf);
/* VF FLR helpers */
Expand Down
18 changes: 18 additions & 0 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,21 @@ static void bnx2x_vf_mbx_teardown_q(struct bnx2x *bp, struct bnx2x_virtf *vf,
bnx2x_vf_mbx_resp(bp, vf);
}

static void bnx2x_vf_mbx_close_vf(struct bnx2x *bp, struct bnx2x_virtf *vf,
struct bnx2x_vf_mbx *mbx)
{
struct bnx2x_vfop_cmd cmd = {
.done = bnx2x_vf_mbx_resp,
.block = false,
};

DP(BNX2X_MSG_IOV, "VF[%d] VF_CLOSE\n", vf->abs_vfid);

vf->op_rc = bnx2x_vfop_close_cmd(bp, vf, &cmd);
if (vf->op_rc)
bnx2x_vf_mbx_resp(bp, vf);
}

/* dispatch request */
static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
struct bnx2x_vf_mbx *mbx)
Expand Down Expand Up @@ -834,6 +849,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
case CHANNEL_TLV_TEARDOWN_Q:
bnx2x_vf_mbx_teardown_q(bp, vf, mbx);
break;
case CHANNEL_TLV_CLOSE:
bnx2x_vf_mbx_close_vf(bp, vf, mbx);
break;
}

} else {
Expand Down

0 comments on commit 99e9d21

Please sign in to comment.