summaryrefslogtreecommitdiff
path: root/drivers/ide/ide-disk.c
diff options
context:
space:
mode:
authorMartin Dalecki <dalecki@evision-ventures.com>2002-04-24 23:36:23 -0700
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-04-24 23:36:23 -0700
commitcf5300915092ce810cccf5d934ee1ddac2f3044c (patch)
treedcf150fa336038cc9dc3fd0d8fb72fd790993988 /drivers/ide/ide-disk.c
parent5694e35c2ae67ceb1ca930829f3073469978420a (diff)
[PATCH] 2.5.10 IDE 41
- Revoke the TCQ stuff. Well having it for some time showed just nicely what has to be done before it can be included cleanly. But it's just not ready yet. For more explanations please simply track the usage of the special field of struct request - *both* in the generic request handling code and in overall driver code.
Diffstat (limited to 'drivers/ide/ide-disk.c')
-rw-r--r--drivers/ide/ide-disk.c373
1 files changed, 114 insertions, 259 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 4269d14d3453..182fac966e53 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -88,162 +88,135 @@ static int lba_capacity_is_ok(struct hd_driveid *id)
return 0; /* lba_capacity value may be bad */
}
-/*
- * Determine the apriopriate hardware command correspnding to the action in
- * question, depending upon the device capabilities and setup.
- */
static u8 get_command(ide_drive_t *drive, int cmd)
{
int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
- /* Well, calculating the command in this variable may be an
- * overoptimization. */
- u8 command = WIN_NOP;
#if 1
lba48bit = drive->addressing;
#endif
- /*
- * 48-bit commands are pretty sanely laid out
- */
if (lba48bit) {
- command = cmd == READ ? WIN_READ_EXT : WIN_WRITE_EXT;
-
- if (drive->using_dma) {
- command++; /* WIN_*DMA_EXT */
- if (drive->using_tcq)
- command++; /* WIN_*DMA_QUEUED_EXT */
- } else if (drive->mult_count)
- command += 5; /* WIN_MULT*_EXT */
-
- return command;
- }
-
- /*
- * 28-bit commands seem not to be, though...
- */
- if (cmd == READ) {
- if (drive->using_dma) {
- if (drive->using_tcq)
- command = WIN_READDMA_QUEUED;
+ if (cmd == READ) {
+ if (drive->using_dma)
+ return WIN_READDMA_EXT;
+ else if (drive->mult_count)
+ return WIN_MULTREAD_EXT;
else
- command = WIN_READDMA;
- } else if (drive->mult_count)
- command = WIN_MULTREAD;
- else
- command = WIN_READ;
+ return WIN_READ_EXT;
+ } else if (cmd == WRITE) {
+ if (drive->using_dma)
+ return WIN_WRITEDMA_EXT;
+ else if (drive->mult_count)
+ return WIN_MULTWRITE_EXT;
+ else
+ return WIN_WRITE_EXT;
+ }
} else {
- if (drive->using_dma) {
- if (drive->using_tcq)
- command = WIN_WRITEDMA_QUEUED;
+ if (cmd == READ) {
+ if (drive->using_dma)
+ return WIN_READDMA;
+ else if (drive->mult_count)
+ return WIN_MULTREAD;
+ else
+ return WIN_READ;
+ } else if (cmd == WRITE) {
+ if (drive->using_dma)
+ return WIN_WRITEDMA;
+ else if (drive->mult_count)
+ return WIN_MULTWRITE;
else
- command = WIN_WRITEDMA;
- } else if (drive->mult_count)
- command = WIN_MULTWRITE;
- else
- command = WIN_WRITE;
+ return WIN_WRITE;
+ }
}
-
- return command;
+ return WIN_NOP;
}
-static ide_startstop_t chs_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block)
+static ide_startstop_t chs_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
{
- struct ata_taskfile *args = &ar->ar_task;
- struct request *rq = ar->ar_rq;
- int sectors = rq->nr_sectors;
+ struct hd_drive_task_hdr taskfile;
+ struct hd_drive_hob_hdr hobfile;
+ struct ata_taskfile args;
+ int sectors;
- unsigned int track = (block / drive->sect);
- unsigned int sect = (block % drive->sect) + 1;
- unsigned int head = (track % drive->head);
- unsigned int cyl = (track / drive->head);
+ unsigned int track = (block / drive->sect);
+ unsigned int sect = (block % drive->sect) + 1;
+ unsigned int head = (track % drive->head);
+ unsigned int cyl = (track / drive->head);
- memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+ memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
+ memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+ sectors = rq->nr_sectors;
if (sectors == 256)
sectors = 0;
- if (ar->ar_flags & ATA_AR_QUEUED) {
- unsigned long flags;
+ taskfile.sector_count = sectors;
- args->taskfile.feature = sectors;
- args->taskfile.sector_count = ar->ar_tag << 3;
+ taskfile.sector_number = sect;
+ taskfile.low_cylinder = cyl;
+ taskfile.high_cylinder = (cyl>>8);
- spin_lock_irqsave(DRIVE_LOCK(drive), flags);
- blkdev_dequeue_request(rq);
- spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
- } else
- args->taskfile.sector_count = sectors;
-
- args->taskfile.sector_number = sect;
- args->taskfile.low_cylinder = cyl;
- args->taskfile.high_cylinder = (cyl>>8);
-
- args->taskfile.device_head = head;
- args->taskfile.device_head |= drive->select.all;
- args->taskfile.command = get_command(drive, rq_data_dir(rq));
+ taskfile.device_head = head;
+ taskfile.device_head |= drive->select.all;
+ taskfile.command = get_command(drive, rq_data_dir(rq));
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
(rq_data_dir(rq)==READ) ? "read" : "writ");
+ if (lba) printk("LBAsect=%lld, ", block);
+ else printk("CHS=%d/%d/%d, ", cyl, head, sect);
printk("sectors=%ld, ", rq->nr_sectors);
- printk("CHS=%d/%d/%d, ", cyl, head, sect);
printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
#endif
- ide_cmd_type_parser(args);
- args->ar = ar;
- rq->special = ar;
+ args.taskfile = taskfile;
+ args.hobfile = hobfile;
+ ide_cmd_type_parser(&args);
+ rq->special = &args;
- return ata_taskfile(drive, args, rq);
+ return ata_taskfile(drive, &args, rq);
}
-static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block)
+static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
{
- struct ata_taskfile *args = &ar->ar_task;
- struct request *rq = ar->ar_rq;
- int sectors = rq->nr_sectors;
+ struct hd_drive_task_hdr taskfile;
+ struct hd_drive_hob_hdr hobfile;
+ struct ata_taskfile args;
+ int sectors;
+ sectors = rq->nr_sectors;
if (sectors == 256)
sectors = 0;
- memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-
- if (ar->ar_flags & ATA_AR_QUEUED) {
- unsigned long flags;
+ memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
+ memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
- args->taskfile.feature = sectors;
- args->taskfile.sector_count = ar->ar_tag << 3;
+ taskfile.sector_count = sectors;
+ taskfile.sector_number = block;
+ taskfile.low_cylinder = (block >>= 8);
- spin_lock_irqsave(DRIVE_LOCK(drive), flags);
- blkdev_dequeue_request(rq);
- spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
- } else
- args->taskfile.sector_count = sectors;
+ taskfile.high_cylinder = (block >>= 8);
- args->taskfile.sector_number = block;
- args->taskfile.low_cylinder = (block >>= 8);
-
- args->taskfile.high_cylinder = (block >>= 8);
-
- args->taskfile.device_head = ((block >> 8) & 0x0f);
- args->taskfile.device_head |= drive->select.all;
- args->taskfile.command = get_command(drive, rq_data_dir(rq));
+ taskfile.device_head = ((block >> 8) & 0x0f);
+ taskfile.device_head |= drive->select.all;
+ taskfile.command = get_command(drive, rq_data_dir(rq));
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
(rq_data_dir(rq)==READ) ? "read" : "writ");
- printk("sector=%lx, sectors=%ld, ", block, rq->nr_sectors);
+ if (lba) printk("LBAsect=%lld, ", block);
+ else printk("CHS=%d/%d/%d, ", cyl, head, sect);
+ printk("sectors=%ld, ", rq->nr_sectors);
printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
#endif
- ide_cmd_type_parser(args);
- args->ar = ar;
- rq->special = ar;
+ args.taskfile = taskfile;
+ args.hobfile = hobfile;
+ ide_cmd_type_parser(&args);
+ rq->special = &args;
- return ata_taskfile(drive, args, rq);
+ return ata_taskfile(drive, &args, rq);
}
/*
@@ -251,58 +224,57 @@ static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct ata_request *
* 320173056 == 163929 MB or 48bit addressing
* 1073741822 == 549756 MB or 48bit addressing fake drive
*/
-static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block)
+
+static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct request *rq, unsigned long long block)
{
- struct ata_taskfile *args = &ar->ar_task;
- struct request *rq = ar->ar_rq;
- int sectors = rq->nr_sectors;
+ struct hd_drive_task_hdr taskfile;
+ struct hd_drive_hob_hdr hobfile;
+ struct ata_taskfile args;
+ int sectors;
- memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr));
- memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+ memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
+ memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+ sectors = rq->nr_sectors;
if (sectors == 65536)
sectors = 0;
- if (ar->ar_flags & ATA_AR_QUEUED) {
- unsigned long flags;
+ taskfile.sector_count = sectors;
+ hobfile.sector_count = sectors >> 8;
- args->taskfile.feature = sectors;
- args->hobfile.feature = sectors >> 8;
- args->taskfile.sector_count = ar->ar_tag << 3;
-
- spin_lock_irqsave(DRIVE_LOCK(drive), flags);
- blkdev_dequeue_request(rq);
- spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
- } else {
- args->taskfile.sector_count = sectors;
- args->hobfile.sector_count = sectors >> 8;
+ if (rq->nr_sectors == 65536) {
+ taskfile.sector_count = 0x00;
+ hobfile.sector_count = 0x00;
}
- args->taskfile.sector_number = block;
- args->taskfile.low_cylinder = (block >>= 8);
- args->taskfile.high_cylinder = (block >>= 8);
+ taskfile.sector_number = block; /* low lba */
+ taskfile.low_cylinder = (block >>= 8); /* mid lba */
+ taskfile.high_cylinder = (block >>= 8); /* hi lba */
- args->hobfile.sector_number = (block >>= 8);
- args->hobfile.low_cylinder = (block >>= 8);
- args->hobfile.high_cylinder = (block >>= 8);
+ hobfile.sector_number = (block >>= 8); /* low lba */
+ hobfile.low_cylinder = (block >>= 8); /* mid lba */
+ hobfile.high_cylinder = (block >>= 8); /* hi lba */
- args->taskfile.device_head = drive->select.all;
- args->hobfile.device_head = args->taskfile.device_head;
- args->hobfile.control = (drive->ctl|0x80);
- args->taskfile.command = get_command(drive, rq_data_dir(rq));
+ taskfile.device_head = drive->select.all;
+ hobfile.device_head = taskfile.device_head;
+ hobfile.control = (drive->ctl|0x80);
+ taskfile.command = get_command(drive, rq_data_dir(rq));
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
(rq_data_dir(rq)==READ) ? "read" : "writ");
- printk("sector=%lx, sectors=%ld, ", block, rq->nr_sectors);
+ if (lba) printk("LBAsect=%lld, ", block);
+ else printk("CHS=%d/%d/%d, ", cyl, head, sect);
+ printk("sectors=%ld, ", rq->nr_sectors);
printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
#endif
- ide_cmd_type_parser(args);
- args->ar = ar;
- rq->special = ar;
+ args.taskfile = taskfile;
+ args.hobfile = hobfile;
+ ide_cmd_type_parser(&args);
+ rq->special = &args;
- return ata_taskfile(drive, args, rq);
+ return ata_taskfile(drive, &args, rq);
}
/*
@@ -310,11 +282,8 @@ static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct ata_request *
* otherwise, to address sectors. It also takes care of issuing special
* DRIVE_CMDs.
*/
-static ide_startstop_t idedisk_do_request(ide_drive_t *drive, struct request *rq, sector_t block)
+static ide_startstop_t idedisk_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
{
- unsigned long flags;
- struct ata_request *ar;
-
/*
* Wait until all request have bin finished.
*/
@@ -336,49 +305,16 @@ static ide_startstop_t idedisk_do_request(ide_drive_t *drive, struct request *rq
return promise_rw_disk(drive, rq, block);
}
- /*
- * get a new command (push ar further down to avoid grabbing lock here
- */
- spin_lock_irqsave(DRIVE_LOCK(drive), flags);
-
- ar = ata_ar_get(drive);
-
- /*
- * we've reached maximum queue depth, bail
- */
- if (!ar) {
- spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
- return ide_started;
- }
-
- ar->ar_rq = rq;
-
- if (drive->using_tcq) {
- int tag = ide_get_tag(drive);
-
- BUG_ON(drive->tcq->active_tag != -1);
-
- /* Set the tag: */
- ar->ar_flags |= ATA_AR_QUEUED;
- ar->ar_tag = tag;
- drive->tcq->ar[tag] = ar;
- drive->tcq->active_tag = tag;
- ar->ar_time = jiffies;
- drive->tcq->queued++;
- }
-
- spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
-
/* 48-bit LBA */
if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing))
- return lba48_do_request(drive, ar, block);
+ return lba48_do_request(drive, rq, block);
/* 28-bit LBA */
if (drive->select.b.lba)
- return lba28_do_request(drive, ar, block);
+ return lba28_do_request(drive, rq, block);
/* 28-bit CHS */
- return chs_do_request(drive, ar, block);
+ return chs_do_request(drive, rq, block);
}
static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
@@ -861,71 +797,11 @@ static int proc_idedisk_read_smart_values
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
-#ifdef CONFIG_BLK_DEV_IDE_TCQ
-static int proc_idedisk_read_tcq
- (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- ide_drive_t *drive = (ide_drive_t *) data;
- char *out = page;
- int len, cmds, i;
- unsigned long tag_mask = 0, flags, cur_jif = jiffies, max_jif;
-
- if (!drive->tcq) {
- len = sprintf(out, "not configured\n");
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
- }
-
- spin_lock_irqsave(&ide_lock, flags);
-
- len = sprintf(out, "TCQ currently on:\t%s\n", drive->using_tcq ? "yes" : "no");
- len += sprintf(out+len, "Max queue depth:\t%d\n",drive->queue_depth);
- len += sprintf(out+len, "Max achieved depth:\t%d\n",drive->tcq->max_depth);
- len += sprintf(out+len, "Max depth since last:\t%d\n",drive->tcq->max_last_depth);
- len += sprintf(out+len, "Current depth:\t\t%d\n", drive->tcq->queued);
- max_jif = 0;
- len += sprintf(out+len, "Active tags:\t\t[ ");
- for (i = 0, cmds = 0; i < drive->queue_depth; i++) {
- struct ata_request *ar = IDE_GET_AR(drive, i);
-
- if (!ar)
- continue;
-
- __set_bit(i, &tag_mask);
- len += sprintf(out+len, "%d, ", i);
- if (cur_jif - ar->ar_time > max_jif)
- max_jif = cur_jif - ar->ar_time;
- cmds++;
- }
- len += sprintf(out+len, "]\n");
-
- len += sprintf(out+len, "Queue:\t\t\treleased [ %d ] - started [ %d ]\n", drive->tcq->immed_rel, drive->tcq->immed_comp);
-
- if (drive->tcq->queued != cmds)
- len += sprintf(out+len, "pending request and queue count mismatch (counted: %d)\n", cmds);
-
- if (tag_mask != drive->tcq->tag_mask)
- len += sprintf(out+len, "tag masks differ (counted %lx != %lx\n", tag_mask, drive->tcq->tag_mask);
-
- len += sprintf(out+len, "DMA status:\t\t%srunning\n", test_bit(IDE_DMA, &HWGROUP(drive)->flags) ? "" : "not ");
-
- len += sprintf(out+len, "Oldest command:\t\t%lu jiffies\n", max_jif);
- len += sprintf(out+len, "Oldest command ever:\t%lu\n", drive->tcq->oldest_command);
-
- drive->tcq->max_last_depth = 0;
-
- spin_unlock_irqrestore(&ide_lock, flags);
- PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
-}
-#endif
-
static ide_proc_entry_t idedisk_proc[] = {
{ "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
{ "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
{ "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL },
{ "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL },
-#ifdef CONFIG_BLK_DEV_IDE_TCQ
- { "tcq", S_IFREG|S_IRUSR, proc_idedisk_read_tcq, NULL },
-#endif
{ NULL, 0, NULL, NULL }
};
@@ -1007,24 +883,6 @@ static int set_acoustic(ide_drive_t *drive, int arg)
return 0;
}
-#ifdef CONFIG_BLK_DEV_IDE_TCQ
-static int set_using_tcq(ide_drive_t *drive, int arg)
-{
- if (!drive->driver)
- return -EPERM;
- if (!drive->channel->dmaproc)
- return -EPERM;
- if (arg == drive->queue_depth && drive->using_tcq)
- return 0;
-
- drive->queue_depth = arg ? arg : 1;
- if (drive->channel->dmaproc(arg ? ide_dma_queued_on : ide_dma_queued_off, drive))
- return -EIO;
-
- return 0;
-}
-#endif
-
static int probe_lba_addressing (ide_drive_t *drive, int arg)
{
drive->addressing = 0;
@@ -1056,9 +914,6 @@ static void idedisk_add_settings(ide_drive_t *drive)
ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic);
ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL);
ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL);
-#ifdef CONFIG_BLK_DEV_IDE_TCQ
- ide_add_setting(drive, "using_tcq", SETTING_RW, HDIO_GET_QDMA, HDIO_SET_QDMA, TYPE_BYTE, 0, IDE_MAX_TAG, 1, 1, &drive->using_tcq, set_using_tcq);
-#endif
}
static int idedisk_suspend(struct device *dev, u32 state, u32 level)