summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2017-07-24 20:28:32 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-07-30 07:44:55 -0700
commit7d8905d064058f4b65057e0101588f362f288bc0 (patch)
tree6901f91921f7b99647fac482d6e6a38c189340de /drivers
parentc7ac15ce89242e3c25fcc49fa4d00028285fab05 (diff)
downloadlinux-7d8905d064058f4b65057e0101588f362f288bc0.tar.bz2
serial: 8250_pci: Enable device after we check black list
If the board we are guessing has been listed in black list we don't need to enable it twice. The associated driver, if any, will take care about proper initialization. To achieve this we split out two helper functions, i.e. serial_pci_is_class_communication() and serial_pci_is_blacklisted() which will be called before pcim_enable_device(). We can do this since PCI specification requires class, device and vendor ID registers to be always present in the configuration space. As an example what happens before this patch applied (These are some debug prints, don't search for them in kernel sources): serial 0000:00:04.1: Mapped GSI28 to IRQ28 serial 0000:00:04.2: Mapped GSI29 to IRQ29 serial 0000:00:04.3: Mapped GSI54 to IRQ54 8250_mid 0000:00:04.1: Mapped GSI28 to IRQ28 8250_mid 0000:00:04.2: Mapped GSI29 to IRQ29 8250_mid 0000:00:04.3: Mapped GSI54 to IRQ54 After we will have just last three lines out of above. 8250_mid 0000:00:04.1: Mapped GSI28 to IRQ28 8250_mid 0000:00:04.2: Mapped GSI29 to IRQ29 8250_mid 0000:00:04.3: Mapped GSI54 to IRQ54 While here, correct a value of error code mentioned in the comment of serial_pci_guess_board(). Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tty/serial/8250/8250_pci.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index e82d7d521010..0c101a7470b0 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -3384,17 +3384,8 @@ static const struct pci_device_id blacklist[] = {
{ PCI_VDEVICE(COMMTECH, PCI_ANY_ID), },
};
-/*
- * Given a complete unknown PCI device, try to use some heuristics to
- * guess what the configuration might be, based on the pitiful PCI
- * serial specs. Returns 0 on success, 1 on failure.
- */
-static int
-serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
+static int serial_pci_is_class_communication(struct pci_dev *dev)
{
- const struct pci_device_id *bldev;
- int num_iomem, num_port, first_port = -1, i;
-
/*
* If it is not a communications device or the programming
* interface is greater than 6, give up.
@@ -3407,6 +3398,13 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
(dev->class & 0xff) > 6)
return -ENODEV;
+ return 0;
+}
+
+static int serial_pci_is_blacklisted(struct pci_dev *dev)
+{
+ const struct pci_device_id *bldev;
+
/*
* Do not access blacklisted devices that are known not to
* feature serial ports or are handled by other modules.
@@ -3419,6 +3417,19 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
return -ENODEV;
}
+ return 0;
+}
+
+/*
+ * Given a complete unknown PCI device, try to use some heuristics to
+ * guess what the configuration might be, based on the pitiful PCI
+ * serial specs. Returns 0 on success, -ENODEV on failure.
+ */
+static int
+serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
+{
+ int num_iomem, num_port, first_port = -1, i;
+
num_iomem = num_port = 0;
for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
@@ -3639,6 +3650,14 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
board = &pci_boards[ent->driver_data];
+ rc = serial_pci_is_class_communication(dev);
+ if (rc)
+ return rc;
+
+ rc = serial_pci_is_blacklisted(dev);
+ if (rc)
+ return rc;
+
rc = pcim_enable_device(dev);
pci_save_state(dev);
if (rc)