diff options
Diffstat (limited to 'drivers/net/ethernet/intel/idpf/idpf_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/idpf/idpf_main.c | 105 |
1 files changed, 88 insertions, 17 deletions
diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c index 8cf4ff697572..de5d722cc21d 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_main.c +++ b/drivers/net/ethernet/intel/idpf/idpf_main.c @@ -3,16 +3,94 @@ #include "idpf.h" #include "idpf_devids.h" +#include "idpf_lan_vf_regs.h" #include "idpf_virtchnl.h" #define DRV_SUMMARY "Intel(R) Infrastructure Data Path Function Linux Driver" +#define IDPF_NETWORK_ETHERNET_PROGIF 0x01 +#define IDPF_CLASS_NETWORK_ETHERNET_PROGIF \ + (PCI_CLASS_NETWORK_ETHERNET << 8 | IDPF_NETWORK_ETHERNET_PROGIF) +#define IDPF_VF_TEST_VAL 0xfeed0000u + MODULE_DESCRIPTION(DRV_SUMMARY); MODULE_IMPORT_NS("LIBETH"); MODULE_IMPORT_NS("LIBETH_XDP"); MODULE_LICENSE("GPL"); /** + * idpf_get_device_type - Helper to find if it is a VF or PF device + * @pdev: PCI device information struct + * + * Return: PF/VF device ID or -%errno on failure. + */ +static int idpf_get_device_type(struct pci_dev *pdev) +{ + void __iomem *addr; + int ret; + + addr = ioremap(pci_resource_start(pdev, 0) + VF_ARQBAL, 4); + if (!addr) { + pci_err(pdev, "Failed to allocate BAR0 mbx region\n"); + return -EIO; + } + + writel(IDPF_VF_TEST_VAL, addr); + if (readl(addr) == IDPF_VF_TEST_VAL) + ret = IDPF_DEV_ID_VF; + else + ret = IDPF_DEV_ID_PF; + + iounmap(addr); + + return ret; +} + +/** + * idpf_dev_init - Initialize device specific parameters + * @adapter: adapter to initialize + * @ent: entry in idpf_pci_tbl + * + * Return: %0 on success, -%errno on failure. + */ +static int idpf_dev_init(struct idpf_adapter *adapter, + const struct pci_device_id *ent) +{ + int ret; + + if (ent->class == IDPF_CLASS_NETWORK_ETHERNET_PROGIF) { + ret = idpf_get_device_type(adapter->pdev); + switch (ret) { + case IDPF_DEV_ID_VF: + idpf_vf_dev_ops_init(adapter); + adapter->crc_enable = true; + break; + case IDPF_DEV_ID_PF: + idpf_dev_ops_init(adapter); + break; + default: + return ret; + } + + return 0; + } + + switch (ent->device) { + case IDPF_DEV_ID_PF: + idpf_dev_ops_init(adapter); + break; + case IDPF_DEV_ID_VF: + idpf_vf_dev_ops_init(adapter); + adapter->crc_enable = true; + break; + default: + return -ENODEV; + } + + return 0; +} + +/** * idpf_remove - Device removal routine * @pdev: PCI device information struct */ @@ -167,21 +245,6 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->req_tx_splitq = true; adapter->req_rx_splitq = true; - switch (ent->device) { - case IDPF_DEV_ID_PF: - idpf_dev_ops_init(adapter); - break; - case IDPF_DEV_ID_VF: - idpf_vf_dev_ops_init(adapter); - adapter->crc_enable = true; - break; - default: - err = -ENODEV; - dev_err(&pdev->dev, "Unexpected dev ID 0x%x in idpf probe\n", - ent->device); - goto err_free; - } - adapter->pdev = pdev; err = pcim_enable_device(pdev); if (err) @@ -261,11 +324,18 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* setup msglvl */ adapter->msg_enable = netif_msg_init(-1, IDPF_AVAIL_NETIF_M); + err = idpf_dev_init(adapter, ent); + if (err) { + dev_err(&pdev->dev, "Unexpected dev ID 0x%x in idpf probe\n", + ent->device); + goto destroy_vc_event_wq; + } + err = idpf_cfg_hw(adapter); if (err) { dev_err(dev, "Failed to configure HW structure for adapter: %d\n", err); - goto err_cfg_hw; + goto destroy_vc_event_wq; } mutex_init(&adapter->vport_ctrl_lock); @@ -286,7 +356,7 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; -err_cfg_hw: +destroy_vc_event_wq: destroy_workqueue(adapter->vc_event_wq); err_vc_event_wq_alloc: destroy_workqueue(adapter->stats_wq); @@ -306,6 +376,7 @@ err_free: static const struct pci_device_id idpf_pci_tbl[] = { { PCI_VDEVICE(INTEL, IDPF_DEV_ID_PF)}, { PCI_VDEVICE(INTEL, IDPF_DEV_ID_VF)}, + { PCI_DEVICE_CLASS(IDPF_CLASS_NETWORK_ETHERNET_PROGIF, ~0)}, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(pci, idpf_pci_tbl); |
