1 // SPDX-License-Identifier: GPL-2.0
3 * PCI Backend - Handle special overlays for broken devices.
5 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
6 * Author: Chris Bookholt <hap10@epoch.ncsc.mil>
9 #include <linux/kernel.h>
10 #include <linux/pci.h>
12 #include "conf_space.h"
13 #include "conf_space_quirks.h"
15 LIST_HEAD(xen_pcibk_quirks
);
16 static inline const struct pci_device_id
*
17 match_one_device(const struct pci_device_id
*id
, const struct pci_dev
*dev
)
19 if ((id
->vendor
== PCI_ANY_ID
|| id
->vendor
== dev
->vendor
) &&
20 (id
->device
== PCI_ANY_ID
|| id
->device
== dev
->device
) &&
21 (id
->subvendor
== PCI_ANY_ID
||
22 id
->subvendor
== dev
->subsystem_vendor
) &&
23 (id
->subdevice
== PCI_ANY_ID
||
24 id
->subdevice
== dev
->subsystem_device
) &&
25 !((id
->class ^ dev
->class) & id
->class_mask
))
30 static struct xen_pcibk_config_quirk
*xen_pcibk_find_quirk(struct pci_dev
*dev
)
32 struct xen_pcibk_config_quirk
*tmp_quirk
;
34 list_for_each_entry(tmp_quirk
, &xen_pcibk_quirks
, quirks_list
)
35 if (match_one_device(&tmp_quirk
->devid
, dev
) != NULL
)
38 printk(KERN_DEBUG DRV_NAME
39 ": quirk didn't match any device known\n");
44 static inline void register_quirk(struct xen_pcibk_config_quirk
*quirk
)
46 list_add_tail(&quirk
->quirks_list
, &xen_pcibk_quirks
);
49 int xen_pcibk_field_is_dup(struct pci_dev
*dev
, unsigned int reg
)
52 struct xen_pcibk_dev_data
*dev_data
= pci_get_drvdata(dev
);
53 struct config_field_entry
*cfg_entry
;
55 list_for_each_entry(cfg_entry
, &dev_data
->config_fields
, list
) {
56 if (OFFSET(cfg_entry
) == reg
) {
64 int xen_pcibk_config_quirks_add_field(struct pci_dev
*dev
, struct config_field
69 switch (field
->size
) {
71 field
->u
.b
.read
= xen_pcibk_read_config_byte
;
72 field
->u
.b
.write
= xen_pcibk_write_config_byte
;
75 field
->u
.w
.read
= xen_pcibk_read_config_word
;
76 field
->u
.w
.write
= xen_pcibk_write_config_word
;
79 field
->u
.dw
.read
= xen_pcibk_read_config_dword
;
80 field
->u
.dw
.write
= xen_pcibk_write_config_dword
;
87 xen_pcibk_config_add_field(dev
, field
);
93 int xen_pcibk_config_quirks_init(struct pci_dev
*dev
)
95 struct xen_pcibk_config_quirk
*quirk
;
98 quirk
= kzalloc(sizeof(*quirk
), GFP_ATOMIC
);
104 quirk
->devid
.vendor
= dev
->vendor
;
105 quirk
->devid
.device
= dev
->device
;
106 quirk
->devid
.subvendor
= dev
->subsystem_vendor
;
107 quirk
->devid
.subdevice
= dev
->subsystem_device
;
108 quirk
->devid
.class = 0;
109 quirk
->devid
.class_mask
= 0;
110 quirk
->devid
.driver_data
= 0UL;
114 register_quirk(quirk
);
119 void xen_pcibk_config_field_free(struct config_field
*field
)
124 int xen_pcibk_config_quirk_release(struct pci_dev
*dev
)
126 struct xen_pcibk_config_quirk
*quirk
;
129 quirk
= xen_pcibk_find_quirk(dev
);
135 list_del(&quirk
->quirks_list
);