0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/init.h>
0014 #include <linux/etherdevice.h>
0015
0016 #include "nfpcore/nfp_dev.h"
0017 #include "nfp_net_ctrl.h"
0018 #include "nfp_net.h"
0019 #include "nfp_main.h"
0020
0021
0022
0023
0024
0025
0026
0027
0028 struct nfp_net_vf {
0029 struct nfp_net *nn;
0030
0031 struct msix_entry irq_entries[NFP_NET_NON_Q_VECTORS +
0032 NFP_NET_MAX_TX_RINGS];
0033 u8 __iomem *q_bar;
0034
0035 struct dentry *ddir;
0036 };
0037
0038 static const char nfp_net_driver_name[] = "nfp_netvf";
0039
0040 static const struct pci_device_id nfp_netvf_pci_device_ids[] = {
0041 { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NFP3800_VF,
0042 PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
0043 PCI_ANY_ID, 0, NFP_DEV_NFP3800_VF,
0044 },
0045 { PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NFP6000_VF,
0046 PCI_VENDOR_ID_NETRONOME, PCI_ANY_ID,
0047 PCI_ANY_ID, 0, NFP_DEV_NFP6000_VF,
0048 },
0049 { PCI_VENDOR_ID_CORIGINE, PCI_DEVICE_ID_NFP3800_VF,
0050 PCI_VENDOR_ID_CORIGINE, PCI_ANY_ID,
0051 PCI_ANY_ID, 0, NFP_DEV_NFP3800_VF,
0052 },
0053 { PCI_VENDOR_ID_CORIGINE, PCI_DEVICE_ID_NFP6000_VF,
0054 PCI_VENDOR_ID_CORIGINE, PCI_ANY_ID,
0055 PCI_ANY_ID, 0, NFP_DEV_NFP6000_VF,
0056 },
0057 { 0, }
0058 };
0059 MODULE_DEVICE_TABLE(pci, nfp_netvf_pci_device_ids);
0060
0061 static void nfp_netvf_get_mac_addr(struct nfp_net *nn)
0062 {
0063 u8 mac_addr[ETH_ALEN];
0064
0065 put_unaligned_be32(nn_readl(nn, NFP_NET_CFG_MACADDR + 0), &mac_addr[0]);
0066 put_unaligned_be16(nn_readw(nn, NFP_NET_CFG_MACADDR + 6), &mac_addr[4]);
0067
0068 if (!is_valid_ether_addr(mac_addr)) {
0069 eth_hw_addr_random(nn->dp.netdev);
0070 return;
0071 }
0072
0073 eth_hw_addr_set(nn->dp.netdev, mac_addr);
0074 ether_addr_copy(nn->dp.netdev->perm_addr, mac_addr);
0075 }
0076
0077 static int nfp_netvf_pci_probe(struct pci_dev *pdev,
0078 const struct pci_device_id *pci_id)
0079 {
0080 const struct nfp_dev_info *dev_info;
0081 struct nfp_net_fw_version fw_ver;
0082 int max_tx_rings, max_rx_rings;
0083 u32 tx_bar_off, rx_bar_off;
0084 u32 tx_bar_sz, rx_bar_sz;
0085 int tx_bar_no, rx_bar_no;
0086 struct nfp_net_vf *vf;
0087 unsigned int num_irqs;
0088 u8 __iomem *ctrl_bar;
0089 struct nfp_net *nn;
0090 u32 startq;
0091 int stride;
0092 int err;
0093
0094 dev_info = &nfp_dev_info[pci_id->driver_data];
0095
0096 vf = kzalloc(sizeof(*vf), GFP_KERNEL);
0097 if (!vf)
0098 return -ENOMEM;
0099 pci_set_drvdata(pdev, vf);
0100
0101 err = pci_enable_device_mem(pdev);
0102 if (err)
0103 goto err_free_vf;
0104
0105 err = pci_request_regions(pdev, nfp_net_driver_name);
0106 if (err) {
0107 dev_err(&pdev->dev, "Unable to allocate device memory.\n");
0108 goto err_pci_disable;
0109 }
0110
0111 pci_set_master(pdev);
0112
0113 err = dma_set_mask_and_coherent(&pdev->dev, dev_info->dma_mask);
0114 if (err)
0115 goto err_pci_regions;
0116
0117
0118
0119
0120
0121
0122
0123 ctrl_bar = ioremap(pci_resource_start(pdev, NFP_NET_CTRL_BAR),
0124 NFP_NET_CFG_BAR_SZ);
0125 if (!ctrl_bar) {
0126 dev_err(&pdev->dev,
0127 "Failed to map resource %d\n", NFP_NET_CTRL_BAR);
0128 err = -EIO;
0129 goto err_pci_regions;
0130 }
0131
0132 nfp_net_get_fw_version(&fw_ver, ctrl_bar);
0133 if (fw_ver.extend & NFP_NET_CFG_VERSION_RESERVED_MASK ||
0134 fw_ver.class != NFP_NET_CFG_VERSION_CLASS_GENERIC) {
0135 dev_err(&pdev->dev, "Unknown Firmware ABI %d.%d.%d.%d\n",
0136 fw_ver.extend, fw_ver.class,
0137 fw_ver.major, fw_ver.minor);
0138 err = -EINVAL;
0139 goto err_ctrl_unmap;
0140 }
0141
0142
0143 if (nfp_net_fw_ver_eq(&fw_ver, 0, 0, 0, 1)) {
0144 stride = 2;
0145 tx_bar_no = NFP_NET_Q0_BAR;
0146 rx_bar_no = NFP_NET_Q1_BAR;
0147 dev_warn(&pdev->dev, "OBSOLETE Firmware detected - VF isolation not available\n");
0148 } else {
0149 switch (fw_ver.major) {
0150 case 1 ... 5:
0151 stride = 4;
0152 tx_bar_no = NFP_NET_Q0_BAR;
0153 rx_bar_no = tx_bar_no;
0154 break;
0155 default:
0156 dev_err(&pdev->dev, "Unsupported Firmware ABI %d.%d.%d.%d\n",
0157 fw_ver.extend, fw_ver.class,
0158 fw_ver.major, fw_ver.minor);
0159 err = -EINVAL;
0160 goto err_ctrl_unmap;
0161 }
0162 }
0163
0164
0165 max_tx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_TXRINGS);
0166 max_rx_rings = readl(ctrl_bar + NFP_NET_CFG_MAX_RXRINGS);
0167
0168 tx_bar_sz = NFP_QCP_QUEUE_ADDR_SZ * max_tx_rings * stride;
0169 rx_bar_sz = NFP_QCP_QUEUE_ADDR_SZ * max_rx_rings * stride;
0170
0171
0172 if (tx_bar_sz > pci_resource_len(pdev, tx_bar_no)) {
0173 dev_err(&pdev->dev,
0174 "TX BAR too small for number of TX rings. Adjusting\n");
0175 tx_bar_sz = pci_resource_len(pdev, tx_bar_no);
0176 max_tx_rings = (tx_bar_sz / NFP_QCP_QUEUE_ADDR_SZ) / 2;
0177 }
0178 if (rx_bar_sz > pci_resource_len(pdev, rx_bar_no)) {
0179 dev_err(&pdev->dev,
0180 "RX BAR too small for number of RX rings. Adjusting\n");
0181 rx_bar_sz = pci_resource_len(pdev, rx_bar_no);
0182 max_rx_rings = (rx_bar_sz / NFP_QCP_QUEUE_ADDR_SZ) / 2;
0183 }
0184
0185 startq = readl(ctrl_bar + NFP_NET_CFG_START_TXQ);
0186 tx_bar_off = nfp_qcp_queue_offset(dev_info, startq);
0187 startq = readl(ctrl_bar + NFP_NET_CFG_START_RXQ);
0188 rx_bar_off = nfp_qcp_queue_offset(dev_info, startq);
0189
0190
0191 nn = nfp_net_alloc(pdev, dev_info, ctrl_bar, true,
0192 max_tx_rings, max_rx_rings);
0193 if (IS_ERR(nn)) {
0194 err = PTR_ERR(nn);
0195 goto err_ctrl_unmap;
0196 }
0197 vf->nn = nn;
0198
0199 nn->dp.is_vf = 1;
0200 nn->stride_tx = stride;
0201 nn->stride_rx = stride;
0202
0203 if (rx_bar_no == tx_bar_no) {
0204 u32 bar_off, bar_sz;
0205 resource_size_t map_addr;
0206
0207
0208 if (tx_bar_off < rx_bar_off)
0209 bar_off = tx_bar_off;
0210 else
0211 bar_off = rx_bar_off;
0212
0213 if ((tx_bar_off + tx_bar_sz) > (rx_bar_off + rx_bar_sz))
0214 bar_sz = (tx_bar_off + tx_bar_sz) - bar_off;
0215 else
0216 bar_sz = (rx_bar_off + rx_bar_sz) - bar_off;
0217
0218 map_addr = pci_resource_start(pdev, tx_bar_no) + bar_off;
0219 vf->q_bar = ioremap(map_addr, bar_sz);
0220 if (!vf->q_bar) {
0221 nn_err(nn, "Failed to map resource %d\n", tx_bar_no);
0222 err = -EIO;
0223 goto err_netdev_free;
0224 }
0225
0226
0227 nn->tx_bar = vf->q_bar + (tx_bar_off - bar_off);
0228
0229 nn->rx_bar = vf->q_bar + (rx_bar_off - bar_off);
0230 } else {
0231 resource_size_t map_addr;
0232
0233
0234 map_addr = pci_resource_start(pdev, tx_bar_no) + tx_bar_off;
0235 nn->tx_bar = ioremap(map_addr, tx_bar_sz);
0236 if (!nn->tx_bar) {
0237 nn_err(nn, "Failed to map resource %d\n", tx_bar_no);
0238 err = -EIO;
0239 goto err_netdev_free;
0240 }
0241
0242
0243 map_addr = pci_resource_start(pdev, rx_bar_no) + rx_bar_off;
0244 nn->rx_bar = ioremap(map_addr, rx_bar_sz);
0245 if (!nn->rx_bar) {
0246 nn_err(nn, "Failed to map resource %d\n", rx_bar_no);
0247 err = -EIO;
0248 goto err_unmap_tx;
0249 }
0250 }
0251
0252 nfp_netvf_get_mac_addr(nn);
0253
0254 num_irqs = nfp_net_irqs_alloc(pdev, vf->irq_entries,
0255 NFP_NET_MIN_VNIC_IRQS,
0256 NFP_NET_NON_Q_VECTORS +
0257 nn->dp.num_r_vecs);
0258 if (!num_irqs) {
0259 nn_warn(nn, "Unable to allocate MSI-X Vectors. Exiting\n");
0260 err = -EIO;
0261 goto err_unmap_rx;
0262 }
0263 nfp_net_irqs_assign(nn, vf->irq_entries, num_irqs);
0264
0265 err = nfp_net_init(nn);
0266 if (err)
0267 goto err_irqs_disable;
0268
0269 nfp_net_info(nn);
0270 vf->ddir = nfp_net_debugfs_device_add(pdev);
0271 nfp_net_debugfs_vnic_add(nn, vf->ddir);
0272
0273 return 0;
0274
0275 err_irqs_disable:
0276 nfp_net_irqs_disable(pdev);
0277 err_unmap_rx:
0278 if (!vf->q_bar)
0279 iounmap(nn->rx_bar);
0280 err_unmap_tx:
0281 if (!vf->q_bar)
0282 iounmap(nn->tx_bar);
0283 else
0284 iounmap(vf->q_bar);
0285 err_netdev_free:
0286 nfp_net_free(nn);
0287 err_ctrl_unmap:
0288 iounmap(ctrl_bar);
0289 err_pci_regions:
0290 pci_release_regions(pdev);
0291 err_pci_disable:
0292 pci_disable_device(pdev);
0293 err_free_vf:
0294 pci_set_drvdata(pdev, NULL);
0295 kfree(vf);
0296 return err;
0297 }
0298
0299 static void nfp_netvf_pci_remove(struct pci_dev *pdev)
0300 {
0301 struct nfp_net_vf *vf;
0302 struct nfp_net *nn;
0303
0304 vf = pci_get_drvdata(pdev);
0305 if (!vf)
0306 return;
0307
0308 nn = vf->nn;
0309
0310
0311
0312
0313 nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
0314 nfp_net_debugfs_dir_clean(&vf->ddir);
0315
0316 nfp_net_clean(nn);
0317
0318 nfp_net_irqs_disable(pdev);
0319
0320 if (!vf->q_bar) {
0321 iounmap(nn->rx_bar);
0322 iounmap(nn->tx_bar);
0323 } else {
0324 iounmap(vf->q_bar);
0325 }
0326 iounmap(nn->dp.ctrl_bar);
0327
0328 nfp_net_free(nn);
0329
0330 pci_release_regions(pdev);
0331 pci_disable_device(pdev);
0332
0333 pci_set_drvdata(pdev, NULL);
0334 kfree(vf);
0335 }
0336
0337 struct pci_driver nfp_netvf_pci_driver = {
0338 .name = nfp_net_driver_name,
0339 .id_table = nfp_netvf_pci_device_ids,
0340 .probe = nfp_netvf_pci_probe,
0341 .remove = nfp_netvf_pci_remove,
0342 .shutdown = nfp_netvf_pci_remove,
0343 };