bnx2x: Support of PF driver of a VF close request
authorAriel Elior <ariele@broadcom.com>
Tue, 1 Jan 2013 05:22:40 +0000 (05:22 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 2 Jan 2013 09:45:07 +0000 (01:45 -0800)
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>
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c

index 9fd43c079045f8901aa436f1b34b5b2be645122a..3dd3a6acdf57567a6600956373a7afcf6ddcb056 100644 (file)
@@ -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
@@ -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),
@@ -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)
 {
index 9f0099c543e0c0ab59555f9dbb0c6b33ddd54769..d2a65d66c325628d1eaf95b5cdcdfdda48d98b14 100644 (file)
@@ -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 */
index af30eb4a37bf8b6cfb6050fce48a350949800966..73368aa28e26958a76d6206a2270a6188d868ca4 100644 (file)
@@ -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)
@@ -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 {