|
@@ -314,9 +314,32 @@ out:
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
|
|
|
|
+ */
|
|
|
|
+static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
|
|
|
|
+{
|
|
|
|
+ switch (req_pio) {
|
|
|
|
+ case 202:
|
|
|
|
+ case 201:
|
|
|
|
+ case 200:
|
|
|
|
+ case 102:
|
|
|
|
+ case 101:
|
|
|
|
+ case 100:
|
|
|
|
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
|
|
|
|
+ case 9:
|
|
|
|
+ case 8:
|
|
|
|
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
|
|
|
|
+ case 7:
|
|
|
|
+ case 6:
|
|
|
|
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
|
|
|
|
+ default:
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static int set_pio_mode(ide_drive_t *drive, int arg)
|
|
static int set_pio_mode(ide_drive_t *drive, int arg)
|
|
{
|
|
{
|
|
- struct request *rq;
|
|
|
|
ide_hwif_t *hwif = drive->hwif;
|
|
ide_hwif_t *hwif = drive->hwif;
|
|
const struct ide_port_ops *port_ops = hwif->port_ops;
|
|
const struct ide_port_ops *port_ops = hwif->port_ops;
|
|
|
|
|
|
@@ -327,17 +350,26 @@ static int set_pio_mode(ide_drive_t *drive, int arg)
|
|
(hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
|
|
(hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
|
|
return -ENOSYS;
|
|
return -ENOSYS;
|
|
|
|
|
|
- if (drive->special.b.set_tune)
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
+ if (set_pio_mode_abuse(drive->hwif, arg)) {
|
|
|
|
+ if (arg == 8 || arg == 9) {
|
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
|
|
|
|
- rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
|
|
|
|
|
|
+ /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
|
|
|
|
+ spin_lock_irqsave(&ide_lock, flags);
|
|
|
|
+ port_ops->set_pio_mode(drive, arg);
|
|
|
|
+ spin_unlock_irqrestore(&ide_lock, flags);
|
|
|
|
+ } else
|
|
|
|
+ port_ops->set_pio_mode(drive, arg);
|
|
|
|
+ } else {
|
|
|
|
+ int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
|
|
|
|
|
|
- drive->tune_req = (u8) arg;
|
|
|
|
- drive->special.b.set_tune = 1;
|
|
|
|
|
|
+ ide_set_pio(drive, arg);
|
|
|
|
|
|
- blk_execute_rq(drive->queue, NULL, rq, 0);
|
|
|
|
- blk_put_request(rq);
|
|
|
|
|
|
+ if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
|
|
|
|
+ if (keep_dma)
|
|
|
|
+ ide_dma_on(drive);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -367,7 +399,7 @@ ide_gen_devset_rw(io_32bit, io_32bit);
|
|
ide_gen_devset_rw(keepsettings, ksettings);
|
|
ide_gen_devset_rw(keepsettings, ksettings);
|
|
ide_gen_devset_rw(unmaskirq, unmaskirq);
|
|
ide_gen_devset_rw(unmaskirq, unmaskirq);
|
|
ide_gen_devset_rw(using_dma, using_dma);
|
|
ide_gen_devset_rw(using_dma, using_dma);
|
|
-__IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode);
|
|
|
|
|
|
+__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
|
|
|
|
|
|
static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
|
|
static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
|
|
{
|
|
{
|