mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-15 16:53:54 +08:00
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: Yuval Mintz <yuvalmin@broadcom.com> 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>
This commit is contained in:
parent
c2bb06db59
commit
3d7d562ca4
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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,53 +1023,59 @@ 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);
|
||||
if (rc) {
|
||||
BNX2X_ERR("Failed to copy response body to VF %d\n",
|
||||
vf->abs_vfid);
|
||||
goto mbx_error;
|
||||
}
|
||||
vf_addr -= sizeof(u64);
|
||||
pf_addr -= 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),
|
||||
(sizeof(union pfvf_tlvs) - sizeof(u64))/4);
|
||||
if (rc) {
|
||||
BNX2X_ERR("Failed to copy response body to VF %d\n",
|
||||
vf->abs_vfid);
|
||||
goto mbx_error;
|
||||
}
|
||||
vf_addr -= sizeof(u64);
|
||||
pf_addr -= sizeof(u64);
|
||||
|
||||
/* ack the FW */
|
||||
storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
|
||||
@ -1060,6 +1106,36 @@ mbx_error:
|
||||
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;
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user