lkml.org 
[lkml]   [2008]   [Mar]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subjectpatch nozomi-fix-initialization-and-early-flow-control-access.patch added to gregkh-2.6 tree
From
Date

This is a note to let you know that I've just added the patch titled

Subject: nozomi: fix initialization and early flow control access

to my gregkh-2.6 tree. Its filename is

nozomi-fix-initialization-and-early-flow-control-access.patch

This tree can be found at
http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/


From fseidel@suse.de Thu Mar 6 13:20:29 2008
From: Frank Seidel <fseidel@suse.de>
Date: Thu, 06 Mar 2008 21:45:57 +0100
Subject: nozomi: fix initialization and early flow control access
To: Greg KH <greg@kroah.com>, LKML <linux-kernel@vger.kernel.org>
Message-ID: <47D05805.7010003@suse.de>


From: Frank Seidel <fseidel@suse.de>

Due to some flaws in the initialization and flow control
code kernel oopses could be triggered e.g. when accessing
the card too early after insertion.
See e.g. kernel.org bug #10077.
The main part of the fix is a trivial state management
making sure the card is realy ready to use before allowing
any access.

Signed-off-by: Frank Seidel <fseidel@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
drivers/char/nozomi.c | 61 +++++++++++++++++++++++++++++++++++---------------
1 file changed, 43 insertions(+), 18 deletions(-)

--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -190,6 +190,14 @@ enum card_type {
F32_8 = 8192, /* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
};

+/* Initialization states a card can be in */
+enum card_state {
+ NOZOMI_STATE_UKNOWN = 0,
+ NOZOMI_STATE_ENABLED = 1, /* pci device enabled */
+ NOZOMI_STATE_ALLOCATED = 2, /* config setup done */
+ NOZOMI_STATE_READY = 3, /* flowcontrols received */
+};
+
/* Two different toggle channels exist */
enum channel_type {
CH_A = 0,
@@ -385,6 +393,7 @@ struct nozomi {
spinlock_t spin_mutex; /* secures access to registers and tty */

unsigned int index_start;
+ enum card_state state;
u32 open_ttys;
};

@@ -686,6 +695,7 @@ static int nozomi_read_config_table(stru
dc->last_ier = dc->last_ier | CTRL_DL;
writew(dc->last_ier, dc->reg_ier);

+ dc->state = NOZOMI_STATE_ALLOCATED;
dev_info(&dc->pdev->dev, "Initialization OK!\n");
return 1;
}
@@ -944,6 +954,14 @@ static int receive_flow_control(struct n
case CTRL_APP2:
port = PORT_APP2;
enable_ier = APP2_DL;
+ if (dc->state == NOZOMI_STATE_ALLOCATED) {
+ /*
+ * After card initialization the flow control
+ * received for APP2 is always the last
+ */
+ dc->state = NOZOMI_STATE_READY;
+ dev_info(&dc->pdev->dev, "Device READY!\n");
+ }
break;
default:
dev_err(&dc->pdev->dev,
@@ -1366,22 +1384,12 @@ static int __devinit nozomi_card_init(st

dc->pdev = pdev;

- /* Find out what card type it is */
- nozomi_get_card_type(dc);
-
ret = pci_enable_device(dc->pdev);
if (ret) {
dev_err(&pdev->dev, "Failed to enable PCI Device\n");
goto err_free;
}

- start = pci_resource_start(dc->pdev, 0);
- if (start == 0) {
- dev_err(&pdev->dev, "No I/O address for card detected\n");
- ret = -ENODEV;
- goto err_disable_device;
- }
-
ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
if (ret) {
dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
@@ -1389,6 +1397,16 @@ static int __devinit nozomi_card_init(st
goto err_disable_device;
}

+ start = pci_resource_start(dc->pdev, 0);
+ if (start == 0) {
+ dev_err(&pdev->dev, "No I/O address for card detected\n");
+ ret = -ENODEV;
+ goto err_rel_regs;
+ }
+
+ /* Find out what card type it is */
+ nozomi_get_card_type(dc);
+
dc->base_addr = ioremap(start, dc->card_type);
if (!dc->base_addr) {
dev_err(&pdev->dev, "Unable to map card MMIO\n");
@@ -1425,6 +1443,14 @@ static int __devinit nozomi_card_init(st
dc->index_start = ndev_idx * MAX_PORT;
ndevs[ndev_idx] = dc;

+ pci_set_drvdata(pdev, dc);
+
+ /* Enable RESET interrupt */
+ dc->last_ier = RESET;
+ iowrite16(dc->last_ier, dc->reg_ier);
+
+ dc->state = NOZOMI_STATE_ENABLED;
+
for (i = 0; i < MAX_PORT; i++) {
mutex_init(&dc->port[i].tty_sem);
dc->port[i].tty_open_count = 0;
@@ -1433,12 +1459,6 @@ static int __devinit nozomi_card_init(st
&pdev->dev);
}

- /* Enable RESET interrupt. */
- dc->last_ier = RESET;
- writew(dc->last_ier, dc->reg_ier);
-
- pci_set_drvdata(pdev, dc);
-
return 0;

err_free_sbuf:
@@ -1553,7 +1573,7 @@ static int ntty_open(struct tty_struct *
struct nozomi *dc = get_dc_by_tty(tty);
unsigned long flags;

- if (!port || !dc)
+ if (!port || !dc || dc->state != NOZOMI_STATE_READY)
return -ENODEV;

if (mutex_lock_interruptible(&port->tty_sem))
@@ -1716,6 +1736,10 @@ static int ntty_tiocmget(struct tty_stru
static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
+ struct nozomi *dc = get_dc_by_tty(tty);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dc->spin_mutex, flags);
if (set & TIOCM_RTS)
set_rts(tty, 1);
else if (clear & TIOCM_RTS)
@@ -1725,6 +1749,7 @@ static int ntty_tiocmset(struct tty_stru
set_dtr(tty, 1);
else if (clear & TIOCM_DTR)
set_dtr(tty, 0);
+ spin_unlock_irqrestore(&dc->spin_mutex, flags);

return 0;
}
@@ -1762,7 +1787,7 @@ static int ntty_ioctl_tiocgicount(struct
icount.brk = cnow.brk;
icount.buf_overrun = cnow.buf_overrun;

- return copy_to_user(argp, &icount, sizeof(icount));
+ return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
}

static int ntty_ioctl(struct tty_struct *tty, struct file *file,

Patches currently in gregkh-2.6 which might be from fseidel@suse.de are

driver-core/nozomi-fix-initialization-and-early-flow-control-access.patch


\
 
 \ /
  Last update: 2008-03-06 22:35    [W:0.035 / U:1.900 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site