serial: 8250_pci: Enable device after we check black list
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Mon, 24 Jul 2017 17:28:32 +0000 (20:28 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 30 Jul 2017 14:44:55 +0000 (07:44 -0700)
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>
drivers/tty/serial/8250/8250_pci.c

index e82d7d5..0c101a7 100644 (file)
@@ -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)