aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-disk.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-04-05 02:14:15 -0400
committerLen Brown <len.brown@intel.com>2009-04-05 02:14:15 -0400
commit478c6a43fcbc6c11609f8cee7c7b57223907754f (patch)
treea7f7952099da60d33032aed6de9c0c56c9f8779e /drivers/ide/ide-disk.c
parent8a3f257c704e02aee9869decd069a806b45be3f1 (diff)
parent6bb597507f9839b13498781e481f5458aea33620 (diff)
Merge branch 'linus' into release
Conflicts: arch/x86/kernel/cpu/cpufreq/longhaul.c Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/ide/ide-disk.c')
-rw-r--r--drivers/ide/ide-disk.c175
1 files changed, 85 insertions, 90 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 806760d24cef..c998cf8e971a 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -28,7 +28,6 @@
28#include <linux/mutex.h> 28#include <linux/mutex.h>
29#include <linux/leds.h> 29#include <linux/leds.h>
30#include <linux/ide.h> 30#include <linux/ide.h>
31#include <linux/hdreg.h>
32 31
33#include <asm/byteorder.h> 32#include <asm/byteorder.h>
34#include <asm/irq.h> 33#include <asm/irq.h>
@@ -53,33 +52,26 @@ static const u8 ide_rw_cmds[] = {
53 ATA_CMD_WRITE_EXT, 52 ATA_CMD_WRITE_EXT,
54}; 53};
55 54
56static const u8 ide_data_phases[] = { 55static void ide_tf_set_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 dma)
57 TASKFILE_MULTI_IN,
58 TASKFILE_MULTI_OUT,
59 TASKFILE_IN,
60 TASKFILE_OUT,
61 TASKFILE_IN_DMA,
62 TASKFILE_OUT_DMA,
63};
64
65static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
66{ 56{
67 u8 index, lba48, write; 57 u8 index, lba48, write;
68 58
69 lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0; 59 lba48 = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
70 write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0; 60 write = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
71 61
72 if (dma) 62 if (dma) {
63 cmd->protocol = ATA_PROT_DMA;
73 index = 8; 64 index = 8;
74 else 65 } else {
75 index = drive->mult_count ? 0 : 4; 66 cmd->protocol = ATA_PROT_PIO;
76 67 if (drive->mult_count) {
77 task->tf.command = ide_rw_cmds[index + lba48 + write]; 68 cmd->tf_flags |= IDE_TFLAG_MULTI_PIO;
78 69 index = 0;
79 if (dma) 70 } else
80 index = 8; /* fixup index */ 71 index = 4;
72 }
81 73
82 task->data_phase = ide_data_phases[index / 2 + write]; 74 cmd->tf.command = ide_rw_cmds[index + lba48 + write];
83} 75}
84 76
85/* 77/*
@@ -93,8 +85,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
93 u16 nsectors = (u16)rq->nr_sectors; 85 u16 nsectors = (u16)rq->nr_sectors;
94 u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48); 86 u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
95 u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); 87 u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
96 ide_task_t task; 88 struct ide_cmd cmd;
97 struct ide_taskfile *tf = &task.tf; 89 struct ide_taskfile *tf = &cmd.tf;
98 ide_startstop_t rc; 90 ide_startstop_t rc;
99 91
100 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) { 92 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
@@ -104,13 +96,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
104 lba48 = 0; 96 lba48 = 0;
105 } 97 }
106 98
107 if (!dma) { 99 memset(&cmd, 0, sizeof(cmd));
108 ide_init_sg_cmd(drive, rq); 100 cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
109 ide_map_sg(drive, rq);
110 }
111
112 memset(&task, 0, sizeof(task));
113 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
114 101
115 if (drive->dev_flags & IDE_DFLAG_LBA) { 102 if (drive->dev_flags & IDE_DFLAG_LBA) {
116 if (lba48) { 103 if (lba48) {
@@ -129,7 +116,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
129 tf->lbam = (u8)(block >> 8); 116 tf->lbam = (u8)(block >> 8);
130 tf->lbah = (u8)(block >> 16); 117 tf->lbah = (u8)(block >> 16);
131 118
132 task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); 119 cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
133 } else { 120 } else {
134 tf->nsect = nsectors & 0xff; 121 tf->nsect = nsectors & 0xff;
135 tf->lbal = block; 122 tf->lbal = block;
@@ -156,23 +143,27 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
156 tf->device = head; 143 tf->device = head;
157 } 144 }
158 145
146 cmd.tf_flags |= IDE_TFLAG_FS;
147
159 if (rq_data_dir(rq)) 148 if (rq_data_dir(rq))
160 task.tf_flags |= IDE_TFLAG_WRITE; 149 cmd.tf_flags |= IDE_TFLAG_WRITE;
150
151 ide_tf_set_cmd(drive, &cmd, dma);
152 cmd.rq = rq;
161 153
162 ide_tf_set_cmd(drive, &task, dma); 154 if (dma == 0) {
163 if (!dma) 155 ide_init_sg_cmd(&cmd, nsectors << 9);
164 hwif->data_phase = task.data_phase; 156 ide_map_sg(drive, &cmd);
165 task.rq = rq; 157 }
166 158
167 rc = do_rw_taskfile(drive, &task); 159 rc = do_rw_taskfile(drive, &cmd);
168 160
169 if (rc == ide_stopped && dma) { 161 if (rc == ide_stopped && dma) {
170 /* fallback to PIO */ 162 /* fallback to PIO */
171 task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK; 163 cmd.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
172 ide_tf_set_cmd(drive, &task, 0); 164 ide_tf_set_cmd(drive, &cmd, 0);
173 hwif->data_phase = task.data_phase; 165 ide_init_sg_cmd(&cmd, nsectors << 9);
174 ide_init_sg_cmd(drive, rq); 166 rc = do_rw_taskfile(drive, &cmd);
175 rc = do_rw_taskfile(drive, &task);
176 } 167 }
177 168
178 return rc; 169 return rc;
@@ -193,7 +184,9 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
193 184
194 if (!blk_fs_request(rq)) { 185 if (!blk_fs_request(rq)) {
195 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command"); 186 blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
196 ide_end_request(drive, 0, 0); 187 if (rq->errors == 0)
188 rq->errors = -EIO;
189 ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
197 return ide_stopped; 190 return ide_stopped;
198 } 191 }
199 192
@@ -216,25 +209,25 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
216 */ 209 */
217static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48) 210static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
218{ 211{
219 ide_task_t args; 212 struct ide_cmd cmd;
220 struct ide_taskfile *tf = &args.tf; 213 struct ide_taskfile *tf = &cmd.tf;
221 u64 addr = 0; 214 u64 addr = 0;
222 215
223 /* Create IDE/ATA command request structure */ 216 memset(&cmd, 0, sizeof(cmd));
224 memset(&args, 0, sizeof(ide_task_t));
225 if (lba48) 217 if (lba48)
226 tf->command = ATA_CMD_READ_NATIVE_MAX_EXT; 218 tf->command = ATA_CMD_READ_NATIVE_MAX_EXT;
227 else 219 else
228 tf->command = ATA_CMD_READ_NATIVE_MAX; 220 tf->command = ATA_CMD_READ_NATIVE_MAX;
229 tf->device = ATA_LBA; 221 tf->device = ATA_LBA;
230 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; 222
223 cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
231 if (lba48) 224 if (lba48)
232 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); 225 cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
233 /* submit command request */ 226
234 ide_no_data_taskfile(drive, &args); 227 ide_no_data_taskfile(drive, &cmd);
235 228
236 /* if OK, compute maximum address value */ 229 /* if OK, compute maximum address value */
237 if ((tf->status & 0x01) == 0) 230 if (!(tf->status & ATA_ERR))
238 addr = ide_get_lba_addr(tf, lba48) + 1; 231 addr = ide_get_lba_addr(tf, lba48) + 1;
239 232
240 return addr; 233 return addr;
@@ -246,13 +239,13 @@ static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
246 */ 239 */
247static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) 240static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
248{ 241{
249 ide_task_t args; 242 struct ide_cmd cmd;
250 struct ide_taskfile *tf = &args.tf; 243 struct ide_taskfile *tf = &cmd.tf;
251 u64 addr_set = 0; 244 u64 addr_set = 0;
252 245
253 addr_req--; 246 addr_req--;
254 /* Create IDE/ATA command request structure */ 247
255 memset(&args, 0, sizeof(ide_task_t)); 248 memset(&cmd, 0, sizeof(cmd));
256 tf->lbal = (addr_req >> 0) & 0xff; 249 tf->lbal = (addr_req >> 0) & 0xff;
257 tf->lbam = (addr_req >>= 8) & 0xff; 250 tf->lbam = (addr_req >>= 8) & 0xff;
258 tf->lbah = (addr_req >>= 8) & 0xff; 251 tf->lbah = (addr_req >>= 8) & 0xff;
@@ -266,13 +259,15 @@ static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
266 tf->command = ATA_CMD_SET_MAX; 259 tf->command = ATA_CMD_SET_MAX;
267 } 260 }
268 tf->device |= ATA_LBA; 261 tf->device |= ATA_LBA;
269 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; 262
263 cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
270 if (lba48) 264 if (lba48)
271 args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB); 265 cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
272 /* submit command request */ 266
273 ide_no_data_taskfile(drive, &args); 267 ide_no_data_taskfile(drive, &cmd);
268
274 /* if OK, compute maximum address value */ 269 /* if OK, compute maximum address value */
275 if ((tf->status & 0x01) == 0) 270 if (!(tf->status & ATA_ERR))
276 addr_set = ide_get_lba_addr(tf, lba48) + 1; 271 addr_set = ide_get_lba_addr(tf, lba48) + 1;
277 272
278 return addr_set; 273 return addr_set;
@@ -389,24 +384,24 @@ static int ide_disk_get_capacity(ide_drive_t *drive)
389static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) 384static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
390{ 385{
391 ide_drive_t *drive = q->queuedata; 386 ide_drive_t *drive = q->queuedata;
392 ide_task_t *task = kmalloc(sizeof(*task), GFP_ATOMIC); 387 struct ide_cmd *cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
393 388
394 /* FIXME: map struct ide_taskfile on rq->cmd[] */ 389 /* FIXME: map struct ide_taskfile on rq->cmd[] */
395 BUG_ON(task == NULL); 390 BUG_ON(cmd == NULL);
396 391
397 memset(task, 0, sizeof(*task)); 392 memset(cmd, 0, sizeof(*cmd));
398 if (ata_id_flush_ext_enabled(drive->id) && 393 if (ata_id_flush_ext_enabled(drive->id) &&
399 (drive->capacity64 >= (1UL << 28))) 394 (drive->capacity64 >= (1UL << 28)))
400 task->tf.command = ATA_CMD_FLUSH_EXT; 395 cmd->tf.command = ATA_CMD_FLUSH_EXT;
401 else 396 else
402 task->tf.command = ATA_CMD_FLUSH; 397 cmd->tf.command = ATA_CMD_FLUSH;
403 task->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE | 398 cmd->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
404 IDE_TFLAG_DYN; 399 IDE_TFLAG_DYN;
405 task->data_phase = TASKFILE_NO_DATA; 400 cmd->protocol = ATA_PROT_NODATA;
406 401
407 rq->cmd_type = REQ_TYPE_ATA_TASKFILE; 402 rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
408 rq->cmd_flags |= REQ_SOFTBARRIER; 403 rq->cmd_flags |= REQ_SOFTBARRIER;
409 rq->special = task; 404 rq->special = cmd;
410} 405}
411 406
412ide_devset_get(multcount, mult_count); 407ide_devset_get(multcount, mult_count);
@@ -456,15 +451,15 @@ static int set_nowerr(ide_drive_t *drive, int arg)
456 451
457static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect) 452static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
458{ 453{
459 ide_task_t task; 454 struct ide_cmd cmd;
460 455
461 memset(&task, 0, sizeof(task)); 456 memset(&cmd, 0, sizeof(cmd));
462 task.tf.feature = feature; 457 cmd.tf.feature = feature;
463 task.tf.nsect = nsect; 458 cmd.tf.nsect = nsect;
464 task.tf.command = ATA_CMD_SET_FEATURES; 459 cmd.tf.command = ATA_CMD_SET_FEATURES;
465 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; 460 cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
466 461
467 return ide_no_data_taskfile(drive, &task); 462 return ide_no_data_taskfile(drive, &cmd);
468} 463}
469 464
470static void update_ordered(ide_drive_t *drive) 465static void update_ordered(ide_drive_t *drive)
@@ -531,15 +526,16 @@ static int set_wcache(ide_drive_t *drive, int arg)
531 526
532static int do_idedisk_flushcache(ide_drive_t *drive) 527static int do_idedisk_flushcache(ide_drive_t *drive)
533{ 528{
534 ide_task_t args; 529 struct ide_cmd cmd;
535 530
536 memset(&args, 0, sizeof(ide_task_t)); 531 memset(&cmd, 0, sizeof(cmd));
537 if (ata_id_flush_ext_enabled(drive->id)) 532 if (ata_id_flush_ext_enabled(drive->id))
538 args.tf.command = ATA_CMD_FLUSH_EXT; 533 cmd.tf.command = ATA_CMD_FLUSH_EXT;
539 else 534 else
540 args.tf.command = ATA_CMD_FLUSH; 535 cmd.tf.command = ATA_CMD_FLUSH;
541 args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; 536 cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
542 return ide_no_data_taskfile(drive, &args); 537
538 return ide_no_data_taskfile(drive, &cmd);
543} 539}
544 540
545ide_devset_get(acoustic, acoustic); 541ide_devset_get(acoustic, acoustic);
@@ -711,17 +707,17 @@ static int ide_disk_init_media(ide_drive_t *drive, struct gendisk *disk)
711static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, 707static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk,
712 int on) 708 int on)
713{ 709{
714 ide_task_t task; 710 struct ide_cmd cmd;
715 int ret; 711 int ret;
716 712
717 if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0) 713 if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
718 return 0; 714 return 0;
719 715
720 memset(&task, 0, sizeof(task)); 716 memset(&cmd, 0, sizeof(cmd));
721 task.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK; 717 cmd.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
722 task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; 718 cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
723 719
724 ret = ide_no_data_taskfile(drive, &task); 720 ret = ide_no_data_taskfile(drive, &cmd);
725 721
726 if (ret) 722 if (ret)
727 drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING; 723 drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
@@ -737,6 +733,5 @@ const struct ide_disk_ops ide_ata_disk_ops = {
737 .init_media = ide_disk_init_media, 733 .init_media = ide_disk_init_media,
738 .set_doorlock = ide_disk_set_doorlock, 734 .set_doorlock = ide_disk_set_doorlock,
739 .do_request = ide_do_rw_disk, 735 .do_request = ide_do_rw_disk,
740 .end_request = ide_end_request,
741 .ioctl = ide_disk_ioctl, 736 .ioctl = ide_disk_ioctl,
742}; 737};