From: Greg Howard The Altix system controller communication driver currently exits the read and write routines with semaphores still held in some error conditions; fix this. Also remove an unnecessary typecast, and use wake_up() instead of wake_up_all() for waking up processes waiting to send or receive data. Update drivers/char/Kconfig to enable this driver for IA64_GENERIC kernels, and update the generic_defconfig to include it in kernel builds. Signed-off-by: Andrew Morton --- 25-akpm/arch/ia64/configs/generic_defconfig | 1 + 25-akpm/drivers/char/Kconfig | 2 +- 25-akpm/drivers/char/snsc.c | 14 ++++++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff -puN arch/ia64/configs/generic_defconfig~altix-system-controller-fixes arch/ia64/configs/generic_defconfig --- 25/arch/ia64/configs/generic_defconfig~altix-system-controller-fixes 2004-08-15 15:34:28.719040160 -0700 +++ 25-akpm/arch/ia64/configs/generic_defconfig 2004-08-15 15:34:28.726039096 -0700 @@ -575,6 +575,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set # CONFIG_STALDRV is not set +CONFIG_SGI_SNSC=y # # Serial drivers diff -puN drivers/char/Kconfig~altix-system-controller-fixes drivers/char/Kconfig --- 25/drivers/char/Kconfig~altix-system-controller-fixes 2004-08-15 15:34:28.720040008 -0700 +++ 25-akpm/drivers/char/Kconfig 2004-08-15 15:34:28.727038944 -0700 @@ -426,7 +426,7 @@ config A2232 config SGI_SNSC bool "SGI Altix system controller communication support" - depends on IA64_SGI_SN2 + depends on (IA64_SGI_SN2 || IA64_GENERIC) help If you have an SGI Altix and you want to enable system controller communication from user space (you want this!), diff -puN drivers/char/snsc.c~altix-system-controller-fixes drivers/char/snsc.c --- 25/drivers/char/snsc.c~altix-system-controller-fixes 2004-08-15 15:34:28.722039704 -0700 +++ 25-akpm/drivers/char/snsc.c 2004-08-15 15:34:28.728038792 -0700 @@ -33,7 +33,7 @@ static irqreturn_t scdrv_interrupt(int irq, void *subch_data, struct pt_regs *regs) { - struct subch_data_s *sd = (struct subch_data_s *) subch_data; + struct subch_data_s *sd = subch_data; unsigned long flags; int status; @@ -43,13 +43,13 @@ scdrv_interrupt(int irq, void *subch_dat if (status > 0) { if (status & SAL_IROUTER_INTR_RECV) { - wake_up_all(&sd->sd_rq); + wake_up(&sd->sd_rq); } if (status & SAL_IROUTER_INTR_XMIT) { ia64_sn_irtr_intr_disable (sd->sd_nasid, sd->sd_subch, SAL_IROUTER_INTR_XMIT); - wake_up_all(&sd->sd_wq); + wake_up(&sd->sd_wq); } } spin_unlock(&sd->sd_wlock); @@ -184,6 +184,7 @@ scdrv_read(struct file *file, char __use if (file->f_flags & O_NONBLOCK) { spin_unlock_irqrestore(&sd->sd_rlock, flags); + up(&sd->sd_rbs); return -EAGAIN; } @@ -197,6 +198,7 @@ scdrv_read(struct file *file, char __use remove_wait_queue(&sd->sd_rq, &wait); if (signal_pending(current)) { /* wait was interrupted */ + up(&sd->sd_rbs); return -ERESTARTSYS; } @@ -264,8 +266,10 @@ scdrv_write(struct file *file, const cha } count = min((int) count, CHUNKSIZE); - if (copy_from_user(sd->sd_wb, buf, count)) + if (copy_from_user(sd->sd_wb, buf, count)) { + up(&sd->sd_wbs); return -EFAULT; + } /* try to send the buffer */ spin_lock_irqsave(&sd->sd_wlock, flags); @@ -277,6 +281,7 @@ scdrv_write(struct file *file, const cha if (file->f_flags & O_NONBLOCK) { spin_unlock(&sd->sd_wlock); + up(&sd->sd_wbs); return -EAGAIN; } @@ -289,6 +294,7 @@ scdrv_write(struct file *file, const cha remove_wait_queue(&sd->sd_wq, &wait); if (signal_pending(current)) { /* wait was interrupted */ + up(&sd->sd_wbs); return -ERESTARTSYS; } _