File Index
Files and directories
Sign in
FILE

ae4dma-pci.c

File preview with syntax highlighting.

linux-6.19.14/drivers/dma/amd/ae4dma/ae4dma-pci.c C
  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
 13static 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
 56static 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
 69static void ae4_deinit(struct ae4_device *ae4)
 70{
 71	ae4_free_irqs(ae4);
 72}
 73
 74static 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
125ae4_error:
126	ae4_deinit(ae4);
127
128	return ret;
129}
130
131static 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
139static const struct pci_device_id ae4_pci_table[] = {
140	{ PCI_VDEVICE(AMD, 0x149B), },
141	/* Last entry must be zero */
142	{ 0, }
143};
144MODULE_DEVICE_TABLE(pci, ae4_pci_table);
145
146static 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
153module_pci_driver(ae4_pci_driver);
154
155MODULE_LICENSE("GPL");
156MODULE_DESCRIPTION("AMD AE4DMA driver");
~/ Read-only file preview.