Prowl: update hardware on mac address change

(c5208b05e7e49e5deb8d45e801807ea717ac36c8 applied to moved file)

Change-Id: I029ca1722ee6cf275f4d3f883bcbf2c71868997d
diff --git a/drivers/qtn/topaz/switch_emac.c b/drivers/qtn/topaz/switch_emac.c
index a1cd80b..bc5eb12 100644
--- a/drivers/qtn/topaz/switch_emac.c
+++ b/drivers/qtn/topaz/switch_emac.c
@@ -368,11 +368,44 @@
 	return tqe_tx(&ctl, skb2);
 }
 
+/*
+ * Google added code to attempt set the hardware MAC address for
+ * quantenna devices.
+ */
+static int topaz_set_hardware_mac(struct net_device *dev, void *p)
+{
+	int ret;
+	struct sockaddr *addr = p;
+	struct emac_common *privc = netdev_priv(dev);
+	uint32_t reg;
+
+	/* verify the dev is down */
+	ret = eth_prepare_mac_addr_change(dev, addr);
+	if (ret < 0)
+		return ret;
+
+	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+
+	/* set the hardware mac address based on code from emac_lib_init_mac */
+	reg = emac_rd(privc, EMAC_MAC_ADDR_CTRL);
+	emac_wr(privc, EMAC_MAC_ADDR_CTRL, reg & ~(MacAddr1Enable));
+	emac_wr(privc, EMAC_MAC_ADDR1_HIGH, *(u16 *)&dev->dev_addr[0]);
+	emac_wr(privc, EMAC_MAC_ADDR1_MED, *(u16 *)&dev->dev_addr[2]);
+	emac_wr(privc, EMAC_MAC_ADDR1_LOW, *(u16 *)&dev->dev_addr[4]);
+	emac_wr(privc, EMAC_MAC_ADDR_CTRL, reg | MacAddr1Enable);
+
+	emac_wr(privc, EMAC_MAC_FLOW_SA_HIGH, *(u16 *)&dev->dev_addr[0]);
+	emac_wr(privc, EMAC_MAC_FLOW_SA_MED, *(u16 *)&dev->dev_addr[2]);
+	emac_wr(privc, EMAC_MAC_FLOW_SA_LOW, *(u16 *)&dev->dev_addr[4]);
+
+	return 0;
+}
+
 static const struct net_device_ops topaz_emac_ndo = {
 	.ndo_open = topaz_emac_ndo_open,
 	.ndo_stop = topaz_emac_ndo_stop,
 	.ndo_start_xmit = topaz_emac_ndo_start_xmit,
-	.ndo_set_mac_address = eth_mac_addr,
+	.ndo_set_mac_address = topaz_set_hardware_mac,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
 	.ndo_set_rx_mode = emac_lib_set_rx_mode,
 #else