aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r--drivers/ide/ide.c52
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 */
320static 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
317static int set_pio_mode(ide_drive_t *drive, int arg) 341static 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);
367ide_gen_devset_rw(keepsettings, ksettings); 399ide_gen_devset_rw(keepsettings, ksettings);
368ide_gen_devset_rw(unmaskirq, unmaskirq); 400ide_gen_devset_rw(unmaskirq, unmaskirq);
369ide_gen_devset_rw(using_dma, using_dma); 401ide_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
372static int generic_ide_suspend(struct device *dev, pm_message_t mesg) 404static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
373{ 405{