1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
--- a/src/wl/sys/wl_linux.c
+++ b/src/wl/sys/wl_linux.c
@@ -504,6 +504,7 @@
#if defined(USE_CFG80211)
struct device *parentdev;
#endif
+ bool msi_supported;
unit = wl_found + instance_base;
err = 0;
@@ -529,6 +530,7 @@
}
bzero(wl, sizeof(wl_info_t));
+ wl->pdev = (struct pci_dev *) btparam;
wl->osh = osh;
wl->unit = unit;
atomic_set(&wl->callbacks, 0);
@@ -654,9 +656,28 @@
tasklet_init(&wl->tx_tasklet, wl_tx_tasklet, (ulong)wl);
+ msi_supported = !wl->pdev->no_msi;
+ pci_info(wl->pdev, "MSI supported: %s\n", msi_supported ? "true" : "false");
+
+ if (msi_supported) {
+ int ret;
+
+ ret = pci_alloc_irq_vectors(wl->pdev, 1, 1, PCI_IRQ_MSI);
+ if (ret < 0) {
+ WL_ERROR(("wl%d: pci_alloc_irq_vectors() failed, ret %d\n", unit, ret));
+ goto fail;
+ }
+ pci_info(wl->pdev, "(MSI) allocated %d IRQ vectors", ret);
+ irq = pci_irq_vector(wl->pdev, 0);
+ pci_info(wl->pdev, "(MSI) requesting IRQ: %d\n", irq);
+ }
+
{
- if (request_irq(irq, wl_isr, IRQF_SHARED, dev->name, wl)) {
- WL_ERROR(("wl%d: request_irq() failed\n", unit));
+ int ret;
+
+ ret = request_irq(irq, wl_isr, IRQF_SHARED, dev->name, wl);
+ if (ret < 0) {
+ WL_ERROR(("wl%d: request_irq() failed, ret %d\n", unit, ret));
goto fail;
}
dev->irq = irq;
@@ -996,8 +1017,10 @@
WL_TRACE(("wl: wl_free\n"));
{
- if (wl->dev && wl->dev->irq)
+ if (wl->dev && wl->dev->irq) {
free_irq(wl->dev->irq, wl);
+ pci_free_irq_vectors(wl->pdev);
+ }
}
#if defined(WL_CONFIG_RFKILL)
--- a/src/wl/sys/wl_linux.h
+++ b/src/wl/sys/wl_linux.h
@@ -21,6 +21,7 @@
#ifndef _wl_linux_h_
#define _wl_linux_h_
+#include <linux/pci.h>
#include <wlc_types.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
#include <wlc_pub.h>
@@ -85,6 +86,7 @@
void *wlc;
osl_t *osh;
struct net_device *dev;
+ struct pci_dev *pdev;
struct semaphore sem;
spinlock_t lock;
|