summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
commit3917ac5846dd0f9ad1238166f90caab9912052e6 (patch)
tree1c298935def4f29edb39192365a65d73de999155 /drivers
parentaf2f803c8b2d469fe38e4a7ce952658dfcb6681a (diff)
o Merge with Linux 2.1.100.
o Cleanup the machine dependencies of floppy and rtc. The driver for the Dallas thingy in the Indy is still missing. o Handle allocation of zero'd pages correct for R4000SC / R4400SC. o Page colouring shit to match the virtual and physical colour of all mapped pages. This tends to produce extreme fragmentation problems, so it's deactivated for now. Users of R4000SC / R4400SC may re-enable the code in arch/mips/mm/init.c by removing the definition of CONF_GIVE_A_SHIT_ABOUT_COLOURS. Should get them somewhat further - but don't shake to hard ... o Fixed ptrace(2)-ing of syscalls, strace is now working again. o Fix the interrupt forwarding from the keyboard driver to the psaux driver, PS/2 mice are now working on the Indy. The fix is somewhat broken as it prevents generic kernels for Indy and machines which handle things different. o Things I can't remember.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acorn/block/fd1772.c2
-rw-r--r--drivers/acorn/block/mfmhd.c8
-rw-r--r--drivers/ap1000/ddv.c2
-rw-r--r--drivers/block/acsi.c4
-rw-r--r--drivers/block/ali14xx.c20
-rw-r--r--drivers/block/ataflop.c4
-rw-r--r--drivers/block/dtc2278.c12
-rw-r--r--drivers/block/floppy.c11
-rw-r--r--drivers/block/hd.c6
-rw-r--r--drivers/block/ht6560b.c6
-rw-r--r--drivers/block/ide-cd.c20
-rw-r--r--drivers/block/ide-cd.h10
-rw-r--r--drivers/block/ide-disk.c31
-rw-r--r--drivers/block/ide-dma.c31
-rw-r--r--drivers/block/ide-floppy.c2
-rw-r--r--drivers/block/ide-pci.c17
-rw-r--r--drivers/block/ide-probe.c54
-rw-r--r--drivers/block/ide-proc.c87
-rw-r--r--drivers/block/ide-tape.c48
-rw-r--r--drivers/block/ide.c701
-rw-r--r--drivers/block/ide.h38
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/md.c2
-rw-r--r--drivers/block/nbd.c2
-rw-r--r--drivers/block/ns87415.c42
-rw-r--r--drivers/block/opti621.c6
-rw-r--r--drivers/block/paride/pd.c6
-rw-r--r--drivers/block/paride/pf.c4
-rw-r--r--drivers/block/pdc4030.c10
-rw-r--r--drivers/block/ps2esdi.c6
-rw-r--r--drivers/block/qd6580.c6
-rw-r--r--drivers/block/raid5.c8
-rw-r--r--drivers/block/rd.c2
-rw-r--r--drivers/block/sl82c105.c17
-rw-r--r--drivers/block/trm290.c19
-rw-r--r--drivers/block/umc8672.c16
-rw-r--r--drivers/block/xd.c8
-rw-r--r--drivers/cdrom/sbpcd.c4
-rw-r--r--drivers/char/apm_bios.c2
-rw-r--r--drivers/char/bttv.c6
-rw-r--r--drivers/char/console.c2
-rw-r--r--drivers/char/esp.c4
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.c4
-rw-r--r--drivers/char/istallion.c2
-rw-r--r--drivers/char/lp.c138
-rw-r--r--drivers/char/nvram.c4
-rw-r--r--drivers/char/pc_keyb.c7
-rw-r--r--drivers/char/random.c10
-rw-r--r--drivers/char/riscom8.c2
-rw-r--r--drivers/char/rocket.c2
-rw-r--r--drivers/char/rtc.c8
-rw-r--r--drivers/char/serial.c10
-rw-r--r--drivers/char/specialix.c2
-rw-r--r--drivers/char/stallion.c2
-rw-r--r--drivers/char/vt.c5
-rw-r--r--drivers/isdn/avmb1/capi.c2
-rw-r--r--drivers/macintosh/macserial.c2
-rw-r--r--drivers/misc/TODO-parport11
-rw-r--r--drivers/misc/parport_procfs.c33
-rw-r--r--drivers/misc/parport_share.c10
-rw-r--r--drivers/net/3c509.c278
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/de4x5.c12
-rw-r--r--drivers/net/depca.c14
-rw-r--r--drivers/net/dlci.c4
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/eql.c3
-rw-r--r--drivers/net/ewrk3.c20
-rw-r--r--drivers/net/ipddp.c2
-rw-r--r--drivers/net/ppp.c8
-rw-r--r--drivers/net/sdla_fr.c10
-rw-r--r--drivers/net/sdla_x25.c4
-rw-r--r--drivers/net/sdlamain.c4
-rw-r--r--drivers/net/smc-mca.c2
-rw-r--r--drivers/pci/oldproc.c75
-rw-r--r--drivers/pci/pci.c99
-rw-r--r--drivers/pci/pcisyms.c8
-rw-r--r--drivers/pci/proc.c2
-rw-r--r--drivers/pci/quirks.c51
-rw-r--r--drivers/sbus/char/rtc.c2
-rw-r--r--drivers/sbus/char/vfc_dev.c2
-rw-r--r--drivers/sbus/char/zs.c2
-rw-r--r--drivers/scsi/ide-scsi.c18
-rw-r--r--drivers/scsi/ppa.c16
-rw-r--r--drivers/scsi/scsi.c2
-rw-r--r--drivers/scsi/scsi_error.c22
-rw-r--r--drivers/scsi/scsi_ioctl.c66
-rw-r--r--drivers/scsi/scsi_syms.c1
-rw-r--r--drivers/scsi/sd.c9
-rw-r--r--drivers/scsi/sd_ioctl.c6
-rw-r--r--drivers/scsi/sr_ioctl.c10
-rw-r--r--drivers/scsi/st.c2
-rw-r--r--drivers/sgi/char/sgiserial.c4
-rw-r--r--drivers/sound/Makefile3
-rw-r--r--drivers/sound/sound_syms.c2
-rw-r--r--drivers/sound/sscape.c2
96 files changed, 1302 insertions, 1009 deletions
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 58ad6ce0d..765aeba67 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1368,7 +1368,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
case FDFLUSH:
return invalidate_drive(drive);
}
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (drive < 0 || drive > 3)
return -EINVAL;
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 82c7e7bf5..40308c4e1 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -1206,14 +1206,14 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
return 0;
case BLKFLSBUF:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
fsync_dev(dev);
invalidate_buffers(dev);
return 0;
case BLKRASET:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (arg > 0xff)
return -EINVAL;
@@ -1227,7 +1227,7 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
return put_user (mfm[minor].nr_sects, (long *)arg);
case BLKFRASET:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
max_readahead[major][minor] = arg;
return 0;
@@ -1239,7 +1239,7 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
return put_user(max_sectors[major][minor], (long *) arg);
case BLKRRPART:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return mfm_reread_partitions(dev);
diff --git a/drivers/ap1000/ddv.c b/drivers/ap1000/ddv.c
index 2348e21d7..d58a5b9fb 100644
--- a/drivers/ap1000/ddv.c
+++ b/drivers/ap1000/ddv.c
@@ -856,6 +856,8 @@ static int ddv_ioctl(struct inode *inode, struct file *file,
case BLKRRPART:
printk("\tBLKRRPART\n");
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return ddv_revalidate(inode->i_rdev,&ddv_gendisk);
case BLKGETSIZE: /* Return device size */
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index f04c0347f..432276973 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -1149,13 +1149,15 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
(long *) arg);
case BLKFLSBUF:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(!inode->i_rdev) return -EINVAL;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
return 0;
case BLKRRPART: /* Re-read partition tables */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return revalidate_acsidisk(inode->i_rdev, 1);
RO_IOCTLS(inode->i_rdev,arg);
default:
diff --git a/drivers/block/ali14xx.c b/drivers/block/ali14xx.c
index c0c7762d6..5d5ca66dc 100644
--- a/drivers/block/ali14xx.c
+++ b/drivers/block/ali14xx.c
@@ -134,15 +134,15 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
/* stuff timing parameters into controller registers */
driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
- save_flags(flags);
- cli();
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
outb_p(regOn, basePort);
outReg(param1, regTab[driveNum].reg1);
outReg(param2, regTab[driveNum].reg2);
outReg(param3, regTab[driveNum].reg3);
outReg(param4, regTab[driveNum].reg4);
outb_p(regOff, basePort);
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
}
/*
@@ -154,8 +154,8 @@ static int findPort (void)
byte t;
unsigned long flags;
- save_flags(flags);
- cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
for (i = 0; i < ALI_NUM_PORTS; ++i) {
basePort = ports[i];
regOff = inb(basePort);
@@ -166,7 +166,7 @@ static int findPort (void)
dataPort = basePort + 8;
t = inReg(0) & 0xf0;
outb_p(regOff, basePort);
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
if (t != 0x50)
return 0;
return 1; /* success */
@@ -174,7 +174,7 @@ static int findPort (void)
}
outb_p(regOff, basePort);
}
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
return 0;
}
@@ -186,15 +186,15 @@ static int initRegisters (void) {
byte t;
unsigned long flags;
- save_flags(flags);
- cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
outb_p(regOn, basePort);
for (p = initData; p->reg != 0; ++p)
outReg(p->data, p->reg);
outb_p(0x01, regPort);
t = inb(regPort) & 0x01;
outb_p(regOff, basePort);
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
return t;
}
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 445e90fca..7a92f74a2 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1631,7 +1631,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
return -EFAULT;
return 0;
case BLKRASET:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (param > 0xff)
return -EINVAL;
@@ -1641,7 +1641,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
return put_user(read_ahead[MAJOR(inode->i_rdev)],
(int *) param);
case BLKFLSBUF:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
diff --git a/drivers/block/dtc2278.c b/drivers/block/dtc2278.c
index 63b9143b6..b656a0bd2 100644
--- a/drivers/block/dtc2278.c
+++ b/drivers/block/dtc2278.c
@@ -74,14 +74,14 @@ static void tune_dtc2278 (ide_drive_t *drive, byte pio)
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
if (pio >= 3) {
- save_flags(flags);
- cli();
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
/*
* This enables PIO mode4 (3?) on the first interface
*/
sub22(1,0xc3);
sub22(0,0xa0);
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
} else {
/* we don't know how to set it back again.. */
}
@@ -97,8 +97,8 @@ void init_dtc2278 (void)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
/*
* This enables the second interface
*/
@@ -114,7 +114,7 @@ void init_dtc2278 (void)
sub22(1,0xc3);
sub22(0,0xa0);
#endif
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
ide_hwifs[0].serialized = 1;
ide_hwifs[1].serialized = 1;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 088980ead..df3dcc2ec 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -1066,7 +1066,8 @@ static void setup_DMA(void)
}
#else
fd_clear_dma_ff(FLOPPY_DMA);
- fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length);
+ dma_cache_wback_inv((unsigned long)raw_cmd->kernel_data,
+ raw_cmd->length);
fd_set_dma_mode(FLOPPY_DMA, (raw_cmd->flags & FD_RAW_READ)
? DMA_MODE_READ
: DMA_MODE_WRITE);
@@ -1826,7 +1827,6 @@ static void floppy_shutdown(void)
if (!initialising)
show_floppy();
cancel_activity();
- sti();
floppy_enable_hlt();
fd_disable_dma(FLOPPY_DMA);
@@ -2876,7 +2876,6 @@ static void do_fd_request(void)
printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT); printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
return;
}
- sti();
if (fdc_busy){
/* fdc busy, this new request will be treated when the
current one is done */
@@ -3208,7 +3207,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
(g->stretch&~(FD_STRETCH|FD_SWAPSIDES)) != 0)
return -EINVAL;
if (type){
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
LOCK_FDC(drive,1);
for (cnt = 0; cnt < N_DRIVE; cnt++){
@@ -3373,7 +3372,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return _COPYOUT(loc);
}
case BLKRASET:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(param > 0xff) return -EINVAL;
read_ahead[MAJOR(inode->i_rdev)] = param;
return 0;
@@ -3381,7 +3380,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return put_user(read_ahead[MAJOR(inode->i_rdev)],
(long *) param);
case BLKFLSBUF:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
return 0;
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 558a1b2d2..52bb33ede 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -603,7 +603,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
}
case BLKRASET:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(arg > 0xff) return -EINVAL;
read_ahead[MAJOR(inode->i_rdev)] = arg;
return 0;
@@ -616,12 +616,14 @@ static int hd_ioctl(struct inode * inode, struct file * file,
return put_user(hd[MINOR(inode->i_rdev)].nr_sects,
(long *) arg);
case BLKFLSBUF:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
return 0;
case BLKRRPART: /* Re-read partition tables */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return revalidate_hddisk(inode->i_rdev, 1);
RO_IOCTLS(inode->i_rdev,arg);
diff --git a/drivers/block/ht6560b.c b/drivers/block/ht6560b.c
index b739f39ee..6bf60e4dd 100644
--- a/drivers/block/ht6560b.c
+++ b/drivers/block/ht6560b.c
@@ -133,8 +133,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
if (select != current_select || timing != current_timing) {
current_select = select;
current_timing = timing;
- save_flags (flags);
- cli();
+ __save_flags (flags); /* local CPU only */
+ __cli(); /* local CPU only */
(void) inb(HT_SELECT_PORT);
(void) inb(HT_SELECT_PORT);
(void) inb(HT_SELECT_PORT);
@@ -150,7 +150,7 @@ static void ht6560b_selectproc (ide_drive_t *drive)
*/
outb (timing, IDE_SELECT_REG);
(void) inb (IDE_STATUS_REG);
- restore_flags (flags);
+ __restore_flags (flags); /* local CPU only */
#ifdef DEBUG
printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, t, timing);
#endif
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index 98b94cadb..898d45f04 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -201,10 +201,14 @@
* now set ionly for CD-R and CD-RW drives. I had
* removed this support because it produced errors.
* It produced errors _only_ for non-writers. duh.
+ * 4.13 May 05, 1998 -- Suppress useless "in progress of becoming ready"
+ * messages, since this is not an error.
+ * -- Change error messages to be const
+ * -- Remove a "\t" which looks ugly in the syslogs
*
*************************************************************************/
-#define IDECD_VERSION "4.12"
+#define IDECD_VERSION "4.13"
#include <linux/module.h>
#include <linux/types.h>
@@ -264,11 +268,13 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
return;
}
if (reqbuf->error_code == 0x70 && reqbuf->sense_key == 0x02
- && reqbuf->asc == 0x3a && reqbuf->ascq == 0x00)
+ && ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) ||
+ (reqbuf->asc == 0x04 && reqbuf->ascq == 0x01)))
{
/*
- * No disc in drive ("Medium not present"),
- * so keep the noise level down to a dull roar.
+ * Suppress the following errors:
+ * "Medium not present", and "in progress of becoming ready",
+ * to keep the noise level down to a dull roar.
*/
return;
}
@@ -276,7 +282,7 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
#if VERBOSE_IDE_CD_ERRORS
{
int i;
- char *s;
+ const char *s;
char buf[80];
printk ("ATAPI device %s:\n", drive->name);
@@ -346,7 +352,7 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
lo = mid+1;
}
- printk (" The failed \"%s\" packet command was: \n\t\"", s);
+ printk (" The failed \"%s\" packet command was: \n \"", s);
for (i=0; i<sizeof (failed_command->c); i++)
printk ("%02x ", failed_command->c[i]);
printk ("\"\n");
@@ -1020,7 +1026,7 @@ static void cdrom_start_read_continuation (ide_drive_t *drive)
#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
#define IDECD_SEEK_TIMER (2 * WAIT_MIN_SLEEP) /* 40 ms */
-#define IDECD_SEEK_TIMEOUT (20 * IDECD_SEEK_TIMER) /* 0.8 sec */
+#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */
static void cdrom_seek_intr (ide_drive_t *drive)
{
diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h
index 1c73b2d80..785fbe1ed 100644
--- a/drivers/block/ide-cd.h
+++ b/drivers/block/ide-cd.h
@@ -415,7 +415,7 @@ struct cdrom_info {
/* From Table 124 of the ATAPI 1.2 spec.
Unchanged in Table 140 of the ATAPI 2.6 draft standard. */
-char *sense_key_texts[16] = {
+const char * const sense_key_texts[16] = {
"No sense data",
"Recovered error",
"Not ready",
@@ -436,9 +436,9 @@ char *sense_key_texts[16] = {
/* From Table 37 of the ATAPI 2.6 draft standard. */
-struct {
+const struct {
unsigned short packet_command;
- char *text;
+ const char * const text;
} packet_command_texts[] = {
{ TEST_UNIT_READY, "Test Unit Ready" },
{ REQUEST_SENSE, "Request Sense" },
@@ -471,9 +471,9 @@ struct {
/* From Table 125 of the ATAPI 1.2 spec.,
with additions from Tables 141 and 142 of the ATAPI 2.6 draft standard. */
-struct {
+const struct {
unsigned short asc_ascq;
- char *text;
+ const char * const text;
} sense_data_texts[] = {
{ 0x0000, "No additional sense information" },
diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c
index 5b46c8302..1ac07f698 100644
--- a/drivers/block/ide-disk.c
+++ b/drivers/block/ide-disk.c
@@ -18,9 +18,10 @@
* Version 1.04 add /proc configurable settings and S.M.A.R.T support
* Version 1.05 add capacity support for ATA3 >= 8GB
* Version 1.06 get boot-up messages to show full cyl count
+ * Version 1.07 disable door-locking if it fails
*/
-#define IDEDISK_VERSION "1.06"
+#define IDEDISK_VERSION "1.07"
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -185,9 +186,7 @@ static void write_intr (ide_drive_t *drive)
}
} else
error = 1;
-
out:
-
if (error)
ide_error(drive, "write_intr", stat);
}
@@ -258,9 +257,7 @@ static void multwrite_intr (ide_drive_t *drive)
}
} else
error = 1;
-
out:
-
if (error)
ide_error(drive, "multwrite_intr", stat);
}
@@ -380,7 +377,7 @@ static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long bl
return;
}
if (!drive->unmask)
- __cli();
+ __cli(); /* local CPU only */
if (drive->mult_count) {
HWGROUP(drive)->wrq = *rq; /* scratchpad */
ide_set_handler (drive, &multwrite_intr, WAIT_CMD);
@@ -405,7 +402,8 @@ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *dr
* since the open() has already succeeded,
* and the door_lock is irrelevant at this point.
*/
- (void) ide_wait_cmd(drive, WIN_DOORLOCK, 0, 0, 0, NULL);
+ if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORLOCK, 0, 0, 0, NULL))
+ drive->doorlocking = 0;
}
return 0;
}
@@ -414,7 +412,8 @@ static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t
{
if (drive->removable && !drive->usage) {
invalidate_buffers(inode->i_rdev);
- (void) ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL);
+ if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL))
+ drive->doorlocking = 0;
}
MOD_DEC_USE_COUNT;
}
@@ -587,8 +586,13 @@ static int set_multcount(ide_drive_t *drive, int arg)
static int set_nowerr(ide_drive_t *drive, int arg)
{
+ unsigned long flags;
+
+ if (ide_spin_wait_hwgroup("set_nowerr", drive, &flags))
+ return -EBUSY;
drive->nowerr = arg;
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
return 0;
}
@@ -658,14 +662,12 @@ static void idedisk_setup (ide_drive_t *drive)
/* check for removable disks (eg. SYQUEST), ignore 'WD' drives */
if (id->config & (1<<7)) { /* removable disk ? */
- if (id->model[0] != 'W' || id->model[1] != 'D')
+ if (id->model[0] != 'W' || id->model[1] != 'D') {
drive->removable = 1;
+ drive->doorlocking = 1;
+ }
}
- /* SunDisk drives: treat as non-removable; can mess up non-Sun systems! FIXME */
- if (id->model[0] == 'S' && id->model[1] == 'u')
- drive->removable = 0;
-
/* Extract geometry if we did not already have one for the drive */
if (!drive->cyl || !drive->head || !drive->sect) {
drive->cyl = drive->bios_cyl = id->cyls;
@@ -714,9 +716,10 @@ static void idedisk_setup (ide_drive_t *drive)
if (drive->cyl > drive->bios_cyl)
drive->bios_cyl = drive->cyl;
}
+#if 0 /* done instead for entire identify block in arch/ide.h stuff */
/* fix byte-ordering of buffer size field */
id->buf_size = le16_to_cpu(id->buf_size);
-
+#endif
printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d",
drive->name, id->model, idedisk_capacity(drive)/2048L, id->buf_size/2,
drive->bios_cyl, drive->bios_head, drive->bios_sect);
diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c
index 2cbed3539..c314d1c82 100644
--- a/drivers/block/ide-dma.c
+++ b/drivers/block/ide-dma.c
@@ -84,7 +84,7 @@
*/
const char *good_dma_drives[] = {"Micropolis 2112A",
"CONNER CTMA 4000",
- "ST34342A",
+ "ST34342A", /* for Sun Ultra */
NULL};
/*
@@ -128,7 +128,7 @@ void ide_dma_intr (ide_drive_t *drive)
}
printk("%s: dma_intr: bad DMA status\n", drive->name);
}
- sti();
+ ide__sti(); /* local CPU only */
ide_error(drive, "dma_intr", stat);
}
@@ -210,7 +210,7 @@ static int config_drive_for_dma (ide_drive_t *drive)
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
- if (id && (id->capability & 1) && !HWIF(drive)->no_autodma) {
+ if (id && (id->capability & 1) && !hwif->no_autodma) {
/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
if (id->field_valid & 4) /* UltraDMA */
if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
@@ -250,6 +250,7 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
unsigned long dma_base = hwif->dma_base;
unsigned int count, reading = 0;
+ byte dma_stat;
switch (func) {
case ide_dma_off:
@@ -267,22 +268,29 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
return 1; /* try PIO instead of DMA */
outl(virt_to_bus(hwif->dmatable), dma_base + 4); /* PRD table */
outb(reading, dma_base); /* specify r/w */
- outb(inb(dma_base+2)|0x06, dma_base+2); /* clear status bits */
+ outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
+ drive->waiting_for_dma = 1;
if (drive->media != ide_disk)
return 0;
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);/* issue cmd to drive */
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
case ide_dma_begin:
+ /* Note that this is done *after* the cmd has
+ * been issued to the drive, as per the BM-IDE spec.
+ * The Promise Ultra33 doesn't work correctly when
+ * we do this part before issuing the drive cmd.
+ */
outb(inb(dma_base)|1, dma_base); /* start DMA */
return 0;
case ide_dma_end: /* returns 1 on error, 0 otherwise */
- {
- byte dma_stat = inb(dma_base+2);
- int rc = (dma_stat & 7) != 4;
+ drive->waiting_for_dma = 0;
+ dma_stat = inb(dma_base+2);
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
- return rc; /* verify good DMA status */
- }
+ return (dma_stat & 7) != 4; /* verify good DMA status */
+ case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
+ dma_stat = inb(dma_base+2);
+ return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
default:
printk("ide_dmaproc: unsupported func: %d\n", func);
return 1;
@@ -331,9 +339,10 @@ __initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigne
/*
* Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
*/
-__initfunc(unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name))
+__initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name))
{
- unsigned long dma_base = 0;
+ unsigned long dma_base = 0;
+ struct pci_dev *dev = hwif->pci_dev;
if (hwif->mate && hwif->mate->dma_base) {
dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c
index a4aa0b460..e59565e21 100644
--- a/drivers/block/ide-floppy.c
+++ b/drivers/block/ide-floppy.c
@@ -713,7 +713,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
#endif /* IDEFLOPPY_DEBUG_LOG */
clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);
- ide_sti();
+ ide__sti(); /* local CPU only */
if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
#if IDEFLOPPY_DEBUG_LOG
diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c
index 9dd5487f3..811b7bed0 100644
--- a/drivers/block/ide-pci.c
+++ b/drivers/block/ide-pci.c
@@ -43,6 +43,7 @@
#define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415})
#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565})
#define DEVID_AEC6210 ((ide_pci_devid_t){0x1191, 0x0005})
+#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
#define IDE_IGNORE ((void *)-1)
@@ -71,7 +72,18 @@ extern void ide_init_ns87415(ide_hwif_t *);
extern void ide_init_cmd646(ide_hwif_t *);
#define INIT_CMD646 &ide_init_cmd646
#else
+#ifdef __sparc_v9__
#define INIT_CMD646 IDE_IGNORE
+#else
+#define INIT_CMD646 NULL
+#endif
+#endif
+
+#ifdef CONFIG_BLK_DEV_SL82C105
+extern void ide_init_sl82c105(ide_hwif_t *);
+#define INIT_W82C105 &ide_init_sl82c105
+#else
+#define INIT_W82C105 IDE_IGNORE
#endif
#ifdef CONFIG_BLK_DEV_RZ1000
@@ -113,6 +125,7 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
{DEVID_TRM290, "TRM290", INIT_TRM290, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
{DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
{DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
+ {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}} },
{IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }};
/*
@@ -269,7 +282,7 @@ check_if_enabled:
ide_pci_enablebit_t *e = &(d->enablebits[port]);
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
continue; /* port not enabled */
- ctl = dev->base_address[1+2*port] & PCI_BASE_ADDRESS_IO_MASK;
+ ctl = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK;
if (!ctl)
ctl = port ? 0x374 : 0x3f4; /* use default value */
base = dev->base_address[2*port] & ~7;
@@ -299,7 +312,7 @@ check_if_enabled:
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0;
- unsigned long dma_base = ide_get_or_set_dma_base(dev, hwif, extra, d->name);
+ unsigned long dma_base = ide_get_or_set_dma_base(hwif, extra, d->name);
if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
/*
* Set up BM-DMA capability (PnP BIOS should have done this)
diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c
index b2ea1bfd9..7af146b28 100644
--- a/drivers/block/ide-probe.c
+++ b/drivers/block/ide-probe.c
@@ -47,7 +47,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL);
ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
- sti();
+ ide__sti(); /* local CPU only */
ide_fix_driveid(id);
#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
@@ -195,12 +195,12 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
delay_50ms(); /* wait for IRQ and DRQ_STAT */
if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
unsigned long flags;
- save_flags(flags);
- cli(); /* some systems need this */
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only; some systems need this */
do_identify(drive, cmd); /* drive returned ID */
rc = 0; /* drive responded with ID */
(void) GET_STAT(); /* clear drive IRQ */
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
} else
rc = 2; /* drive refused ID */
if (!HWIF(drive)->irq) {
@@ -398,8 +398,8 @@ static void probe_hwif (ide_hwif_t *hwif)
return;
}
- save_flags(flags);
- sti(); /* needed for jiffies and irq probing */
+ __save_flags(flags); /* local CPU only */
+ __sti(); /* local CPU only; needed for jiffies and irq probing */
/*
* Second drive should only exist if first drive was found,
* but a lot of cdrom drives are configured as single slaves.
@@ -429,7 +429,7 @@ static void probe_hwif (ide_hwif_t *hwif)
} while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies));
}
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
if (drive->present) {
@@ -486,8 +486,8 @@ static int init_irq (ide_hwif_t *hwif)
ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL;
- save_flags(flags);
- cli();
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
hwif->hwgroup = NULL;
#if MAX_HWIFS > 1
@@ -499,7 +499,9 @@ static int init_irq (ide_hwif_t *hwif)
if (h->hwgroup) { /* scan only initialized hwif's */
if (hwif->irq == h->irq) {
hwif->sharing_irq = h->sharing_irq = 1;
- save_match(hwif, h, &match);
+ if (hwif->chipset != ide_pci || h->chipset != ide_pci) {
+ save_match(hwif, h, &match);
+ }
}
if (hwif->serialized) {
if (hwif->mate && hwif->mate->irq == h->irq)
@@ -520,10 +522,15 @@ static int init_irq (ide_hwif_t *hwif)
} else {
hwgroup = kmalloc(sizeof(ide_hwgroup_t), GFP_KERNEL);
memset(hwgroup, 0, sizeof(ide_hwgroup_t));
- hwgroup->hwif = hwif->next = hwif;
- hwgroup->rq = NULL;
- hwgroup->handler = NULL;
- hwgroup->drive = NULL;
+ hwgroup->hwif = hwif->next = hwif;
+ hwgroup->rq = NULL;
+ hwgroup->handler = NULL;
+ hwgroup->drive = NULL;
+ hwgroup->busy = 0;
+ hwgroup->spinlock = (spinlock_t)SPIN_LOCK_UNLOCKED;
+#if (DEBUG_SPINLOCK > 0)
+ printk("hwgroup(%s) spinlock is %p\n", hwif->name, &hwgroup->spinlock); /* FIXME */
+#endif
init_timer(&hwgroup->timer);
hwgroup->timer.function = &ide_timer_expiry;
hwgroup->timer.data = (unsigned long) hwgroup;
@@ -533,10 +540,11 @@ static int init_irq (ide_hwif_t *hwif)
* Allocate the irq, if not already obtained for another hwif
*/
if (!match || match->irq != hwif->irq) {
- if (ide_request_irq(hwif->irq, &ide_intr, SA_INTERRUPT, hwif->name, hwgroup)) {
+ int sa = (hwif->chipset == ide_pci) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
+ if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) {
if (!match)
kfree(hwgroup);
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
return 1;
}
}
@@ -558,7 +566,7 @@ static int init_irq (ide_hwif_t *hwif)
hwgroup->drive->next = drive;
}
hwgroup->hwif = HWIF(hwgroup->drive);
- restore_flags(flags); /* safe now that hwif->hwgroup is set up */
+ restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */
#ifndef __mc68000__
printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
@@ -685,13 +693,17 @@ static int hwif_init (ide_hwif_t *hwif)
read_ahead[hwif->major] = 8; /* (4kB) */
hwif->present = 1; /* success */
}
+#if (DEBUG_SPINLOCK > 0)
+{
+ static int done = 0;
+ if (!done++)
+ printk("io_request_lock is %p\n", &io_request_lock); /* FIXME */
+}
+#endif
return hwif->present;
}
-
-int ideprobe_init(void);
-
-
+int ideprobe_init (void);
static ide_module_t ideprobe_module = {
IDE_PROBE_MODULE,
ideprobe_init,
diff --git a/drivers/block/ide-proc.c b/drivers/block/ide-proc.c
index a86a51fdd..26a56e740 100644
--- a/drivers/block/ide-proc.c
+++ b/drivers/block/ide-proc.c
@@ -111,7 +111,7 @@ static int proc_ide_write_config
unsigned long startn = 0, n, flags;
const char *start = NULL, *msg = NULL;
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
/*
* Skip over leading whitespace
@@ -124,7 +124,7 @@ static int proc_ide_write_config
* Do one full pass to verify all parameters,
* then do another to actually write the regs.
*/
- save_flags(flags);
+ save_flags(flags); /* all CPUs */
do {
const char *p;
if (for_real) {
@@ -133,14 +133,15 @@ static int proc_ide_write_config
ide_hwgroup_t *mategroup = NULL;
if (hwif->mate && hwif->mate->hwgroup)
mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
- cli(); /* ensure all writes are done together */
- while (mygroup->active || (mategroup && mategroup->active)) {
- restore_flags(flags);
+ cli(); /* all CPUs; ensure all writes are done together */
+ while (mygroup->busy || (mategroup && mategroup->busy)) {
+ sti(); /* all CPUs */
if (0 < (signed long)(jiffies - timeout)) {
printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name);
+ restore_flags(flags); /* all CPUs */
return -EBUSY;
}
- cli();
+ cli(); /* all CPUs */
}
}
p = buffer;
@@ -155,7 +156,7 @@ static int proc_ide_write_config
break;
case 'P': is_pci = 1;
#ifdef CONFIG_BLK_DEV_IDEPCI
- if (!IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL))
+ if (hwif->pci_dev && !IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL))
break;
#endif /* CONFIG_BLK_DEV_IDEPCI */
msg = "not a PCI device";
@@ -174,7 +175,7 @@ static int proc_ide_write_config
msg = "bad/missing register number";
goto parse_error;
}
- if (--n < 0 || *p++ != ':') {
+ if (n-- == 0 || *p++ != ':') {
msg = "missing ':'";
goto parse_error;
}
@@ -223,7 +224,7 @@ static int proc_ide_write_config
break;
}
if (rc) {
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n",
msg, dev->bus->number, dev->devfn, reg, val);
printk("proc_ide_write_config: error %d\n", rc);
@@ -243,10 +244,10 @@ static int proc_ide_write_config
}
}
} while (!for_real++);
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
return count;
parse_error:
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
printk("parse error\n");
return xx_xx_parse_error(start, startn, msg);
}
@@ -259,27 +260,25 @@ static int proc_ide_read_config
#ifdef CONFIG_BLK_DEV_IDEPCI
ide_hwif_t *hwif = (ide_hwif_t *)data;
- int reg = 0;
+ struct pci_dev *dev = hwif->pci_dev;
+ if (!IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL) && dev && dev->bus) {
+ int reg = 0;
- struct pci_dev *dev = hwif->pci_dev;
-
- out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
- dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
- do {
- byte val;
- int rc = pci_read_config_byte(dev, reg, &val);
- if (rc) {
- printk("proc_ide_read_config: error reading bus %02x dev %02x reg 0x%02x\n",
- dev->bus->number, dev->devfn, reg);
- printk("proc_ide_read_config: error %d\n", rc);
- return -EIO;
- out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n');
- } else
- out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n');
- } while (reg < 0x100);
-#else /* CONFIG_BLK_DEV_IDEPCI */
- out += sprintf(out, "(none)\n");
+ out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
+ dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
+ do {
+ byte val;
+ int rc = pci_read_config_byte(dev, reg, &val);
+ if (rc) {
+ printk("proc_ide_read_config: error %d reading bus %02x dev %02x reg 0x%02x\n",
+ rc, dev->bus->number, dev->devfn, reg);
+ out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n');
+ } else
+ out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n');
+ } while (reg < 0x100);
+ } else
#endif /* CONFIG_BLK_DEV_IDEPCI */
+ out += sprintf(out, "(none)\n");
len = out - page;
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
@@ -425,14 +424,13 @@ static int proc_ide_write_settings
(struct file *file, const char *buffer, unsigned long count, void *data)
{
ide_drive_t *drive = (ide_drive_t *) data;
- ide_hwif_t *hwif = HWIF(drive);
char name[MAX_LEN + 1];
int for_real = 0, len;
- unsigned long n, flags;
+ unsigned long n;
const char *start = NULL;
ide_settings_t *setting;
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
/*
* Skip over leading whitespace
@@ -443,27 +441,10 @@ static int proc_ide_write_settings
}
/*
* Do one full pass to verify all parameters,
- * then do another to actually write the pci regs.
+ * then do another to actually write the new settings.
*/
- save_flags(flags);
do {
const char *p;
- if (for_real) {
- unsigned long timeout = jiffies + (3 * HZ);
- ide_hwgroup_t *mygroup = (ide_hwgroup_t *)(hwif->hwgroup);
- ide_hwgroup_t *mategroup = NULL;
- if (hwif->mate && hwif->mate->hwgroup)
- mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
- cli(); /* ensure all writes are done together */
- while (mygroup->active || (mategroup && mategroup->active)) {
- restore_flags(flags);
- if (0 < (signed long)(jiffies - timeout)) {
- printk("/proc/ide/%s/settings: channel(s) busy, cannot write\n", drive->name);
- return -EBUSY;
- }
- cli();
- }
- }
p = buffer;
n = count;
while (n > 0) {
@@ -508,10 +489,8 @@ static int proc_ide_write_settings
ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
}
} while (!for_real++);
- restore_flags(flags);
return count;
parse_error:
- restore_flags(flags);
printk("proc_ide_write_settings(): parse error\n");
return -EINVAL;
}
@@ -573,7 +552,7 @@ static int proc_ide_write_driver
{
ide_drive_t *drive = (ide_drive_t *) data;
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (ide_replace_subdriver(drive, buffer))
return -EINVAL;
diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c
index c4f5c6e23..3b6e2790f 100644
--- a/drivers/block/ide-tape.c
+++ b/drivers/block/ide-tape.c
@@ -1432,8 +1432,8 @@ static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
#if IDETAPE_DEBUG_LOG
printk (KERN_INFO "Reached idetape_add_stage_tail\n");
#endif /* IDETAPE_DEBUG_LOG */
- save_flags (flags);
- cli ();
+ save_flags (flags); /* all CPUs (overkill?) */
+ cli(); /* all CPUs (overkill?) */
stage->next=NULL;
if (tape->last_stage != NULL)
tape->last_stage->next=stage;
@@ -1444,7 +1444,7 @@ static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
tape->next_stage=tape->last_stage;
tape->nr_stages++;
tape->nr_pending_stages++;
- restore_flags (flags);
+ restore_flags (flags); /* all CPUs (overkill?) */
}
/*
@@ -1754,7 +1754,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
#endif /* IDETAPE_DEBUG_LOG */
clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);
- ide_sti();
+ ide__sti(); /* local CPU only */
if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
#if IDETAPE_DEBUG_LOG
@@ -2398,11 +2398,11 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
*/
return (idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh));
}
- save_flags (flags);
- cli ();
+ save_flags (flags); /* all CPUs (overkill?) */
+ cli(); /* all CPUs (overkill?) */
if (tape->active_stage == tape->first_stage)
idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags);
+ restore_flags (flags); /* all CPUs (overkill?) */
rq_ptr = &tape->first_stage->rq;
bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
@@ -2451,13 +2451,13 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
* Pay special attention to possible race conditions.
*/
while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) {
- save_flags (flags);
- cli ();
+ save_flags (flags); /* all CPUs (overkill?) */
+ cli(); /* all CPUs (overkill?) */
if (idetape_pipeline_active (tape)) {
idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags);
+ restore_flags (flags); /* all CPUs (overkill?) */
} else {
- restore_flags (flags);
+ restore_flags (flags); /* all CPUs (overkill?) */
idetape_insert_pipeline_into_queue (drive);
if (idetape_pipeline_active (tape))
continue;
@@ -2514,12 +2514,12 @@ static void idetape_discard_read_pipeline (ide_drive_t *drive)
if (tape->first_stage == NULL)
return;
- save_flags (flags);
- cli ();
+ save_flags (flags); /* all CPUs (overkill?) */
+ cli(); /* all CPUs (overkill?) */
tape->next_stage = NULL;
if (idetape_pipeline_active (tape))
idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags);
+ restore_flags (flags); /* all CPUs (overkill?) */
while (tape->first_stage != NULL)
idetape_remove_stage_head (drive);
@@ -2539,8 +2539,8 @@ static void idetape_wait_for_pipeline (ide_drive_t *drive)
if (!idetape_pipeline_active (tape))
idetape_insert_pipeline_into_queue (drive);
- save_flags (flags);
- cli ();
+ save_flags (flags); /* all CPUs (overkill?) */
+ cli(); /* all CPUs (overkill?) */
if (!idetape_pipeline_active (tape))
goto abort;
#if IDETAPE_DEBUG_BUGS
@@ -2550,7 +2550,7 @@ static void idetape_wait_for_pipeline (ide_drive_t *drive)
#endif /* IDETAPE_DEBUG_BUGS */
idetape_wait_for_request (&tape->last_stage->rq);
abort:
- restore_flags (flags);
+ restore_flags (flags); /* all CPUs (overkill?) */
}
static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
@@ -2795,11 +2795,11 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
* Wait until the first read-ahead request
* is serviced.
*/
- save_flags (flags);
- cli ();
+ save_flags (flags); /* all CPUs (overkill?) */
+ cli(); /* all CPUs (overkill?) */
if (tape->active_stage == tape->first_stage)
idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags);
+ restore_flags (flags); /* all CPUs (overkill?) */
if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
count++;
@@ -3620,14 +3620,14 @@ static int idetape_cleanup (ide_drive_t *drive)
int minor = tape->minor;
unsigned long flags;
- save_flags (flags);
- cli ();
+ save_flags (flags); /* all CPUs (overkill?) */
+ cli(); /* all CPUs (overkill?) */
if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) {
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs (overkill?) */
return 1;
}
idetape_chrdevs[minor].drive = NULL;
- restore_flags (flags);
+ restore_flags (flags); /* all CPUs (overkill?) */
DRIVER(drive)->busy = 0;
(void) ide_unregister_subdriver (drive);
drive->driver_data = NULL;
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 111186eba..191678d77 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -86,6 +86,9 @@
* Version 6.12 integrate ioctl and proc interfaces
* fix parsing of "idex=" command line parameter
* Version 6.13 add support for ide4/ide5 courtesy rjones@orchestream.com
+ * Version 6.14 fixed IRQ sharing among PCI devices
+ * Version 6.15 added SMP awareness to IDE drivers
+ * Version 6.16 fixed various bugs; even more SMP friendly
*
* Some additional driver compile-time options are in ide.h
*
@@ -155,13 +158,13 @@ static unsigned long read_timer(void)
unsigned long t, flags;
int i;
- __save_flags(flags);
- __cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
t = jiffies * 11932;
outb_p(0, 0x43);
i = inb_p(0x40);
i |= inb(0x40) << 8;
- __restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
return (t - i);
}
#endif /* DISK_RECOVERY_TIME */
@@ -178,15 +181,11 @@ static inline void set_recovery_timer (ide_hwif_t *hwif)
*/
static void init_hwif_data (unsigned int index)
{
- byte *p;
unsigned int unit;
ide_hwif_t *hwif = &ide_hwifs[index];
/* bulk initialize hwif & drive info with zeros */
- p = ((byte *) hwif) + sizeof(ide_hwif_t);
- do {
- *--p = 0;
- } while (p > (byte *) hwif);
+ memset(hwif, 0, sizeof(ide_hwif_t));
/* fill in any non-zero initial values */
hwif->index = index;
@@ -299,11 +298,11 @@ void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
#if SUPPORT_VLB_SYNC
if (io_32bit & 2) {
unsigned long flags;
- __save_flags(flags);
- __cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
do_vlb_sync(IDE_NSECTOR_REG);
insl(IDE_DATA_REG, buffer, wcount);
- __restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
} else
#endif /* SUPPORT_VLB_SYNC */
insl(IDE_DATA_REG, buffer, wcount);
@@ -332,11 +331,11 @@ void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
#if SUPPORT_VLB_SYNC
if (io_32bit & 2) {
unsigned long flags;
- __save_flags(flags);
- __cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
do_vlb_sync(IDE_NSECTOR_REG);
outsl(IDE_DATA_REG, buffer, wcount);
- __restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
} else
#endif /* SUPPORT_VLB_SYNC */
outsl(IDE_DATA_REG, buffer, wcount);
@@ -392,6 +391,85 @@ void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun
}
/*
+ * Needed for PCI irq sharing
+ */
+static inline int drive_is_ready (ide_drive_t *drive)
+{
+ if (drive->waiting_for_dma)
+ return HWIF(drive)->dmaproc(ide_dma_test_irq, drive);
+#if 0
+ udelay(1); /* need to guarantee 400ns since last command was issued */
+#endif
+ if (GET_STAT() & BUSY_STAT)
+ return 0; /* drive busy: definitely not interrupting */
+ return 1; /* drive ready: *might* be interrupting */
+}
+
+#if !defined(__SMP__) && defined(DEBUG_SPINLOCKS) && (DEBUG_SPINLOCKS > 1)
+
+static const char *ide_lock_name(spinlock_t *spinlock)
+{
+ int index;
+
+ if (spinlock == &io_request_lock)
+ return "io_request_lock";
+ for (index = 0; index < MAX_HWIFS; index++) {
+ ide_hwif_t *hwif = &ide_hwifs[index];
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+ if (spinlock == &hwgroup->spinlock)
+ return hwif->name;
+ }
+ return "?";
+}
+
+#define IDE_SPIN_LOCK_IRQ(msg,spinlock) \
+{ \
+ static int __babble = 20; \
+ __cli(); \
+ if ((spinlock)->lock && __babble) { \
+ __babble--; \
+ printk("ide_lock: %s: already locked (%s)\n", msg, ide_lock_name(spinlock)); \
+ } \
+ /* spin_lock_irq(spinlock); */ \
+ (spinlock)->lock = 1; \
+}
+
+#define IDE_SPIN_LOCK_IRQSAVE(msg,spinlock,flags) \
+{ \
+ __save_flags(flags); \
+ IDE_SPIN_LOCK_IRQ(msg,spinlock); \
+}
+
+#define IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,flags) \
+{ \
+ static int __babble = 20; \
+ __cli(); \
+ if (!((spinlock)->lock) && __babble) { \
+ __babble--; \
+ printk("ide_unlock: %s: not locked (%s)\n", msg, ide_lock_name(spinlock)); \
+ } \
+ /* spin_unlock_irqrestore(msg,spinlock,flags); */ \
+ (spinlock)->lock = 0; \
+ restore_flags(flags); \
+}
+
+#define IDE_SPIN_UNLOCK(msg,spinlock) \
+{ \
+ unsigned long __flags; \
+ __save_flags(__flags); \
+ IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,__flags); \
+}
+
+#else /* DEBUG_SPINLOCKS */
+
+#define IDE_SPIN_LOCK_IRQ(msg,spinlock) spin_lock_irq(spinlock)
+#define IDE_SPIN_LOCK_IRQSAVE(msg,spinlock,flags) spin_lock_irqsave(spinlock,flags)
+#define IDE_SPIN_UNLOCK(msg,spinlock) spin_unlock(spinlock)
+#define IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,flags) spin_unlock_irqrestore(spinlock,flags)
+
+#endif /* DEBUG_SPINLOCKS */
+
+/*
* This should get invoked any time we exit the driver to
* wait for an interrupt response from a drive. handler() points
* at the appropriate code to handle the next interrupt, and a
@@ -400,7 +478,10 @@ void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun
*/
void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout)
{
+ unsigned long flags;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
+
+ IDE_SPIN_LOCK_IRQSAVE("ide_set_handler", &hwgroup->spinlock, flags);
#ifdef DEBUG
if (hwgroup->handler != NULL) {
printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
@@ -410,6 +491,7 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int t
hwgroup->handler = handler;
hwgroup->timer.expires = jiffies + timeout;
add_timer(&(hwgroup->timer));
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_set_handler", &hwgroup->spinlock, flags);
}
/*
@@ -558,8 +640,8 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
ide_hwif_t *hwif = HWIF(drive);
ide_hwgroup_t *hwgroup = HWGROUP(drive);
- __save_flags(flags);
- __cli(); /* Why ? */
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
/* For an ATAPI device, first try an ATAPI SRST. */
if (drive->media != ide_disk && !do_not_try_atapi) {
@@ -569,7 +651,7 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20);
- __restore_flags (flags);
+ __restore_flags (flags); /* local CPU only */
return;
}
@@ -597,7 +679,7 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
ide_set_handler (drive, &reset_pollfunc, HZ/20);
#endif /* OK_TO_RESET_CONTROLLER */
- __restore_flags (flags);
+ __restore_flags (flags); /* local CPU only */
}
/*
@@ -625,15 +707,17 @@ void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err)
args[2] = IN_BYTE(IDE_NSECTOR_REG);
}
}
- __save_flags(flags);
- __cli();
+ IDE_SPIN_LOCK_IRQSAVE("ide_end_drive_cmd", &io_request_lock, flags);
drive->queue = rq->next;
blk_dev[MAJOR(rq->rq_dev)].current_request = NULL;
HWGROUP(drive)->rq = NULL;
rq->rq_status = RQ_INACTIVE;
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_end_drive_cmd", &io_request_lock, flags);
+ save_flags(flags); /* all CPUs; overkill? */
+ cli(); /* all CPUs; overkill? */
if (rq->sem != NULL)
- up(rq->sem);
- __restore_flags(flags);
+ up(rq->sem); /* inform originator that rq has been serviced */
+ restore_flags(flags); /* all CPUs; overkill? */
}
/*
@@ -644,8 +728,8 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat)
unsigned long flags;
byte err = 0;
- __save_flags (flags);
- /* ide_sti(); HACK */
+ __save_flags (flags); /* local CPU only */
+ ide__sti(); /* local CPU only */
printk("%s: %s: status=0x%02x", drive->name, msg, stat);
#if FANCY_STATUS_DUMPS
printk(" { ");
@@ -698,7 +782,7 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat)
#endif /* FANCY_STATUS_DUMPS */
printk("\n");
}
- __restore_flags (flags);
+ __restore_flags (flags); /* local CPU only */
return err;
}
@@ -732,7 +816,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
byte err;
err = ide_dump_status(drive, msg, stat);
- if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL)
+ if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return;
/* retry only "normal" I/O: */
if (rq->cmd == IDE_DRIVE_CMD) {
@@ -784,7 +868,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
{
ide_set_handler (drive, handler, WAIT_CMD);
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+ OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
OUT_BYTE(nsect,IDE_NSECTOR_REG);
OUT_BYTE(cmd,IDE_COMMAND_REG);
}
@@ -799,7 +883,7 @@ static void drive_cmd_intr (ide_drive_t *drive)
byte stat = GET_STAT();
int retries = 10;
- /* ide_sti(); HACK */
+ ide__sti(); /* local CPU only */
if ((stat & DRQ_STAT) && args && args[3]) {
byte io_32bit = drive->io_32bit;
drive->io_32bit = 0;
@@ -857,17 +941,17 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
udelay(1); /* spec allows drive 400ns to assert "BUSY" */
if ((stat = GET_STAT()) & BUSY_STAT) {
- __save_flags(flags);
- /* ide_sti(); HACK */
+ __save_flags(flags); /* local CPU only */
+ ide__sti(); /* local CPU only */
timeout += jiffies;
while ((stat = GET_STAT()) & BUSY_STAT) {
if (0 < (signed long)(jiffies - timeout)) {
- __restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
ide_error(drive, "status timeout", stat);
return 1;
}
}
- __restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
}
udelay(1); /* allow status to settle, then read it again */
if (OK_STAT((stat = GET_STAT()), good, bad))
@@ -909,17 +993,18 @@ static void execute_drive_cmd (ide_drive_t *drive, struct request *rq)
}
/*
- * do_request() initiates handling of a new I/O request
+ * start_request() initiates handling of a new I/O request
*/
-static inline void do_request (ide_hwgroup_t *hwgroup, ide_hwif_t *hwif, ide_drive_t *drive)
+static inline void start_request (ide_drive_t *drive)
{
unsigned long block, blockend;
struct request *rq = drive->queue;
unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS;
+ ide_hwif_t *hwif = HWIF(drive);
- /* ide_sti(); HACK */
+ ide__sti(); /* local CPU only */
#ifdef DEBUG
- printk("%s: do_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
+ printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
#endif
if (unit >= MAX_DRIVES) {
printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
@@ -946,15 +1031,11 @@ static inline void do_request (ide_hwgroup_t *hwgroup, ide_hwif_t *hwif, ide_dri
#if (DISK_RECOVERY_TIME > 0)
while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
#endif
-
- hwgroup->hwif = hwif;
- hwgroup->drive = drive;
SELECT_DRIVE(hwif, drive);
if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
printk("%s: drive not ready for command\n", drive->name);
return;
}
-
if (!drive->special.all) {
if (rq->cmd == IDE_DRIVE_CMD) {
execute_drive_cmd(drive, rq);
@@ -973,7 +1054,7 @@ kill_rq:
if (drive->driver != NULL)
DRIVER(drive)->end_request(0, HWGROUP(drive));
else
- ide_end_request(0, hwgroup);
+ ide_end_request(0, HWGROUP(drive));
}
/*
@@ -1000,21 +1081,19 @@ repeat:
best = NULL;
drive = hwgroup->drive;
do {
- if (!drive->queue)
- continue;
- if (drive->sleep && 0 < (signed long)(drive->sleep - jiffies))
- continue;
- if (!best) {
- best = drive;
- continue;
+ if (drive->queue && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) {
+ if (!best
+ || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
+ || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
+ {
+ struct blk_dev_struct *bdev = &blk_dev[HWIF(drive)->major];
+ if (bdev->current_request != &bdev->plug)
+ best = drive;
+ }
}
- if (drive->sleep && (!best->sleep || drive->sleep < best->sleep))
- best = drive;
- if (!best->sleep && WAKEUP(drive) < WAKEUP(best))
- best = drive;
} while ((drive = drive->next) != hwgroup->drive);
- if (best != hwgroup->drive && best && best->service_time > WAIT_MIN_SLEEP && !best->sleep && best->nice1) {
- long t = (signed) (WAKEUP(best) - jiffies); /* BUGGY? */
+ if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
+ long t = (signed long)(WAKEUP(best) - jiffies);
if (t >= WAIT_MIN_SLEEP) {
/*
* We *may* have some time to spare, but first let's see if
@@ -1022,9 +1101,10 @@ repeat:
*/
drive = best->next;
do {
- if (drive->sleep) /* this drive tried to be nice to us */
- continue;
- if (WAKEUP(drive) > (jiffies - best->service_time) && WAKEUP(drive) < (jiffies + t)) { /* BUGGY? */
+ if (!drive->sleep
+ && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
+ && 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
+ {
ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP));
goto repeat;
}
@@ -1034,33 +1114,6 @@ repeat:
return best;
}
-static inline void ide_leave_hwgroup (ide_hwgroup_t *hwgroup)
-{
- ide_drive_t *drive = hwgroup->drive;
- unsigned long sleep = 0;
-
- hwgroup->rq = NULL;
- do {
- blk_dev[HWIF(drive)->major].current_request = NULL;
- if (!drive->sleep)
- continue;
- if (!sleep) {
- sleep = drive->sleep;
- continue;
- }
- if (drive->sleep < sleep)
- sleep = drive->sleep;
- } while ((drive = drive->next) != hwgroup->drive);
- if (sleep) {
- if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
- sleep = jiffies + WAIT_MIN_SLEEP;
- hwgroup->timer.expires = sleep;
- add_timer(&hwgroup->timer);
- } else /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
- ide_release_lock(&ide_lock);
- hwgroup->active = 0;
-}
-
/*
* The driver enables interrupts as much as possible. In order to do this,
* (a) the device-interrupt is always masked before entry, and
@@ -1075,30 +1128,68 @@ static inline void ide_leave_hwgroup (ide_hwgroup_t *hwgroup)
* tolerance for latency during I/O. For devices which don't suffer from
* this problem (most don't), the unmask flag can be set using the "hdparm"
* utility, to permit other interrupts during data/cmd transfers.
+ *
+ * Caller must have already acquired spinlock using *spinflags
+ *
*/
-void ide_do_request (ide_hwgroup_t *hwgroup)
+static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags, int masked_irq)
{
- __cli(); /* paranoia */
- if (hwgroup->handler != NULL) {
- printk("%s: EEeekk!! handler not NULL in ide_do_request()\n", hwgroup->hwif->name);
- return;
- }
- do {
- ide_drive_t *drive = choose_drive(hwgroup);
- if (drive != NULL) {
- ide_hwif_t *hwif = HWIF(drive);
- if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif)
- OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
- drive->sleep = 0;
- blk_dev[hwif->major].current_request = hwgroup->rq = drive->queue;
- drive->service_start = jiffies;
- do_request(hwgroup, hwif, drive);
- __cli();
- } else {
- ide_leave_hwgroup(hwgroup); /* no work left for this hwgroup */
+ struct blk_dev_struct *bdev;
+ ide_drive_t *drive;
+ ide_hwif_t *hwif;
+ unsigned long io_flags;
+
+ hwgroup->busy = 1;
+ while (hwgroup->handler == NULL) {
+ IDE_SPIN_LOCK_IRQSAVE("ide_do_request1", &io_request_lock, io_flags);
+ drive = choose_drive(hwgroup);
+ if (drive == NULL) {
+ unsigned long sleep = 0;
+
+ hwgroup->rq = NULL;
+ drive = hwgroup->drive;
+ do {
+ bdev = &blk_dev[HWIF(drive)->major];
+ if (bdev->current_request != &bdev->plug) /* FIXME: this will do for now */
+ bdev->current_request = NULL; /* (broken since patch-2.1.15) */
+ if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
+ sleep = drive->sleep;
+ } while ((drive = drive->next) != hwgroup->drive);
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request2", &io_request_lock, io_flags);
+ if (sleep) {
+ if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
+ sleep = jiffies + WAIT_MIN_SLEEP;
+ hwgroup->timer.expires = sleep;
+ add_timer(&hwgroup->timer);
+ } else {
+ /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
+ ide_release_lock(&ide_lock); /* for atari only */
+ }
+ hwgroup->busy = 0;
return;
}
- } while (hwgroup->handler == NULL);
+ hwif = HWIF(drive);
+ if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) /* set nIEN for previous hwif */
+ OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
+ hwgroup->hwif = hwif;
+ hwgroup->drive = drive;
+ drive->sleep = 0;
+ drive->service_start = jiffies;
+
+ bdev = &blk_dev[hwif->major];
+ if (bdev->current_request == &bdev->plug) /* FIXME: paranoia */
+ printk("%s: Huh? nuking plugged queue\n", drive->name);
+ bdev->current_request = hwgroup->rq = drive->queue;
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request3", &io_request_lock, io_flags);
+
+ if (hwif->irq != masked_irq)
+ disable_irq(hwif->irq);
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request4", &hwgroup->spinlock, *hwgroup_flags);
+ start_request(drive);
+ IDE_SPIN_LOCK_IRQSAVE("ide_do_request5", &hwgroup->spinlock, *hwgroup_flags);
+ if (hwif->irq != masked_irq)
+ enable_irq(hwif->irq);
+ }
}
/*
@@ -1106,100 +1197,136 @@ void ide_do_request (ide_hwgroup_t *hwgroup)
*/
struct request **ide_get_queue (kdev_t dev)
{
- struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
- ide_hwif_t *hwif = bdev->data;
+ ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data;
return &hwif->drives[DEVICE_NR(dev) & 1].queue;
}
/*
- * do_hwgroup_request() invokes ide_do_request() after first masking
- * all possible interrupts for the current hwgroup. This prevents race
- * conditions in the event that an unexpected interrupt occurs while
- * we are in the driver.
- *
- * Note that the io-request lock will guarantee that the driver never gets
- * re-entered even on another interrupt level, so we no longer need to
- * mask the irq's.
+ * do_hwgroup_request() invokes ide_do_request() after claiming hwgroup->busy.
*/
-static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
+static void do_hwgroup_request (const char *msg, ide_hwgroup_t *hwgroup)
{
- if (hwgroup->handler == NULL) {
- del_timer(&hwgroup->timer);
- ide_get_lock(&ide_lock, ide_intr, hwgroup);
- hwgroup->active = 1;
- ide_do_request (hwgroup);
+ unsigned long flags;
+
+ IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, flags);
+ if (hwgroup->busy) {
+ IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, flags);
+ return;
}
+ del_timer(&hwgroup->timer);
+ ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only */
+ ide_do_request(hwgroup, &flags, 0);
+ IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, flags);
+}
+
+/*
+ * As of linux-2.1.95, ll_rw_blk.c invokes our do_idex_request()
+ * functions with the io_request_spinlock already grabbed.
+ * Since we need to do our own spinlock's internally,
+ * on paths that don't necessarily originate through the
+ * do_idex_request() path.
+ *
+ * We have to undo the spinlock on entry, and restore it again on exit.
+ * Fortunately, this is mostly a nop for non-SMP kernels.
+ */
+static inline void unlock_do_hwgroup_request (ide_hwgroup_t *hwgroup)
+{
+ IDE_SPIN_UNLOCK("unlock_do_hwgroup_request", &io_request_lock);
+ do_hwgroup_request ("from unlock_do_hwgroup_request", hwgroup);
+ IDE_SPIN_LOCK_IRQ("unlock_do_hwgroup_request", &io_request_lock);
}
-void do_ide0_request (void) /* invoked with __cli() */
+void do_ide0_request (void)
{
- do_hwgroup_request (ide_hwifs[0].hwgroup);
+ unlock_do_hwgroup_request (ide_hwifs[0].hwgroup);
}
#if MAX_HWIFS > 1
-void do_ide1_request (void) /* invoked with __cli() */
+void do_ide1_request (void)
{
- do_hwgroup_request (ide_hwifs[1].hwgroup);
+ unlock_do_hwgroup_request (ide_hwifs[1].hwgroup);
}
#endif /* MAX_HWIFS > 1 */
#if MAX_HWIFS > 2
-void do_ide2_request (void) /* invoked with __cli() */
+void do_ide2_request (void)
{
- do_hwgroup_request (ide_hwifs[2].hwgroup);
+ unlock_do_hwgroup_request (ide_hwifs[2].hwgroup);
}
#endif /* MAX_HWIFS > 2 */
#if MAX_HWIFS > 3
-void do_ide3_request (void) /* invoked with __cli() */
+void do_ide3_request (void)
{
- do_hwgroup_request (ide_hwifs[3].hwgroup);
+ unlock_do_hwgroup_request (ide_hwifs[3].hwgroup);
}
#endif /* MAX_HWIFS > 3 */
#if MAX_HWIFS > 4
-void do_ide4_request (void) /* invoked with cli() */
+void do_ide4_request (void)
{
- do_hwgroup_request (ide_hwifs[4].hwgroup);
+ unlock_do_hwgroup_request (ide_hwifs[4].hwgroup);
}
#endif /* MAX_HWIFS > 4 */
#if MAX_HWIFS > 5
-void do_ide5_request (void) /* invoked with cli() */
+void do_ide5_request (void)
{
- do_hwgroup_request (ide_hwifs[5].hwgroup);
+ unlock_do_hwgroup_request (ide_hwifs[5].hwgroup);
}
#endif /* MAX_HWIFS > 5 */
+static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
+{
+ unsigned long flags;
+ ide_drive_t *drive;
+
+ IDE_SPIN_LOCK_IRQSAVE("start_next_request", &hwgroup->spinlock, flags);
+ if (hwgroup->handler != NULL) {
+ IDE_SPIN_UNLOCK_IRQRESTORE("start_next_request", &hwgroup->spinlock, flags);
+ return;
+ }
+ drive = hwgroup->drive;
+ set_recovery_timer(HWIF(drive));
+ drive->service_time = jiffies - drive->service_start;
+ ide_do_request(hwgroup, &flags, masked_irq);
+ IDE_SPIN_UNLOCK_IRQRESTORE("start_next_request", &hwgroup->spinlock, flags);
+}
+
void ide_timer_expiry (unsigned long data)
{
ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
- ide_drive_t *drive = hwgroup->drive;
+ ide_drive_t *drive;
ide_handler_t *handler;
unsigned long flags;
- __save_flags(flags);
- __cli();
-
- if ((handler = hwgroup->handler) != NULL) {
- hwgroup->handler = NULL;
- if (hwgroup->poll_timeout != 0) /* polling in progress? */
- handler(drive);
- else { /* abort the operation */
- if (hwgroup->hwif->dmaproc)
- (void) hwgroup->hwif->dmaproc (ide_dma_end, drive);
- ide_error(drive, "irq timeout", GET_STAT());
- }
- __cli();
- if (hwgroup->handler == NULL) {
- set_recovery_timer(HWIF(drive));
- drive->service_time = jiffies - drive->service_start;
- do_hwgroup_request (hwgroup);
+ IDE_SPIN_LOCK_IRQSAVE("ide_timer_expiry1", &hwgroup->spinlock, flags);
+ drive = hwgroup->drive;
+ if ((handler = hwgroup->handler) == NULL) {
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry2", &hwgroup->spinlock, flags);
+ do_hwgroup_request("timer do_hwgroup_request", hwgroup);
+ return;
+ }
+ hwgroup->busy = 1; /* should already be "1" */
+ hwgroup->handler = NULL;
+ if (hwgroup->poll_timeout != 0) { /* polling in progress? */
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry3", &hwgroup->spinlock, flags);
+ handler(drive);
+ } else if (drive_is_ready(drive)) {
+ printk("%s: lost interrupt\n", drive->name);
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry4", &hwgroup->spinlock, flags);
+ handler(drive);
+ } else {
+ if (drive->waiting_for_dma) {
+ (void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
+ printk("%s: timeout waiting for DMA\n", drive->name);
}
- } else
- do_hwgroup_request (hwgroup);
- __restore_flags(flags);
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry5", &hwgroup->spinlock, flags);
+ ide_error(drive, "irq timeout", GET_STAT());
+ }
+ del_timer(&hwgroup->timer);
+ start_next_request(hwgroup, 0);
}
/*
@@ -1238,75 +1365,78 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
/* Try to not flood the console with msgs */
- static unsigned long last_msgtime = 0;
+ static unsigned long last_msgtime = 0, count = 0;
+ ++count;
if (0 < (signed long)(jiffies - (last_msgtime + HZ))) {
last_msgtime = jiffies;
- printk("%s%s: unexpected interrupt, status=0x%02x\n",
- hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat);
+ printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n",
+ hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count);
}
}
}
} while ((hwif = hwif->next) != hwgroup->hwif);
}
-
-#ifdef __sparc_v9__
-#define IDE_IRQ_EQUAL(irq1, irq2) (1)
-#else
-#define IDE_IRQ_EQUAL(irq1, irq2) ((irq1) == (irq2))
-#endif
-
-static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs)
-{
- ide_hwgroup_t *hwgroup = dev_id;
- ide_hwif_t *hwif = hwgroup->hwif;
- ide_handler_t *handler;
-
- if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
- return;
-
- if (IDE_IRQ_EQUAL(irq, hwif->irq)
- && (handler = hwgroup->handler) != NULL) {
- ide_drive_t *drive = hwgroup->drive;
-#if 1 /* temporary, remove later -- FIXME */
- {
- struct request *rq = hwgroup->rq;
- if (rq != NULL
- &&( MAJOR(rq->rq_dev) != HWIF(drive)->major
- || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit))
- {
- printk("ide_intr: got IRQ from wrong device: email mlord@pobox.com!!\n");
- return;
- }
- }
-#endif /* temporary */
- hwgroup->handler = NULL;
- del_timer(&(hwgroup->timer));
- /* if (drive->unmask)
- ide_sti(); HACK */
- handler(drive);
- /* this is necessary, as next rq may be different irq */
- if (hwgroup->handler == NULL) {
- set_recovery_timer(HWIF(drive));
- drive->service_time = jiffies - drive->service_start;
- ide_do_request(hwgroup);
- }
- } else {
- unexpected_intr(irq, hwgroup);
- }
- __cli();
- hwif = hwgroup->hwif;
-}
-
/*
* entry point for all interrupts, caller does __cli() for us
*/
void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
+ ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
+ ide_hwif_t *hwif;
+ ide_drive_t *drive;
+ ide_handler_t *handler;
- spin_lock_irqsave(&io_request_lock, flags);
- do_ide_intr(irq, dev_id, regs);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ __cli(); /* local CPU only */
+ IDE_SPIN_LOCK_IRQSAVE("ide_intr1", &hwgroup->spinlock, flags);
+ hwif = hwgroup->hwif;
+ if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
+ /*
+ * Not expecting an interrupt from this drive.
+ * That means this could be:
+ * (1) an interrupt from another PCI device
+ * sharing the same PCI INT# as us.
+ * or (2) a drive just entered sleep or standby mode,
+ * and is interrupting to let us know.
+ * or (3) a spurious interrupt of unknown origin.
+ *
+ * For PCI, we cannot tell the difference,
+ * so in that case we just ignore it and hope it goes away.
+ */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+ if (IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL))
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+ {
+ /*
+ * Probably not a shared PCI interrupt,
+ * so we can safely try to do something about it:
+ */
+ (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
+ unexpected_intr(irq, hwgroup);
+ }
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr2", &hwgroup->spinlock, flags);
+ return;
+ }
+ drive = hwgroup->drive;
+ if (!drive || !drive_is_ready(drive)) {
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr3", &hwgroup->spinlock, flags);
+ return;
+ }
+ hwgroup->handler = NULL;
+ (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
+ del_timer(&(hwgroup->timer));
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr4", &hwgroup->spinlock, flags);
+ if (drive->unmask)
+ ide__sti(); /* local CPU only */
+ handler(drive); /* service this interrupt, may set handler for next interrupt */
+ /*
+ * Note that handler() may have set things up for another
+ * interrupt to occur soon, but it cannot happen until
+ * we exit from this routine, because it will be the
+ * same irq as is currently being serviced here,
+ * and Linux won't allow another (on any CPU) until we return.
+ */
+ start_next_request(hwgroup, hwif->irq);
}
/*
@@ -1390,10 +1520,8 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
if (action == ide_wait)
rq->sem = &sem;
- __save_flags(flags);
- __cli();
+ IDE_SPIN_LOCK_IRQSAVE("ide_do_drive_cmd", &io_request_lock, flags);
cur_rq = drive->queue;
-
if (cur_rq == NULL || action == ide_preempt) {
rq->next = cur_rq;
drive->queue = rq;
@@ -1407,13 +1535,13 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
rq->next = cur_rq->next;
cur_rq->next = rq;
}
- if (!hwgroup->active) {
- do_hwgroup_request(hwgroup);
- __cli();
- }
- if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_drive_cmd", &io_request_lock, flags);
+ do_hwgroup_request("drive_cmd do_hwgroup_request", hwgroup);
+ save_flags(flags); /* all CPUs; overkill? */
+ cli(); /* all CPUs; overkill? */
+ if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
down(&sem); /* wait for it to be serviced */
- __restore_flags(flags);
+ restore_flags(flags); /* all CPUs; overkill? */
return rq->errors ? -EIO : 0; /* return -EIO if errors */
}
@@ -1428,6 +1556,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
int ide_revalidate_disk(kdev_t i_rdev)
{
ide_drive_t *drive;
+ ide_hwgroup_t *hwgroup;
unsigned int p, major, minor;
long flags;
@@ -1435,15 +1564,15 @@ int ide_revalidate_disk(kdev_t i_rdev)
return -ENODEV;
major = MAJOR(i_rdev);
minor = drive->select.b.unit << PARTN_BITS;
- __save_flags(flags);
- __cli();
+ hwgroup = HWGROUP(drive);
+ IDE_SPIN_LOCK_IRQSAVE("ide_revalidate_disk", &hwgroup->spinlock, flags);
if (drive->busy || (drive->usage > 1)) {
- __restore_flags(flags);
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_revalidate_disk", &hwgroup->spinlock, flags);
return -EBUSY;
};
drive->busy = 1;
MOD_INC_USE_COUNT;
- __restore_flags(flags);
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_revalidate_disk", &hwgroup->spinlock, flags);
for (p = 0; p < (1<<PARTN_BITS); ++p) {
if (drive->part[p].nr_sects > 0) {
@@ -1589,8 +1718,8 @@ void ide_unregister (unsigned int index)
if (index >= MAX_HWIFS)
return;
- __save_flags(flags);
- __cli();
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
hwif = &ide_hwifs[index];
if (!hwif->present)
goto abort;
@@ -1680,7 +1809,7 @@ void ide_unregister (unsigned int index)
}
init_hwif_data (index); /* restore hwif data to pristine status */
abort:
- __restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
}
int ide_register (int arg1, int arg2, int irq)
@@ -1719,7 +1848,7 @@ found:
return hwif->present ? index : -1;
}
-void ide_add_setting(ide_drive_t *drive, char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
+void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
{
ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
@@ -1798,38 +1927,63 @@ repeat:
int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
{
- if (!(setting->rw & SETTING_READ))
- return -EINVAL;
- switch(setting->data_type) {
- case TYPE_BYTE:
- return *((u8 *) setting->data);
- case TYPE_SHORT:
- return *((u16 *) setting->data);
- case TYPE_INT:
- case TYPE_INTA:
- return *((u32 *) setting->data);
- default:
- return -EINVAL;
+ int val = -EINVAL;
+ unsigned long flags;
+
+ if ((setting->rw & SETTING_READ)) {
+ IDE_SPIN_LOCK_IRQSAVE("ide_read_setting", &HWGROUP(drive)->spinlock, flags);
+ switch(setting->data_type) {
+ case TYPE_BYTE:
+ val = *((u8 *) setting->data);
+ break;
+ case TYPE_SHORT:
+ val = *((u16 *) setting->data);
+ break;
+ case TYPE_INT:
+ case TYPE_INTA:
+ val = *((u32 *) setting->data);
+ break;
+ }
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_read_setting", &HWGROUP(drive)->spinlock, flags);
+ }
+ return val;
+}
+
+int ide_spin_wait_hwgroup (const char *msg, ide_drive_t *drive, unsigned long *flags)
+{
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ unsigned long timeout = jiffies + (3 * HZ);
+
+ IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, *flags);
+ while (hwgroup->busy) {
+ IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, *flags);
+ __sti(); /* local CPU only; needed for jiffies */
+ if (0 < (signed long)(jiffies - timeout)) {
+ printk("%s: %s: channel busy\n", drive->name, msg);
+ return -EBUSY;
+ }
+ IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, *flags);
}
+ return 0;
}
int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
{
unsigned long flags;
- int i, rc = 0;
+ int i;
u32 *p;
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (!(setting->rw & SETTING_WRITE))
return -EPERM;
if (val < setting->min || val > setting->max)
return -EINVAL;
- __save_flags(flags);
- __cli();
if (setting->set)
- rc = setting->set(drive, val);
- else switch (setting->data_type) {
+ return setting->set(drive, val);
+ if (ide_spin_wait_hwgroup("ide_write_settings", drive, &flags))
+ return -EBUSY;
+ switch (setting->data_type) {
case TYPE_BYTE:
*((u8 *) setting->data) = val;
break;
@@ -1845,8 +1999,8 @@ int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
*p = val;
break;
}
- __restore_flags(flags);
- return rc;
+ IDE_SPIN_UNLOCK_IRQRESTORE("ide_write_setting4", &HWGROUP(drive)->spinlock, flags);
+ return 0;
}
static int set_io_32bit(ide_drive_t *drive, int arg)
@@ -1956,7 +2110,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return 0;
}
case BLKFLSBUF:
- if (!suser()) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
return 0;
@@ -1965,21 +2119,17 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (long *) arg);
case BLKRRPART: /* Re-read partition tables */
- if (!suser()) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
return ide_revalidate_disk(inode->i_rdev);
+ case HDIO_OBSOLETE_IDENTITY:
case HDIO_GET_IDENTITY:
if (MINOR(inode->i_rdev) & PARTN_MASK)
return -EINVAL;
if (drive->id == NULL)
return -ENOMSG;
-#if 0
- if (copy_to_user((char *)arg, (char *)drive->id, sizeof(*drive->id)))
+ if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
return -EFAULT;
-#else
- if (copy_to_user((char *)arg, (char *)drive->id, 142))
- return -EFAULT;
-#endif
return 0;
case HDIO_GET_NICE:
@@ -1993,7 +2143,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
{
byte args[4], *argbuf = args;
int argsize = 4;
- if (!suser()) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (NULL == (void *) arg)
return ide_do_drive_cmd(drive, &rq, ide_wait);
if (copy_from_user(args, (void *)arg, 4))
@@ -2016,7 +2166,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case HDIO_SCAN_HWIF:
{
int args[3];
- if (!suser()) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (copy_from_user(args, (void *)arg, 3 * sizeof(int)))
return -EFAULT;
if (ide_register(args[0], args[1], args[2]) == -1)
@@ -2024,7 +2174,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return 0;
}
case HDIO_SET_NICE:
- if (!suser()) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (drive->driver == NULL)
return -EPERM;
if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
@@ -2311,7 +2461,7 @@ __initfunc(void ide_setup (char *s))
goto bad_option; /* chipset already specified */
if (i <= -7 && hw != 0)
goto bad_hwif; /* chipset drivers are for "ide0=" only */
- if (ide_hwifs[hw^1].chipset != ide_unknown)
+ if (i <= -7 && ide_hwifs[hw^1].chipset != ide_unknown)
goto bad_option; /* chipset for 2nd port already specified */
printk("\n");
}
@@ -2528,12 +2678,6 @@ __initfunc(static void probe_for_hwifs (void))
ide_probe_for_rz100x();
}
#endif /* CONFIG_BLK_DEV_RZ1000 */
-#ifdef CONFIG_BLK_DEV_SL82C105
- {
- extern void ide_probe_for_sl82c105(void);
- ide_probe_for_sl82c105();
- }
-#endif /* CONFIG_BLK_DEV_SL82C105 */
#endif /* CONFIG_BLK_DEV_IDEPCI */
}
#endif /* CONFIG_PCI */
@@ -2560,21 +2704,21 @@ __initfunc(void ide_init_builtin_drivers (void))
probe_for_hwifs ();
#ifdef CONFIG_BLK_DEV_IDE
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
- ide_get_lock(&ide_lock, NULL, NULL);
+ ide_get_lock(&ide_lock, NULL, NULL); /* for atari only */
disable_irq(ide_hwifs[0].irq);
}
-#endif /* __mc68000__ */
+#endif /* __mc68000__ || CONFIG_APUS */
(void) ideprobe_init();
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
enable_irq(ide_hwifs[0].irq);
- ide_release_lock(&ide_lock);
+ ide_release_lock(&ide_lock); /* for atari only */
}
-#endif /* __mc68000__ */
+#endif /* __mc68000__ || CONFIG_APUS */
#endif /* CONFIG_BLK_DEV_IDE */
#ifdef CONFIG_PROC_FS
@@ -2705,16 +2849,15 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio
{
unsigned long flags;
- __save_flags(flags);
- __cli();
- if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL ||
- drive->busy || drive->usage) {
- __restore_flags(flags);
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
+ if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL || drive->busy || drive->usage) {
+ restore_flags(flags); /* all CPUs */
return 1;
}
drive->driver = driver;
setup_driver_defaults(drive);
- __restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
if (drive->autotune != 2) {
if (driver->supports_dma && HWIF(drive)->dmaproc != NULL)
(void) (HWIF(drive)->dmaproc(ide_dma_check, drive));
@@ -2733,10 +2876,10 @@ int ide_unregister_subdriver (ide_drive_t *drive)
{
unsigned long flags;
- __save_flags(flags);
- __cli();
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) {
- __restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
return 1;
}
#ifdef CONFIG_PROC_FS
@@ -2745,7 +2888,7 @@ int ide_unregister_subdriver (ide_drive_t *drive)
#endif
auto_remove_settings(drive);
drive->driver = NULL;
- __restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
return 0;
}
diff --git a/drivers/block/ide.h b/drivers/block/ide.h
index f4ac72a62..f0c9604f0 100644
--- a/drivers/block/ide.h
+++ b/drivers/block/ide.h
@@ -204,26 +204,28 @@ typedef struct ide_drive_s {
unsigned long service_start; /* time we started last request */
unsigned long service_time; /* service time of last request */
special_t special; /* special action flags */
+ byte keep_settings; /* restore settings after drive reset */
+ byte using_dma; /* disk is using dma for read/write */
+ byte waiting_for_dma; /* dma currently in progress */
+ byte unmask; /* flag: okay to unmask other irqs */
+ byte slow; /* flag: slow data port */
+ byte bswap; /* flag: byte swap data */
+ byte dsc_overlap; /* flag: DSC overlap */
+ byte nice1; /* flag: give potential excess bandwidth */
unsigned present : 1; /* drive is physically present */
unsigned noprobe : 1; /* from: hdx=noprobe */
- byte keep_settings; /* restore settings after drive reset */
unsigned busy : 1; /* currently doing revalidate_disk() */
unsigned removable : 1; /* 1 if need to do check_media_change */
- byte using_dma; /* disk is using dma for read/write */
unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */
- byte unmask; /* flag: okay to unmask other irqs */
unsigned no_unmask : 1; /* disallow setting unmask bit */
unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */
unsigned nobios : 1; /* flag: do not probe bios for drive */
- byte slow; /* flag: slow data port */
- unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
unsigned revalidate : 1; /* request revalidation */
- byte bswap; /* flag: byte swap data */
- byte dsc_overlap; /* flag: DSC overlap */
unsigned atapi_overlap : 1; /* flag: ATAPI overlap (not supported) */
unsigned nice0 : 1; /* flag: give obvious excess bandwidth */
- byte nice1; /* flag: give potential excess bandwidth */
unsigned nice2 : 1; /* flag: give a share in our own bandwidth */
+ unsigned doorlocking : 1; /* flag: for removable only: door lock/unlock works */
+ unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
#if FAKE_FDISK_FOR_EZDRIVE
unsigned remap_0_to_1 : 1; /* flag: partitioned with ezdrive */
#endif /* FAKE_FDISK_FOR_EZDRIVE */
@@ -274,7 +276,8 @@ typedef struct ide_drive_s {
* should either try again later, or revert to PIO for the current request.
*/
typedef enum { ide_dma_read, ide_dma_write, ide_dma_begin, ide_dma_end,
- ide_dma_check, ide_dma_on, ide_dma_off, ide_dma_off_quietly
+ ide_dma_check, ide_dma_on, ide_dma_off, ide_dma_off_quietly,
+ ide_dma_test_irq
} ide_dma_action_t;
typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
@@ -344,7 +347,7 @@ typedef struct hwif_s {
unsigned reset : 1; /* reset after probe */
unsigned no_autodma : 1; /* don't automatically enable DMA at boot */
byte channel; /* for dual-port chips: 0=primary, 1=secondary */
- struct pci_dev *pci_dev; /* for pci chipsets */
+ struct pci_dev *pci_dev; /* for pci chipsets */
ide_pci_devid_t pci_devid; /* for pci chipsets: {VID,DID} */
#if (DISK_RECOVERY_TIME > 0)
unsigned long last_time; /* time when previous rq was done */
@@ -357,14 +360,15 @@ typedef struct hwif_s {
typedef void (ide_handler_t)(ide_drive_t *);
typedef struct hwgroup_s {
+ spinlock_t spinlock; /* protects "busy" and "handler" */
ide_handler_t *handler;/* irq handler, if active */
+ int busy; /* BOOL: protects all fields below */
ide_drive_t *drive; /* current drive */
ide_hwif_t *hwif; /* ptr to current hwif in linked-list */
struct request *rq; /* current request */
struct timer_list timer; /* failsafe timer */
struct request wrq; /* local copy of current write rq */
unsigned long poll_timeout; /* timeout value during long polls */
- int active; /* set when servicing requests */
} ide_hwgroup_t;
/*
@@ -397,7 +401,7 @@ typedef struct ide_settings_s {
struct ide_settings_s *next;
} ide_settings_t;
-void ide_add_setting(ide_drive_t *drive, char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
+void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
void ide_remove_setting(ide_drive_t *drive, char *name);
ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
@@ -667,6 +671,7 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
*/
struct request **ide_get_queue (kdev_t dev);
+int ide_spin_wait_hwgroup(const char *msg, ide_drive_t *drive, unsigned long *flags);
void ide_timer_expiry (unsigned long data);
void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
void ide_geninit (struct gendisk *gd);
@@ -693,6 +698,9 @@ extern struct file_operations ide_fops[];
#endif
#ifdef _IDE_C
+#ifdef CONFIG_BLK_DEV_IDE
+int ideprobe_init (void);
+#endif /* CONFIG_BLK_DEV_IDE */
#ifdef CONFIG_BLK_DEV_IDEDISK
int idedisk_init (void);
#endif /* CONFIG_BLK_DEV_IDEDISK */
@@ -726,13 +734,9 @@ int ide_build_dmatable (ide_drive_t *drive);
void ide_dma_intr (ide_drive_t *drive);
int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
-unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name) __init;
+unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
#endif
-#ifdef CONFIG_BLK_DEV_IDE
-int ideprobe_init (void);
-#endif /* CONFIG_BLK_DEV_IDE */
-
#ifdef CONFIG_BLK_DEV_PDC4030
#include "pdc4030.h"
#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 900ed785a..d1201086d 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -448,7 +448,7 @@ static int loop_get_status(struct loop_device *lo, struct loop_info *arg)
info.lo_flags = lo->lo_flags;
strncpy(info.lo_name, lo->lo_name, LO_NAME_SIZE);
info.lo_encrypt_type = lo->lo_encrypt_type;
- if (lo->lo_encrypt_key_size && suser()) {
+ if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) {
info.lo_encrypt_key_size = lo->lo_encrypt_key_size;
memcpy(info.lo_encrypt_key, lo->lo_encrypt_key,
lo->lo_encrypt_key_size);
diff --git a/drivers/block/md.c b/drivers/block/md.c
index 674c378b1..8b4b487e1 100644
--- a/drivers/block/md.c
+++ b/drivers/block/md.c
@@ -622,7 +622,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
int minor, err;
struct hd_geometry *loc = (struct hd_geometry *) arg;
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (((minor=MINOR(inode->i_rdev)) & 0x80) &&
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 70e445668..cd733884c 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -316,7 +316,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
struct nbd_device *lo;
int dev, error;
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (!inode)
return -EINVAL;
diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c
index f312b251c..e7006ed69 100644
--- a/drivers/block/ns87415.c
+++ b/drivers/block/ns87415.c
@@ -35,7 +35,8 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
struct pci_dev *dev = hwif->pci_dev;
unsigned long flags;
- save_flags(flags); cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
new = *old;
/* adjust IRQ enable bit */
@@ -56,7 +57,7 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
*old = new;
(void) pci_write_config_dword(dev, 0x40, new);
}
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
}
static void ns87415_selectproc (ide_drive_t *drive)
@@ -66,33 +67,25 @@ static void ns87415_selectproc (ide_drive_t *drive)
static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+ byte dma_stat;
switch (func) {
case ide_dma_end: /* returns 1 on error, 0 otherwise */
- {
- byte dma_stat = inb(hwif->dma_base+2);
- int rc = (dma_stat & 7) != 4;
- /* from errata: stop DMA, clear INTR & ERROR */
- outb(7, hwif->dma_base);
- /* clear the INTR & ERROR bits */
- outb(dma_stat|6, hwif->dma_base+2);
- /* verify good DMA status */
- return rc;
- }
+ drive->waiting_for_dma = 0;
+ dma_stat = inb(hwif->dma_base+2);
+ outb(7, hwif->dma_base); /* from errata: stop DMA, clear INTR & ERROR */
+ outb(dma_stat|6, hwif->dma_base+2); /* clear the INTR & ERROR bits */
+ return (dma_stat & 7) != 4; /* verify good DMA status */
case ide_dma_write:
case ide_dma_read:
- /* select DMA xfer */
- ns87415_prepare_drive(drive, 1);
- /* use standard DMA stuff */
- if (!ide_dmaproc(func, drive))
+ ns87415_prepare_drive(drive, 1); /* select DMA xfer */
+ if (!ide_dmaproc(func, drive)) /* use standard DMA stuff */
return 0;
- /* DMA failed: select PIO xfer */
- ns87415_prepare_drive(drive, 0);
+ ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */
return 1;
default:
- /* use standard DMA stuff */
- return ide_dmaproc(func, drive);
+ return ide_dmaproc(func, drive); /* use standard DMA stuff */
}
}
@@ -100,8 +93,7 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
{
struct pci_dev *dev = hwif->pci_dev;
unsigned int ctrl, using_inta;
- byte progif, stat;
- int timeout;
+ byte progif;
/*
* We cannot probe for IRQ: both ports share common IRQ on INTA.
@@ -134,6 +126,9 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
pci_write_config_byte(dev, 0x55, 0xee);
#ifdef __sparc_v9__
+{
+ int timeout;
+ byte stat;
/*
* XXX: Reset the device, if we don't it will not respond
* to SELECT_DRIVE() properly during first probe_hwif().
@@ -148,6 +143,7 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
if (stat == 0xff)
break;
} while ((stat & BUSY_STAT) && --timeout);
+}
#endif
}
if (!using_inta)
diff --git a/drivers/block/opti621.c b/drivers/block/opti621.c
index a6be01938..41b87fbbe 100644
--- a/drivers/block/opti621.c
+++ b/drivers/block/opti621.c
@@ -242,8 +242,8 @@ static void opti621_tune_drive (ide_drive_t *drive, byte pio)
hwif->name, ax, second.data_time, second.recovery_time, drdy);
#endif
- save_flags(flags);
- cli();
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
reg_base = hwif->io_ports[IDE_DATA_OFFSET];
outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */
@@ -268,7 +268,7 @@ static void opti621_tune_drive (ide_drive_t *drive, byte pio)
write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */
/* and read prefetch for both drives */
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
}
/*
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index aa431ae33..c2f9473bc 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -466,7 +466,7 @@ static int pd_ioctl(struct inode *inode,struct file *file,
put_user(pd_hd[dev].start_sect,(long *)&geo->start);
return 0;
case BLKRASET:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(!(inode->i_rdev)) return -EINVAL;
if(arg > 0xff) return -EINVAL;
read_ahead[MAJOR(inode->i_rdev)] = arg;
@@ -484,12 +484,14 @@ static int pd_ioctl(struct inode *inode,struct file *file,
put_user(pd_hd[dev].nr_sects,(long *) arg);
return (0);
case BLKFLSBUF:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(!(inode->i_rdev)) return -EINVAL;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
return 0;
case BLKRRPART:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return pd_revalidate(inode->i_rdev);
RO_IOCTLS(inode->i_rdev,arg);
default:
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 00d629ddd..b894e2cc9 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -416,7 +416,7 @@ static int pf_ioctl(struct inode *inode,struct file *file,
put_user(0,(long *)&geo->start);
return 0;
case BLKRASET:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(!(inode->i_rdev)) return -EINVAL;
if(arg > 0xff) return -EINVAL;
read_ahead[MAJOR(inode->i_rdev)] = arg;
@@ -434,7 +434,7 @@ static int pf_ioctl(struct inode *inode,struct file *file,
put_user(PF.capacity,(long *) arg);
return (0);
case BLKFLSBUF:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(!(inode->i_rdev)) return -EINVAL;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
diff --git a/drivers/block/pdc4030.c b/drivers/block/pdc4030.c
index 30baff570..b5b13b9cb 100644
--- a/drivers/block/pdc4030.c
+++ b/drivers/block/pdc4030.c
@@ -327,15 +327,9 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq)
do {
stat=GET_STAT();
if(stat & DRQ_STAT) {
-/* unsigned long flags;
- save_flags(flags);
- cli();
disable_irq(HWIF(drive)->irq);
-*/
ide_intr(HWIF(drive)->irq,HWGROUP(drive),NULL);
-/* enable_irq(HWIF(drive)->irq);
- restore_flags(flags);
-*/
+ enable_irq(HWIF(drive)->irq);
return;
}
if(IN_BYTE(IDE_SELECT_REG) & 0x01)
@@ -353,7 +347,7 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq)
return;
}
if (!drive->unmask)
- cli();
+ __cli(); /* local CPU only */
HWGROUP(drive)->wrq = *rq; /* scratchpad */
promise_write(drive);
return;
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index cf13eccaf..bef50bd36 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -1091,7 +1091,7 @@ static int ps2esdi_ioctl(struct inode *inode,
}
break;
case BLKRASET:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (!inode->i_rdev)
return -EINVAL;
@@ -1109,7 +1109,7 @@ static int ps2esdi_ioctl(struct inode *inode,
}
break;
case BLKFLSBUF:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (!inode->i_rdev)
return -EINVAL;
@@ -1118,6 +1118,8 @@ static int ps2esdi_ioctl(struct inode *inode,
return 0;
case BLKRRPART:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return (ps2esdi_reread_partitions(inode->i_rdev));
RO_IOCTLS(inode->i_rdev, arg);
}
diff --git a/drivers/block/qd6580.c b/drivers/block/qd6580.c
index 9c13bfea9..9c1d0ed71 100644
--- a/drivers/block/qd6580.c
+++ b/drivers/block/qd6580.c
@@ -49,13 +49,13 @@ static void tune_qd6580 (ide_drive_t *drive, byte pio)
pio = ide_get_best_pio_mode(drive, pio, 3, NULL);
- save_flags(flags);
- cli();
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
outb_p(0x8d,0xb0);
outb_p(0x0 ,0xb2);
outb_p(((pio+1)<<4)|0x0f,0xb3);
inb(0x3f6);
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
}
void init_qd6580 (void)
diff --git a/drivers/block/raid5.c b/drivers/block/raid5.c
index 2b0e97450..88e2eb133 100644
--- a/drivers/block/raid5.c
+++ b/drivers/block/raid5.c
@@ -1209,6 +1209,14 @@ repeat:
sh->pd_idx = pd_idx;
if (sh->phase != PHASE_COMPLETE && sh->phase != PHASE_BEGIN)
PRINTK(("stripe %lu catching the bus!\n", sh->sector));
+ if (sh->bh_new[dd_idx]) {
+ printk("raid5: bug: stripe->bh_new[%d], sector %lu exists\n", dd_idx, sh->sector);
+ printk("raid5: bh %p, bh_new %p\n", bh, sh->bh_new[dd_idx]);
+ lock_stripe(sh);
+ md_wakeup_thread(raid_conf->thread);
+ wait_on_stripe(sh);
+ goto repeat;
+ }
add_stripe_bh(sh, bh, dd_idx, rw);
md_wakeup_thread(raid_conf->thread);
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 180a090d1..a3366d04b 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -164,7 +164,7 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
switch (cmd) {
case BLKFLSBUF:
- if (!suser()) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
invalidate_buffers(inode->i_rdev);
break;
case BLKGETSIZE: /* Return device size */
diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c
index 83426bc5e..ef05e4656 100644
--- a/drivers/block/sl82c105.c
+++ b/drivers/block/sl82c105.c
@@ -19,8 +19,9 @@ int chrp_ide_ports_known = 0;
ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
ide_ioreg_t chrp_idedma_regbase;
-void ide_init_sl82c105(struct pci_dev *dev) {
-
+void ide_init_sl82c105(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = hwif->pci_dev;
unsigned short t16;
unsigned int t32;
@@ -37,15 +38,7 @@ void ide_init_sl82c105(struct pci_dev *dev) {
pci_write_config_dword(dev, 0x40, 0x10ff08a1);
}
-
-void ide_probe_for_sl82c105(void)
-{
- struct pci_dev *dev = NULL;
-
- while ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev)))
- ide_init_sl82c105(dev);
-}
-
+#if 0 /* nobody ever calls these.. ?? */
void chrp_ide_probe(void) {
struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
@@ -75,4 +68,4 @@ void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
if (irq != NULL)
*irq = chrp_ide_irq;
}
-
+#endif
diff --git a/drivers/block/trm290.c b/drivers/block/trm290.c
index 474d434a2..2b0678849 100644
--- a/drivers/block/trm290.c
+++ b/drivers/block/trm290.c
@@ -148,8 +148,8 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
/* select PIO or DMA */
reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82);
- save_flags(flags);
- cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
if (reg != hwif->select_data) {
hwif->select_data = reg;
@@ -164,7 +164,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
outw(reg, hwif->config_data+3);
}
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
}
static void trm290_selectproc (ide_drive_t *drive)
@@ -189,15 +189,20 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
break; /* try PIO instead of DMA */
trm290_prepare_drive(drive, 1); /* select DMA xfer */
outl(virt_to_bus(hwif->dmatable)|reading|writing, hwif->dma_base);
+ drive->waiting_for_dma = 1;
outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */
if (drive->media != ide_disk)
return 0;
ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
+ return 0;
case ide_dma_begin:
return 0;
case ide_dma_end:
+ drive->waiting_for_dma = 0;
return (inw(hwif->dma_base+2) != 0x00ff);
+ case ide_dma_test_irq:
+ return (inw(hwif->dma_base+2) == 0x00ff);
default:
return ide_dmaproc(func, drive);
}
@@ -226,8 +231,8 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
printk("TRM290: using default config base at 0x%04lx\n", hwif->config_data);
}
- save_flags(flags);
- cli();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
/* put config reg into first byte of hwif->select_data */
outb(0x51|(hwif->channel<<3), hwif->config_data+1);
hwif->select_data = 0x21; /* select PIO as default */
@@ -235,13 +240,13 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
reg = inb(hwif->config_data+3); /* get IRQ info */
reg = (reg & 0x10) | 0x03; /* mask IRQs for both ports */
outb(reg, hwif->config_data+3);
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
if ((reg & 0x10))
hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */
else if (!hwif->irq && hwif->mate && hwif->mate->irq)
hwif->irq = hwif->mate->irq; /* sharing IRQ with mate */
- ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 2);
+ ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
hwif->dmaproc = &trm290_dmaproc;
hwif->selectproc = &trm290_selectproc;
hwif->no_autodma = 1; /* play it safe for now */
diff --git a/drivers/block/umc8672.c b/drivers/block/umc8672.c
index 8856dad35..77121ca3e 100644
--- a/drivers/block/umc8672.c
+++ b/drivers/block/umc8672.c
@@ -112,39 +112,39 @@ static void tune_umc (ide_drive_t *drive, byte pio)
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]);
- save_flags(flags);
- cli();
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
if (hwgroup && hwgroup->handler != NULL) {
printk("umc8672: other interface is busy: exiting tune_umc()\n");
} else {
current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
umc_set_speeds (current_speeds);
}
- restore_flags(flags);
+ restore_flags(flags); /* all CPUs */
}
void init_umc8672 (void) /* called from ide.c */
{
unsigned long flags;
- save_flags(flags);
- cli ();
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
if (check_region(0x108, 2)) {
- restore_flags(flags);
+ __restore_flags(flags);
printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
return;
}
outb_p (0x5A,0x108); /* enable umc */
if (in_umc (0xd5) != 0xa0)
{
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
printk ("umc8672: not found\n");
return;
}
outb_p (0xa5,0x108); /* disable umc */
umc_set_speeds (current_speeds);
- restore_flags(flags);
+ __restore_flags(flags); /* local CPU only */
request_region(0x108, 2, "umc8672");
ide_hwifs[0].chipset = ide_umc8672;
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 7a26e28ac..b7d604db8 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -338,7 +338,7 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
}
case BLKRASET:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(arg > 0xff) return -EINVAL;
read_ahead[MAJOR(inode->i_rdev)] = arg;
return 0;
@@ -348,12 +348,12 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
if (!arg) return -EINVAL;
return put_user(xd_struct[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
case BLKFLSBUF: /* Return devices size */
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
return 0;
case HDIO_SET_DMA:
- if (!suser()) return -EACCES;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (xdc_busy) return -EBUSY;
nodma = !arg;
if (nodma && xd_dma_buffer) {
@@ -366,6 +366,8 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
case HDIO_GET_MULTCOUNT:
return put_user(xd_maxsectors, (long *) arg);
case BLKRRPART:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return xd_reread_partitions(inode->i_rdev);
RO_IOCTLS(inode->i_rdev,arg);
default:
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index a3b3e2989..539794595 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -4189,7 +4189,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
switch (cmd) /* Sun-compatible */
{
case DDIOCSDBG: /* DDI Debug */
- if (!suser()) RETURN_UP(-EPERM);
+ if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
i=sbpcd_dbg_ioctl(arg,1);
RETURN_UP(i);
case CDROMRESET: /* hard reset the drive */
@@ -4478,7 +4478,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
} /* end of CDROMREADAUDIO */
case BLKRASET:
- if(!suser()) RETURN_UP(-EACCES);
+ if(!capable(CAP_SYS_ADMIN)) RETURN_UP(-EACCES);
if(!(cdi->dev)) RETURN_UP(-EINVAL);
if(arg > 0xff) RETURN_UP(-EINVAL);
read_ahead[MAJOR(cdi->dev)] = arg;
diff --git a/drivers/char/apm_bios.c b/drivers/char/apm_bios.c
index f4fcf4f7b..c461cf709 100644
--- a/drivers/char/apm_bios.c
+++ b/drivers/char/apm_bios.c
@@ -1050,7 +1050,7 @@ static int do_open(struct inode * inode, struct file * filp)
* we might close the device immediately without doing a
* privileged operation -- cevans
*/
- as->suser = suser();
+ as->suser = capable(CAP_SYS_ADMIN);
as->next = user_list;
user_list = as;
filp->private_data = as;
diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c
index ec66585cf..97d5794f1 100644
--- a/drivers/char/bttv.c
+++ b/drivers/char/bttv.c
@@ -1581,7 +1581,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCSFBUF:
{
struct video_buffer v;
- if(!suser())
+ if(!capable(CAP_SYS_ADMIN))
return -EPERM;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
@@ -1680,7 +1680,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return 0;
case BTTV_WRITEE:
- if(!suser())
+ if(!capable(CAP_SYS_ADMIN))
return -EPERM;
if(copy_from_user((void *) eedata, (void *) arg, 256))
return -EFAULT;
@@ -1688,7 +1688,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return 0;
case BTTV_READEE:
- if(!suser())
+ if(!capable(CAP_SYS_ADMIN))
return -EPERM;
readee(&(btv->i2c), eedata);
if(copy_to_user((void *) arg, (void *) eedata, 256))
diff --git a/drivers/char/console.c b/drivers/char/console.c
index bff096479..9c9e61e8c 100644
--- a/drivers/char/console.c
+++ b/drivers/char/console.c
@@ -347,7 +347,7 @@ int vc_allocate(unsigned int i) /* return 0 on success */
long p, q;
/* prevent users from taking too much memory */
- if (i >= MAX_NR_USER_CONSOLES && !suser())
+ if (i >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
return -EPERM;
/* due to the granularity of kmalloc, we waste some memory here */
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 2ea9cb86f..553bf273b 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -926,7 +926,7 @@ static int startup(struct esp_struct * info)
"esp serial", info);
if (retval) {
- if (suser()) {
+ if (capable(CAP_SYS_ADMIN)) {
if (info->tty)
set_bit(TTY_IO_ERROR,
&info->tty->flags);
@@ -1499,7 +1499,7 @@ static int set_serial_info(struct esp_struct * info,
if (change_irq && (info->line % 8))
return -EINVAL;
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if (change_irq ||
(new_serial.close_delay != info->close_delay) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
diff --git a/drivers/char/ftape/zftape/zftape-ctl.c b/drivers/char/ftape/zftape/zftape-ctl.c
index 3b80c207f..da2010ceb 100644
--- a/drivers/char/ftape/zftape/zftape-ctl.c
+++ b/drivers/char/ftape/zftape/zftape-ctl.c
@@ -1342,9 +1342,9 @@ static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size)
TRACE_FUN(ft_t_flow);
TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
TRACE_ABORT(-EPERM, ft_t_info,
- "only the superuser may send raw qic-117 commands");
+ "need CAP_SYS_ADMIN capability to send raw qic-117 commands");
}
if (zft_qic_mode) {
TRACE_ABORT(-EACCES, ft_t_info,
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 2e0dd3736..404f9c88c 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -1774,7 +1774,7 @@ static int stli_setserial(stliport_t *portp, struct serial_struct *sp)
#endif
copy_from_user(&sio, sp, sizeof(struct serial_struct));
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((sio.baud_base != portp->baud_base) ||
(sio.close_delay != portp->close_delay) ||
((sio.flags & ~ASYNC_USR_MASK) !=
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 2e2ffc341..7df3eb655 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -13,7 +13,7 @@
* lp_read (Status readback) support added by Carsten Gross,
* carsten@sol.wohnheim.uni-ulm.de
* Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
- * parport_sharing hacking by Andrea Arcangeli <arcangeli@mbox.queen.it>
+ * Parport sharing hacking by Andrea Arcangeli <arcangeli@mbox.queen.it>
* Fixed kernel_(to/from)_user memory copy to check for errors
* by Riccardo Facchetti <fizban@tin.it>
*/
@@ -75,6 +75,8 @@
#include <linux/delay.h>
#include <linux/parport.h>
+#undef LP_STATS
+#undef LP_NEED_CAREFUL
#include <linux/lp.h>
#include <asm/irq.h>
@@ -87,17 +89,23 @@
struct lp_struct lp_table[LP_NO] =
{
[0 ... LP_NO-1] = {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT,
- NULL, 0, 0, 0, {0}}
+ NULL,
+#ifdef LP_STATS
+ 0, 0, {0},
+#endif
+ NULL, 0}
};
/* Test if printer is ready (and optionally has no error conditions) */
+#ifdef LP_NEED_CAREFUL
#define LP_READY(minor, status) \
- ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : (status & LP_PBUSY))
-#define LP_CAREFUL_READY(minor, status) \
- ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : 1)
+ ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : ((status) & LP_PBUSY))
#define _LP_CAREFUL_READY(status) \
- (status & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
+ ((status) & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
(LP_PBUSY|LP_PSELECD|LP_PERRORP)
+#else
+#define LP_READY(minor, status) ((status) & LP_PBUSY)
+#endif
#undef LP_DEBUG
#undef LP_READ_DEBUG
@@ -108,8 +116,8 @@ static int lp_preempt(void *handle)
{
struct lp_struct *lps = (struct lp_struct *)handle;
- if (waitqueue_active (&lps->dev->wait_q))
- wake_up_interruptible(&lps->dev->wait_q);
+ if (waitqueue_active (&lps->wait_q))
+ wake_up_interruptible(&lps->wait_q);
/* Don't actually release the port now */
return 1;
@@ -157,31 +165,29 @@ static int lp_reset(int minor)
static inline int lp_char(char lpchar, int minor)
{
- int status;
+ unsigned char status;
unsigned int wait = 0;
unsigned long count = 0;
+#ifdef LP_STATS
struct lp_stats *stats;
+#endif
- for (;;) {
+ for (;;)
+ {
lp_yield(minor);
status = r_str (minor);
- if (++count == LP_CHAR(minor))
+ if (LP_READY(minor, status))
+ break;
+ if (!LP_POLLED(minor) || ++count == LP_CHAR(minor) ||
+ signal_pending(current))
return 0;
- if (LP_POLLING(minor))
- {
- if (LP_READY(minor, status))
- break;
- } else {
- if (!LP_READY(minor, status))
- return 0;
- else
- break;
- }
}
w_dtr(minor, lpchar);
+#ifdef LP_STATS
stats = &LP_STAT(minor);
stats->chars++;
+#endif
/* must wait before taking strobe high, and after taking strobe
low, according spec. Some printers need it, others don't. */
#ifndef __sparc__
@@ -200,6 +206,8 @@ static inline int lp_char(char lpchar, int minor)
#endif
/* take strobe low */
w_ctr(minor, LP_PSELECP | LP_PINITP);
+
+#ifdef LP_STATS
/* update waittime statistics */
if (count > stats->maxwait) {
#ifdef LP_DEBUG
@@ -212,6 +220,7 @@ static inline int lp_char(char lpchar, int minor)
stats->meanwait - count;
stats->meanwait = (255 * stats->meanwait + count + 128) / 256;
stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
+#endif
return 1;
}
@@ -220,13 +229,13 @@ static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct lp_struct *lp_dev = (struct lp_struct *) dev_id;
- if (waitqueue_active (&lp_dev->dev->wait_q))
- wake_up_interruptible(&lp_dev->dev->wait_q);
+ if (waitqueue_active (&lp_dev->wait_q))
+ wake_up_interruptible(&lp_dev->wait_q);
}
static void lp_error(int minor)
{
- if (LP_POLLING(minor) || LP_PREEMPTED(minor)) {
+ if (LP_POLLED(minor) || LP_PREEMPTED(minor)) {
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIMEOUT_POLLED;
lp_parport_release(minor);
@@ -236,7 +245,7 @@ static void lp_error(int minor)
}
static int lp_check_status(int minor) {
- static unsigned char last = 0;
+ unsigned int last = lp_table[minor].last_error;
unsigned char status = r_str(minor);
if ((status & LP_POUTPA)) {
if (last != LP_POUTPA) {
@@ -256,6 +265,8 @@ static int lp_check_status(int minor) {
}
else last = 0;
+ lp_table[minor].last_error = last;
+
if (last != 0) {
if (LP_F(minor) & LP_ABORT)
return 1;
@@ -265,7 +276,7 @@ static int lp_check_status(int minor) {
return 0;
}
-static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
+static int lp_write_buf(unsigned int minor, const char *buf, int count)
{
unsigned long copy_size;
unsigned long total_bytes_written = 0;
@@ -275,9 +286,11 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
if (minor >= LP_NO)
return -ENXIO;
- if (lp_table[minor].dev == NULL)
+ if (lp->dev == NULL)
return -ENXIO;
+ lp_table[minor].last_error = 0;
+
do {
bytes_written = 0;
copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
@@ -289,55 +302,69 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
if (lp_char(lp->lp_buffer[bytes_written], minor)) {
--copy_size;
++bytes_written;
- lp_table[minor].runchars++;
+#ifdef LP_STATS
+ lp->runchars++;
+#endif
} else {
int rc = total_bytes_written + bytes_written;
- if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
- LP_STAT(minor).maxrun = lp_table[minor].runchars;
+
+#ifdef LP_STATS
+ if (lp->runchars > LP_STAT(minor).maxrun)
+ LP_STAT(minor).maxrun = lp->runchars;
LP_STAT(minor).sleeps++;
+#endif
- if (LP_POLLING(minor)) {
- lp_polling:
+ if (signal_pending(current)) {
+ if (total_bytes_written + bytes_written)
+ return total_bytes_written + bytes_written;
+ else
+ return -EINTR;
+ }
+
+#ifdef LP_STATS
+ lp->runchars = 0;
+#endif
+
+ if (LP_POLLED(minor)) {
if (lp_check_status(minor))
return rc ? rc : -EIO;
-#ifdef LP_DEBUG
- printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp_table[minor].runchars, LP_TIME(minor));
+ lp_polling:
+#if defined(LP_DEBUG) && defined(LP_STATS)
+ printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp->runchars, LP_TIME(minor));
#endif
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIME(minor);
lp_schedule (minor);
} else {
cli();
- if (LP_PREEMPTED(minor)) {
+ if (LP_PREEMPTED(minor))
+ {
+ /*
+ * We can' t sleep on the interrupt
+ * since another pardevice need the port.
+ */
sti();
goto lp_polling;
}
- enable_irq(lp->dev->port->irq);
- w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN);
+ w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
status = r_str(minor);
- if ((!(status & LP_PACK) || (status & LP_PBUSY))
- && LP_CAREFUL_READY(minor, status)) {
+ if (!(status & LP_PACK) || (status & LP_PBUSY))
+ {
+ /*
+ * The interrupt is happened in the
+ * meantime so don' t wait for it.
+ */
w_ctr(minor, LP_PSELECP | LP_PINITP);
sti();
continue;
}
current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
- interruptible_sleep_on(&lp->dev->wait_q);
- disable_irq(lp->dev->port->irq);
+ interruptible_sleep_on(&lp->wait_q);
w_ctr(minor, LP_PSELECP | LP_PINITP);
sti();
if (lp_check_status(minor))
return rc ? rc : -EIO;
}
-
- lp_table[minor].runchars = 0;
-
- if (signal_pending(current)) {
- if (total_bytes_written + bytes_written)
- return total_bytes_written + bytes_written;
- else
- return -EINTR;
- }
}
}
@@ -356,10 +383,12 @@ static ssize_t lp_write(struct file * file, const char * buf,
unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
ssize_t retv;
+#ifdef LP_STATS
if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
lp_table[minor].runchars = 0;
lp_table[minor].lastcall = jiffies;
+#endif
/* Claim Parport or sleep until it becomes available
*/
@@ -495,9 +524,8 @@ static int lp_open(struct inode * inode, struct file * file)
return -ENXIO;
if ((LP_F(minor) & LP_EXIST) == 0)
return -ENXIO;
- if (LP_F(minor) & LP_BUSY)
+ if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor)) & LP_BUSY)
return -EBUSY;
- LP_F(minor) |= LP_BUSY;
MOD_INC_USE_COUNT;
@@ -543,8 +571,8 @@ static int lp_release(struct inode * inode, struct file * file)
kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
lp_table[minor].lp_buffer = NULL;
- LP_F(minor) &= ~LP_BUSY;
MOD_DEC_USE_COUNT;
+ LP_F(minor) &= ~LP_BUSY;
return 0;
}
@@ -581,12 +609,14 @@ static int lp_ioctl(struct inode *inode, struct file *file,
else
LP_F(minor) &= ~LP_ABORTOPEN;
break;
+#ifdef LP_NEED_CAREFUL
case LPCAREFUL:
if (arg)
LP_F(minor) |= LP_CAREFUL;
else
LP_F(minor) &= ~LP_CAREFUL;
break;
+#endif
case LPWAIT:
LP_WAIT(minor) = arg;
break;
@@ -609,6 +639,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
case LPRESET:
lp_reset(minor);
break;
+#ifdef LP_STATS
case LPGETSTATS:
if (copy_to_user((int *) arg, &LP_STAT(minor),
sizeof(struct lp_stats)))
@@ -617,6 +648,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
memset(&LP_STAT(minor), 0,
sizeof(struct lp_stats));
break;
+#endif
case LPGETFLAGS:
status = LP_F(minor);
if (copy_to_user((int *) arg, &status, sizeof(int)))
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 329ac7b32..fba8c7d51 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -285,7 +285,7 @@ static int nvram_ioctl( struct inode *inode, struct file *file,
switch( cmd ) {
case NVRAM_INIT: /* initialize NVRAM contents and checksum */
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return( -EACCES );
save_flags(flags);
@@ -301,7 +301,7 @@ static int nvram_ioctl( struct inode *inode, struct file *file,
case NVRAM_SETCKS: /* just set checksum, contents unchanged
* (maybe useful after checksum garbaged
* somehow...) */
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return( -EACCES );
save_flags(flags);
diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c
index e4718688a..c466ae4a4 100644
--- a/drivers/char/pc_keyb.c
+++ b/drivers/char/pc_keyb.c
@@ -522,8 +522,13 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned char scancode;
/* mouse data? */
- if (status & kbd_read_mask & KBD_STAT_MOUSE_OBF)
+ if (status & kbd_read_mask & KBD_STAT_MOUSE_OBF) {
+#if defined(CONFIG_SGI) && defined(CONFIG_PSMOUSE)
+ scancode = kbd_read_input();
+ aux_interrupt(status, scancode);
+#endif
break;
+ }
scancode = kbd_read_input();
if ((status & KBD_STAT_OBF) && do_acknowledge(scancode))
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 226694a71..13d5d6d36 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1199,7 +1199,7 @@ random_ioctl(struct inode * inode, struct file * file,
put_user(ent_count, (int *) arg);
return 0;
case RNDADDTOENTCNT:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
retval = verify_area(VERIFY_READ, (void *) arg, sizeof(int));
if (retval)
@@ -1228,7 +1228,7 @@ random_ioctl(struct inode * inode, struct file * file,
wake_up_interruptible(&random_read_wait);
return 0;
case RNDGETPOOL:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
p = (int *) arg;
retval = verify_area(VERIFY_WRITE, (void *) p, sizeof(int));
@@ -1249,7 +1249,7 @@ random_ioctl(struct inode * inode, struct file * file,
return -EFAULT;
return 0;
case RNDADDENTROPY:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
p = (int *) arg;
retval = verify_area(VERIFY_READ, (void *) p, 2*sizeof(int));
@@ -1287,13 +1287,13 @@ random_ioctl(struct inode * inode, struct file * file,
wake_up_interruptible(&random_read_wait);
return 0;
case RNDZAPENTCNT:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
random_state.entropy_count = 0;
return 0;
case RNDCLEARPOOL:
/* Clear the entropy pool and associated counters. */
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
rand_clear_pool();
return 0;
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index bed251b19..b854fa338 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1447,7 +1447,7 @@ extern inline int rc_set_serial_info(struct riscom_port * port,
change_speed = ((port->flags & ASYNC_SPD_MASK) !=
(tmp.flags & ASYNC_SPD_MASK));
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((tmp.close_delay != port->close_delay) ||
(tmp.closing_wait != port->closing_wait) ||
((tmp.flags & ~ASYNC_USR_MASK) !=
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 901077455..cb4e9d498 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1315,7 +1315,7 @@ static int set_config(struct r_port * info, struct rocket_config * new_info)
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((new_serial.flags & ~ROCKET_USR_MASK) !=
(info->flags & ~ROCKET_USR_MASK))
return -EPERM;
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 9edca1683..5f827bed9 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -220,7 +220,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
* We don't really want Joe User enabling more
* than 64Hz of interrupts on a multi-user machine.
*/
- if ((rtc_freq > 64) && (!suser()))
+ if ((rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE)))
return -EACCES;
if (!(rtc_status & RTC_TIMER_ON)) {
@@ -308,7 +308,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned int yrs;
unsigned long flags;
- if (!suser())
+ if (!capable(CAP_SYS_TIME))
return -EACCES;
if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
@@ -394,7 +394,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
* We don't really want Joe User generating more
* than 64Hz of interrupts on a multi-user machine.
*/
- if ((arg > 64) && (!suser()))
+ if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
return -EACCES;
while (arg > (1<<tmp))
@@ -429,7 +429,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (arg < 1900)
return -EINVAL;
- if (!suser())
+ if (!capable(CAP_SYS_TIME))
return -EACCES;
epoch = arg;
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index dbec8e285..b5e41a2d2 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -995,7 +995,7 @@ static int startup(struct async_struct * info)
* here.
*/
if (serial_inp(info, UART_LSR) == 0xff) {
- if (suser()) {
+ if (capable(CAP_SYS_ADMIN)) {
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
} else
@@ -1027,7 +1027,7 @@ static int startup(struct async_struct * info)
retval = request_irq(state->irq, handler, IRQ_T(info),
"serial", NULL);
if (retval) {
- if (suser()) {
+ if (capable(CAP_SYS_ADMIN)) {
if (info->tty)
set_bit(TTY_IO_ERROR,
&info->tty->flags);
@@ -1660,7 +1660,7 @@ static int set_serial_info(struct async_struct * info,
change_port = (new_serial.port != state->port) ||
(new_serial.hub6 != state->hub6);
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if (change_irq || change_port ||
(new_serial.baud_base != state->baud_base) ||
(new_serial.type != state->type) ||
@@ -1859,7 +1859,7 @@ static int do_autoconfig(struct async_struct * info)
{
int retval;
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (info->state->count > 1)
@@ -1944,7 +1944,7 @@ static int set_multiport_struct(struct async_struct * info,
int retval;
void (*handler)(int, void *, struct pt_regs *);
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
state = info->state;
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index ef5e6f7c7..a5d66bbd8 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -1842,7 +1842,7 @@ extern inline int sx_set_serial_info(struct specialix_port * port,
change_speed = ((port->flags & ASYNC_SPD_MASK) !=
(tmp.flags & ASYNC_SPD_MASK));
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((tmp.close_delay != port->close_delay) ||
(tmp.closing_wait != port->closing_wait) ||
((tmp.flags & ~ASYNC_USR_MASK) !=
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 31fa5ab50..06795e07a 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1338,7 +1338,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct *sp)
#endif
copy_from_user(&sio, sp, sizeof(struct serial_struct));
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((sio.baud_base != portp->baud_base) ||
(sio.close_delay != portp->close_delay) ||
((sio.flags & ~ASYNC_USR_MASK) !=
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6316be514..360ca915f 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -254,7 +254,8 @@ do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kb
if (!(key_map = key_maps[s])) {
int j;
- if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
+ if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
+ !capable(CAP_SYS_RESOURCE))
return -EPERM;
key_map = (ushort *) kmalloc(sizeof(plain_map),
@@ -273,7 +274,7 @@ do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kb
/*
* Attention Key.
*/
- if (((ov == K_SAK) || (v == K_SAK)) && !suser())
+ if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
return -EPERM;
key_map[i] = U(v);
if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c
index 67c39c675..d94a8a771 100644
--- a/drivers/isdn/avmb1/capi.c
+++ b/drivers/isdn/avmb1/capi.c
@@ -384,7 +384,7 @@ static int capi_ioctl(struct inode *inode, struct file *file,
struct capi_manufacturer_cmd mcmd;
if (minor)
return -EINVAL;
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
retval = copy_from_user((void *) &mcmd, (void *) arg,
sizeof(mcmd));
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index 4232f5953..9c3f18c9e 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -964,7 +964,7 @@ static int set_serial_info(struct mac_serial * info,
copy_from_user(&new_serial,new_info,sizeof(new_serial));
old_info = *info;
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((new_serial.baud_base != info->baud_base) ||
(new_serial.type != info->type) ||
(new_serial.close_delay != info->close_delay) ||
diff --git a/drivers/misc/TODO-parport b/drivers/misc/TODO-parport
index 08860cc27..523a1ca94 100644
--- a/drivers/misc/TODO-parport
+++ b/drivers/misc/TODO-parport
@@ -6,20 +6,13 @@ Things to be done.
2. A better lp.c:
- a) It's a _mess_
-
- b) ECP support would be nice. This can only work if both the port and
+ a) ECP support would be nice. This can only work if both the port and
the printer support it.
- c) Errors could do with being handled better. There's no point logging a
- message every 10 seconds when the printer is out of paper.
-
- d) Handle status readback automatically. IEEE1284 printers can post status
+ b) Handle status readback automatically. IEEE1284 printers can post status
bits when they have something to say. We should read out and deal
with (maybe just log) whatever the printer wants to tell the world.
3. Support more hardware (eg m68k, Sun bpp).
4. A better PLIP (make use of bidirectional/ECP/EPP ports).
-
-
diff --git a/drivers/misc/parport_procfs.c b/drivers/misc/parport_procfs.c
index 97717448c..a3f40e9f4 100644
--- a/drivers/misc/parport_procfs.c
+++ b/drivers/misc/parport_procfs.c
@@ -37,8 +37,8 @@ static int irq_write_proc(struct file *file, const char *buffer,
int retval = -EINVAL;
int newirq = PARPORT_IRQ_NONE;
struct parport *pp = (struct parport *)data;
- struct pardevice *cad = pp->cad;
int oldirq = pp->irq;
+ unsigned long flags;
/*
* We can have these valid cases:
@@ -70,36 +70,31 @@ static int irq_write_proc(struct file *file, const char *buffer,
if (oldirq == newirq)
goto out;
+ spin_lock_irqsave(&pp->lock, flags);
if (pp->flags & PARPORT_FLAG_COMA)
goto out_ok;
- if (newirq != PARPORT_IRQ_NONE) {
- void (*handler)(int, void *, struct pt_regs *);
-
- if (cad && cad->irq_func)
- handler = cad->irq_func;
- else
- handler = parport_null_intr_func;
+ retval = -EBUSY;
+ if (pp->cad)
+ goto out_unlock;
- retval = request_irq(newirq, handler,
- SA_INTERRUPT,
- cad ? cad->name : pp->name,
- cad ? cad->private : NULL);
+ if (newirq != PARPORT_IRQ_NONE) {
+ retval = request_irq(newirq, parport_null_intr_func,
+ SA_INTERRUPT, pp->name, NULL);
if (retval)
- goto out;
+ goto out_unlock;
else retval = count;
}
- if (oldirq != PARPORT_IRQ_NONE) {
- if (cad && cad->irq_func)
- free_irq(oldirq, cad->private);
- else
- free_irq(oldirq, NULL);
- }
+ if (oldirq != PARPORT_IRQ_NONE)
+ free_irq(oldirq, NULL);
out_ok:
pp->irq = newirq;
+out_unlock:
+ spin_unlock_irqrestore (&pp->lock, flags);
+
out:
return retval;
}
diff --git a/drivers/misc/parport_share.c b/drivers/misc/parport_share.c
index 7da49fae4..be53e2ba6 100644
--- a/drivers/misc/parport_share.c
+++ b/drivers/misc/parport_share.c
@@ -1,4 +1,5 @@
-/* $Id: parport_share.c,v 1.14 1998/05/04 19:05:05 ralf Exp $
+/* $Id: parport_share.c,v 1.9 1998/05/07 02:59:59 ralf Exp $
+ *
* Parallel-port resource manager code.
*
* Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
@@ -308,7 +309,9 @@ try_again:
}
/* Now we do the change of devices */
+ spin_lock_irqsave(&port->lock, flags);
port->cad = dev;
+ spin_unlock_irqrestore(&port->lock, flags);
/* Swap the IRQ handlers. */
if (port->irq != PARPORT_IRQ_NONE) {
@@ -346,9 +349,8 @@ blocked:
dev->waitprev = port->waittail;
if (port->waittail)
port->waittail->waitnext = dev;
- else {
- port->waithead = dev->port->waittail = dev;
- }
+ else
+ port->waithead = port->waittail = dev;
}
spin_unlock_irqrestore (&port->lock, flags);
}
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index bb9ee3c30..ae344c99d 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -1,8 +1,8 @@
/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
/*
- Written 1993-1995 by Donald Becker.
+ Written 1993-1997 by Donald Becker.
- Copyright 1994,1995 by Donald Becker.
+ Copyright 1994-1997 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency. This software may be used and
distributed according to the terms of the GNU Public License,
@@ -27,10 +27,22 @@
FIXES:
Alan Cox: Removed the 'Unexpected interrupt' bug.
Michael Meskes: Upgraded to Donald Becker's version 1.07.
- Phil Blundell: Media selection support.
+ Alan Cox: Increased the eeprom delay. Regardless of
+ what the docs say some people definitely
+ get problems with lower (but in card spec)
+ delays
+ v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
+ other cleanups. -djb
+ Andrea Arcangeli: Upgraded to Donald Becker's version 1.12.
*/
-static char *version = "3c509.c:1.07 6/15/95 becker@cesdis.gsfc.nasa.gov\n";
+static char *version = "3c509.c:1.12 6/4/97 becker@cesdis.gsfc.nasa.gov\n";
+/* A few values that may be tweaked. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (400*HZ/1000)
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+#define INTR_WORK 10
#include <linux/module.h>
@@ -48,20 +60,19 @@ static char *version = "3c509.c:1.07 6/15/95 becker@cesdis.gsfc.nasa.gov\n";
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/delay.h> /* for udelay() */
-#include <linux/init.h>
#include <asm/bitops.h>
#include <asm/io.h>
#ifdef EL3_DEBUG
-static int el3_debug = EL3_DEBUG;
+int el3_debug = EL3_DEBUG;
#else
-static int el3_debug = 2;
+int el3_debug = 2;
#endif
/* To minimize the size of the driver source I only define operating
constants if they are used several times. You'll need the manual
- if you want to understand driver details. */
+ anyway if you want to understand driver details. */
/* Offsets from base I/O address. */
#define EL3_DATA 0x00
#define EL3_CMD 0x0e
@@ -111,12 +122,14 @@ enum RxFilter {
#define SKB_QUEUE_SIZE 64
struct el3_private {
- struct net_device_stats stats;
+ struct enet_statistics stats;
+ struct device *next_dev;
/* skb send-queue */
int head, size;
struct sk_buff *queue[SKB_QUEUE_SIZE];
};
static int id_port = 0x100;
+static struct device *el3_root_dev = NULL;
static ushort id_read_eeprom(int index);
static ushort read_eeprom(short ioaddr, int index);
@@ -124,28 +137,19 @@ static int el3_open(struct device *dev);
static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void update_stats(int addr, struct device *dev);
-static struct net_device_stats *el3_get_stats(struct device *dev);
+static struct enet_statistics *el3_get_stats(struct device *dev);
static int el3_rx(struct device *dev);
static int el3_close(struct device *dev);
-static int el3_set_config(struct device *dev, struct ifmap *map);
-#ifdef HAVE_MULTICAST
static void set_multicast_list(struct device *dev);
-#endif
-__initfunc(int el3_probe(struct device *dev))
+int el3_probe(struct device *dev)
{
short lrs_state = 0xff, i;
- ushort ioaddr, irq, port;
- short *phys_addr = (short *)dev->dev_addr;
+ ushort ioaddr, irq, if_port;
+ short phys_addr[3];
static int current_tag = 0;
- static int el3_portmap[] = {
- IF_PORT_10BASET,
- IF_PORT_AUI,
- IF_PORT_UNKNOWN,
- IF_PORT_10BASE2
- };
/* First check all slots of the EISA bus. The next slot address to
probe is kept in 'eisa_addr' to support multiple probe() calls. */
@@ -163,7 +167,7 @@ __initfunc(int el3_probe(struct device *dev))
outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
irq = inw(ioaddr + WN0_IRQ) >> 12;
- port = inw(ioaddr + 6)>>14;
+ if_port = inw(ioaddr + 6)>>14;
for (i = 0; i < 3; i++)
phys_addr[i] = htons(read_eeprom(ioaddr, i));
@@ -175,18 +179,14 @@ __initfunc(int el3_probe(struct device *dev))
}
}
-/*
- * This has to be coded according to Documentation/mca.txt before
- * this driver can be used with the 3c529 MCA cards.
- */
-#if 0 /* #ifdef CONFIG_MCA */
+#ifdef CONFIG_MCA
if (MCA_bus) {
mca_adaptor_select_mode(1);
for (i = 0; i < 8; i++)
if ((mca_adaptor_id(i) | 1) == 0x627c) {
ioaddr = mca_pos_base_addr(i);
irq = inw(ioaddr + WN0_IRQ) >> 12;
- port = inw(ioaddr + 6)>>14;
+ if_port = inw(ioaddr + 6)>>14;
for (i = 0; i < 3; i++)
phys_addr[i] = htons(read_eeprom(ioaddr, i));
@@ -203,6 +203,8 @@ __initfunc(int el3_probe(struct device *dev))
outb(0x02, 0xA79); /* Return to WaitForKey state. */
/* Select an open I/O location at 0x1*0 to do contention select. */
for (id_port = 0x100; id_port < 0x200; id_port += 0x10) {
+ if (check_region(id_port, 1))
+ continue;
outb(0x00, id_port);
outb(0xff, id_port);
if (inb(id_port) & 0x01)
@@ -218,13 +220,6 @@ __initfunc(int el3_probe(struct device *dev))
on cards as they are found. Cards with their tag set will not
respond to subsequent ID sequences. */
- if (check_region(id_port,1)) {
- static int once = 1;
- if (once) printk("3c509: Somebody has reserved 0x%x, can't do ID_PORT lookup, nor card auto-probing\n",id_port);
- once = 0;
- return -ENODEV;
- }
-
outb(0x00, id_port);
outb(0x00, id_port);
for(i = 0; i < 255; i++) {
@@ -252,16 +247,16 @@ __initfunc(int el3_probe(struct device *dev))
{
unsigned short iobase = id_read_eeprom(8);
- port = iobase >> 14;
+ if_port = iobase >> 14;
ioaddr = 0x200 + ((iobase & 0x1f) << 4);
}
- if (dev->irq > 1 && dev->irq < 16)
+ if (dev && dev->irq > 1 && dev->irq < 16)
irq = dev->irq;
else
irq = id_read_eeprom(9) >> 12;
- if (dev->base_addr != 0
- && dev->base_addr != (unsigned short)ioaddr) {
+ if (dev && dev->base_addr != 0
+ && dev->base_addr != (unsigned short)ioaddr) {
return -ENODEV;
}
@@ -278,15 +273,20 @@ __initfunc(int el3_probe(struct device *dev))
/* Free the interrupt so that some other card can use it. */
outw(0x0f00, ioaddr + WN0_IRQ);
found:
+ if (dev == NULL) {
+ dev = init_etherdev(dev, sizeof(struct el3_private));
+ }
+ memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
dev->base_addr = ioaddr;
dev->irq = irq;
- dev->if_port = el3_portmap[port];
+ dev->if_port = (dev->mem_start & 0x1f) ? dev->mem_start & 3 : if_port;
+
request_region(dev->base_addr, EL3_IO_EXTENT, "3c509");
{
- static const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
+ const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ",
- dev->name, dev->base_addr, current_tag, if_names[port]);
+ dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
}
/* Read in the station address. */
@@ -295,11 +295,15 @@ __initfunc(int el3_probe(struct device *dev))
printk(", IRQ %d.\n", dev->irq);
/* Make up a EL3-specific-data structure. */
- dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
+ if (dev->priv == NULL)
+ dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
if (dev->priv == NULL)
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct el3_private));
+ ((struct el3_private *)dev->priv)->next_dev = el3_root_dev;
+ el3_root_dev = dev;
+
if (el3_debug > 0)
printk(version);
@@ -308,30 +312,26 @@ __initfunc(int el3_probe(struct device *dev))
dev->hard_start_xmit = &el3_start_xmit;
dev->stop = &el3_close;
dev->get_stats = &el3_get_stats;
- dev->set_config = &el3_set_config;
-#ifdef HAVE_MULTICAST
- dev->set_multicast_list = &set_multicast_list;
-#endif
+ dev->set_multicast_list = &set_multicast_list;
/* Fill in the generic fields of the device structure. */
ether_setup(dev);
- dev->flags |= IFF_PORTSEL;
return 0;
}
/* Read a word from the EEPROM using the regular EEPROM access register.
Assume that we are in register window zero.
*/
-__initfunc(static ushort read_eeprom(short ioaddr, int index))
+static ushort read_eeprom(short ioaddr, int index)
{
outw(EEPROM_READ + index, ioaddr + 10);
/* Pause for at least 162 us. for the read to take place. */
- udelay (300);
+ udelay (500);
return inw(ioaddr + 12);
}
/* Read a word from the EEPROM when in the ISA ID probe state. */
-__initfunc(static ushort id_read_eeprom(int index))
+static ushort id_read_eeprom(int index)
{
int bit, word = 0;
@@ -340,8 +340,8 @@ __initfunc(static ushort id_read_eeprom(int index))
outb(EEPROM_READ + index, id_port);
/* Pause for at least 162 us. for the read to take place. */
- udelay (300);
-
+ udelay (500);
+
for (bit = 15; bit >= 0; bit--)
word = (word << 1) + (inb(id_port) & 0x01);
@@ -354,59 +354,6 @@ __initfunc(static ushort id_read_eeprom(int index))
static int
-el3_set_config(struct device *dev, struct ifmap *map)
-{
- int ioaddr = dev->base_addr;
- if (map->port != dev->if_port) {
- switch (map->port) {
- case IF_PORT_10BASE2:
- case IF_PORT_10BASET:
- case IF_PORT_AUI:
- if (dev->start) {
- if (dev->if_port == IF_PORT_10BASE2)
- /* Turn off thinnet power. */
- outw(StopCoax, ioaddr + EL3_CMD);
- else if (dev->if_port == IF_PORT_10BASET) {
- /* Disable link beat and jabber */
- EL3WINDOW(4);
- outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
- EL3WINDOW(1);
- }
- }
- printk(KERN_INFO "%s: %s port selected.\n", dev->name,
- if_port_text[map->port]);
- dev->if_port = map->port;
- if (dev->start) {
- if (dev->if_port == IF_PORT_10BASE2)
- /* Start the thinnet transceiver. We should really wait 50ms...*/
- outw(StartCoax, ioaddr + EL3_CMD);
- else if (dev->if_port == IF_PORT_10BASET) {
- /* 10baseT interface, enabled link beat and jabber check. */
- EL3WINDOW(4);
- outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
- EL3WINDOW(1);
- }
- }
- break;
- default:
- printk(KERN_ERR "%s: %s port not supported.\n", dev->name,
- if_port_text[map->port]);
- return -EINVAL;
- }
- }
- if (map->irq != dev->irq) {
- printk(KERN_ERR "%s: cannot change interrupt.\n", dev->name);
- return -EINVAL;
- }
- if (map->base_addr != dev->base_addr) {
- printk(KERN_ERR "%s: cannot change base address.\n", dev->name);
- return -EINVAL;
- }
- return 0;
-}
-
-
-static int
el3_open(struct device *dev)
{
int ioaddr = dev->base_addr;
@@ -437,10 +384,10 @@ el3_open(struct device *dev)
for (i = 0; i < 6; i++)
outb(dev->dev_addr[i], ioaddr + i);
- if (dev->if_port == IF_PORT_10BASE2)
+ if (dev->if_port == 3)
/* Start the thinnet transceiver. We should really wait 50ms...*/
outw(StartCoax, ioaddr + EL3_CMD);
- else if (dev->if_port == IF_PORT_10BASET) {
+ else if (dev->if_port == 0) {
/* 10baseT interface, enabled link beat and jabber check. */
EL3WINDOW(4);
outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
@@ -483,7 +430,8 @@ el3_open(struct device *dev)
return 0; /* Always succeed */
}
-static int el3_start_xmit(struct sk_buff *skb, struct device *dev)
+static int
+el3_start_xmit(struct sk_buff *skb, struct device *dev)
{
struct el3_private *lp = (struct el3_private *)dev->priv;
int ioaddr = dev->base_addr;
@@ -491,7 +439,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct device *dev)
/* Transmitter timeout, serious problems. */
if (dev->tbusy) {
int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 40*HZ/100)
+ if (tickssofar < TX_TIMEOUT)
return 1;
printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
"Tx FIFO room %d.\n",
@@ -532,12 +480,15 @@ static int el3_start_xmit(struct sk_buff *skb, struct device *dev)
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
printk("%s: Transmitter access conflict.\n", dev->name);
else {
- lp->stats.tx_bytes+=skb->len;
/* Put out the doubleword header... */
outw(skb->len, ioaddr + TX_FIFO);
outw(0x00, ioaddr + TX_FIFO);
/* ... and the packet rounded to a doubleword. */
+#ifdef __powerpc__
+ outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+#else
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+#endif
dev->trans_start = jiffies;
if (inw(ioaddr + TX_FREE) > 1536) {
@@ -570,7 +521,7 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct device *dev = (struct device *)dev_id;
int ioaddr, status;
- int i = 0;
+ int i = INTR_WORK;
if (dev == NULL) {
printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
@@ -622,7 +573,7 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
}
- if (++i > 10) {
+ if (--i < 0) {
printk("%s: Infinite loop in interrupt, status %4.4x.\n",
dev->name, status);
/* Clear all interrupts. */
@@ -643,7 +594,8 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
-static struct net_device_stats *el3_get_stats(struct device *dev)
+static struct enet_statistics *
+el3_get_stats(struct device *dev)
{
struct el3_private *lp = (struct el3_private *)dev->priv;
unsigned long flags;
@@ -720,18 +672,21 @@ el3_rx(struct device *dev)
pkt_len, rx_status);
if (skb != NULL) {
skb->dev = dev;
- skb_reserve(skb,2); /* Align IP on 16 byte */
+ skb_reserve(skb, 2); /* Align IP on 16 byte */
/* 'skb->data' points to the start of sk_buff data area. */
- insl(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
- (pkt_len + 3) >> 2);
+#ifdef __powerpc__
+ insl_unswapped(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
+ (pkt_len + 3) >> 2);
+#else
+ insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
+ (pkt_len + 3) >> 2);
+#endif
- skb->protocol=eth_type_trans(skb,dev);
+ skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
- lp->stats.rx_bytes+=skb->len;
lp->stats.rx_packets++;
- lp->stats.rx_bytes+=pkt_len;
continue;
} else if (el3_debug)
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
@@ -747,7 +702,6 @@ el3_rx(struct device *dev)
return 0;
}
-#ifdef HAVE_MULTICAST
/*
* Set or clear the multicast filter for this adaptor.
*/
@@ -772,7 +726,6 @@ set_multicast_list(struct device *dev)
else
outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
}
-#endif
static int
el3_close(struct device *dev)
@@ -792,10 +745,10 @@ el3_close(struct device *dev)
outw(RxDisable, ioaddr + EL3_CMD);
outw(TxDisable, ioaddr + EL3_CMD);
- if (dev->if_port == IF_PORT_10BASE2)
+ if (dev->if_port == 3)
/* Turn off thinnet power. Green! */
outw(StopCoax, ioaddr + EL3_CMD);
- else if (dev->if_port == IF_PORT_10BASET) {
+ else if (dev->if_port == 0) {
/* Disable link beat and jabber, if_port may change ere next open(). */
EL3WINDOW(4);
outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
@@ -813,69 +766,50 @@ el3_close(struct device *dev)
}
#ifdef MODULE
-#define MAX_3C_CARDS 4 /* Max number of NE cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_3C_CARDS] = { 0, };
-static struct device dev_3c509[MAX_3C_CARDS] = {
- {
- NULL, /* assign a chunk of namelist[] below */
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, NULL
- },
-};
-
-static int io[MAX_3C_CARDS] = { 0, };
-static int irq[MAX_3C_CARDS] = { 0, };
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_3C_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C_CARDS) "i");
+/* Parameter that may be passed into the module. */
+static int debug = -1;
+static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1};
int
init_module(void)
{
- int this_dev, found = 0;
-
- for (this_dev = 0; this_dev < MAX_3C_CARDS; this_dev++) {
- struct device *dev = &dev_3c509[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
- dev->irq = irq[this_dev];
- dev->base_addr = io[this_dev];
- dev->init = el3_probe;
- if (io[this_dev] == 0) {
- if (this_dev != 0) break; /* only complain once */
- printk("3c509: WARNING! Module load-time probing works reliably only for EISA bus!!\n");
- }
- if (register_netdev(dev) != 0) {
- printk(KERN_WARNING "3c509.c: No 3c509 card found (i/o = 0x%x).\n", io[this_dev]);
- if (found != 0) return 0; /* Got at least one. */
- return -ENXIO;
- }
- found++;
+ int el3_cards = 0;
+
+ if (debug >= 0)
+ el3_debug = debug;
+
+ el3_root_dev = NULL;
+ while (el3_probe(0) == 0) {
+ if (irq[el3_cards] > 1)
+ el3_root_dev->irq = irq[el3_cards];
+ if (xcvr[el3_cards] >= 0)
+ el3_root_dev->if_port = xcvr[el3_cards];
+ el3_cards++;
}
- return 0;
+
+ return el3_cards ? 0 : -ENODEV;
}
void
cleanup_module(void)
{
- int this_dev;
-
- for (this_dev = 0; this_dev < MAX_3C_CARDS; this_dev++) {
- struct device *dev = &dev_3c509[this_dev];
- if (dev->priv != NULL) {
- unregister_netdev(dev);
- kfree_s(dev->priv,sizeof(struct el3_private));
- dev->priv = NULL;
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, EL3_IO_EXTENT);
- }
+ struct device *next_dev;
+
+ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+ while (el3_root_dev) {
+ next_dev = ((struct el3_private *)el3_root_dev->priv)->next_dev;
+ unregister_netdev(el3_root_dev);
+ release_region(el3_root_dev->base_addr, EL3_IO_EXTENT);
+ kfree(el3_root_dev);
+ el3_root_dev = next_dev;
}
}
#endif /* MODULE */
/*
* Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c509.c"
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c509.c"
* version-control: t
* kept-new-versions: 5
* tab-width: 4
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index a9ddfa475..6bb3dfd54 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1957,7 +1957,7 @@ static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd)
data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
return 0;
diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c
index c0c52d24f..06f527d70 100644
--- a/drivers/net/de4x5.c
+++ b/drivers/net/de4x5.c
@@ -5487,7 +5487,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
if (status)
break;
status = -EPERM;
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
break;
status = 0;
copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
@@ -5505,7 +5505,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DE4X5_SET_PROM: /* Set Promiscuous Mode */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
omr = inl(DE4X5_OMR);
omr |= OMR_PR;
outl(omr, DE4X5_OMR);
@@ -5516,7 +5516,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DE4X5_CLR_PROM: /* Clear Promiscuous Mode */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
omr = inl(DE4X5_OMR);
omr &= ~OMR_PR;
outb(omr, DE4X5_OMR);
@@ -5531,7 +5531,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DE4X5_MCA_EN: /* Enable pass all multicast addressing */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
omr = inl(DE4X5_OMR);
omr |= OMR_PM;
outl(omr, DE4X5_OMR);
@@ -5552,7 +5552,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DE4X5_CLR_STATS: /* Zero out the driver statistics */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
cli();
memset(&lp->pktStats, 0, sizeof(lp->pktStats));
sti();
@@ -5569,7 +5569,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DE4X5_SET_OMR: /* Set the OMR Register contents */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, 1))) {
copy_from_user(tmp.addr, ioc->data, 1);
outl(tmp.addr[0], DE4X5_OMR);
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 56578f58e..0320cc322 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -1714,7 +1714,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
}
break;
case DEPCA_SET_HWADDR: /* Set the hardware address */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) {
copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
for (i = 0; i < ETH_ALEN; i++) {
@@ -1736,7 +1736,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DEPCA_SET_PROM: /* Set Promiscuous Mode */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
while (dev->tbusy); /* Stop ring access */
set_bit(0, (void *) &dev->tbusy);
while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
@@ -1754,7 +1754,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
while (dev->tbusy); /* Stop ring access */
set_bit(0, (void *) &dev->tbusy);
while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
@@ -1782,7 +1782,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
}
break;
case DEPCA_SET_MCA: /* Set a multicast address */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) {
copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
set_multicast_list(dev);
@@ -1793,7 +1793,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DEPCA_CLR_MCA: /* Clear all multicast addresses */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
set_multicast_list(dev);
} else {
status = -EPERM;
@@ -1801,7 +1801,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DEPCA_MCA_EN: /* Enable pass all multicast addressing */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
set_multicast_list(dev);
} else {
status = -EPERM;
@@ -1818,7 +1818,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case DEPCA_CLR_STATS: /* Zero out the driver statistics */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
cli();
memset(&lp->pktStats, 0, sizeof(lp->pktStats));
sti();
diff --git a/drivers/net/dlci.c b/drivers/net/dlci.c
index 8ceb7a8c7..6343463d0 100644
--- a/drivers/net/dlci.c
+++ b/drivers/net/dlci.c
@@ -322,7 +322,7 @@ int dlci_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
{
struct dlci_local *dlp;
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return(-EPERM);
dlp = dev->priv;
@@ -542,7 +542,7 @@ int dlci_ioctl(unsigned int cmd, void *arg)
struct dlci_add add;
int err;
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return(-EPERM);
if(copy_from_user(&add, arg, sizeof(struct dlci_add)))
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index c896844b2..cc23deba7 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1528,7 +1528,7 @@ static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
data[3] = mdio_read(ioaddr, data[0], data[1]);
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(ioaddr, data[0], data[1], data[2]);
return 0;
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index f654b2cdd..abb7e6c78 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -329,7 +329,8 @@ static int eql_close(struct device *dev)
static int eql_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
{
- if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG && !suser())
+ if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG &&
+ !capable(CAP_NET_ADMIN))
return -EPERM;
switch (cmd)
{
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index f17343b40..315cc27da 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -1684,7 +1684,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
}
break;
case EWRK3_SET_HWADDR: /* Set the hardware address */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) {
csr = inb(EWRK3_CSR);
csr |= (CSR_TXD | CSR_RXD);
@@ -1705,7 +1705,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_SET_PROM: /* Set Promiscuous Mode */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
csr = inb(EWRK3_CSR);
csr |= CSR_PME;
csr &= ~CSR_MCE;
@@ -1716,7 +1716,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_CLR_PROM: /* Clear Promiscuous Mode */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
csr = inb(EWRK3_CSR);
csr &= ~CSR_PME;
outb(csr, EWRK3_CSR);
@@ -1749,7 +1749,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_SET_MCA: /* Set a multicast address */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) {
copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
set_multicast_list(dev);
@@ -1760,7 +1760,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_CLR_MCA: /* Clear all multicast addresses */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
set_multicast_list(dev);
} else {
status = -EPERM;
@@ -1768,7 +1768,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_MCA_EN: /* Enable multicast addressing */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
csr = inb(EWRK3_CSR);
csr |= CSR_MCE;
csr &= ~CSR_PME;
@@ -1788,7 +1788,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_CLR_STATS: /* Zero out the driver statistics */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
cli();
memset(&lp->pktStats, 0, sizeof(lp->pktStats));
sti();
@@ -1805,7 +1805,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
}
break;
case EWRK3_SET_CSR: /* Set the CSR Register contents */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
if (!(status = verify_area(VERIFY_READ, ioc->data, 1))) {
copy_from_user(tmp.addr, ioc->data, 1);
outb(tmp.addr[0], EWRK3_CSR);
@@ -1816,7 +1816,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_GET_EEPROM: /* Get the EEPROM contents */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
for (i = 0; i < (EEPROM_MAX >> 1); i++) {
tmp.val[i] = (short) Read_EEPROM(iobase, i);
}
@@ -1835,7 +1835,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
break;
case EWRK3_SET_EEPROM: /* Set the EEPROM contents */
- if (suser()) {
+ if (capable(CAP_NET_ADMIN)) {
if (!(status = verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) {
copy_from_user(tmp.addr, ioc->data, EEPROM_MAX);
for (i = 0; i < (EEPROM_MAX >> 1); i++) {
diff --git a/drivers/net/ipddp.c b/drivers/net/ipddp.c
index 16e52bd98..df22a0ee7 100644
--- a/drivers/net/ipddp.c
+++ b/drivers/net/ipddp.c
@@ -307,7 +307,7 @@ static int ipddp_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
{
struct ipddp_route *rt = (struct ipddp_route *)ifr->ifr_data;
- if(!suser())
+ if(!capable(CAP_NET_ADMIN))
return -EPERM;
switch(cmd)
diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c
index 4db4094e2..9d4a237c7 100644
--- a/drivers/net/ppp.c
+++ b/drivers/net/ppp.c
@@ -8,7 +8,7 @@
* Dynamic PPP devices by Jim Freeman <jfree@caldera.com>.
* ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se>
*
- * ==FILEVERSION 980319==
+ * ==FILEVERSION 980501==
*
* NOTE TO MAINTAINERS:
* If you modify this file at all, please set the number above to the
@@ -107,8 +107,10 @@ typedef struct sk_buff sk_buff;
#define PPP_LQR 0xc025 /* Link Quality Reporting Protocol */
#endif
+#ifdef CONFIG_MODULES
static int ppp_register_compressor (struct compressor *cp);
static void ppp_unregister_compressor (struct compressor *cp);
+#endif
/*
* Local functions
@@ -2279,7 +2281,7 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
/*
* The user must have an euid of root to do these requests.
*/
- if (!suser ())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
/*
* Set the MRU value
@@ -3210,6 +3212,7 @@ static struct compressor *find_compressor (int type)
return (struct compressor *) 0;
}
+#ifdef CONFIG_MODULES
static int ppp_register_compressor (struct compressor *cp)
{
struct compressor_link *new;
@@ -3261,6 +3264,7 @@ static void ppp_unregister_compressor (struct compressor *cp)
}
restore_flags(flags);
}
+#endif
/*************************************************************
* Module support routines
diff --git a/drivers/net/sdla_fr.c b/drivers/net/sdla_fr.c
index 79bd5d4ca..36b74b90e 100644
--- a/drivers/net/sdla_fr.c
+++ b/drivers/net/sdla_fr.c
@@ -831,7 +831,7 @@ static int if_header(struct sk_buff *skb, struct device *dev,
{
int hdr_len = 0;
skb->protocol = type;
- hdr_len = wan_encapsulate(skb, dev);
+ hdr_len = wanrouter_encapsulate(skb, dev);
if (hdr_len < 0)
{
hdr_len = 0;
@@ -1486,7 +1486,7 @@ static void fr502_rx_intr(sdla_t * card)
/* Decapsulate packet and pass it up the protocol stack */
skb->dev = dev;
buf = skb_pull(skb, 1); /* remove hardware header */
- if (!wan_type_trans(skb, dev))
+ if (!wanrouter_type_trans(skb, dev))
{
/* can't decapsulate packet */
dev_kfree_skb(skb);
@@ -1601,7 +1601,7 @@ static void fr508_rx_intr(sdla_t * card)
skb->dev = dev;
/* remove hardware header */
buf = skb_pull(skb, 1);
- if (!wan_type_trans(skb, dev))
+ if (!wanrouter_type_trans(skb, dev))
{
/* can't decapsulate packet */
dev_kfree_skb(skb);
@@ -2746,7 +2746,7 @@ static int process_udp_mgmt_pkt(char udp_pkt_src, sdla_t * card, struct sk_buff
stack */
new_skb->dev = dev;
buf = skb_pull(new_skb, 1); /* remove hardware header */
- if (!wan_type_trans(new_skb, dev))
+ if (!wanrouter_type_trans(new_skb, dev))
{
++chan->UDP_FPIPE_mgmt_not_passed_to_stack;
/* can't decapsulate packet */
@@ -2944,7 +2944,7 @@ static int process_udp_driver_call(char udp_pkt_src, sdla_t * card, struct sk_bu
new_skb->dev = dev;
/* remove hardware header */
buf = skb_pull(new_skb, 1);
- if (!wan_type_trans(new_skb, dev))
+ if (!wanrouter_type_trans(new_skb, dev))
{
/* can't decapsulate packet */
++chan->UDP_DRVSTATS_mgmt_not_passed_to_stack;
diff --git a/drivers/net/sdla_x25.c b/drivers/net/sdla_x25.c
index 6a1759040..af7d31844 100644
--- a/drivers/net/sdla_x25.c
+++ b/drivers/net/sdla_x25.c
@@ -649,7 +649,7 @@ static int if_header (struct sk_buff* skb, struct device* dev,
skb->protocol = type;
if (!chan->protocol)
{
- hdr_len = wan_encapsulate(skb, dev);
+ hdr_len = wanrouter_encapsulate(skb, dev);
if (hdr_len < 0)
{
hdr_len = 0;
@@ -999,7 +999,7 @@ static void rx_intr (sdla_t* card)
chan->rx_skb = NULL; /* dequeue packet */
/* Decapsulate packet, if necessary */
- if (!skb->protocol && !wan_type_trans(skb, dev))
+ if (!skb->protocol && !wanrouter_type_trans(skb, dev))
{
/* can't decapsulate packet */
dev_kfree_skb(skb);
diff --git a/drivers/net/sdlamain.c b/drivers/net/sdlamain.c
index eed8c9f36..44fabaecb 100644
--- a/drivers/net/sdlamain.c
+++ b/drivers/net/sdlamain.c
@@ -152,7 +152,7 @@ int init_module (void)
wandev->setup = &setup;
wandev->shutdown = &shutdown;
wandev->ioctl = &ioctl;
- err = register_wandev(wandev);
+ err = register_wan_device(wandev);
if (err)
{
printk(KERN_ERR
@@ -179,7 +179,7 @@ void cleanup_module (void)
for (i = 0; i < ncards; ++i)
{
sdla_t* card = &card_array[i];
- unregister_wandev(card->devname);
+ unregister_wan_device(card->devname);
}
kfree(card_array);
}
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index 79d6d8076..152beacbc 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -337,7 +337,7 @@ int init_module(void)
dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
- dev->init = ultra_probe;
+ dev->init = ultramca_probe;
if (io[this_dev] == 0)
{
if (this_dev != 0)
diff --git a/drivers/pci/oldproc.c b/drivers/pci/oldproc.c
index 0af8170ca..9e43ff0a6 100644
--- a/drivers/pci/oldproc.c
+++ b/drivers/pci/oldproc.c
@@ -1,5 +1,5 @@
/*
- * $Id: oldproc.c,v 1.10 1998/03/15 13:50:11 ecd Exp $
+ * $Id: oldproc.c,v 1.12 1998/05/01 10:58:21 mj Exp $
*
* Backward-compatible procfs interface for PCI.
*
@@ -60,10 +60,14 @@ struct pci_dev_info dev_info[] = {
DEVICE( ATI, ATI_210888CX, "210888CX"),
DEVICE( ATI, ATI_215GB, "Mach64 GB"),
DEVICE( ATI, ATI_215GD, "Mach64 GD (Rage Pro)"),
+ DEVICE( ATI, ATI_215GI, "Mach64 GI (Rage Pro)"),
DEVICE( ATI, ATI_215GP, "Mach64 GP (Rage Pro)"),
+ DEVICE( ATI, ATI_215GQ, "Mach64 GQ (Rage Pro)"),
DEVICE( ATI, ATI_215GT, "Mach64 GT (Rage II)"),
DEVICE( ATI, ATI_215GTB, "Mach64 GT (Rage II)"),
DEVICE( ATI, ATI_210888GX, "210888GX"),
+ DEVICE( ATI, ATI_215LG, "Mach64 LG (Rage Pro)"),
+ DEVICE( ATI, ATI_264LT, "Mach64 LT"),
DEVICE( ATI, ATI_264VT, "Mach64 VT"),
DEVICE( VLSI, VLSI_82C592, "82C592-FC1"),
DEVICE( VLSI, VLSI_82C593, "82C593-FC1"),
@@ -116,6 +120,9 @@ struct pci_dev_info dev_info[] = {
DEVICE( IBM, IBM_82G2675, "82G2675"),
DEVICE( IBM, IBM_MCA, "MicroChannel"),
DEVICE( IBM, IBM_82351, "82351"),
+ DEVICE( IBM, IBM_SERVERAID, "ServeRAID"),
+ DEVICE( IBM, IBM_TR_WAKE, "Wake On LAN Token Ring"),
+ DEVICE( IBM, IBM_3780IDSP, "MWave DSP"),
DEVICE( WD, WD_7197, "WD 7197"),
DEVICE( AMD, AMD_LANCE, "79C970"),
DEVICE( AMD, AMD_SCSI, "53C974"),
@@ -135,12 +142,15 @@ struct pci_dev_info dev_info[] = {
DEVICE( CT, CT_65548, "65548"),
DEVICE( CT, CT_65550, "65550"),
DEVICE( CT, CT_65554, "65554"),
+ DEVICE( CT, CT_65555, "65555"),
DEVICE( MIRO, MIRO_36050, "ZR36050"),
DEVICE( NEC, NEC_PCX2, "PowerVR PCX2"),
DEVICE( FD, FD_36C70, "TMC-18C30"),
- DEVICE( SI, SI_6201, "6201"),
+ DEVICE( SI, SI_5591_AGP, "5591/5592 AGP"),
DEVICE( SI, SI_6202, "6202"),
DEVICE( SI, SI_503, "85C503"),
+ DEVICE( SI, SI_ACPI, "ACPI"),
+ DEVICE( SI, SI_5597_VGA, "5597/5598 VGA"),
DEVICE( SI, SI_6205, "6205"),
DEVICE( SI, SI_501, "85C501"),
DEVICE( SI, SI_496, "85C496"),
@@ -149,8 +159,9 @@ struct pci_dev_info dev_info[] = {
DEVICE( SI, SI_5511, "85C5511"),
DEVICE( SI, SI_5513, "85C5513"),
DEVICE( SI, SI_5571, "5571"),
- DEVICE( SI, SI_5597, "5597"),
- DEVICE( SI, SI_7001, "7001"),
+ DEVICE( SI, SI_5591, "5591/5592 Host"),
+ DEVICE( SI, SI_5597, "5597/5598 Host"),
+ DEVICE( SI, SI_7001, "7001 USB"),
DEVICE( HP, HP_J2585A, "J2585A"),
DEVICE( HP, HP_J2585B, "J2585B (Lassen)"),
DEVICE( PCTECH, PCTECH_RZ1000, "RZ1000 (buggy)"),
@@ -198,6 +209,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( UMC, UMC_UM8891N, "UM8891N"),
DEVICE( X, X_AGX016, "ITT AGX016"),
DEVICE( PICOP, PICOP_PT86C52X, "PT86C52x Vesuvius"),
+ DEVICE( PICOP, PICOP_PT80C524, "PT80C524 Nile"),
DEVICE( APPLE, APPLE_BANDIT, "Bandit"),
DEVICE( APPLE, APPLE_GC, "Grand Central"),
DEVICE( APPLE, APPLE_HYDRA, "Hydra"),
@@ -242,6 +254,8 @@ struct pci_dev_info dev_info[] = {
DEVICE( WINBOND, WINBOND_83C553, "W83C553"),
DEVICE( DATABOOK, DATABOOK_87144, "DB87144"),
DEVICE( PLX, PLX_9080, "PCI9080 I2O"),
+ DEVICE( MADGE, MADGE_MK2, "Smart 16/4 BM Mk2 Ringnode"),
+ DEVICE( 3COM, 3COM_3C339, "3C339 TokenRing"),
DEVICE( 3COM, 3COM_3C590, "3C590 10bT"),
DEVICE( 3COM, 3COM_3C595TX, "3C595 100bTX"),
DEVICE( 3COM, 3COM_3C595T4, "3C595 100bT4"),
@@ -249,6 +263,8 @@ struct pci_dev_info dev_info[] = {
DEVICE( 3COM, 3COM_3C900TPO, "3C900 10bTPO"),
DEVICE( 3COM, 3COM_3C900COMBO,"3C900 10b Combo"),
DEVICE( 3COM, 3COM_3C905TX, "3C905 100bTX"),
+ DEVICE( 3COM, 3COM_3C905T4, "3C905 100bT4"),
+ DEVICE( 3COM, 3COM_3C905B_TX, "3C905B 100bTX"),
DEVICE( SMC, SMC_EPIC100, "9432 TX"),
DEVICE( AL, AL_M1445, "M1445"),
DEVICE( AL, AL_M1449, "M1449"),
@@ -274,6 +290,8 @@ struct pci_dev_info dev_info[] = {
DEVICE( ASP, ASP_ABP940, "ABP940"),
DEVICE( ASP, ASP_ABP940U, "ABP940U"),
DEVICE( ASP, ASP_ABP940UW, "ABP940UW"),
+ DEVICE( MACRONIX, MACRONIX_MX98713,"MX98713"),
+ DEVICE( MACRONIX, MACRONIX_MX987x5,"MX98715 / MX98725"),
DEVICE( CERN, CERN_SPSB_PMC, "STAR/RD24 SCI-PCI (PMC)"),
DEVICE( CERN, CERN_SPSB_PCI, "STAR/RD24 SCI-PCI (PMC)"),
DEVICE( CERN, CERN_HIPPI_DST, "HIPPI destination"),
@@ -282,12 +300,14 @@ struct pci_dev_info dev_info[] = {
DEVICE( TEKRAM2, TEKRAM2_690c, "DC690c"),
DEVICE( TUNDRA, TUNDRA_CA91C042,"CA91C042 Universe"),
DEVICE( AMCC, AMCC_MYRINET, "Myrinet PCI (M2-PCI-32)"),
+ DEVICE( AMCC, AMCC_PARASTATION,"ParaStation Interface"),
DEVICE( AMCC, AMCC_S5933, "S5933 PCI44"),
DEVICE( AMCC, AMCC_S5933_HEPC3,"S5933 Traquair HEPC3"),
DEVICE( INTERG, INTERG_1680, "IGA-1680"),
DEVICE( INTERG, INTERG_1682, "IGA-1682"),
DEVICE( REALTEK, REALTEK_8029, "8029"),
DEVICE( REALTEK, REALTEK_8129, "8129"),
+ DEVICE( REALTEK, REALTEK_8139, "8139"),
DEVICE( TRUEVISION, TRUEVISION_T1000,"TARGA 1000"),
DEVICE( INIT, INIT_320P, "320 P"),
DEVICE( INIT, INIT_360P, "360 P"),
@@ -304,6 +324,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( VIA, VIA_82C595_97, "VT 82C595 Apollo VP2/97"),
DEVICE( VIA, VIA_82C586_2, "VT 82C586 Apollo USB"),
DEVICE( VIA, VIA_82C586_3, "VT 82C586B Apollo ACPI"),
+ DEVICE( VIA, VIA_86C100A, "VT 86C100A"),
DEVICE( VIA, VIA_82C597_1, "VT 82C597 Apollo VP3 AGP"),
DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"),
DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"),
@@ -342,6 +363,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( FORE, FORE_PCA200PC, "PCA-200PC"),
DEVICE( FORE, FORE_PCA200E, "PCA-200E"),
DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI"),
+ DEVICE( PHILIPS, PHILIPS_SAA7145,"SAA7145"),
DEVICE( PHILIPS, PHILIPS_SAA7146,"SAA7146"),
DEVICE( CYCLONE, CYCLONE_SDK, "SDK"),
DEVICE( ALLIANCE, ALLIANCE_PROMOTIO, "Promotion-6410"),
@@ -356,6 +378,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( DIGI, DIGI_CX, "AccelPort C/X"),
DEVICE( DIGI, DIGI_XRJ, "AccelPort Xr/J"),
DEVICE( DIGI, DIGI_EPCJ, "AccelPort EPC/J"),
+ DEVICE( DIGI, DIGI_XR_920, "AccelPort Xr 920"),
DEVICE( MUTECH, MUTECH_MV1000, "MV-1000"),
DEVICE( RENDITION, RENDITION_VERITE,"Verite 1000"),
DEVICE( RENDITION, RENDITION_VERITE2100,"Verite 2100"),
@@ -377,20 +400,21 @@ struct pci_dev_info dev_info[] = {
DEVICE( IKON, IKON_10117, "10117 Greensheet"),
DEVICE( ZORAN, ZORAN_36057, "ZR36057"),
DEVICE( ZORAN, ZORAN_36120, "ZR36120"),
+ DEVICE( KINETIC, KINETIC_2915, "2915 CAMAC"),
DEVICE( COMPEX, COMPEX_ENET100VG4, "Readylink ENET100-VG4"),
DEVICE( COMPEX, COMPEX_RL2000, "ReadyLink 2000"),
DEVICE( RP, RP8OCTA, "RocketPort 8 Oct"),
DEVICE( RP, RP8INTF, "RocketPort 8 Intf"),
DEVICE( RP, RP16INTF, "RocketPort 16 Intf"),
DEVICE( RP, RP32INTF, "RocketPort 32 Intf"),
- DEVICE( ESSENTIAL, ROADRUNNER, "RoadRunner serial HIPPI"),
DEVICE( CYCLADES, CYCLOM_Y_Lo, "Cyclom-Y below 1Mbyte"),
DEVICE( CYCLADES, CYCLOM_Y_Hi, "Cyclom-Y above 1Mbyte"),
DEVICE( CYCLADES, CYCLOM_Z_Lo, "Cyclom-Z below 1Mbyte"),
DEVICE( CYCLADES, CYCLOM_Z_Hi, "Cyclom-Z above 1Mbyte"),
+ DEVICE( ESSENTIAL, ESSENTIAL_ROADRUNNER,"Roadrunner serial HIPPI"),
DEVICE( O2, O2_6832, "6832"),
DEVICE( 3DFX, 3DFX_VOODOO, "Voodoo"),
- DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2"),
+ DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2"),
DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX"),
DEVICE( STALLION, STALLION_ECHPCI832,"EasyConnection 8/32"),
DEVICE( STALLION, STALLION_ECHPCI864,"EasyConnection 8/64"),
@@ -400,15 +424,20 @@ struct pci_dev_info dev_info[] = {
DEVICE( OPTIBASE, OPTIBASE_VPLEX, "VideoPlex"),
DEVICE( OPTIBASE, OPTIBASE_VPLEXCC,"VideoPlex CC"),
DEVICE( OPTIBASE, OPTIBASE_VQUEST,"VideoQuest"),
+ DEVICE( SATSAGEM, SATSAGEM_PCR2101,"PCR2101 DVB receiver"),
+ DEVICE( SATSAGEM, SATSAGEM_TELSATTURBO,"Telsat Turbo DVB"),
+ DEVICE( HUGHES, HUGHES_DIRECPC, "DirecPC"),
DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI"),
DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST"),
DEVICE( NVIDIA_SGS, NVIDIA_SGS_RIVA128, "Riva 128"),
+ DEVICE( CBOARDS, CBOARDS_DAS1602_16,"DAS1602/16"),
DEVICE( SYMPHONY, SYMPHONY_101, "82C101"),
DEVICE( TEKRAM, TEKRAM_DC290, "DC-290"),
DEVICE( 3DLABS, 3DLABS_300SX, "GLINT 300SX"),
DEVICE( 3DLABS, 3DLABS_500TX, "GLINT 500TX"),
DEVICE( 3DLABS, 3DLABS_DELTA, "GLINT Delta"),
DEVICE( 3DLABS, 3DLABS_PERMEDIA,"PERMEDIA"),
+ DEVICE( 3DLABS, 3DLABS_MX, "GLINT MX"),
DEVICE( AVANCE, AVANCE_ALG2064, "ALG2064i"),
DEVICE( AVANCE, AVANCE_2302, "ALG-2302"),
DEVICE( NETVIN, NETVIN_NV5000SC,"NV5000"),
@@ -450,6 +479,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( INTEL, INTEL_82371MX, "430MX - 82371MX MPIIX"),
DEVICE( INTEL, INTEL_82437MX, "430MX - 82437MX MTSC"),
DEVICE( INTEL, INTEL_82441, "82441FX Natoma"),
+ DEVICE( INTEL, INTEL_82380FB, "82380FB Mobile"),
DEVICE( INTEL, INTEL_82439, "82439HX Triton II"),
DEVICE( INTEL, INTEL_82371SB_0,"82371SB PIIX3 ISA"),
DEVICE( INTEL, INTEL_82371SB_1,"82371SB PIIX3 IDE"),
@@ -462,9 +492,13 @@ struct pci_dev_info dev_info[] = {
DEVICE( INTEL, INTEL_82371AB_3,"82371AB PIIX4 ACPI"),
DEVICE( INTEL, INTEL_82443LX_0,"440LX - 82443LX PAC Host"),
DEVICE( INTEL, INTEL_82443LX_1,"440LX - 82443LX PAC AGP"),
+ DEVICE( INTEL, INTEL_82443BX_0,"440BX - 82443BX Host"),
+ DEVICE( INTEL, INTEL_82443BX_1,"440BX - 82443BX AGP"),
+ DEVICE( INTEL, INTEL_82443BX_2,"440BX - 82443BX Host (no AGP)"),
DEVICE( INTEL, INTEL_P6, "Orion P6"),
DEVICE( INTEL, INTEL_82450GX, "82450GX Orion P6"),
DEVICE( KTI, KTI_ET32P2, "ET32P2"),
+ DEVICE( ADAPTEC, ADAPTEC_7810, "AIC-7810 RAID"),
DEVICE( ADAPTEC, ADAPTEC_7850, "AIC-7850"),
DEVICE( ADAPTEC, ADAPTEC_7855, "AIC-7855"),
DEVICE( ADAPTEC, ADAPTEC_5800, "AIC-5800"),
@@ -481,7 +515,9 @@ struct pci_dev_info dev_info[] = {
DEVICE( ADAPTEC, ADAPTEC_7882, "AIC-7882U"),
DEVICE( ADAPTEC, ADAPTEC_7883, "AIC-7883U"),
DEVICE( ADAPTEC, ADAPTEC_7884, "AIC-7884U"),
+ DEVICE( ADAPTEC, ADAPTEC_1030, "ABA-1030 DVB receiver"),
DEVICE( ATRONICS, ATRONICS_2015, "IDE-2015PL"),
+ DEVICE( TIGERJET, TIGERJET_300, "Tiger300 ISDN"),
DEVICE( ARK, ARK_STING, "Stingray"),
DEVICE( ARK, ARK_STINGARK, "Stingray ARK 2000PV"),
DEVICE( ARK, ARK_2000MT, "2000MT")
@@ -658,6 +694,7 @@ static const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_WINBOND: return "Winbond";
case PCI_VENDOR_ID_DATABOOK: return "Databook";
case PCI_VENDOR_ID_PLX: return "PLX";
+ case PCI_VENDOR_ID_MADGE: return "Madge Networks";
case PCI_VENDOR_ID_3COM: return "3Com";
case PCI_VENDOR_ID_SMC: return "SMC";
case PCI_VENDOR_ID_AL: return "Acer Labs";
@@ -665,6 +702,7 @@ static const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_SURECOM: return "Surecom";
case PCI_VENDOR_ID_NEOMAGIC: return "Neomagic";
case PCI_VENDOR_ID_ASP: return "Advanced System Products";
+ case PCI_VENDOR_ID_MACRONIX: return "Macronix";
case PCI_VENDOR_ID_CERN: return "CERN";
case PCI_VENDOR_ID_NVIDIA: return "NVidia";
case PCI_VENDOR_ID_IMS: return "IMS";
@@ -699,17 +737,23 @@ static const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_AURAVISION: return "Auravision";
case PCI_VENDOR_ID_IKON: return "Ikon";
case PCI_VENDOR_ID_ZORAN: return "Zoran";
+ case PCI_VENDOR_ID_KINETIC: return "Kinetic";
case PCI_VENDOR_ID_COMPEX: return "Compex";
case PCI_VENDOR_ID_RP: return "Comtrol";
case PCI_VENDOR_ID_CYCLADES: return "Cyclades";
case PCI_VENDOR_ID_O2: return "O2 Micro";
case PCI_VENDOR_ID_3DFX: return "3Dfx";
- case PCI_VENDOR_ID_STALLION: return "Stallion Technologies";
case PCI_VENDOR_ID_SIGMADES: return "Sigma Designs";
+ case PCI_VENDOR_ID_CCUBE: return "C-Cube";
+ case PCI_VENDOR_ID_DIPIX: return "Dipix";
+ case PCI_VENDOR_ID_STALLION: return "Stallion Technologies";
case PCI_VENDOR_ID_OPTIBASE: return "Optibase";
+ case PCI_VENDOR_ID_SATSAGEM: return "SatSagem";
+ case PCI_VENDOR_ID_HUGHES: return "Hughes";
case PCI_VENDOR_ID_ENSONIQ: return "Ensoniq";
case PCI_VENDOR_ID_PICTUREL: return "Picture Elements";
case PCI_VENDOR_ID_NVIDIA_SGS: return "NVidia/SGS Thomson";
+ case PCI_VENDOR_ID_CBOARDS: return "ComputerBoards";
case PCI_VENDOR_ID_SYMPHONY: return "Symphony";
case PCI_VENDOR_ID_TEKRAM: return "Tekram";
case PCI_VENDOR_ID_3DLABS: return "3Dlabs";
@@ -720,6 +764,7 @@ static const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_KTI: return "KTI";
case PCI_VENDOR_ID_ADAPTEC: return "Adaptec";
case PCI_VENDOR_ID_ATRONICS: return "Atronics";
+ case PCI_VENDOR_ID_TIGERJET: return "TigerJet";
case PCI_VENDOR_ID_ARK: return "ARK Logic";
default: return "Unknown vendor";
}
@@ -744,7 +789,7 @@ static const char *pci_strdev(unsigned int vendor, unsigned int device)
static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
{
unsigned long base;
- unsigned int l, class_rev, bus, devfn;
+ unsigned int class_rev, bus, devfn;
unsigned short vendor, device, status;
unsigned char bist, latency, min_gnt, max_lat;
int reg, len = 0;
@@ -835,12 +880,7 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
if (len + 40 > size) {
return -1;
}
- pcibios_read_config_dword(bus, devfn,
- PCI_BASE_ADDRESS_0 + (reg << 2), &l);
- if (l == 0xffffffff)
- base = 0;
- else
- base = l;
+ base = dev->base_address[reg];
if (!base)
continue;
@@ -863,12 +903,7 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
case PCI_BASE_ADDRESS_MEM_TYPE_1M:
type = "20 bit"; break;
case PCI_BASE_ADDRESS_MEM_TYPE_64:
- type = "64 bit";
- /* read top 32 bit address of base addr: */
- reg += 4;
- pcibios_read_config_dword(bus, devfn, reg, &l);
- base |= ((u64) l) << 32;
- break;
+ type = "64 bit"; break;
}
len += sprintf(buf + len,
"\n %srefetchable %s memory at "
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f944e1fd5..202d791c0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1,5 +1,5 @@
/*
- * $Id: pci.c,v 1.79 1998/04/17 16:25:24 mj Exp $
+ * $Id: pci.c,v 1.84 1998/05/02 19:22:06 mj Exp $
*
* PCI Bus Services
*
@@ -68,11 +68,48 @@ pci_find_class(unsigned int class, struct pci_dev *from)
}
+int
+pci_read_config_byte(struct pci_dev *dev, u8 where, u8 *val)
+{
+ return pcibios_read_config_byte(dev->bus->number, dev->devfn, where, val);
+}
+
+int
+pci_read_config_word(struct pci_dev *dev, u8 where, u16 *val)
+{
+ return pcibios_read_config_word(dev->bus->number, dev->devfn, where, val);
+}
+
+int
+pci_read_config_dword(struct pci_dev *dev, u8 where, u32 *val)
+{
+ return pcibios_read_config_dword(dev->bus->number, dev->devfn, where, val);
+}
+
+int
+pci_write_config_byte(struct pci_dev *dev, u8 where, u8 val)
+{
+ return pcibios_write_config_byte(dev->bus->number, dev->devfn, where, val);
+}
+
+int
+pci_write_config_word(struct pci_dev *dev, u8 where, u16 val)
+{
+ return pcibios_write_config_word(dev->bus->number, dev->devfn, where, val);
+}
+
+int
+pci_write_config_dword(struct pci_dev *dev, u8 where, u32 val)
+{
+ return pcibios_write_config_dword(dev->bus->number, dev->devfn, where, val);
+}
+
+
void
pci_set_master(struct pci_dev *dev)
{
- unsigned short cmd;
- unsigned char lat;
+ u16 cmd;
+ u8 lat;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (! (cmd & PCI_COMMAND_MASTER)) {
@@ -89,16 +126,43 @@ pci_set_master(struct pci_dev *dev)
}
}
+__initfunc(void pci_read_bases(struct pci_dev *dev, unsigned int howmany))
+{
+ unsigned int reg;
+ u32 l;
+
+ for(reg=0; reg<howmany; reg++) {
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
+ if (l == 0xffffffff)
+ continue;
+ dev->base_address[reg] = l;
+ if ((l & PCI_MEMORY_RANGE_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ reg++;
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
+ if (l) {
+#if BITS_PER_LONG == 64
+ dev->base_address[reg-1] |= ((unsigned long) l) << 32;
+#else
+ printk("PCI: Unable to handle 64-bit address for device %02x:%02x\n",
+ dev->bus->number, dev->devfn);
+ dev->base_address[reg-1] = 0;
+#endif
+ }
+ }
+ }
+}
+
__initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
{
unsigned int devfn, l, max, class;
unsigned char cmd, irq, tmp, hdr_type, is_multi = 0;
- struct pci_dev *dev;
+ struct pci_dev *dev, **bus_last;
struct pci_bus *child;
int reg;
DBG("pci_scan_bus for bus %d\n", bus->number);
+ bus_last = &bus->devices;
max = bus->secondary;
for (devfn = 0; devfn < 0xff; ++devfn) {
if (PCI_FUNC(devfn) && !is_multi) {
@@ -111,8 +175,8 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l);
/* some broken boards return 0 if a slot is empty: */
- if (l == 0xffffffff || l == 0x00000000) {
- hdr_type = 0;
+ if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) {
+ is_multi = 0;
continue;
}
@@ -133,11 +197,12 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class);
class >>= 8; /* upper 3 bytes */
dev->class = class;
+ class >>= 8;
dev->hdr_type = hdr_type;
switch (hdr_type & 0x7f) { /* header type */
case PCI_HEADER_TYPE_NORMAL: /* standard header */
- if (class >> 8 == PCI_CLASS_BRIDGE_PCI)
+ if (class == PCI_CLASS_BRIDGE_PCI)
goto bad;
/*
* If the card generates interrupts, read IRQ number
@@ -151,25 +216,19 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
* read base address registers, again pcibios_fixup() can
* tweak these
*/
- for (reg = 0; reg < 6; reg++) {
- pcibios_read_config_dword(bus->number, devfn, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
- dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
- }
+ pci_read_bases(dev, 6);
pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l);
dev->rom_address = (l == 0xffffffff) ? 0 : l;
break;
case PCI_HEADER_TYPE_BRIDGE: /* bridge header */
- if (class >> 8 != PCI_CLASS_BRIDGE_PCI)
+ if (class != PCI_CLASS_BRIDGE_PCI)
goto bad;
- for (reg = 0; reg < 2; reg++) {
- pcibios_read_config_dword(bus->number, devfn, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
- dev->base_address[reg] = (l == 0xffffffff) ? 0 : l;
- }
+ pci_read_bases(dev, 2);
pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l);
dev->rom_address = (l == 0xffffffff) ? 0 : l;
break;
case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */
- if (class >> 16 != PCI_BASE_CLASS_BRIDGE)
+ if (class != PCI_CLASS_BRIDGE_CARDBUS)
goto bad;
for (reg = 0; reg < 2; reg++) {
pcibios_read_config_dword(bus->number, devfn, PCI_CB_MEMORY_BASE_0 + (reg << 3), &l);
@@ -201,8 +260,8 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
* Now insert it into the list of devices held
* by the parent bus.
*/
- dev->sibling = bus->devices;
- bus->devices = dev;
+ *bus_last = dev;
+ bus_last = &dev->sibling;
#if 0
/*
@@ -217,7 +276,7 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
/*
* If it's a bridge, scan the bus behind it.
*/
- if (class >> 8 == PCI_CLASS_BRIDGE_PCI) {
+ if (class == PCI_CLASS_BRIDGE_PCI) {
unsigned int buses;
unsigned short cr;
diff --git a/drivers/pci/pcisyms.c b/drivers/pci/pcisyms.c
index b0178fdf1..530f98db9 100644
--- a/drivers/pci/pcisyms.c
+++ b/drivers/pci/pcisyms.c
@@ -1,5 +1,5 @@
/*
- * $Id: pcisyms.c,v 1.4 1998/04/17 16:34:19 mj Exp $
+ * $Id: pcisyms.c,v 1.7 1998/05/02 19:20:06 mj Exp $
*
* PCI Bus Services -- Exported Symbols
*
@@ -16,6 +16,12 @@ EXPORT_SYMBOL(pcibios_read_config_dword);
EXPORT_SYMBOL(pcibios_write_config_byte);
EXPORT_SYMBOL(pcibios_write_config_word);
EXPORT_SYMBOL(pcibios_write_config_dword);
+EXPORT_SYMBOL(pci_read_config_byte);
+EXPORT_SYMBOL(pci_read_config_word);
+EXPORT_SYMBOL(pci_read_config_dword);
+EXPORT_SYMBOL(pci_write_config_byte);
+EXPORT_SYMBOL(pci_write_config_word);
+EXPORT_SYMBOL(pci_write_config_dword);
EXPORT_SYMBOL(pci_devices);
EXPORT_SYMBOL(pci_root);
EXPORT_SYMBOL(pci_find_class);
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 7424a20d4..3e15ce47d 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -57,7 +57,7 @@ proc_bus_pci_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
* undefined locations (think of Intel PIIX4 as a typical example).
*/
- if (fsuser())
+ if (capable(CAP_SYS_ADMIN))
size = PCI_CFG_SPACE_SIZE;
else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
size = 128;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 552756e5f..77ef16f91 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1,5 +1,5 @@
/*
- * $Id: quirks.c,v 1.3 1998/02/06 19:51:42 mj Exp $
+ * $Id: quirks.c,v 1.5 1998/05/02 19:24:14 mj Exp $
*
* PCI Chipset-Specific Quirks
*
@@ -7,8 +7,7 @@
*
* This is the right place for all special fixups for on-board
* devices not depending on system architecture -- for example
- * bus bridges. The only thing implemented in this release is
- * the bridge optimization, but others might appear later.
+ * bus bridges.
*/
#include <linux/config.h>
@@ -88,21 +87,19 @@ __initfunc(static void quirk_bridge(struct pci_dev *dev, int pos))
printk(" %s: ", bridge_optimization[i].type);
bmap = &bridge_mapping[pos + i];
if (!bmap->addr) {
- printk("Not supported.");
+ printk("Not supported.\n");
} else {
- pcibios_read_config_byte(dev->bus->number, dev->devfn, bmap->addr, &val);
+ pci_read_config_byte(dev, bmap->addr, &val);
if ((val & bmap->mask) == bmap->value)
- printk("%s.", bridge_optimization[i].on);
+ printk("%s.\n", bridge_optimization[i].on);
else {
- printk("%s.", bridge_optimization[i].off);
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- bmap->addr,
- (val & (0xff - bmap->mask))
- + bmap->value);
- printk("Changed! Now %s.", bridge_optimization[i].on);
+ printk("%s", bridge_optimization[i].off);
+ pci_write_config_byte(dev,
+ bmap->addr,
+ (val & (0xff - bmap->mask)) + bmap->value);
+ printk(" -> %s.\n", bridge_optimization[i].on);
}
}
- printk("\n");
}
}
@@ -113,27 +110,18 @@ __initfunc(static void quirk_bridge(struct pci_dev *dev, int pos))
which can cause problems in combination with the 82441FX/PPro MTRRs */
__initfunc(static void quirk_passive_release(struct pci_dev *dev, int arg))
{
- struct pci_dev *piix3;
+ struct pci_dev *d = NULL;
unsigned char dlc;
/* We have to make sure a particular bit is set in the PIIX3
ISA bridge, so we have to go out and find it. */
- for (piix3 = pci_devices; ; piix3 = piix3->next) {
- if (!piix3)
- return;
-
- if (piix3->vendor == PCI_VENDOR_ID_INTEL
- && piix3->device == PCI_DEVICE_ID_INTEL_82371SB_0)
- break;
- }
-
- pcibios_read_config_byte(piix3->bus->number, piix3->devfn, 0x82, &dlc);
-
- if (!(dlc & 1<<1)) {
- printk("PIIX3: Enabling Passive Release\n");
- dlc |= 1<<1;
- pcibios_write_config_byte(piix3->bus->number, piix3->devfn,
- 0x82, dlc);
+ while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
+ pci_read_config_byte(d, 0x82, &dlc);
+ if (!(dlc & 1<<1)) {
+ printk("PIIX3: Enabling Passive Release\n");
+ dlc |= 1<<1;
+ pci_write_config_byte(d, 0x82, dlc);
+ }
}
}
@@ -141,7 +129,7 @@ __initfunc(static void quirk_passive_release(struct pci_dev *dev, int arg))
typedef void (*quirk_handler)(struct pci_dev *, int);
/*
- * Mpping from quirk handler functions to names.
+ * Mapping from quirk handler functions to names.
*/
struct quirk_name {
@@ -185,6 +173,7 @@ static struct quirk_info quirk_list[] __initdata = {
{ PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8891A, quirk_bridge, 0x01 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, quirk_bridge, 0x00 },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82434, quirk_bridge, 0x00 },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82430, quirk_bridge, 0x00 },
#endif
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release, 0x00 },
};
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index ccc8dd2cd..160c7e5de 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -91,7 +91,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case RTCSET:
- if (!suser())
+ if (!capable(CAP_SYS_TIME))
return -EPERM;
copy_from_user_ret(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time), -EFAULT);
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index cb822dd2a..81a8b7477 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -205,7 +205,7 @@ static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg)
unsigned char *buffer;
int ret;
- if(!suser()) return -EPERM;
+ if(!capable(CAP_SYS_ADMIN)) return -EPERM;
switch(cmd) {
case VFC_I2C_SEND:
diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c
index f7c477ea4..3d8d24a02 100644
--- a/drivers/sbus/char/zs.c
+++ b/drivers/sbus/char/zs.c
@@ -1265,7 +1265,7 @@ static int set_serial_info(struct sun_serial * info,
return -EFAULT;
old_info = *info;
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((new_serial.baud_base != info->baud_base) ||
(new_serial.type != info->type) ||
(new_serial.close_delay != info->close_delay) ||
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index d81cb5187..05c0ecab9 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -260,7 +260,7 @@ static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
struct request *rq = hwgroup->rq;
idescsi_pc_t *pc = (idescsi_pc_t *) rq->buffer;
int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
- u8 *scsi_buf = pc->scsi_cmd->request_buffer;
+ u8 *scsi_buf;
if (rq->cmd != IDESCSI_PC_RQ) {
ide_end_request (uptodate, hwgroup);
@@ -282,6 +282,7 @@ static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number);
if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) {
printk(", rst = ");
+ scsi_buf = pc->scsi_cmd->request_buffer;
hexdump(scsi_buf, IDE_MIN(16, pc->scsi_cmd->request_bufflen));
} else printk("\n");
}
@@ -326,7 +327,7 @@ static void idescsi_pc_intr (ide_drive_t *drive)
if ((status & DRQ_STAT) == 0) { /* No more interrupts */
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
- ide_sti();
+ ide__sti();
if (status & ERR_STAT)
rq->errors++;
idescsi_end_request (1, HWGROUP(drive));
@@ -345,7 +346,18 @@ static void idescsi_pc_intr (ide_drive_t *drive)
if ( temp > pc->request_transfer) {
if (temp > pc->buffer_size) {
printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n");
- idescsi_discard_data (drive,bcount);
+ temp = pc->buffer_size - pc->actually_transferred;
+ if (temp) {
+ clear_bit(PC_WRITING, &pc->flags);
+ if (pc->sg)
+ idescsi_input_buffers(drive, pc, temp);
+ else
+ atapi_input_bytes(drive, pc->current_position, temp);
+ printk(KERN_ERR "ide-scsi: transferred %d of %d bytes\n", temp, bcount);
+ }
+ pc->actually_transferred += temp;
+ pc->current_position += temp;
+ idescsi_discard_data (drive,bcount - temp);
ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc));
return;
}
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index ebdcb560c..5e67230e3 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -50,13 +50,6 @@ NULL, /* cur_cmd */ \
#include "ppa.h"
#include <linux/parport.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#ifndef PARPORT_MODULES
-#define PARPORT_MODULES "parport_pc"
-#endif
-#endif
-
#define NO_HOSTS 4
static ppa_struct ppa_hosts[NO_HOSTS] =
{PPA_EMPTY, PPA_EMPTY, PPA_EMPTY, PPA_EMPTY};
@@ -98,7 +91,6 @@ static int ppa_pb_claim(int host_no)
return 1;
}
- PPA_BASE(host_no) = ppa_hosts[host_no].dev->port->base;
if (ppa_hosts[host_no].cur_cmd)
ppa_hosts[host_no].cur_cmd->SCp.phase++;
return 0;
@@ -130,12 +122,8 @@ int ppa_detect(Scsi_Host_Template * host)
nhosts = 0;
try_again = 0;
-#ifdef CONFIG_KMOD
- if (!pb) {
- request_module(PARPORT_MODULES);
+ if (!pb)
pb = parport_enumerate();
- }
-#endif
if (!pb) {
printk("ppa: parport reports no devices.\n");
@@ -155,7 +143,7 @@ int ppa_detect(Scsi_Host_Template * host)
if (ppa_pb_claim(i))
while (ppa_hosts[i].p_busy)
schedule(); /* Whe can safe schedule() here */
- ppb = PPA_BASE(i);
+ ppb = PPA_BASE(i) = ppa_hosts[i].dev->port->base;
w_ctr(ppb, 0x0c);
modes = ppa_hosts[i].dev->port->modes;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 0dc7f398f..469de6d25 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1609,6 +1609,7 @@ void scsi_bottom_half_handler(void)
if( SCpnt == NULL )
return;
+ spin_lock_irqsave(&io_request_lock, flags);
atomic_inc(&recursion_depth);
SCnext = SCpnt->bh_next;
@@ -1700,6 +1701,7 @@ void scsi_bottom_half_handler(void)
} /* for(; SCpnt...) */
atomic_dec(&recursion_depth);
+ spin_unlock_irqrestore(&io_request_lock, flags);
} /* while(1==1) */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 70adb0040..d10651019 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -159,7 +159,7 @@ scsi_delete_timer(Scsi_Cmnd * SCset)
*
* Notes:
*/
-void scsi_times_out (Scsi_Cmnd * SCpnt)
+static void do_scsi_times_out (Scsi_Cmnd * SCpnt)
{
/*
@@ -222,6 +222,15 @@ void scsi_times_out (Scsi_Cmnd * SCpnt)
}
}
+void scsi_times_out (Scsi_Cmnd * SCpnt)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&io_request_lock, flags);
+ do_scsi_times_out(SCpnt);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
/*
* Function scsi_block_when_processing_errors
*
@@ -264,6 +273,9 @@ scsi_block_when_processing_errors(Scsi_Device * SDpnt)
STATIC
void scsi_eh_times_out (Scsi_Cmnd * SCpnt)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&io_request_lock, flags);
SCpnt->request.rq_status = RQ_SCSI_DONE;
SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
SCpnt->eh_state = SCSI_STATE_TIMEOUT;
@@ -273,7 +285,8 @@ void scsi_eh_times_out (Scsi_Cmnd * SCpnt)
if (SCpnt->host->eh_action != NULL)
up(SCpnt->host->eh_action);
else
- panic("Missing scsi error handler thread");
+ printk("Missing scsi error handler thread\n");
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
@@ -446,6 +459,11 @@ scsi_test_unit_ready(Scsi_Cmnd * SCpnt)
return SCpnt->eh_state;
}
+/*
+ * This would normally need to get the IO request lock,
+ * but as it doesn't actually touch anything that needs
+ * to be locked we can avoid the lock here..
+ */
STATIC
void scsi_sleep_done (struct semaphore * sem)
{
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index a052caadf..b5692acd1 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -17,8 +17,13 @@
#include "hosts.h"
#include <scsi/scsi_ioctl.h>
-#define MAX_RETRIES 5
-#define MAX_TIMEOUT (9 * HZ)
+#define NORMAL_RETRIES 5
+#define NORMAL_TIMEOUT (10 * HZ)
+#define FORMAT_UNIT_TIMEOUT (2 * 60 * 60 * HZ)
+#define START_STOP_TIMEOUT (60 * HZ)
+#define MOVE_MEDIUM_TIMEOUT (5 * 60 * HZ)
+#define READ_ELEMENT_STATUS_TIMEOUT (5 * 60 * HZ)
+
#define MAX_BUF PAGE_SIZE
#define max(a,b) (((a) > (b)) ? (a) : (b))
@@ -61,7 +66,7 @@ static int ioctl_probe(struct Scsi_Host * host, void *buffer)
/*
*
* The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
- * The MAX_TIMEOUT and MAX_RETRIES variables are used.
+ * The NORMAL_TIMEOUT and NORMAL_RETRIES variables are used.
*
* dev is the SCSI device struct ptr, *(int *) arg is the length of the
* input data, if any, not including the command string & counts,
@@ -94,7 +99,8 @@ static void scsi_ioctl_done (Scsi_Cmnd * SCpnt)
}
}
-static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
+static int ioctl_internal_command(Scsi_Device *dev, char * cmd,
+ int timeout, int retries)
{
unsigned long flags;
int result;
@@ -107,9 +113,7 @@ static int ioctl_internal_command(Scsi_Device *dev, char * cmd)
struct semaphore sem = MUTEX_LOCKED;
SCpnt->request.sem = &sem;
spin_lock_irqsave(&io_request_lock, flags);
- scsi_do_cmd(SCpnt, cmd, NULL, 0,
- scsi_ioctl_done, MAX_TIMEOUT,
- MAX_RETRIES);
+ scsi_do_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, timeout, retries);
spin_unlock_irqrestore(&io_request_lock, flags);
down(&sem);
SCpnt->request.sem = NULL;
@@ -250,21 +254,24 @@ int scsi_ioctl_send_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic)
switch (opcode)
{
case FORMAT_UNIT:
- timeout = 2 * 60 * 60 * HZ; /* 2 Hours */
+ timeout = FORMAT_UNIT_TIMEOUT;
retries = 1;
break;
case START_STOP:
- timeout = 2 * 60 * HZ; /* 2 minutes */
- retries = 1;
+ timeout = START_STOP_TIMEOUT;
+ retries = NORMAL_RETRIES;
break;
case MOVE_MEDIUM:
+ timeout = MOVE_MEDIUM_TIMEOUT;
+ retries = NORMAL_RETRIES;
+ break;
case READ_ELEMENT_STATUS:
- timeout = 5 * 60 * HZ; /* 5 minutes */
- retries = 1;
+ timeout = READ_ELEMENT_STATUS_TIMEOUT;
+ retries = NORMAL_RETRIES;
break;
default:
- timeout = MAX_TIMEOUT;
- retries = MAX_RETRIES;
+ timeout = NORMAL_TIMEOUT;
+ retries = NORMAL_RETRIES;
break;
}
@@ -372,13 +379,13 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
put_user( dev->host->host_no, (int *) arg);
return 0;
case SCSI_IOCTL_TAGGED_ENABLE:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(!dev->tagged_supported) return -EINVAL;
dev->tagged_queue = 1;
dev->current_tag = 1;
return 0;
case SCSI_IOCTL_TAGGED_DISABLE:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(!dev->tagged_supported) return -EINVAL;
dev->tagged_queue = 0;
dev->current_tag = 0;
@@ -386,7 +393,7 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
case SCSI_IOCTL_PROBE_HOST:
return ioctl_probe(dev->host, arg);
case SCSI_IOCTL_SEND_COMMAND:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
return scsi_ioctl_send_command((Scsi_Device *) dev,
(Scsi_Ioctl_Command *) arg);
case SCSI_IOCTL_DOORLOCK:
@@ -395,7 +402,8 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
scsi_cmd[1] = dev->lun << 5;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = SCSI_REMOVAL_PREVENT;
- return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+ NORMAL_TIMEOUT, NORMAL_RETRIES);
break;
case SCSI_IOCTL_DOORUNLOCK:
if (!dev->removable || !dev->lockable) return 0;
@@ -403,13 +411,31 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
scsi_cmd[1] = dev->lun << 5;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = SCSI_REMOVAL_ALLOW;
- return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+ NORMAL_TIMEOUT, NORMAL_RETRIES);
case SCSI_IOCTL_TEST_UNIT_READY:
scsi_cmd[0] = TEST_UNIT_READY;
scsi_cmd[1] = dev->lun << 5;
scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
scsi_cmd[4] = 0;
- return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd);
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+ NORMAL_TIMEOUT, NORMAL_RETRIES);
+ break;
+ case SCSI_IOCTL_START_UNIT:
+ scsi_cmd[0] = START_STOP;
+ scsi_cmd[1] = dev->lun << 5;
+ scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
+ scsi_cmd[4] = 1;
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+ START_STOP_TIMEOUT, NORMAL_RETRIES);
+ break;
+ case SCSI_IOCTL_STOP_UNIT:
+ scsi_cmd[0] = START_STOP;
+ scsi_cmd[1] = dev->lun << 5;
+ scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
+ scsi_cmd[4] = 0;
+ return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd,
+ START_STOP_TIMEOUT, NORMAL_RETRIES);
break;
default :
if (dev->host->hostt->ioctl)
diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
index 924ec8e0c..c6d83f8a2 100644
--- a/drivers/scsi/scsi_syms.c
+++ b/drivers/scsi/scsi_syms.c
@@ -65,6 +65,7 @@ EXPORT_SYMBOL(scsi_release_command);
EXPORT_SYMBOL(print_Scsi_Cmnd);
EXPORT_SYMBOL(scsi_block_when_processing_errors);
EXPORT_SYMBOL(scsi_mark_host_reset);
+EXPORT_SYMBOL(scsi_ioctl_send_command);
#if defined(CONFIG_SCSI_LOGGING) /* { */
EXPORT_SYMBOL(scsi_logging_level);
#endif
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index e7da5c954..ac752b2e5 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1060,8 +1060,15 @@ static int check_scsidisk_media_change(kdev_t full_dev){
}
inode.i_rdev = full_dev; /* This is all we really need here */
- retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0);
+ /* Using Start/Stop enables differentiation between drive with
+ * no cartridge loaded - NOT READY, drive with changed cartridge -
+ * UNIT ATTENTION, or with same cartridge - GOOD STATUS.
+ * This also handles drives that auto spin down. eg iomega jaz 1GB
+ * as this will spin up the drive.
+ */
+ retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_START_UNIT, 0);
+
if(retval){ /* Unable to test, unit probably not ready. This usually
* means there is no disc in the drive. Mark as changed,
* and we will figure it out later once the drive is
diff --git a/drivers/scsi/sd_ioctl.c b/drivers/scsi/sd_ioctl.c
index 2f771552a..a29d958d1 100644
--- a/drivers/scsi/sd_ioctl.c
+++ b/drivers/scsi/sd_ioctl.c
@@ -79,7 +79,7 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
return 0;
case BLKRASET:
- if (!suser())
+ if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if(!(inode->i_rdev)) return -EINVAL;
if(arg > 0xff) return -EINVAL;
@@ -96,13 +96,15 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
return 0;
case BLKFLSBUF:
- if(!suser()) return -EACCES;
+ if(!capable(CAP_SYS_ADMIN)) return -EACCES;
if(!(inode->i_rdev)) return -EINVAL;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
return 0;
case BLKRRPART: /* Re-read partition tables */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
return revalidate_scsidisk(dev, 1);
RO_IOCTLS(dev, arg);
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index e864582b3..1d34cf7ec 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -106,8 +106,8 @@ retry:
break;
case ILLEGAL_REQUEST:
if (!quiet)
- printk("sr%d: CDROM (ioctl) reports ILLEGAL REQUEST.\n",
- target);
+ printk(KERN_ERR "sr%d: CDROM (ioctl) reports ILLEGAL "
+ "REQUEST.\n", target);
if (SCpnt->sense_buffer[12] == 0x20 &&
SCpnt->sense_buffer[13] == 0x00) {
/* sense: Invalid command operation code */
@@ -121,7 +121,7 @@ retry:
#endif
break;
default:
- printk("sr%d: CDROM (ioctl) error, command: ", target);
+ printk(KERN_ERR "sr%d: CDROM (ioctl) error, command: ", target);
print_command(sr_cmd);
print_sense("sr", SCpnt);
err = -EIO;
@@ -792,7 +792,7 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
return 0;
case BLKRASET:
- if(!suser())
+ if(!capable(CAP_SYS_ADMIN))
return -EACCES;
if(!(cdi->dev))
return -EINVAL;
@@ -804,7 +804,7 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
RO_IOCTLS(cdi->dev,arg);
case BLKFLSBUF:
- if(!suser())
+ if(!capable(CAP_SYS_ADMIN))
return -EACCES;
if(!(cdi->dev))
return -EINVAL;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 35af3e391..a0adf83b3 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -2831,7 +2831,7 @@ st_ioctl(struct inode * inode,struct file * file,
if (i)
return (-EFAULT);
- if (mtc.mt_op == MTSETDRVBUFFER && !suser()) {
+ if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
printk(KERN_WARNING "st%d: MTSETDRVBUFFER only allowed for root.\n", dev);
return (-EPERM);
}
diff --git a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c
index 7239e216b..e5aacc366 100644
--- a/drivers/sgi/char/sgiserial.c
+++ b/drivers/sgi/char/sgiserial.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: sgiserial.c,v 1.8 1998/04/05 11:24:34 ralf Exp $
+ * $Id: sgiserial.c,v 1.9 1998/05/04 09:12:59 ralf Exp $
*/
#include <linux/config.h> /* for CONFIG_REMOTE_DEBUG */
@@ -1218,7 +1218,7 @@ static int set_serial_info(struct sgi_serial * info,
copy_from_user(&new_serial,new_info,sizeof(new_serial));
old_info = *info;
- if (!suser()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if ((new_serial.baud_base != info->baud_base) ||
(new_serial.type != info->type) ||
(new_serial.close_delay != info->close_delay) ||
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 1f71965f2..4cfb171dc 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -76,6 +76,9 @@ endif
ifeq ($(CONFIG_GUS),y)
L_OBJS += gus.o
+ ifeq ($(CONFIG_GUSMAX),y)
+ CONFIG_MSS = y
+ endif
else
ifeq ($(CONFIG_GUS),m)
M_OBJS += gus.o
diff --git a/drivers/sound/sound_syms.c b/drivers/sound/sound_syms.c
index 2758660d5..dd06d250a 100644
--- a/drivers/sound/sound_syms.c
+++ b/drivers/sound/sound_syms.c
@@ -26,6 +26,7 @@ EXPORT_SYMBOL(num_audiodevs);
EXPORT_SYMBOL(note_to_freq);
EXPORT_SYMBOL(compute_finetune);
EXPORT_SYMBOL(seq_copy_to_input);
+EXPORT_SYMBOL(seq_input_event);
EXPORT_SYMBOL(sequencer_init);
EXPORT_SYMBOL(sequencer_timer);
@@ -61,6 +62,7 @@ EXPORT_SYMBOL(conf_printf2);
EXPORT_SYMBOL(sound_timer_init);
EXPORT_SYMBOL(sound_timer_interrupt);
EXPORT_SYMBOL(sound_timer_syncinterval);
+EXPORT_SYMBOL(sound_timer_devs);
/* Locking */
EXPORT_SYMBOL(sound_locker);
diff --git a/drivers/sound/sscape.c b/drivers/sound/sscape.c
index 8ea3e87f8..2da737c5c 100644
--- a/drivers/sound/sscape.c
+++ b/drivers/sound/sscape.c
@@ -970,7 +970,7 @@ void cleanup_module(void)
if (mss)
unload_ss_ms_sound(&config);
SOUND_LOCK_END;
- unload_sscape(&config);
+ unload_sscape(&mpu_config);
}
#endif