|
@@ -24,6 +24,15 @@
|
|
|
*
|
|
|
******************************************************************************/
|
|
|
|
|
|
+#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"
|
|
@@ -9521,6 +9530,44 @@ err_vsi:
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * i40e_macaddr_init - explicitly write the mac address filters.
|
|
|
+ *
|
|
|
+ * @vsi: pointer to the vsi.
|
|
|
+ * @macaddr: the MAC address
|
|
|
+ *
|
|
|
+ * This is needed when the macaddr has been obtained by other
|
|
|
+ * means than the default, e.g., from Open Firmware or IDPROM.
|
|
|
+ * Returns 0 on success, negative on failure
|
|
|
+ **/
|
|
|
+static int i40e_macaddr_init(struct i40e_vsi *vsi, u8 *macaddr)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ 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);
|
|
|
+ if (ret) {
|
|
|
+ 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,
|
|
|
+ vsi->back->hw.aq.asq_last_status));
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* i40e_vsi_setup - Set up a VSI by a given type
|
|
|
* @pf: board private structure
|
|
@@ -9645,6 +9692,17 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
|
|
|
switch (vsi->type) {
|
|
|
/* setup the netdev if needed */
|
|
|
case I40E_VSI_MAIN:
|
|
|
+ /* Apply relevant filters if a platform-specific mac
|
|
|
+ * address was selected.
|
|
|
+ */
|
|
|
+ if (!!(pf->flags & I40E_FLAG_PF_MAC)) {
|
|
|
+ ret = i40e_macaddr_init(vsi, pf->hw.mac.addr);
|
|
|
+ if (ret) {
|
|
|
+ dev_warn(&pf->pdev->dev,
|
|
|
+ "could not set up macaddr; err %d\n",
|
|
|
+ ret);
|
|
|
+ }
|
|
|
+ }
|
|
|
case I40E_VSI_VMDQ2:
|
|
|
case I40E_VSI_FCOE:
|
|
|
ret = i40e_config_netdev(vsi);
|
|
@@ -10473,6 +10531,36 @@ static void i40e_print_features(struct i40e_pf *pf)
|
|
|
WARN_ON(i > INFO_STRING_LEN);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * i40e_get_platform_mac_addr - get platform-specific MAC address
|
|
|
+ *
|
|
|
+ * @pdev: PCI device information struct
|
|
|
+ * @pf: board private structure
|
|
|
+ *
|
|
|
+ * Look up the MAC address in Open Firmware on systems that support it,
|
|
|
+ * and use IDPROM on SPARC if no OF address is found. On return, the
|
|
|
+ * I40E_FLAG_PF_MAC will be wset in pf->flags if a platform-specific value
|
|
|
+ * has been selected.
|
|
|
+ **/
|
|
|
+static void i40e_get_platform_mac_addr(struct pci_dev *pdev, struct i40e_pf *pf)
|
|
|
+{
|
|
|
+ struct device_node *dp = pci_device_to_OF_node(pdev);
|
|
|
+ const unsigned char *addr;
|
|
|
+ u8 *mac_addr = pf->hw.mac.addr;
|
|
|
+
|
|
|
+ pf->flags &= ~I40E_FLAG_PF_MAC;
|
|
|
+ addr = of_get_mac_address(dp);
|
|
|
+ if (addr) {
|
|
|
+ ether_addr_copy(mac_addr, addr);
|
|
|
+ pf->flags |= I40E_FLAG_PF_MAC;
|
|
|
+#ifdef CONFIG_SPARC
|
|
|
+ } else {
|
|
|
+ ether_addr_copy(mac_addr, idprom->id_ethaddr);
|
|
|
+ pf->flags |= I40E_FLAG_PF_MAC;
|
|
|
+#endif /* CONFIG_SPARC */
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* i40e_probe - Device initialization routine
|
|
|
* @pdev: PCI device information struct
|
|
@@ -10683,6 +10771,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
}
|
|
|
|
|
|
i40e_get_mac_addr(hw, hw->mac.addr);
|
|
|
+ /* allow a platform config to override the HW addr */
|
|
|
+ i40e_get_platform_mac_addr(pdev, pf);
|
|
|
if (!is_valid_ether_addr(hw->mac.addr)) {
|
|
|
dev_info(&pdev->dev, "invalid MAC address %pM\n", hw->mac.addr);
|
|
|
err = -EIO;
|