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 <[email protected]>
9  */
10 
11 #include "ae4dma.h"
12 
ae4_get_irqs(struct ae4_device * ae4)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 
ae4_free_irqs(struct ae4_device * ae4)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 
ae4_deinit(struct ae4_device * ae4)69 static void ae4_deinit(struct ae4_device *ae4)
70 {
71 	ae4_free_irqs(ae4);
72 }
73 
ae4_pci_probe(struct pci_dev * pdev,const struct pci_device_id * id)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 
ae4_pci_remove(struct pci_dev * pdev)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, 0x14C8), },
141 	{ PCI_VDEVICE(AMD, 0x14DC), },
142 	{ PCI_VDEVICE(AMD, 0x149B), },
143 	/* Last entry must be zero */
144 	{ 0, }
145 };
146 MODULE_DEVICE_TABLE(pci, ae4_pci_table);
147 
148 static struct pci_driver ae4_pci_driver = {
149 	.name = "ae4dma",
150 	.id_table = ae4_pci_table,
151 	.probe = ae4_pci_probe,
152 	.remove = ae4_pci_remove,
153 };
154 
155 module_pci_driver(ae4_pci_driver);
156 
157 MODULE_LICENSE("GPL");
158 MODULE_DESCRIPTION("AMD AE4DMA driver");
159