This adds support for BrainBoxes Multi I/O cards (4+1 serial + 1 parallel port):
02:00.0 0702: 135a:4100 (rev 02)
Subsystem: 135a:0443
Flags: fast devsel, IRQ 18
Memory at f7d02000 (32-bit, non-prefetchable) [size=128]
I/O ports at e000 [size=128]
I/O ports at e080 [size=64]
I/O ports at e0c0 [size=16]
Memory at f7d01000 (32-bit, non-prefetchable) [size=128]
Memory at f7d00000 (32-bit, non-prefetchable) [size=128]
Capabilities: [50] MSI: Enable- Count=1/4 Maskable- 64bit+
Capabilities: [78] Power Management version 3
Capabilities: [80] Express Legacy Endpoint, MSI 01
Capabilities: [100] Virtual Channel
Capabilities: [800] Advanced Error Reporting
Reported-by: Nikola Ciprich <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/parport/parport_serial.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 087e847b1da2..eda733c8f6e0 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -65,6 +65,7 @@ enum parport_pc_pci_cards {
wch_ch353_1s1p,
wch_ch353_2s1p,
wch_ch382_2s1p,
+ brainboxes_5s1p,
sunix_2s1p,
};
@@ -153,6 +154,7 @@ static struct parport_pc_pci cards[] = {
/* wch_ch353_1s1p*/ { 1, { { 1, -1}, } },
/* wch_ch353_2s1p*/ { 1, { { 2, -1}, } },
/* wch_ch382_2s1p*/ { 1, { { 2, -1}, } },
+ /* brainboxes_5s1p */ { 1, { { 3, -1 }, } },
/* sunix_2s1p */ { 1, { { 3, -1 }, } },
};
@@ -258,6 +260,10 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
{ 0x4348, 0x7053, 0x4348, 0x3253, 0, 0, wch_ch353_2s1p},
{ 0x1c00, 0x3250, 0x1c00, 0x3250, 0, 0, wch_ch382_2s1p},
+ /* BrainBoxes PX272/PX306 MIO card */
+ { PCI_VENDOR_ID_INTASHIELD, 0x4100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_5s1p },
+
/*
* More SUNIX variations. At least one of these has part number
* '5079A but subdevice 0x102. That board reports 0x0708 as
@@ -501,6 +507,12 @@ static struct pciserial_board pci_parport_serial_boards[] = {
.uart_offset = 8,
.first_offset = 0xC0,
},
+ [brainboxes_5s1p] = {
+ .flags = FL_BASE2,
+ .num_ports = 5,
+ .base_baud = 921600,
+ .uart_offset = 8,
+ },
[sunix_2s1p] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 2,
--
2.15.1
dev_warn() will print device name with associated driver,
no need to keep this open coded.
While here, adjust indentation in the rest of dev_dbg() calls.
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/parport/parport_serial.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 7cf847e6e660..e30b1a1d769d 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -568,10 +568,9 @@ static int parport_register(struct pci_dev *dev, const struct pci_device_id *id)
int irq;
if (priv->num_par == ARRAY_SIZE (priv->port)) {
- printk (KERN_WARNING
- "parport_serial: %s: only %zu parallel ports "
- "supported (%d reported)\n", pci_name (dev),
- ARRAY_SIZE(priv->port), card->numports);
+ dev_warn(&dev->dev,
+ "only %zu parallel ports supported (%d reported)\n",
+ ARRAY_SIZE(priv->port), card->numports);
break;
}
@@ -587,12 +586,12 @@ static int parport_register(struct pci_dev *dev, const struct pci_device_id *id)
irq = dev->irq;
if (irq == IRQ_NONE) {
dev_dbg(&dev->dev,
- "PCI parallel port detected: I/O at %#lx(%#lx)\n",
+ "PCI parallel port detected: I/O at %#lx(%#lx)\n",
io_lo, io_hi);
irq = PARPORT_IRQ_NONE;
} else {
dev_dbg(&dev->dev,
- "PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n",
+ "PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n",
io_lo, io_hi, irq);
}
port = parport_pc_probe_port (io_lo, io_hi, irq,
--
2.15.1
Eliminate some boilerplate code by using module_pci_driver() instead of
init/exit, moving the salient bits from init into probe.
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/parport/parport_serial.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index e30b1a1d769d..be28cc1fa37e 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -691,22 +691,8 @@ static struct pci_driver parport_serial_pci_driver = {
.pm = &parport_serial_pm_ops,
},
};
-
-
-static int __init parport_serial_init (void)
-{
- return pci_register_driver (&parport_serial_pci_driver);
-}
-
-static void __exit parport_serial_exit (void)
-{
- pci_unregister_driver (&parport_serial_pci_driver);
- return;
-}
+module_pci_driver(parport_serial_pci_driver);
MODULE_AUTHOR("Tim Waugh <[email protected]>");
MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
MODULE_LICENSE("GPL");
-
-module_init(parport_serial_init);
-module_exit(parport_serial_exit);
--
2.15.1
No functional changes involved.
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/parport/parport_serial.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index e71340014638..ae9e01ef7599 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -1,20 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Support for common PCI multi-I/O cards (which is most of them)
*
* Copyright (C) 2001 Tim Waugh <[email protected]>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- *
* Multi-function PCI cards are supposed to present separate logical
* devices on the bus. A common thing to do seems to be to just use
* one logical device with lots of base address registers for both
* parallel ports and serial ports. This driver is for dealing with
* that.
- *
*/
#include <linux/interrupt.h>
--
2.15.1
From: Andy Shevchenko <[email protected]>
There is no need to repeat the work that is already done in the PCI
driver core. The patch removes excerpts from suspend and resume
callbacks.
Note that there is no more calls performed to enable or disable a PCI
device during suspend-resume cycle. Nowadays they seems to be
superflous. Someone can read more in [1].
While here, convert calls to new driver API.
[1] https://www.kernel.org/doc/ols/2009/ols2009-pages-319-330.pdf
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/parport/parport_serial.c | 40 ++++++++++++----------------------------
1 file changed, 12 insertions(+), 28 deletions(-)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index eda733c8f6e0..9689503641dc 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -661,57 +661,41 @@ static void parport_serial_pci_remove(struct pci_dev *dev)
return;
}
-#ifdef CONFIG_PM
-static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)
+static int __maybe_unused parport_serial_pci_suspend(struct device *dev)
{
- struct parport_serial_private *priv = pci_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct parport_serial_private *priv = pci_get_drvdata(pdev);
if (priv->serial)
pciserial_suspend_ports(priv->serial);
/* FIXME: What about parport? */
-
- pci_save_state(dev);
- pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
-static int parport_serial_pci_resume(struct pci_dev *dev)
+static int __maybe_unused parport_serial_pci_resume(struct device *dev)
{
- struct parport_serial_private *priv = pci_get_drvdata(dev);
- int err;
-
- pci_set_power_state(dev, PCI_D0);
- pci_restore_state(dev);
-
- /*
- * The device may have been disabled. Re-enable it.
- */
- err = pci_enable_device(dev);
- if (err) {
- printk(KERN_ERR "parport_serial: %s: error enabling "
- "device for resume (%d)\n", pci_name(dev), err);
- return err;
- }
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct parport_serial_private *priv = pci_get_drvdata(pdev);
if (priv->serial)
pciserial_resume_ports(priv->serial);
/* FIXME: What about parport? */
-
return 0;
}
-#endif
+
+static SIMPLE_DEV_PM_OPS(parport_serial_pm_ops,
+ parport_serial_pci_suspend, parport_serial_pci_resume);
static struct pci_driver parport_serial_pci_driver = {
.name = "parport_serial",
.id_table = parport_serial_pci_tbl,
.probe = parport_serial_pci_probe,
.remove = parport_serial_pci_remove,
-#ifdef CONFIG_PM
- .suspend = parport_serial_pci_suspend,
- .resume = parport_serial_pci_resume,
-#endif
+ .driver = {
+ .pm = &parport_serial_pm_ops,
+ },
};
--
2.15.1
When ->probe() calls helper functions return theirs error codes
instead of shadowing them.
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/parport/parport_serial.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index ac72ad1cabf5..7cf847e6e660 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -536,12 +536,10 @@ static int serial_register(struct pci_dev *dev, const struct pci_device_id *id)
struct serial_private *serial;
board = &pci_parport_serial_boards[id->driver_data];
-
if (board->num_ports == 0)
return 0;
serial = pciserial_init_ports(dev, board);
-
if (IS_ERR(serial))
return PTR_ERR(serial);
@@ -627,14 +625,16 @@ static int parport_serial_pci_probe(struct pci_dev *dev,
if (err)
return err;
- if (parport_register(dev, id))
- return -ENODEV;
+ err = parport_register(dev, id);
+ if (err)
+ return err;
- if (serial_register (dev, id)) {
+ err = serial_register(dev, id);
+ if (err) {
int i;
for (i = 0; i < priv->num_par; i++)
parport_pc_unregister_port (priv->port[i]);
- return -ENODEV;
+ return err;
}
return 0;
--
2.15.1
This makes the error handling much more simpler than open-coding everything
and in addition makes the probe function smaller an tidier.
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/parport/parport_serial.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 9689503641dc..ac72ad1cabf5 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -617,27 +617,23 @@ static int parport_serial_pci_probe(struct pci_dev *dev,
struct parport_serial_private *priv;
int err;
- priv = kzalloc (sizeof *priv, GFP_KERNEL);
+ priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+
pci_set_drvdata (dev, priv);
- err = pci_enable_device (dev);
- if (err) {
- kfree (priv);
+ err = pcim_enable_device(dev);
+ if (err)
return err;
- }
- if (parport_register (dev, id)) {
- kfree (priv);
+ if (parport_register(dev, id))
return -ENODEV;
- }
if (serial_register (dev, id)) {
int i;
for (i = 0; i < priv->num_par; i++)
parport_pc_unregister_port (priv->port[i]);
- kfree (priv);
return -ENODEV;
}
@@ -657,7 +653,6 @@ static void parport_serial_pci_remove(struct pci_dev *dev)
for (i = 0; i < priv->num_par; i++)
parport_pc_unregister_port (priv->port[i]);
- kfree (priv);
return;
}
--
2.15.1
While here, remove init.h inclusion since we are not using it directly and
module.h will do this for us.
No functional changes intended.
Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/parport/parport_serial.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index be28cc1fa37e..e71340014638 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -17,14 +17,14 @@
*
*/
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/parport.h>
#include <linux/parport_pc.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
#include <linux/8250_pci.h>
enum parport_pc_pci_cards {
--
2.15.1
Tested-by: Nikola Ciprich <[email protected]>
Tested-by: Nikola Ciprich <[email protected]>
Tested-by: Nikola Ciprich <[email protected]>
Tested-by: Nikola Ciprich <[email protected]>
Tested-by: Nikola Ciprich <[email protected]>
Tested-by: Nikola Ciprich <[email protected]>
Tested-by: Nikola Ciprich <[email protected]>
Tested-by: Nikola Ciprich <[email protected]>