Example #1
0
/* CLOSE VF - opposite to INIT_VF */
void bnx2x_vfpf_close_vf(struct bnx2x *bp)
{
	struct vfpf_close_tlv *req = &bp->vf2pf_mbox->req.close;
	struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
	int i, rc;
	u32 vf_id;

	/* If we haven't got a valid VF id, there is no sense to
	 * continue with sending messages
	 */
	if (bnx2x_get_vf_id(bp, &vf_id))
		goto free_irq;

	/* Close the queues */
	for_each_queue(bp, i)
		bnx2x_vfpf_teardown_queue(bp, i);

	/* clear mailbox and prep first tlv */
	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_CLOSE, sizeof(*req));

	req->vf_id = vf_id;

	/* add list termination tlv */
	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));

	/* output tlvs list */
	bnx2x_dp_tlv_list(bp, req);

	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);

	if (rc)
		BNX2X_ERR("Sending CLOSE failed. rc was: %d\n", rc);

	else if (resp->hdr.status != PFVF_STATUS_SUCCESS)
		BNX2X_ERR("Sending CLOSE failed: pf response was %d\n",
			  resp->hdr.status);

	bnx2x_vfpf_finalize(bp, &req->first_tlv);

free_irq:
	/* Disable HW interrupts, NAPI */
	bnx2x_netif_stop(bp, 0);
	/* Delete all NAPI objects */
	bnx2x_del_all_napi(bp);

	/* Release IRQs */
	bnx2x_free_irq(bp);
}
Example #2
0
/* Clear the mailbox and init the header of the first tlv */
void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
		     u16 type, u16 length)
{
	DP(BNX2X_MSG_IOV, "preparing to send %d tlv over vf pf channel\n",
	   type);

	/* Clear mailbox */
	memset(bp->vf2pf_mbox, 0, sizeof(struct bnx2x_vf_mbx_msg));

	/* init type and length */
	bnx2x_add_tlv(bp, &first_tlv->tl, 0, type, length);

	/* init first tlv header */
	first_tlv->resp_msg_offset = sizeof(bp->vf2pf_mbox->req);
}
Example #3
0
int bnx2x_vfpf_release(struct bnx2x *bp)
{
	struct vfpf_release_tlv *req = &bp->vf2pf_mbox->req.release;
	struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
	u32 rc, vf_id;

	/* clear mailbox and prep first tlv */
	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_RELEASE, sizeof(*req));

	if (bnx2x_get_vf_id(bp, &vf_id)) {
		rc = -EAGAIN;
		goto out;
	}

	req->vf_id = vf_id;

	/* add list termination tlv */
	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));

	/* output tlvs list */
	bnx2x_dp_tlv_list(bp, req);

	/* send release request */
	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);

	if (rc)
		/* PF timeout */
		goto out;

	if (resp->hdr.status == PFVF_STATUS_SUCCESS) {
		/* PF released us */
		DP(BNX2X_MSG_SP, "vf released\n");
	} else {
		/* PF reports error */
		BNX2X_ERR("PF failed our release request - are we out of sync? response status: %d\n",
			  resp->hdr.status);
		rc = -EAGAIN;
		goto out;
	}
out:
	bnx2x_vfpf_finalize(bp, &req->first_tlv);

	return rc;
}
Example #4
0
/* Tell PF about SB addresses */
int bnx2x_vfpf_init(struct bnx2x *bp)
{
	struct vfpf_init_tlv *req = &bp->vf2pf_mbox->req.init;
	struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
	int rc, i;

	/* clear mailbox and prep first tlv */
	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_INIT, sizeof(*req));

	/* status blocks */
	for_each_eth_queue(bp, i)
		req->sb_addr[i] = (dma_addr_t)bnx2x_fp(bp, i,
						       status_blk_mapping);

	/* statistics - requests only supports single queue for now */
	req->stats_addr = bp->fw_stats_data_mapping +
			  offsetof(struct bnx2x_fw_stats_data, queue_stats);

	/* add list termination tlv */
	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));

	/* output tlvs list */
	bnx2x_dp_tlv_list(bp, req);

	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
	if (rc)
		goto out;

	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
		BNX2X_ERR("INIT VF failed: %d. Breaking...\n",
			  resp->hdr.status);
		rc = -EAGAIN;
		goto out;
	}

	DP(BNX2X_MSG_SP, "INIT VF Succeeded\n");
out:
	bnx2x_vfpf_finalize(bp, &req->first_tlv);

	return rc;
}
Example #5
0
int bnx2x_vfpf_teardown_queue(struct bnx2x *bp, int qidx)
{
	struct vfpf_q_op_tlv *req = &bp->vf2pf_mbox->req.q_op;
	struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
	int rc;

	/* clear mailbox and prep first tlv */
	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_TEARDOWN_Q,
			sizeof(*req));

	req->vf_qid = qidx;

	/* add list termination tlv */
	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));

	/* output tlvs list */
	bnx2x_dp_tlv_list(bp, req);

	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);

	if (rc) {
		BNX2X_ERR("Sending TEARDOWN for queue %d failed: %d\n", qidx,
			  rc);
		goto out;
	}

	/* PF failed the transaction */
	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
		BNX2X_ERR("TEARDOWN for queue %d failed: %d\n", qidx,
			  resp->hdr.status);
		rc = -EINVAL;
	}

out:
	bnx2x_vfpf_finalize(bp, &req->first_tlv);
	return rc;
}
Example #6
0
/* request pf to add a mac for the vf */
int bnx2x_vfpf_set_mac(struct bnx2x *bp)
{
	struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters;
	struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
	int rc = 0;

	/* clear mailbox and prep first tlv */
	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SET_Q_FILTERS,
			sizeof(*req));

	req->flags = VFPF_SET_Q_FILTERS_MAC_VLAN_CHANGED;
	req->vf_qid = 0;
	req->n_mac_vlan_filters = 1;
	req->filters[0].flags =
		VFPF_Q_FILTER_DEST_MAC_VALID | VFPF_Q_FILTER_SET_MAC;

	/* sample bulletin board for new mac */
	bnx2x_sample_bulletin(bp);

	/* copy mac from device to request */
	memcpy(req->filters[0].mac, bp->dev->dev_addr, ETH_ALEN);

	/* add list termination tlv */
	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));

	/* output tlvs list */
	bnx2x_dp_tlv_list(bp, req);

	/* send message to pf */
	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
	if (rc) {
		BNX2X_ERR("failed to send message to pf. rc was %d\n", rc);
		goto out;
	}

	/* failure may mean PF was configured with a new mac for us */
	while (resp->hdr.status == PFVF_STATUS_FAILURE) {
		DP(BNX2X_MSG_IOV,
		   "vfpf SET MAC failed. Check bulletin board for new posts\n");

		/* check if bulletin board was updated */
		if (bnx2x_sample_bulletin(bp) == PFVF_BULLETIN_UPDATED) {
			/* copy mac from device to request */
			memcpy(req->filters[0].mac, bp->dev->dev_addr,
			       ETH_ALEN);

			/* send message to pf */
			rc = bnx2x_send_msg2pf(bp, &resp->hdr.status,
					       bp->vf2pf_mbox_mapping);
		} else {
			/* no new info in bulletin */
			break;
		}
	}

	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
		BNX2X_ERR("vfpf SET MAC failed: %d\n", resp->hdr.status);
		rc = -EINVAL;
	}
out:
	bnx2x_vfpf_finalize(bp, &req->first_tlv);

	return 0;
}
Example #7
0
/* ask the pf to open a queue for the vf */
int bnx2x_vfpf_setup_q(struct bnx2x *bp, int fp_idx)
{
	struct vfpf_setup_q_tlv *req = &bp->vf2pf_mbox->req.setup_q;
	struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
	struct bnx2x_fastpath *fp = &bp->fp[fp_idx];
	u16 tpa_agg_size = 0, flags = 0;
	int rc;

	/* clear mailbox and prep first tlv */
	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SETUP_Q, sizeof(*req));

	/* select tpa mode to request */
	if (!fp->disable_tpa) {
		flags |= VFPF_QUEUE_FLG_TPA;
		flags |= VFPF_QUEUE_FLG_TPA_IPV6;
		if (fp->mode == TPA_MODE_GRO)
			flags |= VFPF_QUEUE_FLG_TPA_GRO;
		tpa_agg_size = TPA_AGG_SIZE;
	}

	/* calculate queue flags */
	flags |= VFPF_QUEUE_FLG_STATS;
	flags |= VFPF_QUEUE_FLG_CACHE_ALIGN;
	flags |= VFPF_QUEUE_FLG_VLAN;
	DP(NETIF_MSG_IFUP, "vlan removal enabled\n");

	/* Common */
	req->vf_qid = fp_idx;
	req->param_valid = VFPF_RXQ_VALID | VFPF_TXQ_VALID;

	/* Rx */
	req->rxq.rcq_addr = fp->rx_comp_mapping;
	req->rxq.rcq_np_addr = fp->rx_comp_mapping + BCM_PAGE_SIZE;
	req->rxq.rxq_addr = fp->rx_desc_mapping;
	req->rxq.sge_addr = fp->rx_sge_mapping;
	req->rxq.vf_sb = fp_idx;
	req->rxq.sb_index = HC_INDEX_ETH_RX_CQ_CONS;
	req->rxq.hc_rate = bp->rx_ticks ? 1000000/bp->rx_ticks : 0;
	req->rxq.mtu = bp->dev->mtu;
	req->rxq.buf_sz = fp->rx_buf_size;
	req->rxq.sge_buf_sz = BCM_PAGE_SIZE * PAGES_PER_SGE;
	req->rxq.tpa_agg_sz = tpa_agg_size;
	req->rxq.max_sge_pkt = SGE_PAGE_ALIGN(bp->dev->mtu) >> SGE_PAGE_SHIFT;
	req->rxq.max_sge_pkt = ((req->rxq.max_sge_pkt + PAGES_PER_SGE - 1) &
			  (~(PAGES_PER_SGE-1))) >> PAGES_PER_SGE_SHIFT;
	req->rxq.flags = flags;
	req->rxq.drop_flags = 0;
	req->rxq.cache_line_log = BNX2X_RX_ALIGN_SHIFT;
	req->rxq.stat_id = -1; /* No stats at the moment */

	/* Tx */
	req->txq.txq_addr = fp->txdata_ptr[FIRST_TX_COS_INDEX]->tx_desc_mapping;
	req->txq.vf_sb = fp_idx;
	req->txq.sb_index = HC_INDEX_ETH_TX_CQ_CONS_COS0;
	req->txq.hc_rate = bp->tx_ticks ? 1000000/bp->tx_ticks : 0;
	req->txq.flags = flags;
	req->txq.traffic_type = LLFC_TRAFFIC_TYPE_NW;

	/* add list termination tlv */
	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));

	/* output tlvs list */
	bnx2x_dp_tlv_list(bp, req);

	rc = bnx2x_send_msg2pf(bp, &resp->hdr.status, bp->vf2pf_mbox_mapping);
	if (rc)
		BNX2X_ERR("Sending SETUP_Q message for queue[%d] failed!\n",
			  fp_idx);

	if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
		BNX2X_ERR("Status of SETUP_Q for queue[%d] is %d\n",
			  fp_idx, resp->hdr.status);
		rc = -EINVAL;
	}

	bnx2x_vfpf_finalize(bp, &req->first_tlv);

	return rc;
}
Example #8
0
int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
{
	int rc = 0, attempts = 0;
	struct vfpf_acquire_tlv *req = &bp->vf2pf_mbox->req.acquire;
	struct pfvf_acquire_resp_tlv *resp = &bp->vf2pf_mbox->resp.acquire_resp;
	u32 vf_id;
	bool resources_acquired = false;

	/* clear mailbox and prep first tlv */
	bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_ACQUIRE, sizeof(*req));

	if (bnx2x_get_vf_id(bp, &vf_id)) {
		rc = -EAGAIN;
		goto out;
	}

	req->vfdev_info.vf_id = vf_id;
	req->vfdev_info.vf_os = 0;

	req->resc_request.num_rxqs = rx_count;
	req->resc_request.num_txqs = tx_count;
	req->resc_request.num_sbs = bp->igu_sb_cnt;
	req->resc_request.num_mac_filters = VF_ACQUIRE_MAC_FILTERS;
	req->resc_request.num_mc_filters = VF_ACQUIRE_MC_FILTERS;

	/* pf 2 vf bulletin board address */
	req->bulletin_addr = bp->pf2vf_bulletin_mapping;

	/* add list termination tlv */
	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));

	/* output tlvs list */
	bnx2x_dp_tlv_list(bp, req);

	while (!resources_acquired) {
		DP(BNX2X_MSG_SP, "attempting to acquire resources\n");

		/* send acquire request */
		rc = bnx2x_send_msg2pf(bp,
				       &resp->hdr.status,
				       bp->vf2pf_mbox_mapping);

		/* PF timeout */
		if (rc)
			goto out;

		/* copy acquire response from buffer to bp */
		memcpy(&bp->acquire_resp, resp, sizeof(bp->acquire_resp));

		attempts++;

		/* test whether the PF accepted our request. If not, humble the
		 * the request and try again.
		 */
		if (bp->acquire_resp.hdr.status == PFVF_STATUS_SUCCESS) {
			DP(BNX2X_MSG_SP, "resources acquired\n");
			resources_acquired = true;
		} else if (bp->acquire_resp.hdr.status ==
			   PFVF_STATUS_NO_RESOURCE &&
			   attempts < VF_ACQUIRE_THRESH) {
			DP(BNX2X_MSG_SP,
			   "PF unwilling to fulfill resource request. Try PF recommended amount\n");

			/* humble our request */
			req->resc_request.num_txqs =
				bp->acquire_resp.resc.num_txqs;
			req->resc_request.num_rxqs =
				bp->acquire_resp.resc.num_rxqs;
			req->resc_request.num_sbs =
				bp->acquire_resp.resc.num_sbs;
			req->resc_request.num_mac_filters =
				bp->acquire_resp.resc.num_mac_filters;
			req->resc_request.num_vlan_filters =
				bp->acquire_resp.resc.num_vlan_filters;
			req->resc_request.num_mc_filters =
				bp->acquire_resp.resc.num_mc_filters;

			/* Clear response buffer */
			memset(&bp->vf2pf_mbox->resp, 0,
			       sizeof(union pfvf_tlvs));
		} else {
			/* PF reports error */
			BNX2X_ERR("Failed to get the requested amount of resources: %d. Breaking...\n",
				  bp->acquire_resp.hdr.status);
			rc = -EAGAIN;
			goto out;
		}
	}

	/* get HW info */
	bp->common.chip_id |= (bp->acquire_resp.pfdev_info.chip_num & 0xffff);
	bp->link_params.chip_id = bp->common.chip_id;
	bp->db_size = bp->acquire_resp.pfdev_info.db_size;
	bp->common.int_block = INT_BLOCK_IGU;
	bp->common.chip_port_mode = CHIP_2_PORT_MODE;
	bp->igu_dsb_id = -1;
	bp->mf_ov = 0;
	bp->mf_mode = 0;
	bp->common.flash_size = 0;
	bp->flags |=
		NO_WOL_FLAG | NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG | NO_FCOE_FLAG;
	bp->igu_sb_cnt = 1;
	bp->igu_base_sb = bp->acquire_resp.resc.hw_sbs[0].hw_sb_id;
	strlcpy(bp->fw_ver, bp->acquire_resp.pfdev_info.fw_ver,
		sizeof(bp->fw_ver));

	if (is_valid_ether_addr(bp->acquire_resp.resc.current_mac_addr))
		memcpy(bp->dev->dev_addr,
		       bp->acquire_resp.resc.current_mac_addr,
		       ETH_ALEN);

out:
	bnx2x_vfpf_finalize(bp, &req->first_tlv);
	return rc;
}