diff options
author | Maciej Szmigiero <mhej@o2.pl> | 2011-12-01 16:39:22 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-12-09 22:07:46 -0500 |
commit | 7f97c000e87751fdca69d14cba2bbba795c1a972 (patch) | |
tree | febcbb9ca2ab65cd26ed06df84981ebe8f8a3589 /drivers/tty | |
parent | 7d73aaf1d45d9bd95638680361db4d019ebb75bb (diff) |
serial: fix serial_cs I/O windows for Argosy RS-COM 2P
Current serial_cs driver has a problem when trying to detect whether
a card has multiple ports: serial_config() calls pcmcia_loop_config()
which iterates over card CIS configurations by calling
serial_check_for_multi() for each of them.
This function wants to check (and select) a configuration
that has either one long I/O window spanning multiple ports or two 8-port
windows for two serial ports.
Problem is, that every pcmcia_loop_config() iteration only updates
the windows (via pcmcia_do_loop_config() in resource[0] and resource[1])
when CONF_AUTO_SET_IO flag is set on the device, which is set only later
in the code.
Fix it by setting this flag earlier.
In addition to this, when multi-port card is detected
and it does not have an one, long I/O window
multi_config_check_notpicky() tries to locate two I/O windows and assumes
they are continuous without checking.
On an Argosy RS-COM 2P this selects first configuration, which
unfortunately has two non-continuous I/O windows.
The net effect is that the second serial port on the card does not work.
Fix it by checking whether the windows are really continuous.
Signed-off-by: Maciej Szmigiero <mhej@o2.pl>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/serial_cs.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/drivers/tty/serial/serial_cs.c b/drivers/tty/serial/serial_cs.c index eef736ff810a..86090605a84e 100644 --- a/drivers/tty/serial/serial_cs.c +++ b/drivers/tty/serial/serial_cs.c | |||
@@ -317,7 +317,7 @@ static int serial_probe(struct pcmcia_device *link) | |||
317 | info->p_dev = link; | 317 | info->p_dev = link; |
318 | link->priv = info; | 318 | link->priv = info; |
319 | 319 | ||
320 | link->config_flags |= CONF_ENABLE_IRQ; | 320 | link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
321 | if (do_sound) | 321 | if (do_sound) |
322 | link->config_flags |= CONF_ENABLE_SPKR; | 322 | link->config_flags |= CONF_ENABLE_SPKR; |
323 | 323 | ||
@@ -445,7 +445,7 @@ static int simple_config(struct pcmcia_device *link) | |||
445 | 445 | ||
446 | /* First pass: look for a config entry that looks normal. | 446 | /* First pass: look for a config entry that looks normal. |
447 | * Two tries: without IO aliases, then with aliases */ | 447 | * Two tries: without IO aliases, then with aliases */ |
448 | link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO; | 448 | link->config_flags |= CONF_AUTO_SET_VPP; |
449 | for (try = 0; try < 4; try++) | 449 | for (try = 0; try < 4; try++) |
450 | if (!pcmcia_loop_config(link, simple_config_check, &try)) | 450 | if (!pcmcia_loop_config(link, simple_config_check, &try)) |
451 | goto found_port; | 451 | goto found_port; |
@@ -501,7 +501,8 @@ static int multi_config_check_notpicky(struct pcmcia_device *p_dev, | |||
501 | { | 501 | { |
502 | int *base2 = priv_data; | 502 | int *base2 = priv_data; |
503 | 503 | ||
504 | if (!p_dev->resource[0]->end || !p_dev->resource[1]->end) | 504 | if (!p_dev->resource[0]->end || !p_dev->resource[1]->end || |
505 | p_dev->resource[0]->start + 8 != p_dev->resource[1]->start) | ||
505 | return -ENODEV; | 506 | return -ENODEV; |
506 | 507 | ||
507 | p_dev->resource[0]->end = p_dev->resource[1]->end = 8; | 508 | p_dev->resource[0]->end = p_dev->resource[1]->end = 8; |
@@ -520,7 +521,6 @@ static int multi_config(struct pcmcia_device *link) | |||
520 | struct serial_info *info = link->priv; | 521 | struct serial_info *info = link->priv; |
521 | int i, base2 = 0; | 522 | int i, base2 = 0; |
522 | 523 | ||
523 | link->config_flags |= CONF_AUTO_SET_IO; | ||
524 | /* First, look for a generic full-sized window */ | 524 | /* First, look for a generic full-sized window */ |
525 | if (!pcmcia_loop_config(link, multi_config_check, &info->multi)) | 525 | if (!pcmcia_loop_config(link, multi_config_check, &info->multi)) |
526 | base2 = link->resource[0]->start + 8; | 526 | base2 = link->resource[0]->start + 8; |