diff options
author | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-05 02:14:15 -0400 |
commit | 478c6a43fcbc6c11609f8cee7c7b57223907754f (patch) | |
tree | a7f7952099da60d33032aed6de9c0c56c9f8779e /drivers/ide/ide-disk.c | |
parent | 8a3f257c704e02aee9869decd069a806b45be3f1 (diff) | |
parent | 6bb597507f9839b13498781e481f5458aea33620 (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.c | 175 |
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 | ||
56 | static const u8 ide_data_phases[] = { | 55 | static 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 | |||
65 | static 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 | */ |
217 | static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48) | 210 | static 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 | */ |
247 | static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) | 240 | static 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) | |||
389 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | 384 | static 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 | ||
412 | ide_devset_get(multcount, mult_count); | 407 | ide_devset_get(multcount, mult_count); |
@@ -456,15 +451,15 @@ static int set_nowerr(ide_drive_t *drive, int arg) | |||
456 | 451 | ||
457 | static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect) | 452 | static 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 | ||
470 | static void update_ordered(ide_drive_t *drive) | 465 | static void update_ordered(ide_drive_t *drive) |
@@ -531,15 +526,16 @@ static int set_wcache(ide_drive_t *drive, int arg) | |||
531 | 526 | ||
532 | static int do_idedisk_flushcache(ide_drive_t *drive) | 527 | static 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 | ||
545 | ide_devset_get(acoustic, acoustic); | 541 | ide_devset_get(acoustic, acoustic); |
@@ -711,17 +707,17 @@ static int ide_disk_init_media(ide_drive_t *drive, struct gendisk *disk) | |||
711 | static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, | 707 | static 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 | }; |