1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AMD AE4DMA driver 4 * 5 * Copyright (c) 2024, Advanced Micro Devices, Inc. 6 * All Rights Reserved. 7 * 8 * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com> 9 */ 10 11 #include "ae4dma.h" 12 13 static int ae4_get_irqs(struct ae4_device *ae4) 14 { 15 struct ae4_msix *ae4_msix = ae4->ae4_msix; 16 struct pt_device *pt = &ae4->pt; 17 struct device *dev = pt->dev; 18 struct pci_dev *pdev; 19 int i, v, ret; 20 21 pdev = to_pci_dev(dev); 22 23 for (v = 0; v < ARRAY_SIZE(ae4_msix->msix_entry); v++) 24 ae4_msix->msix_entry[v].entry = v; 25 26 ret = pci_alloc_irq_vectors(pdev, v, v, PCI_IRQ_MSIX); 27 if (ret != v) { 28 if (ret > 0) 29 pci_free_irq_vectors(pdev); 30 31 dev_err(dev, "could not enable MSI-X (%d), trying MSI\n", ret); 32 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); 33 if (ret < 0) { 34 dev_err(dev, "could not enable MSI (%d)\n", ret); 35 return ret; 36 } 37 38 ret = pci_irq_vector(pdev, 0); 39 if (ret < 0) { 40 pci_free_irq_vectors(pdev); 41 return ret; 42 } 43 44 for (i = 0; i < MAX_AE4_HW_QUEUES; i++) 45 ae4->ae4_irq[i] = ret; 46 47 } else { 48 ae4_msix->msix_count = ret; 49 for (i = 0; i < ae4_msix->msix_count; i++) 50 ae4->ae4_irq[i] = pci_irq_vector(pdev, i); 51 } 52 53 return ret; 54 } 55 56 static void ae4_free_irqs(struct ae4_device *ae4) 57 { 58 struct ae4_msix *ae4_msix = ae4->ae4_msix; 59 struct pt_device *pt = &ae4->pt; 60 struct device *dev = pt->dev; 61 struct pci_dev *pdev; 62 63 pdev = to_pci_dev(dev); 64 65 if (ae4_msix && (ae4_msix->msix_count || ae4->ae4_irq[MAX_AE4_HW_QUEUES - 1])) 66 pci_free_irq_vectors(pdev); 67 } 68 69 static void ae4_deinit(struct ae4_device *ae4) 70 { 71 ae4_free_irqs(ae4); 72 } 73 74 static int ae4_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 75 { 76 struct device *dev = &pdev->dev; 77 struct ae4_device *ae4; 78 struct pt_device *pt; 79 int bar_mask; 80 int ret = 0; 81 82 ae4 = devm_kzalloc(dev, sizeof(*ae4), GFP_KERNEL); 83 if (!ae4) 84 return -ENOMEM; 85 86 ae4->ae4_msix = devm_kzalloc(dev, sizeof(struct ae4_msix), GFP_KERNEL); 87 if (!ae4->ae4_msix) 88 return -ENOMEM; 89 90 ret = pcim_enable_device(pdev); 91 if (ret) 92 goto ae4_error; 93 94 bar_mask = pci_select_bars(pdev, IORESOURCE_MEM); 95 ret = pcim_iomap_regions(pdev, bar_mask, "ae4dma"); 96 if (ret) 97 goto ae4_error; 98 99 pt = &ae4->pt; 100 pt->dev = dev; 101 pt->ver = AE4_DMA_VERSION; 102 103 pt->io_regs = pcim_iomap_table(pdev)[0]; 104 if (!pt->io_regs) { 105 ret = -ENOMEM; 106 goto ae4_error; 107 } 108 109 ret = ae4_get_irqs(ae4); 110 if (ret < 0) 111 goto ae4_error; 112 113 pci_set_master(pdev); 114 115 dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48)); 116 117 dev_set_drvdata(dev, ae4); 118 119 ret = ae4_core_init(ae4); 120 if (ret) 121 goto ae4_error; 122 123 return 0; 124 125 ae4_error: 126 ae4_deinit(ae4); 127 128 return ret; 129 } 130 131 static void ae4_pci_remove(struct pci_dev *pdev) 132 { 133 struct ae4_device *ae4 = dev_get_drvdata(&pdev->dev); 134 135 ae4_destroy_work(ae4); 136 ae4_deinit(ae4); 137 } 138 139 static const struct pci_device_id ae4_pci_table[] = { 140 { PCI_VDEVICE(AMD, 0x149B), }, 141 /* Last entry must be zero */ 142 { 0, } 143 }; 144 MODULE_DEVICE_TABLE(pci, ae4_pci_table); 145 146 static struct pci_driver ae4_pci_driver = { 147 .name = "ae4dma", 148 .id_table = ae4_pci_table, 149 .probe = ae4_pci_probe, 150 .remove = ae4_pci_remove, 151 }; 152 153 module_pci_driver(ae4_pci_driver); 154 155 MODULE_LICENSE("GPL"); 156 MODULE_DESCRIPTION("AMD AE4DMA driver"); 157