diff options
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r-- | drivers/ide/ide.c | 135 |
1 files changed, 85 insertions, 50 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 9dcf5aed92cb..04f8f13cb9d7 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -114,7 +114,7 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) | |||
114 | memset(drive, 0, sizeof(*drive)); | 114 | memset(drive, 0, sizeof(*drive)); |
115 | 115 | ||
116 | drive->media = ide_disk; | 116 | drive->media = ide_disk; |
117 | drive->select.all = (unit<<4)|0xa0; | 117 | drive->select = (unit << 4) | ATA_DEVICE_OBS; |
118 | drive->hwif = hwif; | 118 | drive->hwif = hwif; |
119 | drive->ready_stat = ATA_DRDY; | 119 | drive->ready_stat = ATA_DRDY; |
120 | drive->bad_wstat = BAD_W_STAT; | 120 | drive->bad_wstat = BAD_W_STAT; |
@@ -138,7 +138,7 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif) | |||
138 | for (i = 0; i < MAX_DRIVES; i++) { | 138 | for (i = 0; i < MAX_DRIVES; i++) { |
139 | ide_drive_t *drive = &hwif->drives[i]; | 139 | ide_drive_t *drive = &hwif->drives[i]; |
140 | 140 | ||
141 | if (drive->present) { | 141 | if (drive->dev_flags & IDE_DFLAG_PRESENT) { |
142 | spin_unlock_irq(&ide_lock); | 142 | spin_unlock_irq(&ide_lock); |
143 | device_unregister(&drive->gendev); | 143 | device_unregister(&drive->gendev); |
144 | wait_for_completion(&drive->gendev_rel_comp); | 144 | wait_for_completion(&drive->gendev_rel_comp); |
@@ -227,8 +227,7 @@ void ide_unregister(ide_hwif_t *hwif) | |||
227 | kfree(hwif->sg_table); | 227 | kfree(hwif->sg_table); |
228 | unregister_blkdev(hwif->major, hwif->name); | 228 | unregister_blkdev(hwif->major, hwif->name); |
229 | 229 | ||
230 | if (hwif->dma_base) | 230 | ide_release_dma_engine(hwif); |
231 | ide_release_dma_engine(hwif); | ||
232 | 231 | ||
233 | mutex_unlock(&ide_cfg_mtx); | 232 | mutex_unlock(&ide_cfg_mtx); |
234 | } | 233 | } |
@@ -254,7 +253,7 @@ ide_devset_get(io_32bit, io_32bit); | |||
254 | 253 | ||
255 | static int set_io_32bit(ide_drive_t *drive, int arg) | 254 | static int set_io_32bit(ide_drive_t *drive, int arg) |
256 | { | 255 | { |
257 | if (drive->no_io_32bit) | 256 | if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) |
258 | return -EPERM; | 257 | return -EPERM; |
259 | 258 | ||
260 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) | 259 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) |
@@ -265,19 +264,22 @@ static int set_io_32bit(ide_drive_t *drive, int arg) | |||
265 | return 0; | 264 | return 0; |
266 | } | 265 | } |
267 | 266 | ||
268 | ide_devset_get(ksettings, keep_settings); | 267 | ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS); |
269 | 268 | ||
270 | static int set_ksettings(ide_drive_t *drive, int arg) | 269 | static int set_ksettings(ide_drive_t *drive, int arg) |
271 | { | 270 | { |
272 | if (arg < 0 || arg > 1) | 271 | if (arg < 0 || arg > 1) |
273 | return -EINVAL; | 272 | return -EINVAL; |
274 | 273 | ||
275 | drive->keep_settings = arg; | 274 | if (arg) |
275 | drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS; | ||
276 | else | ||
277 | drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS; | ||
276 | 278 | ||
277 | return 0; | 279 | return 0; |
278 | } | 280 | } |
279 | 281 | ||
280 | ide_devset_get(using_dma, using_dma); | 282 | ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA); |
281 | 283 | ||
282 | static int set_using_dma(ide_drive_t *drive, int arg) | 284 | static int set_using_dma(ide_drive_t *drive, int arg) |
283 | { | 285 | { |
@@ -311,9 +313,32 @@ out: | |||
311 | #endif | 313 | #endif |
312 | } | 314 | } |
313 | 315 | ||
316 | /* | ||
317 | * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away | ||
318 | */ | ||
319 | static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) | ||
320 | { | ||
321 | switch (req_pio) { | ||
322 | case 202: | ||
323 | case 201: | ||
324 | case 200: | ||
325 | case 102: | ||
326 | case 101: | ||
327 | case 100: | ||
328 | return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0; | ||
329 | case 9: | ||
330 | case 8: | ||
331 | return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0; | ||
332 | case 7: | ||
333 | case 6: | ||
334 | return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0; | ||
335 | default: | ||
336 | return 0; | ||
337 | } | ||
338 | } | ||
339 | |||
314 | static int set_pio_mode(ide_drive_t *drive, int arg) | 340 | static int set_pio_mode(ide_drive_t *drive, int arg) |
315 | { | 341 | { |
316 | struct request *rq; | ||
317 | ide_hwif_t *hwif = drive->hwif; | 342 | ide_hwif_t *hwif = drive->hwif; |
318 | const struct ide_port_ops *port_ops = hwif->port_ops; | 343 | const struct ide_port_ops *port_ops = hwif->port_ops; |
319 | 344 | ||
@@ -324,56 +349,65 @@ static int set_pio_mode(ide_drive_t *drive, int arg) | |||
324 | (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) | 349 | (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) |
325 | return -ENOSYS; | 350 | return -ENOSYS; |
326 | 351 | ||
327 | if (drive->special.b.set_tune) | 352 | if (set_pio_mode_abuse(drive->hwif, arg)) { |
328 | return -EBUSY; | 353 | if (arg == 8 || arg == 9) { |
354 | unsigned long flags; | ||
329 | 355 | ||
330 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 356 | /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ |
331 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; | 357 | spin_lock_irqsave(&ide_lock, flags); |
358 | port_ops->set_pio_mode(drive, arg); | ||
359 | spin_unlock_irqrestore(&ide_lock, flags); | ||
360 | } else | ||
361 | port_ops->set_pio_mode(drive, arg); | ||
362 | } else { | ||
363 | int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); | ||
332 | 364 | ||
333 | drive->tune_req = (u8) arg; | 365 | ide_set_pio(drive, arg); |
334 | drive->special.b.set_tune = 1; | ||
335 | 366 | ||
336 | blk_execute_rq(drive->queue, NULL, rq, 0); | 367 | if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { |
337 | blk_put_request(rq); | 368 | if (keep_dma) |
369 | ide_dma_on(drive); | ||
370 | } | ||
371 | } | ||
338 | 372 | ||
339 | return 0; | 373 | return 0; |
340 | } | 374 | } |
341 | 375 | ||
342 | ide_devset_get(unmaskirq, unmask); | 376 | ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK); |
343 | 377 | ||
344 | static int set_unmaskirq(ide_drive_t *drive, int arg) | 378 | static int set_unmaskirq(ide_drive_t *drive, int arg) |
345 | { | 379 | { |
346 | if (drive->no_unmask) | 380 | if (drive->dev_flags & IDE_DFLAG_NO_UNMASK) |
347 | return -EPERM; | 381 | return -EPERM; |
348 | 382 | ||
349 | if (arg < 0 || arg > 1) | 383 | if (arg < 0 || arg > 1) |
350 | return -EINVAL; | 384 | return -EINVAL; |
351 | 385 | ||
352 | drive->unmask = arg; | 386 | if (arg) |
387 | drive->dev_flags |= IDE_DFLAG_UNMASK; | ||
388 | else | ||
389 | drive->dev_flags &= ~IDE_DFLAG_UNMASK; | ||
353 | 390 | ||
354 | return 0; | 391 | return 0; |
355 | } | 392 | } |
356 | 393 | ||
357 | #define ide_gen_devset_rw(_name, _func) \ | 394 | ide_ext_devset_rw_sync(io_32bit, io_32bit); |
358 | __IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func) | 395 | ide_ext_devset_rw_sync(keepsettings, ksettings); |
359 | 396 | ide_ext_devset_rw_sync(unmaskirq, unmaskirq); | |
360 | ide_gen_devset_rw(io_32bit, io_32bit); | 397 | ide_ext_devset_rw_sync(using_dma, using_dma); |
361 | ide_gen_devset_rw(keepsettings, ksettings); | 398 | __IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); |
362 | ide_gen_devset_rw(unmaskirq, unmaskirq); | ||
363 | ide_gen_devset_rw(using_dma, using_dma); | ||
364 | __IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode); | ||
365 | 399 | ||
366 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) | 400 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) |
367 | { | 401 | { |
368 | ide_drive_t *drive = dev->driver_data; | 402 | ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); |
369 | ide_hwif_t *hwif = HWIF(drive); | 403 | ide_hwif_t *hwif = HWIF(drive); |
370 | struct request *rq; | 404 | struct request *rq; |
371 | struct request_pm_state rqpm; | 405 | struct request_pm_state rqpm; |
372 | ide_task_t args; | 406 | ide_task_t args; |
373 | int ret; | 407 | int ret; |
374 | 408 | ||
375 | /* Call ACPI _GTM only once */ | 409 | /* call ACPI _GTM only once */ |
376 | if (!(drive->dn % 2)) | 410 | if ((drive->dn & 1) == 0 || pair == NULL) |
377 | ide_acpi_get_timing(hwif); | 411 | ide_acpi_get_timing(hwif); |
378 | 412 | ||
379 | memset(&rqpm, 0, sizeof(rqpm)); | 413 | memset(&rqpm, 0, sizeof(rqpm)); |
@@ -382,33 +416,32 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg) | |||
382 | rq->cmd_type = REQ_TYPE_PM_SUSPEND; | 416 | rq->cmd_type = REQ_TYPE_PM_SUSPEND; |
383 | rq->special = &args; | 417 | rq->special = &args; |
384 | rq->data = &rqpm; | 418 | rq->data = &rqpm; |
385 | rqpm.pm_step = ide_pm_state_start_suspend; | 419 | rqpm.pm_step = IDE_PM_START_SUSPEND; |
386 | if (mesg.event == PM_EVENT_PRETHAW) | 420 | if (mesg.event == PM_EVENT_PRETHAW) |
387 | mesg.event = PM_EVENT_FREEZE; | 421 | mesg.event = PM_EVENT_FREEZE; |
388 | rqpm.pm_state = mesg.event; | 422 | rqpm.pm_state = mesg.event; |
389 | 423 | ||
390 | ret = blk_execute_rq(drive->queue, NULL, rq, 0); | 424 | ret = blk_execute_rq(drive->queue, NULL, rq, 0); |
391 | blk_put_request(rq); | 425 | blk_put_request(rq); |
392 | /* only call ACPI _PS3 after both drivers are suspended */ | 426 | |
393 | if (!ret && (((drive->dn % 2) && hwif->drives[0].present | 427 | /* call ACPI _PS3 only after both devices are suspended */ |
394 | && hwif->drives[1].present) | 428 | if (ret == 0 && ((drive->dn & 1) || pair == NULL)) |
395 | || !hwif->drives[0].present | ||
396 | || !hwif->drives[1].present)) | ||
397 | ide_acpi_set_state(hwif, 0); | 429 | ide_acpi_set_state(hwif, 0); |
430 | |||
398 | return ret; | 431 | return ret; |
399 | } | 432 | } |
400 | 433 | ||
401 | static int generic_ide_resume(struct device *dev) | 434 | static int generic_ide_resume(struct device *dev) |
402 | { | 435 | { |
403 | ide_drive_t *drive = dev->driver_data; | 436 | ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); |
404 | ide_hwif_t *hwif = HWIF(drive); | 437 | ide_hwif_t *hwif = HWIF(drive); |
405 | struct request *rq; | 438 | struct request *rq; |
406 | struct request_pm_state rqpm; | 439 | struct request_pm_state rqpm; |
407 | ide_task_t args; | 440 | ide_task_t args; |
408 | int err; | 441 | int err; |
409 | 442 | ||
410 | /* Call ACPI _STM only once */ | 443 | /* call ACPI _PS0 / _STM only once */ |
411 | if (!(drive->dn % 2)) { | 444 | if ((drive->dn & 1) == 0 || pair == NULL) { |
412 | ide_acpi_set_state(hwif, 1); | 445 | ide_acpi_set_state(hwif, 1); |
413 | ide_acpi_push_timing(hwif); | 446 | ide_acpi_push_timing(hwif); |
414 | } | 447 | } |
@@ -422,7 +455,7 @@ static int generic_ide_resume(struct device *dev) | |||
422 | rq->cmd_flags |= REQ_PREEMPT; | 455 | rq->cmd_flags |= REQ_PREEMPT; |
423 | rq->special = &args; | 456 | rq->special = &args; |
424 | rq->data = &rqpm; | 457 | rq->data = &rqpm; |
425 | rqpm.pm_step = ide_pm_state_start_resume; | 458 | rqpm.pm_step = IDE_PM_START_RESUME; |
426 | rqpm.pm_state = PM_EVENT_ON; | 459 | rqpm.pm_state = PM_EVENT_ON; |
427 | 460 | ||
428 | err = blk_execute_rq(drive->queue, NULL, rq, 1); | 461 | err = blk_execute_rq(drive->queue, NULL, rq, 1); |
@@ -554,6 +587,7 @@ static struct device_attribute ide_dev_attrs[] = { | |||
554 | __ATTR_RO(model), | 587 | __ATTR_RO(model), |
555 | __ATTR_RO(firmware), | 588 | __ATTR_RO(firmware), |
556 | __ATTR(serial, 0400, serial_show, NULL), | 589 | __ATTR(serial, 0400, serial_show, NULL), |
590 | __ATTR(unload_heads, 0644, ide_park_show, ide_park_store), | ||
557 | __ATTR_NULL | 591 | __ATTR_NULL |
558 | }; | 592 | }; |
559 | 593 | ||
@@ -708,22 +742,22 @@ static int ide_set_disk_chs(const char *str, struct kernel_param *kp) | |||
708 | module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0); | 742 | module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0); |
709 | MODULE_PARM_DESC(chs, "force device as a disk (using CHS)"); | 743 | MODULE_PARM_DESC(chs, "force device as a disk (using CHS)"); |
710 | 744 | ||
711 | static void ide_dev_apply_params(ide_drive_t *drive) | 745 | static void ide_dev_apply_params(ide_drive_t *drive, u8 unit) |
712 | { | 746 | { |
713 | int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit; | 747 | int i = drive->hwif->index * MAX_DRIVES + unit; |
714 | 748 | ||
715 | if (ide_nodma & (1 << i)) { | 749 | if (ide_nodma & (1 << i)) { |
716 | printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name); | 750 | printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name); |
717 | drive->nodma = 1; | 751 | drive->dev_flags |= IDE_DFLAG_NODMA; |
718 | } | 752 | } |
719 | if (ide_noflush & (1 << i)) { | 753 | if (ide_noflush & (1 << i)) { |
720 | printk(KERN_INFO "ide: disabling flush requests for %s\n", | 754 | printk(KERN_INFO "ide: disabling flush requests for %s\n", |
721 | drive->name); | 755 | drive->name); |
722 | drive->noflush = 1; | 756 | drive->dev_flags |= IDE_DFLAG_NOFLUSH; |
723 | } | 757 | } |
724 | if (ide_noprobe & (1 << i)) { | 758 | if (ide_noprobe & (1 << i)) { |
725 | printk(KERN_INFO "ide: skipping probe for %s\n", drive->name); | 759 | printk(KERN_INFO "ide: skipping probe for %s\n", drive->name); |
726 | drive->noprobe = 1; | 760 | drive->dev_flags |= IDE_DFLAG_NOPROBE; |
727 | } | 761 | } |
728 | if (ide_nowerr & (1 << i)) { | 762 | if (ide_nowerr & (1 << i)) { |
729 | printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n", | 763 | printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n", |
@@ -732,7 +766,7 @@ static void ide_dev_apply_params(ide_drive_t *drive) | |||
732 | } | 766 | } |
733 | if (ide_cdroms & (1 << i)) { | 767 | if (ide_cdroms & (1 << i)) { |
734 | printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name); | 768 | printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name); |
735 | drive->present = 1; | 769 | drive->dev_flags |= IDE_DFLAG_PRESENT; |
736 | drive->media = ide_cdrom; | 770 | drive->media = ide_cdrom; |
737 | /* an ATAPI device ignores DRDY */ | 771 | /* an ATAPI device ignores DRDY */ |
738 | drive->ready_stat = 0; | 772 | drive->ready_stat = 0; |
@@ -741,11 +775,12 @@ static void ide_dev_apply_params(ide_drive_t *drive) | |||
741 | drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl; | 775 | drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl; |
742 | drive->head = drive->bios_head = ide_disks_chs[i].head; | 776 | drive->head = drive->bios_head = ide_disks_chs[i].head; |
743 | drive->sect = drive->bios_sect = ide_disks_chs[i].sect; | 777 | drive->sect = drive->bios_sect = ide_disks_chs[i].sect; |
744 | drive->forced_geom = 1; | 778 | |
745 | printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n", | 779 | printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n", |
746 | drive->name, | 780 | drive->name, |
747 | drive->cyl, drive->head, drive->sect); | 781 | drive->cyl, drive->head, drive->sect); |
748 | drive->present = 1; | 782 | |
783 | drive->dev_flags |= IDE_DFLAG_FORCED_GEOM | IDE_DFLAG_PRESENT; | ||
749 | drive->media = ide_disk; | 784 | drive->media = ide_disk; |
750 | drive->ready_stat = ATA_DRDY; | 785 | drive->ready_stat = ATA_DRDY; |
751 | } | 786 | } |
@@ -785,7 +820,7 @@ void ide_port_apply_params(ide_hwif_t *hwif) | |||
785 | } | 820 | } |
786 | 821 | ||
787 | for (i = 0; i < MAX_DRIVES; i++) | 822 | for (i = 0; i < MAX_DRIVES; i++) |
788 | ide_dev_apply_params(&hwif->drives[i]); | 823 | ide_dev_apply_params(&hwif->drives[i], i); |
789 | } | 824 | } |
790 | 825 | ||
791 | /* | 826 | /* |