Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d7d562c authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller
Browse files

bnx2x: Add ndo_get_phys_port_id support



Each network interface (either PF or VF) is identified by its port's MAC id.

Signed-off-by: default avatarYuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: default avatarAriel Elior <ariele@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c2bb06db
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1546,6 +1546,7 @@ struct bnx2x {
#define IS_VF_FLAG			(1 << 22)
#define INTERRUPTS_ENABLED_FLAG		(1 << 23)
#define BC_SUPPORTS_RMMOD_CMD		(1 << 24)
#define HAS_PHYS_PORT_ID		(1 << 25)

#define BP_NOMCP(bp)			((bp)->flags & NO_MCP_FLAG)

@@ -1876,6 +1877,8 @@ struct bnx2x {
	u32 dump_preset_idx;
	bool					stats_started;
	struct semaphore			stats_sema;

	u8					phys_port_id[ETH_ALEN];
};

/* Tx queues may be less or equal to Rx queues */
+23 −0
Original line number Diff line number Diff line
@@ -11149,6 +11149,14 @@ static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
			bnx2x_get_cnic_mac_hwinfo(bp);
	}

	if (!BP_NOMCP(bp)) {
		/* Read physical port identifier from shmem */
		val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
		val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
		bnx2x_set_mac_buf(bp->phys_port_id, val, val2);
		bp->flags |= HAS_PHYS_PORT_ID;
	}

	memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);

	if (!bnx2x_is_valid_ether_addr(bp, bp->dev->dev_addr))
@@ -12044,6 +12052,20 @@ static int bnx2x_validate_addr(struct net_device *dev)
	return 0;
}

static int bnx2x_get_phys_port_id(struct net_device *netdev,
				  struct netdev_phys_port_id *ppid)
{
	struct bnx2x *bp = netdev_priv(netdev);

	if (!(bp->flags & HAS_PHYS_PORT_ID))
		return -EOPNOTSUPP;

	ppid->id_len = sizeof(bp->phys_port_id);
	memcpy(ppid->id, bp->phys_port_id, ppid->id_len);

	return 0;
}

static const struct net_device_ops bnx2x_netdev_ops = {
	.ndo_open		= bnx2x_open,
	.ndo_stop		= bnx2x_close,
@@ -12073,6 +12095,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
#ifdef CONFIG_NET_RX_BUSY_POLL
	.ndo_busy_poll		= bnx2x_low_latency_recv,
#endif
	.ndo_get_phys_port_id	= bnx2x_get_phys_port_id,
};

static int bnx2x_set_coherency_mask(struct bnx2x *bp)
+122 −27
Original line number Diff line number Diff line
@@ -60,6 +60,30 @@ void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv)
	mutex_unlock(&bp->vf2pf_mutex);
}

/* Finds a TLV by type in a TLV buffer; If found, returns pointer to the TLV */
static void *bnx2x_search_tlv_list(struct bnx2x *bp, void *tlvs_list,
				   enum channel_tlvs req_tlv)
{
	struct channel_tlv *tlv = (struct channel_tlv *)tlvs_list;

	do {
		if (tlv->type == req_tlv)
			return tlv;

		if (!tlv->length) {
			BNX2X_ERR("Found TLV with length 0\n");
			return NULL;
		}

		tlvs_list += tlv->length;
		tlv = (struct channel_tlv *)tlvs_list;
	} while (tlv->type != CHANNEL_TLV_LIST_END);

	DP(BNX2X_MSG_IOV, "TLV list does not contain %d TLV\n", req_tlv);

	return NULL;
}

/* list the types and lengths of the tlvs on the buffer */
void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
{
@@ -196,6 +220,7 @@ 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;
	struct vfpf_port_phys_id_resp_tlv *phys_port_resp;
	u32 vf_id;
	bool resources_acquired = false;

@@ -219,8 +244,14 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
	/* pf 2 vf bulletin board address */
	req->bulletin_addr = bp->pf2vf_bulletin_mapping;

	/* Request physical port identifier */
	bnx2x_add_tlv(bp, req, req->first_tlv.tl.length,
		      CHANNEL_TLV_PHYS_PORT_ID, sizeof(struct channel_tlv));

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

	/* output tlvs list */
@@ -287,6 +318,15 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
		}
	}

	/* Retrieve physical port id (if possible) */
	phys_port_resp = (struct vfpf_port_phys_id_resp_tlv *)
			 bnx2x_search_tlv_list(bp, resp,
					       CHANNEL_TLV_PHYS_PORT_ID);
	if (phys_port_resp) {
		memcpy(bp->phys_port_id, phys_port_resp->id, ETH_ALEN);
		bp->flags |= HAS_PHYS_PORT_ID;
	}

	/* get HW info */
	bp->common.chip_id |= (bp->acquire_resp.pfdev_info.chip_num & 0xffff);
	bp->link_params.chip_id = bp->common.chip_id;
@@ -983,45 +1023,52 @@ static int bnx2x_copy32_vf_dmae(struct bnx2x *bp, u8 from_vf,
	return bnx2x_issue_dmae_with_comp(bp, &dmae);
}

static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf)
static void bnx2x_vf_mbx_resp_single_tlv(struct bnx2x *bp,
					 struct bnx2x_virtf *vf)
{
	struct bnx2x_vf_mbx *mbx = BP_VF_MBX(bp, vf->index);
	u64 vf_addr;
	dma_addr_t pf_addr;
	u16 length, type;
	int rc;
	struct pfvf_general_resp_tlv *resp = &mbx->msg->resp.general_resp;

	/* prepare response */
	type = mbx->first_tlv.tl.type;
	length = type == CHANNEL_TLV_ACQUIRE ?
		sizeof(struct pfvf_acquire_resp_tlv) :
		sizeof(struct pfvf_general_resp_tlv);
	bnx2x_add_tlv(bp, resp, 0, type, length);
	resp->hdr.status = bnx2x_pfvf_status_codes(vf->op_rc);
	bnx2x_add_tlv(bp, resp, length, CHANNEL_TLV_LIST_END,
	bnx2x_add_tlv(bp, &mbx->msg->resp, 0, type, length);
	bnx2x_add_tlv(bp, &mbx->msg->resp, length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));
}

static void bnx2x_vf_mbx_resp_send_msg(struct bnx2x *bp,
				       struct bnx2x_virtf *vf)
{
	struct bnx2x_vf_mbx *mbx = BP_VF_MBX(bp, vf->index);
	struct pfvf_general_resp_tlv *resp = &mbx->msg->resp.general_resp;
	dma_addr_t pf_addr;
	u64 vf_addr;
	int rc;

	bnx2x_dp_tlv_list(bp, resp);
	DP(BNX2X_MSG_IOV, "mailbox vf address hi 0x%x, lo 0x%x, offset 0x%x\n",
	   mbx->vf_addr_hi, mbx->vf_addr_lo, mbx->first_tlv.resp_msg_offset);

	resp->hdr.status = bnx2x_pfvf_status_codes(vf->op_rc);

	/* send response */
	vf_addr = HILO_U64(mbx->vf_addr_hi, mbx->vf_addr_lo) +
		  mbx->first_tlv.resp_msg_offset;
	pf_addr = mbx->msg_mapping +
		  offsetof(struct bnx2x_vf_mbx_msg, resp);

	/* copy the response body, if there is one, before the header, as the vf
	 * is sensitive to the header being written
	/* Copy the response buffer. The first u64 is written afterwards, as
	 * the vf is sensitive to the header being written
	 */
	if (resp->hdr.tl.length > sizeof(u64)) {
		length = resp->hdr.tl.length - sizeof(u64);
	vf_addr += sizeof(u64);
	pf_addr += sizeof(u64);
	rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr, vf->abs_vfid,
				  U64_HI(vf_addr),
				  U64_LO(vf_addr),
					  length/4);
				  (sizeof(union pfvf_tlvs) - sizeof(u64))/4);
	if (rc) {
		BNX2X_ERR("Failed to copy response body to VF %d\n",
			  vf->abs_vfid);
@@ -1029,7 +1076,6 @@ static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf)
	}
	vf_addr -= sizeof(u64);
	pf_addr -= sizeof(u64);
	}

	/* ack the FW */
	storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
@@ -1060,6 +1106,36 @@ static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf)
	bnx2x_vf_release(bp, vf, false); /* non blocking */
}

static void bnx2x_vf_mbx_resp(struct bnx2x *bp,
				       struct bnx2x_virtf *vf)
{
	bnx2x_vf_mbx_resp_single_tlv(bp, vf);
	bnx2x_vf_mbx_resp_send_msg(bp, vf);
}

static void bnx2x_vf_mbx_resp_phys_port(struct bnx2x *bp,
					struct bnx2x_virtf *vf,
					void *buffer,
					u16 *offset)
{
	struct vfpf_port_phys_id_resp_tlv *port_id;

	if (!(bp->flags & HAS_PHYS_PORT_ID))
		return;

	bnx2x_add_tlv(bp, buffer, *offset, CHANNEL_TLV_PHYS_PORT_ID,
		      sizeof(struct vfpf_port_phys_id_resp_tlv));

	port_id = (struct vfpf_port_phys_id_resp_tlv *)
		  (((u8 *)buffer) + *offset);
	memcpy(port_id->id, bp->phys_port_id, ETH_ALEN);

	/* Offset should continue representing the offset to the tail
	 * of TLV data (outside this function scope)
	 */
	*offset += sizeof(struct vfpf_port_phys_id_resp_tlv);
}

static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
				      struct bnx2x_vf_mbx *mbx, int vfop_status)
{
@@ -1067,6 +1143,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
	struct pfvf_acquire_resp_tlv *resp = &mbx->msg->resp.acquire_resp;
	struct pf_vf_resc *resc = &resp->resc;
	u8 status = bnx2x_pfvf_status_codes(vfop_status);
	u16 length;

	memset(resp, 0, sizeof(*resp));

@@ -1140,9 +1217,24 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
			resc->hw_sbs[i].sb_qid);
	DP_CONT(BNX2X_MSG_IOV, "]\n");

	/* prepare response */
	length = sizeof(struct pfvf_acquire_resp_tlv);
	bnx2x_add_tlv(bp, &mbx->msg->resp, 0, CHANNEL_TLV_ACQUIRE, length);

	/* Handle possible VF requests for physical port identifiers.
	 * 'length' should continue to indicate the offset of the first empty
	 * place in the buffer (i.e., where next TLV should be inserted)
	 */
	if (bnx2x_search_tlv_list(bp, &mbx->msg->req,
				  CHANNEL_TLV_PHYS_PORT_ID))
		bnx2x_vf_mbx_resp_phys_port(bp, vf, &mbx->msg->resp, &length);

	bnx2x_add_tlv(bp, &mbx->msg->resp, length, CHANNEL_TLV_LIST_END,
		      sizeof(struct channel_list_end_tlv));

	/* send the response */
	vf->op_rc = vfop_status;
	bnx2x_vf_mbx_resp(bp, vf);
	bnx2x_vf_mbx_resp_send_msg(bp, vf);
}

static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
@@ -1874,6 +1966,9 @@ void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event)
	/* process the VF message header */
	mbx->first_tlv = mbx->msg->req.first_tlv;

	/* Clean response buffer to refrain from falsely seeing chains */
	memset(&mbx->msg->resp, 0, sizeof(union pfvf_tlvs));

	/* dispatch the request (will prepare the response) */
	bnx2x_vf_mbx_request(bp, vf, mbx);
	goto mbx_done;
+7 −0
Original line number Diff line number Diff line
@@ -188,6 +188,12 @@ struct pfvf_acquire_resp_tlv {
	} resc;
};

struct vfpf_port_phys_id_resp_tlv {
	struct channel_tlv tl;
	u8 id[ETH_ALEN];
	u8 padding[2];
};

#define VFPF_INIT_FLG_STATS_COALESCE	(1 << 0) /* when set the VFs queues
						  * stats will be coalesced on
						  * the leading RSS queue
@@ -398,6 +404,7 @@ enum channel_tlvs {
	CHANNEL_TLV_PF_SET_MAC,
	CHANNEL_TLV_PF_SET_VLAN,
	CHANNEL_TLV_UPDATE_RSS,
	CHANNEL_TLV_PHYS_PORT_ID,
	CHANNEL_TLV_MAX
};