*
******************************************************************************/
+#include <linux/etherdevice.h>
+#include <linux/of_net.h>
+#include <linux/pci.h>
+
+#ifdef CONFIG_SPARC
+#include <asm/idprom.h>
+#include <asm/prom.h>
+#endif
+
/* Local includes */
#include "i40e.h"
#include "i40e_diag.h"
return NULL;
}
+/**
+ * i40e_macaddr_init - explicitly write the mac address filters. This
+ * is needed when the macaddr has been obtained by other means than
+ * the default, e.g., from Open Firmware or IDPROM.
+ *
+ * @vsi: pointer to the vsi.
+ * @macaddr: the MAC address
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40e_macaddr_init(struct i40e_vsi *vsi, u8 *macaddr)
+{
+ int ret, aq_err;
+ struct i40e_aqc_add_macvlan_element_data element;
+
+ ret = i40e_aq_mac_address_write(&vsi->back->hw,
+ I40E_AQC_WRITE_TYPE_LAA_WOL,
+ macaddr, NULL);
+ if (ret) {
+ dev_info(&vsi->back->pdev->dev,
+ "Addr change for VSI failed: %d\n", ret);
+ return -EADDRNOTAVAIL;
+ }
+
+ memset(&element, 0, sizeof(element));
+ ether_addr_copy(element.mac_addr, macaddr);
+ element.flags = cpu_to_le16(I40E_AQC_MACVLAN_ADD_PERFECT_MATCH);
+ ret = i40e_aq_add_macvlan(&vsi->back->hw, vsi->seid, &element, 1, NULL);
+ aq_err = vsi->back->hw.aq.asq_last_status;
+ if (aq_err != I40E_AQ_RC_OK) {
+ dev_info(&vsi->back->pdev->dev,
+ "add filter failed err %s aq_err %s\n",
+ i40e_stat_str(&vsi->back->hw, ret),
+ i40e_aq_str(&vsi->back->hw, aq_err));
+ }
+ return ret;
+}
+
/**
* i40e_vsi_setup - Set up a VSI by a given type
* @pf: board private structure
case I40E_VSI_VMDQ2:
case I40E_VSI_FCOE:
ret = i40e_config_netdev(vsi);
+ if (ret)
+ goto err_netdev;
+ ret = i40e_macaddr_init(vsi, pf->hw.mac.addr);
if (ret)
goto err_netdev;
ret = register_netdev(vsi->netdev);
kfree(string);
}
+/**
+ * i40e_get_platform_mac_addr - get mac address from Open Firmware
+ * or IDPROM if supported by the platform
+ *
+ * @pdev: PCI device information struct
+ * @mac_addr: the MAC address to be returned
+ *
+ * Look up the MAC address in Open Firmware on systems that support it,
+ * and use IDPROM on SPARC if no OF address is found.
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int i40e_get_platform_mac_addr(struct pci_dev *pdev, u8 *mac_addr)
+{
+ struct device_node *dp = pci_device_to_OF_node(pdev);
+ const unsigned char *addr;
+
+ addr = of_get_mac_address(dp);
+ if (addr) {
+ ether_addr_copy(mac_addr, addr);
+ return 0;
+ }
+#ifdef CONFIG_SPARC
+ ether_addr_copy(mac_addr, idprom->id_ethaddr);
+ return 0;
+#else
+ return -EINVAL;
+#endif /* CONFIG_SPARC */
+}
+
/**
* i40e_probe - Device initialization routine
* @pdev: PCI device information struct
i40e_aq_stop_lldp(hw, true, NULL);
}
- i40e_get_mac_addr(hw, hw->mac.addr);
+ err = i40e_get_platform_mac_addr(pdev, hw->mac.addr);
+ if (err)
+ i40e_get_mac_addr(hw, hw->mac.addr);
if (!is_valid_ether_addr(hw->mac.addr)) {
dev_info(&pdev->dev, "invalid MAC address %pM\n", hw->mac.addr);
err = -EIO;