aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNavdeep Parhar <np@FreeBSD.org>2020-11-09 00:08:35 +0000
committerNavdeep Parhar <np@FreeBSD.org>2020-11-09 00:08:35 +0000
commitde0a3472d8f8597f2d2aaf3a3f7841fd1fec7778 (patch)
tree178b0830f35cbb5835c98a706c8f81dd51c6cf2e
parentb54ed68408082bf0890e8d61d593f3180cb0d4b8 (diff)
downloadsrc-de0a3472d8f8597f2d2aaf3a3f7841fd1fec7778.tar.gz
src-de0a3472d8f8597f2d2aaf3a3f7841fd1fec7778.zip
cxgbe(4): Allow the PF driver to set a VF's MAC address.
The MAC address can be set with the optional mac-addr property in the VF section of the iovctl.conf(5) used to instantiate the VFs. MFC after: 2 weeks Sponsored by: Chelsio Communications
Notes
Notes: svn path=/head/; revision=367502
-rw-r--r--sys/dev/cxgbe/common/common.h2
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c42
-rw-r--r--sys/dev/cxgbe/t4_iov.c65
3 files changed, 109 insertions, 0 deletions
diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h
index c502d068f0f7..522b52f141bf 100644
--- a/sys/dev/cxgbe/common/common.h
+++ b/sys/dev/cxgbe/common/common.h
@@ -691,6 +691,8 @@ void t4_idma_monitor_init(struct adapter *adapter,
void t4_idma_monitor(struct adapter *adapter,
struct sge_idma_monitor_state *idma,
int hz, int ticks);
+int t4_set_vf_mac(struct adapter *adapter, unsigned int pf, unsigned int vf,
+ unsigned int naddr, u8 *addr);
unsigned int t4_get_regs_len(struct adapter *adapter);
void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size);
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index cc12c2ab8712..6e78b5a4f762 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -10202,6 +10202,48 @@ void t4_idma_monitor(struct adapter *adapter,
}
/**
+ * t4_set_vf_mac - Set MAC address for the specified VF
+ * @adapter: The adapter
+ * @pf: the PF used to instantiate the VFs
+ * @vf: one of the VFs instantiated by the specified PF
+ * @naddr: the number of MAC addresses
+ * @addr: the MAC address(es) to be set to the specified VF
+ */
+int t4_set_vf_mac(struct adapter *adapter, unsigned int pf, unsigned int vf,
+ unsigned int naddr, u8 *addr)
+{
+ struct fw_acl_mac_cmd cmd;
+
+ 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_WRITE |
+ V_FW_ACL_MAC_CMD_PFN(pf) |
+ V_FW_ACL_MAC_CMD_VFN(vf));
+
+ /* Note: Do not enable the ACL */
+ cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd));
+ cmd.nmac = naddr;
+
+ switch (pf) {
+ case 3:
+ memcpy(cmd.macaddr3, addr, sizeof(cmd.macaddr3));
+ break;
+ case 2:
+ memcpy(cmd.macaddr2, addr, sizeof(cmd.macaddr2));
+ break;
+ case 1:
+ memcpy(cmd.macaddr1, addr, sizeof(cmd.macaddr1));
+ break;
+ case 0:
+ memcpy(cmd.macaddr0, addr, sizeof(cmd.macaddr0));
+ break;
+ }
+
+ return t4_wr_mbox(adapter, adapter->mbox, &cmd, sizeof(cmd), &cmd);
+}
+
+/**
* t4_read_pace_tbl - read the pace table
* @adap: the adapter
* @pace_vals: holds the returned values
diff --git a/sys/dev/cxgbe/t4_iov.c b/sys/dev/cxgbe/t4_iov.c
index f45a2cc0561f..f943c41ecfb4 100644
--- a/sys/dev/cxgbe/t4_iov.c
+++ b/sys/dev/cxgbe/t4_iov.c
@@ -42,12 +42,19 @@ __FBSDID("$FreeBSD$");
#endif
#include "common/common.h"
+#include "common/t4_regs.h"
#include "t4_if.h"
struct t4iov_softc {
device_t sc_dev;
device_t sc_main;
bool sc_attached;
+
+ int pf;
+ int regs_rid;
+ struct resource *regs_res;
+ bus_space_handle_t bh;
+ bus_space_tag_t bt;
};
struct {
@@ -113,6 +120,13 @@ struct {
{0x6087, "Chelsio T6225-CR 87"},
};
+static inline uint32_t
+t4iov_read_reg(struct t4iov_softc *sc, uint32_t reg)
+{
+
+ return bus_space_read_4(sc->bt, sc->bh, reg);
+}
+
static int t4iov_attach_child(device_t dev);
static int
@@ -179,10 +193,28 @@ static int
t4iov_attach(device_t dev)
{
struct t4iov_softc *sc;
+ uint32_t pl_rev, whoami;
sc = device_get_softc(dev);
sc->sc_dev = dev;
+ sc->regs_rid = PCIR_BAR(0);
+ sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->regs_rid, RF_ACTIVE);
+ if (sc->regs_res == NULL) {
+ device_printf(dev, "cannot map registers.\n");
+ return (ENXIO);
+ }
+ sc->bt = rman_get_bustag(sc->regs_res);
+ sc->bh = rman_get_bushandle(sc->regs_res);
+
+ pl_rev = t4iov_read_reg(sc, A_PL_REV);
+ whoami = t4iov_read_reg(sc, A_PL_WHOAMI);
+ if (G_CHIPID(pl_rev) <= CHELSIO_T5)
+ sc->pf = G_SOURCEPF(whoami);
+ else
+ sc->pf = G_T6_SOURCEPF(whoami);
+
sc->sc_main = pci_find_dbsf(pci_get_domain(dev), pci_get_bus(dev),
pci_get_slot(dev), 4);
if (sc->sc_main == NULL)
@@ -218,6 +250,7 @@ t4iov_attach_child(device_t dev)
#ifdef PCI_IOV
pf_schema = pci_iov_schema_alloc_node();
vf_schema = pci_iov_schema_alloc_node();
+ pci_iov_schema_add_unicast_mac(vf_schema, "mac-addr", 0, NULL);
error = pci_iov_attach_name(dev, pf_schema, vf_schema, "%s",
device_get_nameunit(pdev));
if (error) {
@@ -266,6 +299,10 @@ t4iov_detach(device_t dev)
if (error)
return (error);
}
+ if (sc->regs_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->regs_rid,
+ sc->regs_res);
+ }
return (0);
}
@@ -286,6 +323,34 @@ t4iov_iov_uninit(device_t dev)
static int
t4iov_add_vf(device_t dev, uint16_t vfnum, const struct nvlist *config)
{
+ const void *mac;
+ struct t4iov_softc *sc;
+ struct adapter *adap;
+ uint8_t ma[ETHER_ADDR_LEN];
+ size_t size;
+ int rc;
+
+ if (nvlist_exists_binary(config, "mac-addr")) {
+ mac = nvlist_get_binary(config, "mac-addr", &size);
+ bcopy(mac, ma, ETHER_ADDR_LEN);
+
+ sc = device_get_softc(dev);
+ MPASS(sc->sc_attached);
+ MPASS(sc->sc_main != NULL);
+ adap = device_get_softc(sc->sc_main);
+ if (begin_synchronized_op(adap, NULL, SLEEP_OK | INTR_OK,
+ "t4vfma") != 0)
+ return (ENXIO);
+ rc = -t4_set_vf_mac(adap, sc->pf, vfnum + 1, 1, ma);
+ end_synchronized_op(adap, 0);
+ if (rc != 0) {
+ device_printf(dev,
+ "Failed to set VF%d MAC address to "
+ "%02x:%02x:%02x:%02x:%02x:%02x, rc = %d\n", vfnum,
+ ma[0], ma[1], ma[2], ma[3], ma[4], ma[5], rc);
+ return (rc);
+ }
+ }
return (0);
}