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:
Yuval Mintz 2013-10-09 16:06:28 +02:00 committed by David S. Miller
parent c2bb06db59
commit 3d7d562ca4
4 changed files with 155 additions and 27 deletions

View File

@ -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 */

View File

@ -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)

View File

@ -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 @@ 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;

View File

@ -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
};