summaryrefslogtreecommitdiffstats
path: root/drivers/block
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/block
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/block')
-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
34 files changed, 716 insertions, 542 deletions
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: