Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 351227
b: refs/heads/master
c: be1f1ff
h: refs/heads/master
i:
  351225: f6e9670
  351223: 7463c5f
v: v3
  • Loading branch information
Ariel Elior authored and David S. Miller committed Jan 2, 2013
1 parent edbc9a1 commit 45bd410
Show file tree
Hide file tree
Showing 8 changed files with 408 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1ab4434c64f8d4786e4a26299e0ebb138a0a6415
refs/heads/master: be1f1ffaf9acf06f556a00e2d1548c70af2b6dea
2 changes: 1 addition & 1 deletion trunk/drivers/net/ethernet/broadcom/bnx2x/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

obj-$(CONFIG_BNX2X) += bnx2x.o

bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o bnx2x_sp.o
bnx2x-objs := bnx2x_main.o bnx2x_link.o bnx2x_cmn.o bnx2x_ethtool.o bnx2x_stats.o bnx2x_dcb.o bnx2x_sp.o bnx2x_vfpf.o
13 changes: 13 additions & 0 deletions trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "bnx2x_sp.h"
#include "bnx2x_dcb.h"
#include "bnx2x_stats.h"
#include "bnx2x_vfpf.h"

enum bnx2x_int_mode {
BNX2X_INT_MODE_MSIX,
Expand Down Expand Up @@ -1244,6 +1245,9 @@ struct bnx2x {
struct bnx2x_vf_mbx_msg *vf2pf_mbox;
dma_addr_t vf2pf_mbox_mapping;

/* we set aside a copy of the acquire response */
struct pfvf_acquire_resp_tlv acquire_resp;

struct net_device *dev;
struct pci_dev *pdev;

Expand Down Expand Up @@ -2207,6 +2211,15 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define BNX2X_VPD_LEN 128
#define VENDOR_ID_LEN 4

#define VF_ACQUIRE_THRESH 3
#define VF_ACQUIRE_MAC_FILTERS 1
#define VF_ACQUIRE_MC_FILTERS 10

#define GOOD_ME_REG(me_reg) (((me_reg) & ME_REG_VF_VALID) && \
(!((me_reg) & ME_REG_VF_ERR)))
int bnx2x_get_vf_id(struct bnx2x *bp, u32 *vf_id);
int bnx2x_send_msg2pf(struct bnx2x *bp, u8 *done, dma_addr_t msg_mapping);
int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count);
/* Congestion management fairness mode */
#define CMNG_FNS_NONE 0
#define CMNG_FNS_MINMAX 1
Expand Down
185 changes: 185 additions & 0 deletions trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12234,6 +12234,12 @@ static int bnx2x_init_one(struct pci_dev *pdev,
goto init_one_exit;
}

if (IS_VF(bp)) {
rc = bnx2x_vfpf_acquire(bp, tx_count, rx_count);
if (rc)
goto init_one_exit;
}

/* calc qm_cid_count */
bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
BNX2X_DEV_INFO("qm_cid_count %d\n", bp->qm_cid_count);
Expand Down Expand Up @@ -13157,4 +13163,183 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
return cp;
}

int bnx2x_send_msg2pf(struct bnx2x *bp, u8 *done, dma_addr_t msg_mapping)
{
struct cstorm_vf_zone_data __iomem *zone_data =
REG_ADDR(bp, PXP_VF_ADDR_CSDM_GLOBAL_START);
int tout = 600, interval = 100; /* wait for 60 seconds */

if (*done) {
BNX2X_ERR("done was non zero before message to pf was sent\n");
WARN_ON(true);
return -EINVAL;
}

/* Write message address */
writel(U64_LO(msg_mapping),
&zone_data->non_trigger.vf_pf_channel.msg_addr_lo);
writel(U64_HI(msg_mapping),
&zone_data->non_trigger.vf_pf_channel.msg_addr_hi);

/* make sure the address is written before FW accesses it */
wmb();

/* Trigger the PF FW */
writeb(1, &zone_data->trigger.vf_pf_channel.addr_valid);

/* Wait for PF to complete */
while ((tout >= 0) && (!*done)) {
msleep(interval);
tout -= 1;

/* progress indicator - HV can take its own sweet time in
* answering VFs...
*/
DP_CONT(BNX2X_MSG_IOV, ".");
}

if (!*done) {
BNX2X_ERR("PF response has timed out\n");
return -EAGAIN;
}
DP(BNX2X_MSG_SP, "Got a response from PF\n");
return 0;
}

int bnx2x_get_vf_id(struct bnx2x *bp, u32 *vf_id)
{
u32 me_reg;
int tout = 10, interval = 100; /* Wait for 1 sec */

do {
/* pxp traps vf read of doorbells and returns me reg value */
me_reg = readl(bp->doorbells);
if (GOOD_ME_REG(me_reg))
break;

msleep(interval);

BNX2X_ERR("Invalid ME register value: 0x%08x\n. Is pf driver up?",
me_reg);
} while (tout-- > 0);

if (!GOOD_ME_REG(me_reg)) {
BNX2X_ERR("Invalid ME register value: 0x%08x\n", me_reg);
return -EINVAL;
}

BNX2X_ERR("valid ME register value: 0x%08x\n", me_reg);

*vf_id = (me_reg & ME_REG_VF_NUM_MASK) >> ME_REG_VF_NUM_SHIFT;

return 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))
return -EAGAIN;

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;

/* 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)
return rc;

/* 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);
return -EAGAIN;
}
}

/* 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);

return 0;
}
6 changes: 6 additions & 0 deletions trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -6558,6 +6558,12 @@
#define PXP_VF_ADDR_IGU_SIZE 0x3000
#define PXP_VF_ADDR_IGU_END\
((PXP_VF_ADDR_IGU_START) + (PXP_VF_ADDR_IGU_SIZE) - 1)

#define PXP_VF_ADDR_CSDM_GLOBAL_START 0x7600
#define PXP_VF_ADDR_CSDM_GLOBAL_SIZE (PXP_ADDR_REG_SIZE)
#define PXP_VF_ADDR_CSDM_GLOBAL_END\
((PXP_VF_ADDR_CSDM_GLOBAL_START) + (PXP_VF_ADDR_CSDM_GLOBAL_SIZE) - 1)

#define PXP_VF_ADDR_DB_START 0x7c00
#define PXP_VF_ADDR_DB_SIZE 0x200
#define PXP_VF_ADDR_DB_END\
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ struct bnx2x_vf_mbx_msg {
union pfvf_tlvs resp;
};

void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
u16 length);
void bnx2x_vfpf_prep(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv,
u16 type, u16 length);
void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list);
#endif /* bnx2x_sriov.h */
80 changes: 80 additions & 0 deletions trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* bnx2x_vfpf.c: Broadcom Everest network driver.
*
* Copyright 2009-2012 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2, available
* at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
*
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a
* license other than the GPL, without Broadcom's express prior written
* consent.
*
* Maintained by: Eilon Greenstein <eilong@broadcom.com>
* Written by: Shmulik Ravid <shmulikr@broadcom.com>
* Ariel Elior <ariele@broadcom.com>
*/

#include "bnx2x.h"
#include "bnx2x_sriov.h"

/* place a given tlv on the tlv buffer at a given offset */
void bnx2x_add_tlv(struct bnx2x *bp, void *tlvs_list, u16 offset, u16 type,
u16 length)
{
struct channel_tlv *tl =
(struct channel_tlv *)(tlvs_list + offset);

tl->type = type;
tl->length = length;
}

/* 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);
}

/* list the types and lengths of the tlvs on the buffer */
void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
{
int i = 1;
struct channel_tlv *tlv = (struct channel_tlv *)tlvs_list;

while (tlv->type != CHANNEL_TLV_LIST_END) {
/* output tlv */
DP(BNX2X_MSG_IOV, "TLV number %d: type %d, length %d\n", i,
tlv->type, tlv->length);

/* advance to next tlv */
tlvs_list += tlv->length;

/* cast general tlv list pointer to channel tlv header*/
tlv = (struct channel_tlv *)tlvs_list;

i++;

/* break condition for this loop */
if (i > MAX_TLVS_IN_LIST) {
WARN(true, "corrupt tlvs");
return;
}
}

/* output last tlv */
DP(BNX2X_MSG_IOV, "TLV number %d: type %d, length %d\n", i,
tlv->type, tlv->length);
}
Loading

0 comments on commit 45bd410

Please sign in to comment.