diff options
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r-- | drivers/ide/ide.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 9d3482d907c9..73e1cc5839d3 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -314,9 +314,32 @@ out: | |||
314 | #endif | 314 | #endif |
315 | } | 315 | } |
316 | 316 | ||
317 | /* | ||
318 | * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away | ||
319 | */ | ||
320 | static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) | ||
321 | { | ||
322 | switch (req_pio) { | ||
323 | case 202: | ||
324 | case 201: | ||
325 | case 200: | ||
326 | case 102: | ||
327 | case 101: | ||
328 | case 100: | ||
329 | return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0; | ||
330 | case 9: | ||
331 | case 8: | ||
332 | return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0; | ||
333 | case 7: | ||
334 | case 6: | ||
335 | return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0; | ||
336 | default: | ||
337 | return 0; | ||
338 | } | ||
339 | } | ||
340 | |||
317 | static int set_pio_mode(ide_drive_t *drive, int arg) | 341 | static int set_pio_mode(ide_drive_t *drive, int arg) |
318 | { | 342 | { |
319 | struct request *rq; | ||
320 | ide_hwif_t *hwif = drive->hwif; | 343 | ide_hwif_t *hwif = drive->hwif; |
321 | const struct ide_port_ops *port_ops = hwif->port_ops; | 344 | const struct ide_port_ops *port_ops = hwif->port_ops; |
322 | 345 | ||
@@ -327,17 +350,26 @@ static int set_pio_mode(ide_drive_t *drive, int arg) | |||
327 | (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) | 350 | (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) |
328 | return -ENOSYS; | 351 | return -ENOSYS; |
329 | 352 | ||
330 | if (drive->special.b.set_tune) | 353 | if (set_pio_mode_abuse(drive->hwif, arg)) { |
331 | return -EBUSY; | 354 | if (arg == 8 || arg == 9) { |
355 | unsigned long flags; | ||
332 | 356 | ||
333 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 357 | /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ |
334 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; | 358 | spin_lock_irqsave(&ide_lock, flags); |
359 | port_ops->set_pio_mode(drive, arg); | ||
360 | spin_unlock_irqrestore(&ide_lock, flags); | ||
361 | } else | ||
362 | port_ops->set_pio_mode(drive, arg); | ||
363 | } else { | ||
364 | int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); | ||
335 | 365 | ||
336 | drive->tune_req = (u8) arg; | 366 | ide_set_pio(drive, arg); |
337 | drive->special.b.set_tune = 1; | ||
338 | 367 | ||
339 | blk_execute_rq(drive->queue, NULL, rq, 0); | 368 | if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { |
340 | blk_put_request(rq); | 369 | if (keep_dma) |
370 | ide_dma_on(drive); | ||
371 | } | ||
372 | } | ||
341 | 373 | ||
342 | return 0; | 374 | return 0; |
343 | } | 375 | } |
@@ -367,7 +399,7 @@ ide_gen_devset_rw(io_32bit, io_32bit); | |||
367 | ide_gen_devset_rw(keepsettings, ksettings); | 399 | ide_gen_devset_rw(keepsettings, ksettings); |
368 | ide_gen_devset_rw(unmaskirq, unmaskirq); | 400 | ide_gen_devset_rw(unmaskirq, unmaskirq); |
369 | ide_gen_devset_rw(using_dma, using_dma); | 401 | ide_gen_devset_rw(using_dma, using_dma); |
370 | __IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode); | 402 | __IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); |
371 | 403 | ||
372 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) | 404 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) |
373 | { | 405 | { |