Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dma/amd/ae4dma/ae4dma-pci.c
26285 views
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
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
158