summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Cascón <pablo.cascon@netronome.com>2017-05-28 17:52:53 -0700
committerDavid S. Miller <davem@davemloft.net>2017-05-30 11:27:03 -0400
commit9d3727595b11ab8f2837b54922efd2998f2cade5 (patch)
treeb5bd59072f2dc37dcf8c62643f726d77a1472b9c
parentd935bc84c9403f30afedc2212e6dafe7669a738d (diff)
nfp: add set_mac_address support while the interface is up
Expose FW app ability to change MAC address at runtime. Make sure we only depend on it if FW app advertised the right capability. Signed-off-by: Pablo Cascón <pablo.cascon@netronome.com> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c44
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h2
2 files changed, 36 insertions, 10 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index b3f5c8af6789..9312a737fbc9 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2123,17 +2123,16 @@ void nfp_net_coalesce_write_cfg(struct nfp_net *nn)
/**
* nfp_net_write_mac_addr() - Write mac address to the device control BAR
* @nn: NFP Net device to reconfigure
+ * @addr: MAC address to write
*
* Writes the MAC address from the netdev to the device control BAR. Does not
* perform the required reconfig. We do a bit of byte swapping dance because
* firmware is LE.
*/
-static void nfp_net_write_mac_addr(struct nfp_net *nn)
+static void nfp_net_write_mac_addr(struct nfp_net *nn, const u8 *addr)
{
- nn_writel(nn, NFP_NET_CFG_MACADDR + 0,
- get_unaligned_be32(nn->dp.netdev->dev_addr));
- nn_writew(nn, NFP_NET_CFG_MACADDR + 6,
- get_unaligned_be16(nn->dp.netdev->dev_addr + 4));
+ nn_writel(nn, NFP_NET_CFG_MACADDR + 0, get_unaligned_be32(addr));
+ nn_writew(nn, NFP_NET_CFG_MACADDR + 6, get_unaligned_be16(addr + 4));
}
static void nfp_net_vec_clear_ring_data(struct nfp_net *nn, unsigned int idx)
@@ -2238,7 +2237,7 @@ static int nfp_net_set_config_and_enable(struct nfp_net *nn)
nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, nn->dp.num_rx_rings == 64 ?
0xffffffffffffffffULL : ((u64)1 << nn->dp.num_rx_rings) - 1);
- nfp_net_write_mac_addr(nn);
+ nfp_net_write_mac_addr(nn, nn->dp.netdev->dev_addr);
nn_writel(nn, NFP_NET_CFG_MTU, nn->dp.netdev->mtu);
@@ -2997,6 +2996,27 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)
}
}
+static int nfp_net_set_mac_address(struct net_device *netdev, void *addr)
+{
+ struct nfp_net *nn = netdev_priv(netdev);
+ struct sockaddr *saddr = addr;
+ int err;
+
+ err = eth_prepare_mac_addr_change(netdev, addr);
+ if (err)
+ return err;
+
+ nfp_net_write_mac_addr(nn, saddr->sa_data);
+
+ err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_MACADDR);
+ if (err)
+ return err;
+
+ eth_commit_mac_addr_change(netdev, addr);
+
+ return 0;
+}
+
const struct net_device_ops nfp_net_netdev_ops = {
.ndo_open = nfp_net_netdev_open,
.ndo_stop = nfp_net_netdev_close,
@@ -3006,7 +3026,7 @@ const struct net_device_ops nfp_net_netdev_ops = {
.ndo_tx_timeout = nfp_net_tx_timeout,
.ndo_set_rx_mode = nfp_net_set_rx_mode,
.ndo_change_mtu = nfp_net_change_mtu,
- .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_mac_address = nfp_net_set_mac_address,
.ndo_set_features = nfp_net_set_features,
.ndo_features_check = nfp_net_features_check,
.ndo_get_phys_port_name = nfp_port_get_phys_port_name,
@@ -3029,7 +3049,7 @@ void nfp_net_info(struct nfp_net *nn)
nn->fw_ver.resv, nn->fw_ver.class,
nn->fw_ver.major, nn->fw_ver.minor,
nn->max_mtu);
- nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ nn_info(nn, "CAP: %#x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
nn->cap,
nn->cap & NFP_NET_CFG_CTRL_PROMISC ? "PROMISC " : "",
nn->cap & NFP_NET_CFG_CTRL_L2BC ? "L2BCFILT " : "",
@@ -3051,7 +3071,8 @@ void nfp_net_info(struct nfp_net *nn)
nn->cap & NFP_NET_CFG_CTRL_NVGRE ? "NVGRE " : "",
nfp_net_ebpf_capable(nn) ? "BPF " : "",
nn->cap & NFP_NET_CFG_CTRL_CSUM_COMPLETE ?
- "RXCSUM_COMPLETE " : "");
+ "RXCSUM_COMPLETE " : "",
+ nn->cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "");
}
/**
@@ -3211,7 +3232,7 @@ int nfp_net_init(struct nfp_net *nn)
if (nn->dp.chained_metadata_format && nn->fw_ver.major != 4)
nn->cap &= ~NFP_NET_CFG_CTRL_RSS;
- nfp_net_write_mac_addr(nn);
+ nfp_net_write_mac_addr(nn, nn->dp.netdev->dev_addr);
/* Determine RX packet/metadata boundary offset */
if (nn->fw_ver.major >= 2) {
@@ -3241,6 +3262,9 @@ int nfp_net_init(struct nfp_net *nn)
* and netdev->hw_features advertises which features are
* supported. By default we enable most features.
*/
+ if (nn->cap & NFP_NET_CFG_CTRL_LIVE_ADDR)
+ netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+
netdev->hw_features = NETIF_F_HIGHDMA;
if (nn->cap & NFP_NET_CFG_CTRL_RXCSUM_ANY) {
netdev->hw_features |= NETIF_F_RXCSUM;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
index df75b8dc3617..c8208bf370e0 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
@@ -135,6 +135,7 @@
#define NFP_NET_CFG_CTRL_LSO2 (0x1 << 28) /* LSO/TSO (version 2) */
#define NFP_NET_CFG_CTRL_RSS2 (0x1 << 29) /* RSS (version 2) */
#define NFP_NET_CFG_CTRL_CSUM_COMPLETE (0x1 << 30) /* Checksum complete */
+#define NFP_NET_CFG_CTRL_LIVE_ADDR (0x1 << 31) /* live MAC addr change */
#define NFP_NET_CFG_CTRL_LSO_ANY (NFP_NET_CFG_CTRL_LSO | \
NFP_NET_CFG_CTRL_LSO2)
@@ -157,6 +158,7 @@
#define NFP_NET_CFG_UPDATE_IRQMOD (0x1 << 8) /* IRQ mod change */
#define NFP_NET_CFG_UPDATE_VXLAN (0x1 << 9) /* VXLAN port change */
#define NFP_NET_CFG_UPDATE_BPF (0x1 << 10) /* BPF program load */
+#define NFP_NET_CFG_UPDATE_MACADDR (0x1 << 11) /* MAC address change */
#define NFP_NET_CFG_UPDATE_ERR (0x1 << 31) /* A error occurred */
#define NFP_NET_CFG_TXRS_ENABLE 0x0008
#define NFP_NET_CFG_RXRS_ENABLE 0x0010