Skip to content

Commit 99b3c58

Browse files
Piotr Gregorbjorn-helgaas
authored andcommitted
PCI: Test INTx masking during enumeration, not at run-time
The test for INTx masking via PCI_COMMAND_INTX_DISABLE performed in pci_intx_mask_supported() should be done before the device can be used. This is to avoid writing PCI_COMMAND while the driver owns the device, in case that has any effect on MSI/MSI-X interrupts. Move the content of pci_intx_mask_supported() to pci_intx_mask_broken() and call it from pci_setup_device(). The test result can be queried at any time later using the same pci_intx_mask_supported() interface as before (though with changed implementation), so callers (uio, vfio) should be unaffected. Signed-off-by: Piotr Gregor <[email protected]> [bhelgaas: changelog, remove quirk check, remove locking, move dev->broken_intx_masking assignment to caller] Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Alex Williamson <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]>
1 parent 2ea659a commit 99b3c58

File tree

3 files changed

+41
-43
lines changed

3 files changed

+41
-43
lines changed

drivers/pci/pci.c

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3708,46 +3708,6 @@ void pci_intx(struct pci_dev *pdev, int enable)
37083708
}
37093709
EXPORT_SYMBOL_GPL(pci_intx);
37103710

3711-
/**
3712-
* pci_intx_mask_supported - probe for INTx masking support
3713-
* @dev: the PCI device to operate on
3714-
*
3715-
* Check if the device dev support INTx masking via the config space
3716-
* command word.
3717-
*/
3718-
bool pci_intx_mask_supported(struct pci_dev *dev)
3719-
{
3720-
bool mask_supported = false;
3721-
u16 orig, new;
3722-
3723-
if (dev->broken_intx_masking)
3724-
return false;
3725-
3726-
pci_cfg_access_lock(dev);
3727-
3728-
pci_read_config_word(dev, PCI_COMMAND, &orig);
3729-
pci_write_config_word(dev, PCI_COMMAND,
3730-
orig ^ PCI_COMMAND_INTX_DISABLE);
3731-
pci_read_config_word(dev, PCI_COMMAND, &new);
3732-
3733-
/*
3734-
* There's no way to protect against hardware bugs or detect them
3735-
* reliably, but as long as we know what the value should be, let's
3736-
* go ahead and check it.
3737-
*/
3738-
if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
3739-
dev_err(&dev->dev, "Command register changed from 0x%x to 0x%x: driver or hardware bug?\n",
3740-
orig, new);
3741-
} else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) {
3742-
mask_supported = true;
3743-
pci_write_config_word(dev, PCI_COMMAND, orig);
3744-
}
3745-
3746-
pci_cfg_access_unlock(dev);
3747-
return mask_supported;
3748-
}
3749-
EXPORT_SYMBOL_GPL(pci_intx_mask_supported);
3750-
37513711
static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
37523712
{
37533713
struct pci_bus *bus = dev->bus;
@@ -3798,7 +3758,7 @@ static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
37983758
* @dev: the PCI device to operate on
37993759
*
38003760
* Check if the device dev has its INTx line asserted, mask it and
3801-
* return true in that case. False is returned if not interrupt was
3761+
* return true in that case. False is returned if no interrupt was
38023762
* pending.
38033763
*/
38043764
bool pci_check_and_mask_intx(struct pci_dev *dev)

drivers/pci/probe.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,34 @@ static void pci_msi_setup_pci_dev(struct pci_dev *dev)
13291329
pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
13301330
}
13311331

1332+
/**
1333+
* pci_intx_mask_broken - test PCI_COMMAND_INTX_DISABLE writability
1334+
* @dev: PCI device
1335+
*
1336+
* Test whether PCI_COMMAND_INTX_DISABLE is writable for @dev. Check this
1337+
* at enumeration-time to avoid modifying PCI_COMMAND at run-time.
1338+
*/
1339+
static int pci_intx_mask_broken(struct pci_dev *dev)
1340+
{
1341+
u16 orig, toggle, new;
1342+
1343+
pci_read_config_word(dev, PCI_COMMAND, &orig);
1344+
toggle = orig ^ PCI_COMMAND_INTX_DISABLE;
1345+
pci_write_config_word(dev, PCI_COMMAND, toggle);
1346+
pci_read_config_word(dev, PCI_COMMAND, &new);
1347+
1348+
pci_write_config_word(dev, PCI_COMMAND, orig);
1349+
1350+
/*
1351+
* PCI_COMMAND_INTX_DISABLE was reserved and read-only prior to PCI
1352+
* r2.3, so strictly speaking, a device is not *broken* if it's not
1353+
* writable. But we'll live with the misnomer for now.
1354+
*/
1355+
if (new != toggle)
1356+
return 1;
1357+
return 0;
1358+
}
1359+
13321360
/**
13331361
* pci_setup_device - fill in class and map information of a device
13341362
* @dev: the device structure to fill
@@ -1399,6 +1427,8 @@ int pci_setup_device(struct pci_dev *dev)
13991427
}
14001428
}
14011429

1430+
dev->broken_intx_masking = pci_intx_mask_broken(dev);
1431+
14021432
switch (dev->hdr_type) { /* header type */
14031433
case PCI_HEADER_TYPE_NORMAL: /* standard header */
14041434
if (class == PCI_CLASS_BRIDGE_PCI)

include/linux/pci.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ struct pci_dev {
366366
unsigned int is_thunderbolt:1; /* Thunderbolt controller */
367367
unsigned int __aer_firmware_first_valid:1;
368368
unsigned int __aer_firmware_first:1;
369-
unsigned int broken_intx_masking:1;
369+
unsigned int broken_intx_masking:1; /* INTx masking can't be used */
370370
unsigned int io_window_1k:1; /* Intel P2P bridge 1K I/O windows */
371371
unsigned int irq_managed:1;
372372
unsigned int has_secondary_link:1;
@@ -1003,6 +1003,15 @@ int __must_check pci_reenable_device(struct pci_dev *);
10031003
int __must_check pcim_enable_device(struct pci_dev *pdev);
10041004
void pcim_pin_device(struct pci_dev *pdev);
10051005

1006+
static inline bool pci_intx_mask_supported(struct pci_dev *pdev)
1007+
{
1008+
/*
1009+
* INTx masking is supported if PCI_COMMAND_INTX_DISABLE is
1010+
* writable and no quirk has marked the feature broken.
1011+
*/
1012+
return !pdev->broken_intx_masking;
1013+
}
1014+
10061015
static inline int pci_is_enabled(struct pci_dev *pdev)
10071016
{
10081017
return (atomic_read(&pdev->enable_cnt) > 0);
@@ -1026,7 +1035,6 @@ int __must_check pci_set_mwi(struct pci_dev *dev);
10261035
int pci_try_set_mwi(struct pci_dev *dev);
10271036
void pci_clear_mwi(struct pci_dev *dev);
10281037
void pci_intx(struct pci_dev *dev, int enable);
1029-
bool pci_intx_mask_supported(struct pci_dev *dev);
10301038
bool pci_check_and_mask_intx(struct pci_dev *dev);
10311039
bool pci_check_and_unmask_intx(struct pci_dev *dev);
10321040
int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask);

0 commit comments

Comments
 (0)