diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h index 820e4e10daf..c502d068f0f 100644 --- a/sys/dev/cxgbe/common/common.h +++ b/sys/dev/cxgbe/common/common.h @@ -912,6 +912,8 @@ int t4vf_get_sge_params(struct adapter *adapter); int t4vf_get_rss_glb_config(struct adapter *adapter); int t4vf_get_vfres(struct adapter *adapter); int t4vf_prep_adapter(struct adapter *adapter); +int t4vf_get_vf_mac(struct adapter *adapter, unsigned int port, + unsigned int *naddr, u8 *addr); int t4_bar2_sge_qregs(struct adapter *adapter, unsigned int qid, enum t4_bar2_qtype qtype, int user, u64 *pbar2_qoffset, unsigned int *pbar2_qid); diff --git a/sys/dev/cxgbe/common/t4vf_hw.c b/sys/dev/cxgbe/common/t4vf_hw.c index 009f34b63ee..171c4512e4c 100644 --- a/sys/dev/cxgbe/common/t4vf_hw.c +++ b/sys/dev/cxgbe/common/t4vf_hw.c @@ -382,3 +382,49 @@ int t4vf_prep_adapter(struct adapter *adapter) return 0; } + +/* + * t4vf_get_vf_mac - Get the MAC address to be set to the VI of this VF. + * @adapter: The adapter + * @port: The port associated with vf + * @naddr: the number of ACL MAC addresses returned in addr + * @addr: Placeholder for MAC addresses + * + * Find the MAC address to be set to the VF's VI. The requested MAC address + * is from the host OS via callback in the PF driver. + */ +int t4vf_get_vf_mac(struct adapter *adapter, unsigned int port, + unsigned int *naddr, u8 *addr) +{ + struct fw_acl_mac_cmd cmd; + int ret; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_ACL_MAC_CMD) | + F_FW_CMD_REQUEST | + F_FW_CMD_READ); + cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd)); + ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &cmd); + if (ret) + return ret; + + if (cmd.nmac < *naddr) + *naddr = cmd.nmac; + + switch (port) { + case 3: + memcpy(addr, cmd.macaddr3, sizeof(cmd.macaddr3)); + break; + case 2: + memcpy(addr, cmd.macaddr2, sizeof(cmd.macaddr2)); + break; + case 1: + memcpy(addr, cmd.macaddr1, sizeof(cmd.macaddr1)); + break; + case 0: + memcpy(addr, cmd.macaddr0, sizeof(cmd.macaddr0)); + break; + } + + return ret; +} diff --git a/sys/dev/cxgbe/t4_vf.c b/sys/dev/cxgbe/t4_vf.c index ec5d528184f..4c51f89d36b 100644 --- a/sys/dev/cxgbe/t4_vf.c +++ b/sys/dev/cxgbe/t4_vf.c @@ -481,7 +481,7 @@ static int t4vf_attach(device_t dev) { struct adapter *sc; - int rc = 0, i, j, rqidx, tqidx; + int rc = 0, i, j, rqidx, tqidx, n, p, pmask; struct make_dev_args mda; struct intrs_and_queues iaq; struct sge *s; @@ -618,8 +618,10 @@ t4vf_attach(device_t dev) * First pass over all the ports - allocate VIs and initialize some * basic parameters like mac address, port type, etc. */ + pmask = sc->params.vfres.pmask; for_each_port(sc, i) { struct port_info *pi; + uint8_t mac[ETHER_ADDR_LEN]; pi = malloc(sizeof(*pi), M_CXGBE, M_ZERO | M_WAITOK); sc->port[i] = pi; @@ -645,6 +647,15 @@ t4vf_attach(device_t dev) goto done; } + /* Prefer the MAC address set by the PF, if there is one. */ + n = 1; + p = ffs(pmask) - 1; + MPASS(p >= 0); + rc = t4vf_get_vf_mac(sc, p, &n, mac); + if (rc == 0 && n == 1) + t4_os_set_hw_addr(pi, mac); + pmask &= ~(1 << p); + /* No t4_link_start. */ snprintf(pi->lockname, sizeof(pi->lockname), "%sp%d",