forked from Minki/linux
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (33 commits) ide-cd: remove dead dsc_overlap setting ide: push local_irq_{save,restore}() to do_identify() ide: remove superfluous local_irq_{save,restore}() from ide_dump_status() ide: move legacy ISA/VLB ports handling to ide-legacy.c (v2) ide: move Power Management support to ide-pm.c ide: use ATA_DMA_* defines in ide-dma-sff.c ide: checkpatch.pl fixes for ide-lib.c ide: remove inline tags from ide-probe.c ide: remove redundant code from ide_end_drive_cmd() ide: struct device - replace bus_id with dev_name(), dev_set_name() ide: rework handling of serialized ports (v2) cy82c693: remove superfluous ide_cy82c693 chipset type trm290: add IDE_HFLAG_TRM290 host flag ide: add ->max_sectors field to struct ide_port_info rz1000: apply chipset quirks early (v2) ide: always set nIEN on idle devices ide: fix ->quirk_list checking in ide_do_request() gayle: set IDE_HFLAG_SERIALIZE explictly cmd64x: set IDE_HFLAG_SERIALIZE explictly for CMD646 ali14xx: doesn't use shared IRQs ...
This commit is contained in:
commit
74a6d0f064
@ -62,6 +62,9 @@ config IDE_TIMINGS
|
||||
config IDE_ATAPI
|
||||
bool
|
||||
|
||||
config IDE_LEGACY
|
||||
bool
|
||||
|
||||
config BLK_DEV_IDE_SATA
|
||||
bool "Support for SATA (deprecated; conflicts with libata SATA driver)"
|
||||
default n
|
||||
@ -856,6 +859,7 @@ config BLK_DEV_4DRIVES
|
||||
config BLK_DEV_ALI14XX
|
||||
tristate "ALI M14xx support"
|
||||
select IDE_TIMINGS
|
||||
select IDE_LEGACY
|
||||
help
|
||||
This driver is enabled at runtime using the "ali14xx.probe" kernel
|
||||
boot parameter. It enables support for the secondary IDE interface
|
||||
@ -866,6 +870,7 @@ config BLK_DEV_ALI14XX
|
||||
|
||||
config BLK_DEV_DTC2278
|
||||
tristate "DTC-2278 support"
|
||||
select IDE_LEGACY
|
||||
help
|
||||
This driver is enabled at runtime using the "dtc2278.probe" kernel
|
||||
boot parameter. It enables support for the secondary IDE interface
|
||||
@ -876,6 +881,7 @@ config BLK_DEV_DTC2278
|
||||
config BLK_DEV_HT6560B
|
||||
tristate "Holtek HT6560B support"
|
||||
select IDE_TIMINGS
|
||||
select IDE_LEGACY
|
||||
help
|
||||
This driver is enabled at runtime using the "ht6560b.probe" kernel
|
||||
boot parameter. It enables support for the secondary IDE interface
|
||||
@ -886,6 +892,7 @@ config BLK_DEV_HT6560B
|
||||
config BLK_DEV_QD65XX
|
||||
tristate "QDI QD65xx support"
|
||||
select IDE_TIMINGS
|
||||
select IDE_LEGACY
|
||||
help
|
||||
This driver is enabled at runtime using the "qd65xx.probe" kernel
|
||||
boot parameter. It permits faster I/O speeds to be set. See the
|
||||
@ -894,6 +901,7 @@ config BLK_DEV_QD65XX
|
||||
|
||||
config BLK_DEV_UMC8672
|
||||
tristate "UMC-8672 support"
|
||||
select IDE_LEGACY
|
||||
help
|
||||
This driver is enabled at runtime using the "umc8672.probe" kernel
|
||||
boot parameter. It enables support for the secondary IDE interface
|
||||
|
@ -5,7 +5,7 @@
|
||||
EXTRA_CFLAGS += -Idrivers/ide
|
||||
|
||||
ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
|
||||
ide-taskfile.o ide-park.o ide-pio-blacklist.o
|
||||
ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o
|
||||
|
||||
# core IDE code
|
||||
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
|
||||
@ -15,6 +15,7 @@ ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
|
||||
ide-core-$(CONFIG_BLK_DEV_IDEDMA_SFF) += ide-dma-sff.o
|
||||
ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o
|
||||
ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
|
||||
ide-core-$(CONFIG_IDE_LEGACY) += ide-legacy.o
|
||||
|
||||
obj-$(CONFIG_IDE) += ide-core.o
|
||||
|
||||
|
@ -424,10 +424,10 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
|
||||
.name = DRV_NAME,
|
||||
.init_chipset = init_chipset_cmd64x,
|
||||
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
|
||||
.chipset = ide_cmd646,
|
||||
.port_ops = &cmd64x_port_ops,
|
||||
.dma_ops = &cmd648_dma_ops,
|
||||
.host_flags = IDE_HFLAG_ABUSE_PREFETCH,
|
||||
.host_flags = IDE_HFLAG_SERIALIZE |
|
||||
IDE_HFLAG_ABUSE_PREFETCH,
|
||||
.pio_mask = ATA_PIO5,
|
||||
.mwdma_mask = ATA_MWDMA2,
|
||||
.udma_mask = ATA_UDMA2,
|
||||
|
@ -292,7 +292,6 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = {
|
||||
.name = DRV_NAME,
|
||||
.init_iops = init_iops_cy82c693,
|
||||
.port_ops = &cy82c693_port_ops,
|
||||
.chipset = ide_cy82c693,
|
||||
.host_flags = IDE_HFLAG_SINGLE,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.swdma_mask = ATA_SWDMA2,
|
||||
|
@ -117,6 +117,10 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
|
||||
hw->chipset = ide_generic;
|
||||
}
|
||||
|
||||
static const struct ide_port_info gayle_port_info = {
|
||||
.host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA,
|
||||
};
|
||||
|
||||
/*
|
||||
* Probe for a Gayle IDE interface (and optionally for an IDE doubler)
|
||||
*/
|
||||
@ -178,7 +182,7 @@ found:
|
||||
hws[i] = &hw[i];
|
||||
}
|
||||
|
||||
rc = ide_host_add(NULL, hws, NULL);
|
||||
rc = ide_host_add(&gayle_port_info, hws, NULL);
|
||||
if (rc)
|
||||
release_mem_region(res_start, res_n);
|
||||
|
||||
|
@ -135,7 +135,6 @@
|
||||
/* various tuning parameters */
|
||||
#define HPT_RESET_STATE_ENGINE
|
||||
#undef HPT_DELAY_INTERRUPT
|
||||
#define HPT_SERIALIZE_IO 0
|
||||
|
||||
static const char *quirk_drives[] = {
|
||||
"QUANTUM FIREBALLlct08 08",
|
||||
@ -1288,7 +1287,6 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
|
||||
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
|
||||
{
|
||||
struct hpt_info *info = hpt3xx_get_info(hwif->dev);
|
||||
int serialize = HPT_SERIALIZE_IO;
|
||||
u8 chip_type = info->chip_type;
|
||||
|
||||
/* Cache the channel's MISC. control registers' offset */
|
||||
@ -1305,13 +1303,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
|
||||
* Clock is shared between the channels,
|
||||
* so we'll have to serialize them... :-(
|
||||
*/
|
||||
serialize = 1;
|
||||
hwif->host->host_flags |= IDE_HFLAG_SERIALIZE;
|
||||
hwif->rw_disk = &hpt3xxn_rw_disk;
|
||||
}
|
||||
|
||||
/* Serialize access to this device if needed */
|
||||
if (serialize && hwif->mate)
|
||||
hwif->serialized = hwif->mate->serialized = 1;
|
||||
}
|
||||
|
||||
static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
|
||||
|
@ -615,10 +615,10 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
|
||||
in_params[0].buffer.length = sizeof(struct GTM_buffer);
|
||||
in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm;
|
||||
in_params[1].type = ACPI_TYPE_BUFFER;
|
||||
in_params[1].buffer.length = sizeof(ATA_ID_WORDS * 2);
|
||||
in_params[1].buffer.length = ATA_ID_WORDS * 2;
|
||||
in_params[1].buffer.pointer = (u8 *)&master->idbuff;
|
||||
in_params[2].type = ACPI_TYPE_BUFFER;
|
||||
in_params[2].buffer.length = sizeof(ATA_ID_WORDS * 2);
|
||||
in_params[2].buffer.length = ATA_ID_WORDS * 2;
|
||||
in_params[2].buffer.pointer = (u8 *)&slave->idbuff;
|
||||
/* Output buffer: _STM has no output */
|
||||
|
||||
|
@ -262,7 +262,6 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
|
||||
struct request *failed = (struct request *) rq->buffer;
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
void *sense = &info->sense_data;
|
||||
unsigned long flags;
|
||||
|
||||
if (failed) {
|
||||
if (failed->sense) {
|
||||
@ -278,11 +277,9 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
|
||||
failed->hard_nr_sectors))
|
||||
BUG();
|
||||
} else {
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
if (__blk_end_request(failed, -EIO,
|
||||
failed->data_len))
|
||||
if (blk_end_request(failed, -EIO,
|
||||
failed->data_len))
|
||||
BUG();
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
}
|
||||
} else
|
||||
cdrom_analyze_sense_data(drive, NULL, sense);
|
||||
@ -317,7 +314,8 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
|
||||
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct request *rq = hwif->hwgroup->rq;
|
||||
ide_hwgroup_t *hwgroup = hwif->hwgroup;
|
||||
struct request *rq = hwgroup->rq;
|
||||
int stat, err, sense_key;
|
||||
|
||||
/* check for errors */
|
||||
@ -426,16 +424,17 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
|
||||
if (time_after(jiffies, info->write_timeout))
|
||||
do_end_request = 1;
|
||||
else {
|
||||
struct request_queue *q = drive->queue;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* take a breather relying on the unplug
|
||||
* timer to kick us again
|
||||
*/
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
blk_plug_device(drive->queue);
|
||||
spin_unlock_irqrestore(&ide_lock,
|
||||
flags);
|
||||
spin_lock_irqsave(q->queue_lock, flags);
|
||||
blk_plug_device(q);
|
||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -504,12 +503,14 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
|
||||
|
||||
end_request:
|
||||
if (stat & ATA_ERR) {
|
||||
struct request_queue *q = drive->queue;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
spin_lock_irqsave(q->queue_lock, flags);
|
||||
blkdev_dequeue_request(rq);
|
||||
HWGROUP(drive)->rq = NULL;
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
||||
|
||||
hwgroup->rq = NULL;
|
||||
|
||||
cdrom_queue_request_sense(drive, rq->sense, rq);
|
||||
} else
|
||||
@ -773,52 +774,6 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
|
||||
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
|
||||
}
|
||||
|
||||
#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
|
||||
#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
|
||||
#define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */
|
||||
|
||||
static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
|
||||
{
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
int stat;
|
||||
static int retry = 10;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
if (cdrom_decode_status(drive, 0, &stat))
|
||||
return ide_stopped;
|
||||
|
||||
drive->atapi_flags |= IDE_AFLAG_SEEKING;
|
||||
|
||||
if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
|
||||
if (--retry == 0)
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
}
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
sector_t frame = rq->sector;
|
||||
|
||||
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
|
||||
|
||||
sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
|
||||
|
||||
memset(rq->cmd, 0, BLK_MAX_CDB);
|
||||
rq->cmd[0] = GPCMD_SEEK;
|
||||
put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
|
||||
|
||||
rq->timeout = ATAPI_WAIT_PC;
|
||||
}
|
||||
|
||||
static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
|
||||
{
|
||||
struct request *rq = drive->hwif->hwgroup->rq;
|
||||
|
||||
return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up a possibly partially-processed request so that we can start it over
|
||||
* entirely, or even put it back on the request queue.
|
||||
@ -950,7 +905,8 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
|
||||
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct request *rq = HWGROUP(drive)->rq;
|
||||
ide_hwgroup_t *hwgroup = hwif->hwgroup;
|
||||
struct request *rq = hwgroup->rq;
|
||||
xfer_func_t *xferfunc;
|
||||
ide_expiry_t *expiry = NULL;
|
||||
int dma_error = 0, dma, stat, thislen, uptodate = 0;
|
||||
@ -1148,17 +1104,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
|
||||
|
||||
end_request:
|
||||
if (blk_pc_request(rq)) {
|
||||
unsigned long flags;
|
||||
unsigned int dlen = rq->data_len;
|
||||
|
||||
if (dma)
|
||||
rq->data_len = 0;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
if (__blk_end_request(rq, 0, dlen))
|
||||
if (blk_end_request(rq, 0, dlen))
|
||||
BUG();
|
||||
HWGROUP(drive)->rq = NULL;
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
|
||||
hwgroup->rq = NULL;
|
||||
} else {
|
||||
if (!uptodate)
|
||||
rq->cmd_flags |= REQ_FAILED;
|
||||
@ -1260,7 +1214,6 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
|
||||
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
|
||||
sector_t block)
|
||||
{
|
||||
struct cdrom_info *info = drive->driver_data;
|
||||
ide_handler_t *fn;
|
||||
int xferlen;
|
||||
|
||||
@ -1270,44 +1223,14 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
|
||||
(unsigned long long)block);
|
||||
|
||||
if (blk_fs_request(rq)) {
|
||||
if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
unsigned long elapsed = jiffies - info->start_seek;
|
||||
int stat = hwif->tp_ops->read_status(hwif);
|
||||
xferlen = 32768;
|
||||
fn = cdrom_start_rw_cont;
|
||||
|
||||
if ((stat & ATA_DSC) != ATA_DSC) {
|
||||
if (elapsed < IDECD_SEEK_TIMEOUT) {
|
||||
ide_stall_queue(drive,
|
||||
IDECD_SEEK_TIMER);
|
||||
return ide_stopped;
|
||||
}
|
||||
printk(KERN_ERR PFX "%s: DSC timeout\n",
|
||||
drive->name);
|
||||
}
|
||||
drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
|
||||
}
|
||||
if (rq_data_dir(rq) == READ &&
|
||||
IDE_LARGE_SEEK(info->last_block, block,
|
||||
IDECD_SEEK_THRESHOLD) &&
|
||||
(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)) {
|
||||
xferlen = 0;
|
||||
fn = cdrom_start_seek_continuation;
|
||||
if (cdrom_start_rw(drive, rq) == ide_stopped)
|
||||
return ide_stopped;
|
||||
|
||||
drive->dma = 0;
|
||||
info->start_seek = jiffies;
|
||||
|
||||
ide_cd_prepare_seek_request(drive, rq);
|
||||
} else {
|
||||
xferlen = 32768;
|
||||
fn = cdrom_start_rw_cont;
|
||||
|
||||
if (cdrom_start_rw(drive, rq) == ide_stopped)
|
||||
return ide_stopped;
|
||||
|
||||
if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
|
||||
return ide_stopped;
|
||||
}
|
||||
info->last_block = block;
|
||||
if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
|
||||
return ide_stopped;
|
||||
} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
|
||||
rq->cmd_type == REQ_TYPE_ATA_PC) {
|
||||
xferlen = rq->data_len;
|
||||
@ -1908,13 +1831,6 @@ static ide_proc_entry_t idecd_proc[] = {
|
||||
{ NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
|
||||
|
||||
static const struct ide_proc_devset idecd_settings[] = {
|
||||
IDE_PROC_DEVSET(dsc_overlap, 0, 1),
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive)
|
||||
{
|
||||
return idecd_proc;
|
||||
@ -1922,7 +1838,7 @@ static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive)
|
||||
|
||||
static const struct ide_proc_devset *ide_cd_proc_devsets(ide_drive_t *drive)
|
||||
{
|
||||
return idecd_settings;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2022,11 +1938,6 @@ static int ide_cdrom_setup(ide_drive_t *drive)
|
||||
/* set correct block size */
|
||||
blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
|
||||
|
||||
if (drive->next != drive)
|
||||
drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
|
||||
else
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
|
||||
if (ide_cdrom_register(drive, nslots)) {
|
||||
printk(KERN_ERR PFX "%s: %s failed to register device with the"
|
||||
" cdrom driver.\n", drive->name, __func__);
|
||||
@ -2063,7 +1974,6 @@ static void ide_cd_release(struct kref *kref)
|
||||
kfree(info->toc);
|
||||
if (devinfo->handle == drive)
|
||||
unregister_cdrom(devinfo);
|
||||
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
|
||||
drive->driver_data = NULL;
|
||||
blk_queue_prep_rq(drive->queue, NULL);
|
||||
g->private_data = NULL;
|
||||
|
@ -88,8 +88,6 @@ struct cdrom_info {
|
||||
struct request_sense sense_data;
|
||||
|
||||
struct request request_sense_request;
|
||||
unsigned long last_block;
|
||||
unsigned long start_seek;
|
||||
|
||||
u8 max_speed; /* Max speed of the drive. */
|
||||
u8 current_speed; /* Current speed of the drive. */
|
||||
|
@ -98,10 +98,10 @@ int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
__le32 *table = (__le32 *)hwif->dmatable_cpu;
|
||||
unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
|
||||
unsigned int count = 0;
|
||||
int i;
|
||||
struct scatterlist *sg;
|
||||
u8 is_trm290 = !!(hwif->host_flags & IDE_HFLAG_TRM290);
|
||||
|
||||
hwif->sg_nents = ide_build_sglist(drive, rq);
|
||||
if (hwif->sg_nents == 0)
|
||||
@ -176,15 +176,10 @@ int ide_dma_setup(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct request *rq = hwif->hwgroup->rq;
|
||||
unsigned int reading;
|
||||
unsigned int reading = rq_data_dir(rq) ? 0 : ATA_DMA_WR;
|
||||
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
|
||||
u8 dma_stat;
|
||||
|
||||
if (rq_data_dir(rq))
|
||||
reading = 0;
|
||||
else
|
||||
reading = 1 << 3;
|
||||
|
||||
/* fall back to pio! */
|
||||
if (!ide_build_dmatable(drive, rq)) {
|
||||
ide_map_sg(drive, rq);
|
||||
@ -209,10 +204,11 @@ int ide_dma_setup(ide_drive_t *drive)
|
||||
|
||||
/* clear INTR & ERROR flags */
|
||||
if (mmio)
|
||||
writeb(dma_stat | 6,
|
||||
writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
|
||||
else
|
||||
outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
|
||||
outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
|
||||
hwif->dma_base + ATA_DMA_STATUS);
|
||||
|
||||
drive->waiting_for_dma = 1;
|
||||
return 0;
|
||||
@ -246,14 +242,13 @@ static int dma_timer_expiry(ide_drive_t *drive)
|
||||
|
||||
hwif->hwgroup->expiry = NULL; /* one free ride for now */
|
||||
|
||||
/* 1 dmaing, 2 error, 4 intr */
|
||||
if (dma_stat & 2) /* ERROR */
|
||||
if (dma_stat & ATA_DMA_ERR) /* ERROR */
|
||||
return -1;
|
||||
|
||||
if (dma_stat & 1) /* DMAing */
|
||||
if (dma_stat & ATA_DMA_ACTIVE) /* DMAing */
|
||||
return WAIT_CMD;
|
||||
|
||||
if (dma_stat & 4) /* Got an Interrupt */
|
||||
if (dma_stat & ATA_DMA_INTR) /* Got an Interrupt */
|
||||
return WAIT_CMD;
|
||||
|
||||
return 0; /* Status is unknown -- reset the bus */
|
||||
@ -279,12 +274,11 @@ void ide_dma_start(ide_drive_t *drive)
|
||||
*/
|
||||
if (hwif->host_flags & IDE_HFLAG_MMIO) {
|
||||
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
/* start DMA */
|
||||
writeb(dma_cmd | 1,
|
||||
writeb(dma_cmd | ATA_DMA_START,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
} else {
|
||||
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
|
||||
outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
|
||||
outb(dma_cmd | ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
|
||||
}
|
||||
|
||||
wmb();
|
||||
@ -296,19 +290,18 @@ int ide_dma_end(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
|
||||
u8 dma_stat = 0, dma_cmd = 0;
|
||||
u8 dma_stat = 0, dma_cmd = 0, mask;
|
||||
|
||||
drive->waiting_for_dma = 0;
|
||||
|
||||
/* stop DMA */
|
||||
if (mmio) {
|
||||
/* get DMA command mode */
|
||||
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
/* stop DMA */
|
||||
writeb(dma_cmd & ~1,
|
||||
writeb(dma_cmd & ~ATA_DMA_START,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
|
||||
} else {
|
||||
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
|
||||
outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
|
||||
outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
|
||||
}
|
||||
|
||||
/* get DMA status */
|
||||
@ -316,16 +309,21 @@ int ide_dma_end(ide_drive_t *drive)
|
||||
|
||||
if (mmio)
|
||||
/* clear the INTR & ERROR bits */
|
||||
writeb(dma_stat | 6,
|
||||
writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
|
||||
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
|
||||
else
|
||||
outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
|
||||
outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
|
||||
hwif->dma_base + ATA_DMA_STATUS);
|
||||
|
||||
/* purge DMA mappings */
|
||||
ide_destroy_dmatable(drive);
|
||||
/* verify good DMA status */
|
||||
wmb();
|
||||
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
|
||||
|
||||
/* verify good DMA status */
|
||||
mask = ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR;
|
||||
if ((dma_stat & mask) != ATA_DMA_INTR)
|
||||
return 0x10 | dma_stat;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_end);
|
||||
|
||||
@ -335,11 +333,7 @@ int ide_dma_test_irq(ide_drive_t *drive)
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
|
||||
|
||||
/* return 1 if INTR asserted */
|
||||
if ((dma_stat & 4) == 4)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return (dma_stat & ATA_DMA_INTR) ? 1 : 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_dma_test_irq);
|
||||
|
||||
|
@ -84,11 +84,11 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
|
||||
ide_dma_on(drive);
|
||||
}
|
||||
|
||||
if (!__blk_end_request(rq, error, nr_bytes)) {
|
||||
if (dequeue)
|
||||
HWGROUP(drive)->rq = NULL;
|
||||
if (!blk_end_request(rq, error, nr_bytes))
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (ret == 0 && dequeue)
|
||||
drive->hwif->hwgroup->rq = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -107,16 +107,7 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
|
||||
int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
|
||||
{
|
||||
unsigned int nr_bytes = nr_sectors << 9;
|
||||
struct request *rq;
|
||||
unsigned long flags;
|
||||
int ret = 1;
|
||||
|
||||
/*
|
||||
* room for locking improvements here, the calls below don't
|
||||
* need the queue lock held at all
|
||||
*/
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
rq = HWGROUP(drive)->rq;
|
||||
struct request *rq = drive->hwif->hwgroup->rq;
|
||||
|
||||
if (!nr_bytes) {
|
||||
if (blk_pc_request(rq))
|
||||
@ -125,105 +116,10 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
|
||||
nr_bytes = rq->hard_cur_sectors << 9;
|
||||
}
|
||||
|
||||
ret = __ide_end_request(drive, rq, uptodate, nr_bytes, 1);
|
||||
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return ret;
|
||||
return __ide_end_request(drive, rq, uptodate, nr_bytes, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(ide_end_request);
|
||||
|
||||
static void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct request_pm_state *pm = rq->data;
|
||||
|
||||
#ifdef DEBUG_PM
|
||||
printk(KERN_INFO "%s: complete_power_step(step: %d)\n",
|
||||
drive->name, pm->pm_step);
|
||||
#endif
|
||||
if (drive->media != ide_disk)
|
||||
return;
|
||||
|
||||
switch (pm->pm_step) {
|
||||
case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
|
||||
if (pm->pm_state == PM_EVENT_FREEZE)
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
else
|
||||
pm->pm_step = IDE_PM_STANDBY;
|
||||
break;
|
||||
case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
break;
|
||||
case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
|
||||
pm->pm_step = IDE_PM_IDLE;
|
||||
break;
|
||||
case IDE_PM_IDLE: /* Resume step 2 (idle)*/
|
||||
pm->pm_step = IDE_PM_RESTORE_DMA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct request_pm_state *pm = rq->data;
|
||||
ide_task_t *args = rq->special;
|
||||
|
||||
memset(args, 0, sizeof(*args));
|
||||
|
||||
switch (pm->pm_step) {
|
||||
case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
|
||||
if (drive->media != ide_disk)
|
||||
break;
|
||||
/* Not supported? Switch to next step now. */
|
||||
if (ata_id_flush_enabled(drive->id) == 0 ||
|
||||
(drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
|
||||
ide_complete_power_step(drive, rq);
|
||||
return ide_stopped;
|
||||
}
|
||||
if (ata_id_flush_ext_enabled(drive->id))
|
||||
args->tf.command = ATA_CMD_FLUSH_EXT;
|
||||
else
|
||||
args->tf.command = ATA_CMD_FLUSH;
|
||||
goto out_do_tf;
|
||||
case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
|
||||
args->tf.command = ATA_CMD_STANDBYNOW1;
|
||||
goto out_do_tf;
|
||||
case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
|
||||
ide_set_max_pio(drive);
|
||||
/*
|
||||
* skip IDE_PM_IDLE for ATAPI devices
|
||||
*/
|
||||
if (drive->media != ide_disk)
|
||||
pm->pm_step = IDE_PM_RESTORE_DMA;
|
||||
else
|
||||
ide_complete_power_step(drive, rq);
|
||||
return ide_stopped;
|
||||
case IDE_PM_IDLE: /* Resume step 2 (idle) */
|
||||
args->tf.command = ATA_CMD_IDLEIMMEDIATE;
|
||||
goto out_do_tf;
|
||||
case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
|
||||
/*
|
||||
* Right now, all we do is call ide_set_dma(drive),
|
||||
* we could be smarter and check for current xfer_speed
|
||||
* in struct drive etc...
|
||||
*/
|
||||
if (drive->hwif->dma_ops == NULL)
|
||||
break;
|
||||
/*
|
||||
* TODO: respect IDE_DFLAG_USING_DMA
|
||||
*/
|
||||
ide_set_dma(drive);
|
||||
break;
|
||||
}
|
||||
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
return ide_stopped;
|
||||
|
||||
out_do_tf:
|
||||
args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
args->data_phase = TASKFILE_NO_DATA;
|
||||
return do_rw_taskfile(drive, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_end_dequeued_request - complete an IDE I/O
|
||||
* @drive: IDE device for the I/O
|
||||
@ -242,48 +138,12 @@ out_do_tf:
|
||||
int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
|
||||
int uptodate, int nr_sectors)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
BUG_ON(!blk_rq_started(rq));
|
||||
ret = __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
|
||||
return ret;
|
||||
return __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_end_dequeued_request);
|
||||
|
||||
|
||||
/**
|
||||
* ide_complete_pm_request - end the current Power Management request
|
||||
* @drive: target drive
|
||||
* @rq: request
|
||||
*
|
||||
* This function cleans up the current PM request and stops the queue
|
||||
* if necessary.
|
||||
*/
|
||||
static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
#ifdef DEBUG_PM
|
||||
printk("%s: completing PM request, %s\n", drive->name,
|
||||
blk_pm_suspend_request(rq) ? "suspend" : "resume");
|
||||
#endif
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
if (blk_pm_suspend_request(rq)) {
|
||||
blk_stop_queue(drive->queue);
|
||||
} else {
|
||||
drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
|
||||
blk_start_queue(drive->queue);
|
||||
}
|
||||
HWGROUP(drive)->rq = NULL;
|
||||
if (__blk_end_request(rq, 0, 0))
|
||||
BUG();
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_end_drive_cmd - end an explicit drive command
|
||||
* @drive: command
|
||||
@ -300,19 +160,12 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
|
||||
|
||||
void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct request *rq;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
rq = HWGROUP(drive)->rq;
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
struct request *rq = hwgroup->rq;
|
||||
|
||||
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
|
||||
ide_task_t *task = (ide_task_t *)rq->special;
|
||||
|
||||
if (rq->errors == 0)
|
||||
rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT);
|
||||
|
||||
if (task) {
|
||||
struct ide_taskfile *tf = &task->tf;
|
||||
|
||||
@ -333,15 +186,14 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
HWGROUP(drive)->rq = NULL;
|
||||
rq->errors = err;
|
||||
if (unlikely(__blk_end_request(rq, (rq->errors ? -EIO : 0),
|
||||
blk_rq_bytes(rq))))
|
||||
BUG();
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
}
|
||||
hwgroup->rq = NULL;
|
||||
|
||||
rq->errors = err;
|
||||
|
||||
if (unlikely(blk_end_request(rq, (rq->errors ? -EIO : 0),
|
||||
blk_rq_bytes(rq))))
|
||||
BUG();
|
||||
}
|
||||
EXPORT_SYMBOL(ide_end_drive_cmd);
|
||||
|
||||
static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
|
||||
@ -720,40 +572,6 @@ static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
|
||||
}
|
||||
}
|
||||
|
||||
static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct request_pm_state *pm = rq->data;
|
||||
|
||||
if (blk_pm_suspend_request(rq) &&
|
||||
pm->pm_step == IDE_PM_START_SUSPEND)
|
||||
/* Mark drive blocked when starting the suspend sequence. */
|
||||
drive->dev_flags |= IDE_DFLAG_BLOCKED;
|
||||
else if (blk_pm_resume_request(rq) &&
|
||||
pm->pm_step == IDE_PM_START_RESUME) {
|
||||
/*
|
||||
* The first thing we do on wakeup is to wait for BSY bit to
|
||||
* go away (with a looong timeout) as a drive on this hwif may
|
||||
* just be POSTing itself.
|
||||
* We do that before even selecting as the "other" device on
|
||||
* the bus may be broken enough to walk on our toes at this
|
||||
* point.
|
||||
*/
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
int rc;
|
||||
#ifdef DEBUG_PM
|
||||
printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
|
||||
#endif
|
||||
rc = ide_wait_not_busy(hwif, 35000);
|
||||
if (rc)
|
||||
printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
|
||||
SELECT_DRIVE(drive);
|
||||
hwif->tp_ops->set_irq(hwif, 1);
|
||||
rc = ide_wait_not_busy(hwif, 100000);
|
||||
if (rc)
|
||||
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* start_request - start of I/O and command issuing for IDE
|
||||
*
|
||||
@ -927,7 +745,7 @@ repeat:
|
||||
|
||||
/*
|
||||
* Issue a new request to a drive from hwgroup
|
||||
* Caller must have already done spin_lock_irqsave(&ide_lock, ..);
|
||||
* Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..);
|
||||
*
|
||||
* A hwgroup is a serialized group of IDE interfaces. Usually there is
|
||||
* exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
|
||||
@ -939,7 +757,7 @@ repeat:
|
||||
* possibly along with many other devices. This is especially common in
|
||||
* PCI-based systems with off-board IDE controller cards.
|
||||
*
|
||||
* The IDE driver uses the single global ide_lock spinlock to protect
|
||||
* The IDE driver uses a per-hwgroup spinlock to protect
|
||||
* access to the request queues, and to protect the hwgroup->busy flag.
|
||||
*
|
||||
* The first thread into the driver for a particular hwgroup sets the
|
||||
@ -955,7 +773,7 @@ repeat:
|
||||
* will start the next request from the queue. If no more work remains,
|
||||
* the driver will clear the hwgroup->busy flag and exit.
|
||||
*
|
||||
* The ide_lock (spinlock) is used to protect all access to the
|
||||
* The per-hwgroup spinlock is used to protect all access to the
|
||||
* hwgroup->busy flag, but is otherwise not needed for most processing in
|
||||
* the driver. This makes the driver much more friendlier to shared IRQs
|
||||
* than previous designs, while remaining 100% (?) SMP safe and capable.
|
||||
@ -968,7 +786,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
|
||||
ide_startstop_t startstop;
|
||||
int loops = 0;
|
||||
|
||||
/* caller must own ide_lock */
|
||||
/* caller must own hwgroup->lock */
|
||||
BUG_ON(!irqs_disabled());
|
||||
|
||||
while (!hwgroup->busy) {
|
||||
@ -1023,12 +841,12 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
|
||||
}
|
||||
again:
|
||||
hwif = HWIF(drive);
|
||||
if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) {
|
||||
if (hwif != hwgroup->hwif) {
|
||||
/*
|
||||
* set nIEN for previous hwif, drives in the
|
||||
* quirk_list may not like intr setups/cleanups
|
||||
*/
|
||||
if (drive->quirk_list != 1)
|
||||
if (drive->quirk_list == 0)
|
||||
hwif->tp_ops->set_irq(hwif, 0);
|
||||
}
|
||||
hwgroup->hwif = hwif;
|
||||
@ -1036,11 +854,6 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
|
||||
drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
|
||||
drive->service_start = jiffies;
|
||||
|
||||
if (blk_queue_plugged(drive->queue)) {
|
||||
printk(KERN_ERR "ide: huh? queue was plugged!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* we know that the queue isn't empty, but this can happen
|
||||
* if the q->prep_rq_fn() decides to kill a request
|
||||
@ -1090,11 +903,11 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
|
||||
*/
|
||||
if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
|
||||
disable_irq_nosync(hwif->irq);
|
||||
spin_unlock(&ide_lock);
|
||||
spin_unlock(&hwgroup->lock);
|
||||
local_irq_enable_in_hardirq();
|
||||
/* allow other IRQs while we start this request */
|
||||
startstop = start_request(drive, rq);
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
|
||||
enable_irq(hwif->irq);
|
||||
if (startstop == ide_stopped)
|
||||
@ -1192,7 +1005,7 @@ void ide_timer_expiry (unsigned long data)
|
||||
unsigned long flags;
|
||||
unsigned long wait = -1;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
spin_lock_irqsave(&hwgroup->lock, flags);
|
||||
|
||||
if (((handler = hwgroup->handler) == NULL) ||
|
||||
(hwgroup->req_gen != hwgroup->req_gen_timer)) {
|
||||
@ -1225,7 +1038,7 @@ void ide_timer_expiry (unsigned long data)
|
||||
hwgroup->timer.expires = jiffies + wait;
|
||||
hwgroup->req_gen_timer = hwgroup->req_gen;
|
||||
add_timer(&hwgroup->timer);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1235,7 +1048,7 @@ void ide_timer_expiry (unsigned long data)
|
||||
* the handler() function, which means we need to
|
||||
* globally mask the specific IRQ:
|
||||
*/
|
||||
spin_unlock(&ide_lock);
|
||||
spin_unlock(&hwgroup->lock);
|
||||
hwif = HWIF(drive);
|
||||
/* disable_irq_nosync ?? */
|
||||
disable_irq(hwif->irq);
|
||||
@ -1259,14 +1072,14 @@ void ide_timer_expiry (unsigned long data)
|
||||
hwif->tp_ops->read_status(hwif));
|
||||
}
|
||||
drive->service_time = jiffies - drive->service_start;
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
enable_irq(hwif->irq);
|
||||
if (startstop == ide_stopped)
|
||||
hwgroup->busy = 0;
|
||||
}
|
||||
}
|
||||
ide_do_request(hwgroup, IDE_NO_IRQ);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1359,18 +1172,16 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
|
||||
ide_hwif_t *hwif;
|
||||
ide_hwif_t *hwif = hwgroup->hwif;
|
||||
ide_drive_t *drive;
|
||||
ide_handler_t *handler;
|
||||
ide_startstop_t startstop;
|
||||
irqreturn_t irq_ret = IRQ_NONE;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
hwif = hwgroup->hwif;
|
||||
spin_lock_irqsave(&hwgroup->lock, flags);
|
||||
|
||||
if (!ide_ack_intr(hwif)) {
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
if (!ide_ack_intr(hwif))
|
||||
goto out;
|
||||
|
||||
if ((handler = hwgroup->handler) == NULL || hwgroup->polling) {
|
||||
/*
|
||||
@ -1406,9 +1217,9 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
(void)hwif->tp_ops->read_status(hwif);
|
||||
#endif /* CONFIG_BLK_DEV_IDEPCI */
|
||||
}
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return IRQ_NONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
drive = hwgroup->drive;
|
||||
if (!drive) {
|
||||
/*
|
||||
@ -1417,10 +1228,10 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
*
|
||||
* [Note - this can occur if the drive is hot unplugged]
|
||||
*/
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
goto out_handled;
|
||||
}
|
||||
if (!drive_is_ready(drive)) {
|
||||
|
||||
if (!drive_is_ready(drive))
|
||||
/*
|
||||
* This happens regularly when we share a PCI IRQ with
|
||||
* another device. Unfortunately, it can also happen
|
||||
@ -1428,9 +1239,8 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
* their status register is up to date. Hopefully we have
|
||||
* enough advance overhead that the latter isn't a problem.
|
||||
*/
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
goto out;
|
||||
|
||||
if (!hwgroup->busy) {
|
||||
hwgroup->busy = 1; /* paranoia */
|
||||
printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
|
||||
@ -1438,7 +1248,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
hwgroup->handler = NULL;
|
||||
hwgroup->req_gen++;
|
||||
del_timer(&hwgroup->timer);
|
||||
spin_unlock(&ide_lock);
|
||||
spin_unlock(&hwgroup->lock);
|
||||
|
||||
if (hwif->port_ops && hwif->port_ops->clear_irq)
|
||||
hwif->port_ops->clear_irq(drive);
|
||||
@ -1449,7 +1259,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
/* service this interrupt, may set handler for next interrupt */
|
||||
startstop = handler(drive);
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
/*
|
||||
* Note that handler() may have set things up for another
|
||||
* interrupt to occur soon, but it cannot happen until
|
||||
@ -1467,8 +1277,11 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
"on exit\n", drive->name);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
out_handled:
|
||||
irq_ret = IRQ_HANDLED;
|
||||
out:
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
return irq_ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1488,16 +1301,17 @@ irqreturn_t ide_intr (int irq, void *dev_id)
|
||||
|
||||
void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
struct request_queue *q = drive->queue;
|
||||
unsigned long flags;
|
||||
ide_hwgroup_t *hwgroup = HWGROUP(drive);
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
hwgroup->rq = NULL;
|
||||
__elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
|
||||
blk_start_queueing(drive->queue);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(q->queue_lock, flags);
|
||||
__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
|
||||
blk_start_queueing(q);
|
||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(ide_do_drive_cmd);
|
||||
|
||||
void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
|
||||
|
@ -19,7 +19,6 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
|
||||
const struct ide_ioctl_devset *s)
|
||||
{
|
||||
const struct ide_devset *ds;
|
||||
unsigned long flags;
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
for (; (ds = s->setting); s++) {
|
||||
@ -33,9 +32,7 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
|
||||
|
||||
read_val:
|
||||
mutex_lock(&ide_setting_mtx);
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
err = ds->get(drive);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
mutex_unlock(&ide_setting_mtx);
|
||||
return err >= 0 ? put_user(err, (long __user *)arg) : err;
|
||||
|
||||
@ -98,7 +95,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
|
||||
return -EPERM;
|
||||
|
||||
if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
|
||||
(drive->media == ide_disk || drive->media == ide_floppy ||
|
||||
(drive->media != ide_tape ||
|
||||
(drive->dev_flags & IDE_DFLAG_SCSI)))
|
||||
return -EPERM;
|
||||
|
||||
|
@ -835,10 +835,12 @@ static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
|
||||
void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
|
||||
unsigned int timeout, ide_expiry_t *expiry)
|
||||
{
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&hwgroup->lock, flags);
|
||||
__ide_set_handler(drive, handler, timeout, expiry);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_set_handler);
|
||||
@ -860,10 +862,11 @@ EXPORT_SYMBOL(ide_set_handler);
|
||||
void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
|
||||
unsigned timeout, ide_expiry_t *expiry)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
ide_hwgroup_t *hwgroup = hwif->hwgroup;
|
||||
unsigned long flags;
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
spin_lock_irqsave(&hwgroup->lock, flags);
|
||||
__ide_set_handler(drive, handler, timeout, expiry);
|
||||
hwif->tp_ops->exec_command(hwif, cmd);
|
||||
/*
|
||||
@ -873,19 +876,20 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
|
||||
* FIXME: we could skip this delay with care on non shared devices
|
||||
*/
|
||||
ndelay(400);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(ide_execute_command);
|
||||
|
||||
void ide_execute_pkt_cmd(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
ide_hwgroup_t *hwgroup = hwif->hwgroup;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
spin_lock_irqsave(&hwgroup->lock, flags);
|
||||
hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET);
|
||||
ndelay(400);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
|
||||
|
||||
@ -1076,22 +1080,16 @@ static void pre_reset(ide_drive_t *drive)
|
||||
*/
|
||||
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
||||
{
|
||||
unsigned int unit;
|
||||
unsigned long flags, timeout;
|
||||
ide_hwif_t *hwif;
|
||||
ide_hwgroup_t *hwgroup;
|
||||
struct ide_io_ports *io_ports;
|
||||
const struct ide_tp_ops *tp_ops;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
ide_hwgroup_t *hwgroup = hwif->hwgroup;
|
||||
struct ide_io_ports *io_ports = &hwif->io_ports;
|
||||
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
|
||||
const struct ide_port_ops *port_ops;
|
||||
unsigned long flags, timeout;
|
||||
unsigned int unit;
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
hwif = HWIF(drive);
|
||||
hwgroup = HWGROUP(drive);
|
||||
|
||||
io_ports = &hwif->io_ports;
|
||||
|
||||
tp_ops = hwif->tp_ops;
|
||||
spin_lock_irqsave(&hwgroup->lock, flags);
|
||||
|
||||
/* We must not reset with running handlers */
|
||||
BUG_ON(hwgroup->handler != NULL);
|
||||
@ -1106,7 +1104,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
||||
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
|
||||
hwgroup->polling = 1;
|
||||
__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
return ide_started;
|
||||
}
|
||||
|
||||
@ -1129,9 +1127,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
||||
if (time_before_eq(timeout, now))
|
||||
break;
|
||||
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
timeout = schedule_timeout_uninterruptible(timeout - now);
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
spin_lock_irqsave(&hwgroup->lock, flags);
|
||||
} while (timeout);
|
||||
finish_wait(&ide_park_wq, &wait);
|
||||
|
||||
@ -1143,7 +1141,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
||||
pre_reset(&hwif->drives[unit]);
|
||||
|
||||
if (io_ports->ctl_addr == 0) {
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
ide_complete_drive_reset(drive, -ENXIO);
|
||||
return ide_stopped;
|
||||
}
|
||||
@ -1179,7 +1177,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
||||
if (port_ops && port_ops->resetproc)
|
||||
port_ops->resetproc(drive);
|
||||
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
return ide_started;
|
||||
}
|
||||
|
||||
|
58
drivers/ide/ide-legacy.c
Normal file
58
drivers/ide/ide-legacy.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ide.h>
|
||||
|
||||
static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
|
||||
u8 port_no, const struct ide_port_info *d,
|
||||
unsigned long config)
|
||||
{
|
||||
unsigned long base, ctl;
|
||||
int irq;
|
||||
|
||||
if (port_no == 0) {
|
||||
base = 0x1f0;
|
||||
ctl = 0x3f6;
|
||||
irq = 14;
|
||||
} else {
|
||||
base = 0x170;
|
||||
ctl = 0x376;
|
||||
irq = 15;
|
||||
}
|
||||
|
||||
if (!request_region(base, 8, d->name)) {
|
||||
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
|
||||
d->name, base, base + 7);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!request_region(ctl, 1, d->name)) {
|
||||
printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
|
||||
d->name, ctl);
|
||||
release_region(base, 8);
|
||||
return;
|
||||
}
|
||||
|
||||
ide_std_init_ports(hw, base, ctl);
|
||||
hw->irq = irq;
|
||||
hw->chipset = d->chipset;
|
||||
hw->config = config;
|
||||
|
||||
hws[port_no] = hw;
|
||||
}
|
||||
|
||||
int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
|
||||
{
|
||||
hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
|
||||
|
||||
memset(&hw, 0, sizeof(hw));
|
||||
|
||||
if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
|
||||
ide_legacy_init_one(hws, &hw[0], 0, d, config);
|
||||
ide_legacy_init_one(hws, &hw[1], 1, d, config);
|
||||
|
||||
if (hws[0] == NULL && hws[1] == NULL &&
|
||||
(d->host_flags & IDE_HFLAG_SINGLE))
|
||||
return -ENOENT;
|
||||
|
||||
return ide_host_add(d, hws, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_legacy_device_add);
|
@ -43,7 +43,6 @@ const char *ide_xfer_verbose(u8 mode)
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_xfer_verbose);
|
||||
|
||||
/**
|
||||
@ -87,7 +86,7 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
|
||||
* This is used by most chipset support modules when "auto-tuning".
|
||||
*/
|
||||
|
||||
u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
|
||||
u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
|
||||
{
|
||||
u16 *id = drive->id;
|
||||
int pio_mode = -1, overridden = 0;
|
||||
@ -131,7 +130,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
|
||||
|
||||
return pio_mode;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
|
||||
|
||||
/* req_pio == "255" for auto-tune */
|
||||
@ -162,7 +160,6 @@ void ide_set_pio(ide_drive_t *drive, u8 req_pio)
|
||||
|
||||
(void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_set_pio);
|
||||
|
||||
/**
|
||||
@ -173,7 +170,7 @@ EXPORT_SYMBOL_GPL(ide_set_pio);
|
||||
* Enable or disable bounce buffering for the device. Drives move
|
||||
* between PIO and DMA and that changes the rules we need.
|
||||
*/
|
||||
|
||||
|
||||
void ide_toggle_bounce(ide_drive_t *drive, int on)
|
||||
{
|
||||
u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */
|
||||
@ -243,14 +240,13 @@ int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
|
||||
return ide_config_drive_speed(drive, mode);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(ide_set_dma_mode);
|
||||
|
||||
/**
|
||||
* ide_set_xfer_rate - set transfer rate
|
||||
* @drive: drive to set
|
||||
* @rate: speed to attempt to set
|
||||
*
|
||||
*
|
||||
* General helper for setting the speed of an IDE device. This
|
||||
* function knows about user enforced limits from the configuration
|
||||
* which ->set_pio_mode/->set_dma_mode does not.
|
||||
@ -277,21 +273,16 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
|
||||
|
||||
static void ide_dump_opcode(ide_drive_t *drive)
|
||||
{
|
||||
struct request *rq;
|
||||
struct request *rq = drive->hwif->hwgroup->rq;
|
||||
ide_task_t *task = NULL;
|
||||
|
||||
spin_lock(&ide_lock);
|
||||
rq = NULL;
|
||||
if (HWGROUP(drive))
|
||||
rq = HWGROUP(drive)->rq;
|
||||
spin_unlock(&ide_lock);
|
||||
if (!rq)
|
||||
return;
|
||||
|
||||
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
|
||||
task = rq->special;
|
||||
|
||||
printk("ide: failed opcode was: ");
|
||||
printk(KERN_ERR "ide: failed opcode was: ");
|
||||
if (task == NULL)
|
||||
printk(KERN_CONT "unknown\n");
|
||||
else
|
||||
@ -329,44 +320,55 @@ static void ide_dump_sector(ide_drive_t *drive)
|
||||
drive->hwif->tp_ops->tf_read(drive, &task);
|
||||
|
||||
if (lba48 || (tf->device & ATA_LBA))
|
||||
printk(", LBAsect=%llu",
|
||||
printk(KERN_CONT ", LBAsect=%llu",
|
||||
(unsigned long long)ide_get_lba_addr(tf, lba48));
|
||||
else
|
||||
printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
|
||||
tf->device & 0xf, tf->lbal);
|
||||
printk(KERN_CONT ", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
|
||||
tf->device & 0xf, tf->lbal);
|
||||
}
|
||||
|
||||
static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
|
||||
{
|
||||
printk("{ ");
|
||||
if (err & ATA_ABORTED) printk("DriveStatusError ");
|
||||
printk(KERN_ERR "{ ");
|
||||
if (err & ATA_ABORTED)
|
||||
printk(KERN_CONT "DriveStatusError ");
|
||||
if (err & ATA_ICRC)
|
||||
printk((err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
|
||||
if (err & ATA_UNC) printk("UncorrectableError ");
|
||||
if (err & ATA_IDNF) printk("SectorIdNotFound ");
|
||||
if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
|
||||
if (err & ATA_AMNF) printk("AddrMarkNotFound ");
|
||||
printk("}");
|
||||
printk(KERN_CONT "%s",
|
||||
(err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
|
||||
if (err & ATA_UNC)
|
||||
printk(KERN_CONT "UncorrectableError ");
|
||||
if (err & ATA_IDNF)
|
||||
printk(KERN_CONT "SectorIdNotFound ");
|
||||
if (err & ATA_TRK0NF)
|
||||
printk(KERN_CONT "TrackZeroNotFound ");
|
||||
if (err & ATA_AMNF)
|
||||
printk(KERN_CONT "AddrMarkNotFound ");
|
||||
printk(KERN_CONT "}");
|
||||
if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK ||
|
||||
(err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) {
|
||||
ide_dump_sector(drive);
|
||||
if (HWGROUP(drive) && HWGROUP(drive)->rq)
|
||||
printk(", sector=%llu",
|
||||
printk(KERN_CONT ", sector=%llu",
|
||||
(unsigned long long)HWGROUP(drive)->rq->sector);
|
||||
}
|
||||
printk("\n");
|
||||
printk(KERN_CONT "\n");
|
||||
}
|
||||
|
||||
static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
|
||||
{
|
||||
printk("{ ");
|
||||
if (err & ATAPI_ILI) printk("IllegalLengthIndication ");
|
||||
if (err & ATAPI_EOM) printk("EndOfMedia ");
|
||||
if (err & ATA_ABORTED) printk("AbortedCommand ");
|
||||
if (err & ATA_MCR) printk("MediaChangeRequested ");
|
||||
if (err & ATAPI_LFS) printk("LastFailedSense=0x%02x ",
|
||||
(err & ATAPI_LFS) >> 4);
|
||||
printk("}\n");
|
||||
printk(KERN_ERR "{ ");
|
||||
if (err & ATAPI_ILI)
|
||||
printk(KERN_CONT "IllegalLengthIndication ");
|
||||
if (err & ATAPI_EOM)
|
||||
printk(KERN_CONT "EndOfMedia ");
|
||||
if (err & ATA_ABORTED)
|
||||
printk(KERN_CONT "AbortedCommand ");
|
||||
if (err & ATA_MCR)
|
||||
printk(KERN_CONT "MediaChangeRequested ");
|
||||
if (err & ATAPI_LFS)
|
||||
printk(KERN_CONT "LastFailedSense=0x%02x ",
|
||||
(err & ATAPI_LFS) >> 4);
|
||||
printk(KERN_CONT "}\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -382,34 +384,37 @@ static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
|
||||
|
||||
u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 err = 0;
|
||||
|
||||
local_irq_save(flags);
|
||||
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
|
||||
printk(KERN_ERR "%s: %s: status=0x%02x { ", drive->name, msg, stat);
|
||||
if (stat & ATA_BUSY)
|
||||
printk("Busy ");
|
||||
printk(KERN_CONT "Busy ");
|
||||
else {
|
||||
if (stat & ATA_DRDY) printk("DriveReady ");
|
||||
if (stat & ATA_DF) printk("DeviceFault ");
|
||||
if (stat & ATA_DSC) printk("SeekComplete ");
|
||||
if (stat & ATA_DRQ) printk("DataRequest ");
|
||||
if (stat & ATA_CORR) printk("CorrectedError ");
|
||||
if (stat & ATA_IDX) printk("Index ");
|
||||
if (stat & ATA_ERR) printk("Error ");
|
||||
if (stat & ATA_DRDY)
|
||||
printk(KERN_CONT "DriveReady ");
|
||||
if (stat & ATA_DF)
|
||||
printk(KERN_CONT "DeviceFault ");
|
||||
if (stat & ATA_DSC)
|
||||
printk(KERN_CONT "SeekComplete ");
|
||||
if (stat & ATA_DRQ)
|
||||
printk(KERN_CONT "DataRequest ");
|
||||
if (stat & ATA_CORR)
|
||||
printk(KERN_CONT "CorrectedError ");
|
||||
if (stat & ATA_IDX)
|
||||
printk(KERN_CONT "Index ");
|
||||
if (stat & ATA_ERR)
|
||||
printk(KERN_CONT "Error ");
|
||||
}
|
||||
printk("}\n");
|
||||
printk(KERN_CONT "}\n");
|
||||
if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) {
|
||||
err = ide_read_error(drive);
|
||||
printk("%s: %s: error=0x%02x ", drive->name, msg, err);
|
||||
printk(KERN_ERR "%s: %s: error=0x%02x ", drive->name, msg, err);
|
||||
if (drive->media == ide_disk)
|
||||
ide_dump_ata_error(drive, err);
|
||||
else
|
||||
ide_dump_atapi_error(drive, err);
|
||||
}
|
||||
ide_dump_opcode(drive);
|
||||
local_irq_restore(flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_dump_status);
|
||||
|
@ -7,17 +7,16 @@ DECLARE_WAIT_QUEUE_HEAD(ide_park_wq);
|
||||
|
||||
static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
|
||||
{
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
struct request_queue *q = drive->queue;
|
||||
struct request *rq;
|
||||
int rc;
|
||||
|
||||
timeout += jiffies;
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
if (drive->dev_flags & IDE_DFLAG_PARKED) {
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
int reset_timer;
|
||||
int reset_timer = time_before(timeout, drive->sleep);
|
||||
|
||||
reset_timer = time_before(timeout, drive->sleep);
|
||||
drive->sleep = timeout;
|
||||
wake_up_all(&ide_park_wq);
|
||||
if (reset_timer && hwgroup->sleeping &&
|
||||
@ -26,10 +25,10 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
|
||||
hwgroup->busy = 0;
|
||||
blk_start_queueing(q);
|
||||
}
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
|
||||
rq = blk_get_request(q, READ, __GFP_WAIT);
|
||||
rq->cmd[0] = REQ_PARK_HEADS;
|
||||
@ -62,20 +61,21 @@ ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ide_drive_t *drive = to_ide_device(dev);
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
unsigned long now;
|
||||
unsigned int msecs;
|
||||
|
||||
if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
now = jiffies;
|
||||
if (drive->dev_flags & IDE_DFLAG_PARKED &&
|
||||
time_after(drive->sleep, now))
|
||||
msecs = jiffies_to_msecs(drive->sleep - now);
|
||||
else
|
||||
msecs = 0;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
|
||||
return snprintf(buf, 20, "%u\n", msecs);
|
||||
}
|
||||
|
235
drivers/ide/ide-pm.c
Normal file
235
drivers/ide/ide-pm.c
Normal file
@ -0,0 +1,235 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/hdreg.h>
|
||||
|
||||
int generic_ide_suspend(struct device *dev, pm_message_t mesg)
|
||||
{
|
||||
ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct request *rq;
|
||||
struct request_pm_state rqpm;
|
||||
ide_task_t args;
|
||||
int ret;
|
||||
|
||||
/* call ACPI _GTM only once */
|
||||
if ((drive->dn & 1) == 0 || pair == NULL)
|
||||
ide_acpi_get_timing(hwif);
|
||||
|
||||
memset(&rqpm, 0, sizeof(rqpm));
|
||||
memset(&args, 0, sizeof(args));
|
||||
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
|
||||
rq->cmd_type = REQ_TYPE_PM_SUSPEND;
|
||||
rq->special = &args;
|
||||
rq->data = &rqpm;
|
||||
rqpm.pm_step = IDE_PM_START_SUSPEND;
|
||||
if (mesg.event == PM_EVENT_PRETHAW)
|
||||
mesg.event = PM_EVENT_FREEZE;
|
||||
rqpm.pm_state = mesg.event;
|
||||
|
||||
ret = blk_execute_rq(drive->queue, NULL, rq, 0);
|
||||
blk_put_request(rq);
|
||||
|
||||
/* call ACPI _PS3 only after both devices are suspended */
|
||||
if (ret == 0 && ((drive->dn & 1) || pair == NULL))
|
||||
ide_acpi_set_state(hwif, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int generic_ide_resume(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct request *rq;
|
||||
struct request_pm_state rqpm;
|
||||
ide_task_t args;
|
||||
int err;
|
||||
|
||||
/* call ACPI _PS0 / _STM only once */
|
||||
if ((drive->dn & 1) == 0 || pair == NULL) {
|
||||
ide_acpi_set_state(hwif, 1);
|
||||
ide_acpi_push_timing(hwif);
|
||||
}
|
||||
|
||||
ide_acpi_exec_tfs(drive);
|
||||
|
||||
memset(&rqpm, 0, sizeof(rqpm));
|
||||
memset(&args, 0, sizeof(args));
|
||||
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
|
||||
rq->cmd_type = REQ_TYPE_PM_RESUME;
|
||||
rq->cmd_flags |= REQ_PREEMPT;
|
||||
rq->special = &args;
|
||||
rq->data = &rqpm;
|
||||
rqpm.pm_step = IDE_PM_START_RESUME;
|
||||
rqpm.pm_state = PM_EVENT_ON;
|
||||
|
||||
err = blk_execute_rq(drive->queue, NULL, rq, 1);
|
||||
blk_put_request(rq);
|
||||
|
||||
if (err == 0 && dev->driver) {
|
||||
ide_driver_t *drv = to_ide_driver(dev->driver);
|
||||
|
||||
if (drv->resume)
|
||||
drv->resume(drive);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct request_pm_state *pm = rq->data;
|
||||
|
||||
#ifdef DEBUG_PM
|
||||
printk(KERN_INFO "%s: complete_power_step(step: %d)\n",
|
||||
drive->name, pm->pm_step);
|
||||
#endif
|
||||
if (drive->media != ide_disk)
|
||||
return;
|
||||
|
||||
switch (pm->pm_step) {
|
||||
case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
|
||||
if (pm->pm_state == PM_EVENT_FREEZE)
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
else
|
||||
pm->pm_step = IDE_PM_STANDBY;
|
||||
break;
|
||||
case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
break;
|
||||
case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
|
||||
pm->pm_step = IDE_PM_IDLE;
|
||||
break;
|
||||
case IDE_PM_IDLE: /* Resume step 2 (idle)*/
|
||||
pm->pm_step = IDE_PM_RESTORE_DMA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct request_pm_state *pm = rq->data;
|
||||
ide_task_t *args = rq->special;
|
||||
|
||||
memset(args, 0, sizeof(*args));
|
||||
|
||||
switch (pm->pm_step) {
|
||||
case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
|
||||
if (drive->media != ide_disk)
|
||||
break;
|
||||
/* Not supported? Switch to next step now. */
|
||||
if (ata_id_flush_enabled(drive->id) == 0 ||
|
||||
(drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
|
||||
ide_complete_power_step(drive, rq);
|
||||
return ide_stopped;
|
||||
}
|
||||
if (ata_id_flush_ext_enabled(drive->id))
|
||||
args->tf.command = ATA_CMD_FLUSH_EXT;
|
||||
else
|
||||
args->tf.command = ATA_CMD_FLUSH;
|
||||
goto out_do_tf;
|
||||
case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
|
||||
args->tf.command = ATA_CMD_STANDBYNOW1;
|
||||
goto out_do_tf;
|
||||
case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
|
||||
ide_set_max_pio(drive);
|
||||
/*
|
||||
* skip IDE_PM_IDLE for ATAPI devices
|
||||
*/
|
||||
if (drive->media != ide_disk)
|
||||
pm->pm_step = IDE_PM_RESTORE_DMA;
|
||||
else
|
||||
ide_complete_power_step(drive, rq);
|
||||
return ide_stopped;
|
||||
case IDE_PM_IDLE: /* Resume step 2 (idle) */
|
||||
args->tf.command = ATA_CMD_IDLEIMMEDIATE;
|
||||
goto out_do_tf;
|
||||
case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
|
||||
/*
|
||||
* Right now, all we do is call ide_set_dma(drive),
|
||||
* we could be smarter and check for current xfer_speed
|
||||
* in struct drive etc...
|
||||
*/
|
||||
if (drive->hwif->dma_ops == NULL)
|
||||
break;
|
||||
/*
|
||||
* TODO: respect IDE_DFLAG_USING_DMA
|
||||
*/
|
||||
ide_set_dma(drive);
|
||||
break;
|
||||
}
|
||||
|
||||
pm->pm_step = IDE_PM_COMPLETED;
|
||||
return ide_stopped;
|
||||
|
||||
out_do_tf:
|
||||
args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
|
||||
args->data_phase = TASKFILE_NO_DATA;
|
||||
return do_rw_taskfile(drive, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_complete_pm_request - end the current Power Management request
|
||||
* @drive: target drive
|
||||
* @rq: request
|
||||
*
|
||||
* This function cleans up the current PM request and stops the queue
|
||||
* if necessary.
|
||||
*/
|
||||
void ide_complete_pm_request(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct request_queue *q = drive->queue;
|
||||
unsigned long flags;
|
||||
|
||||
#ifdef DEBUG_PM
|
||||
printk("%s: completing PM request, %s\n", drive->name,
|
||||
blk_pm_suspend_request(rq) ? "suspend" : "resume");
|
||||
#endif
|
||||
spin_lock_irqsave(q->queue_lock, flags);
|
||||
if (blk_pm_suspend_request(rq)) {
|
||||
blk_stop_queue(q);
|
||||
} else {
|
||||
drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
|
||||
blk_start_queue(q);
|
||||
}
|
||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
||||
|
||||
drive->hwif->hwgroup->rq = NULL;
|
||||
|
||||
if (blk_end_request(rq, 0, 0))
|
||||
BUG();
|
||||
}
|
||||
|
||||
void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
struct request_pm_state *pm = rq->data;
|
||||
|
||||
if (blk_pm_suspend_request(rq) &&
|
||||
pm->pm_step == IDE_PM_START_SUSPEND)
|
||||
/* Mark drive blocked when starting the suspend sequence. */
|
||||
drive->dev_flags |= IDE_DFLAG_BLOCKED;
|
||||
else if (blk_pm_resume_request(rq) &&
|
||||
pm->pm_step == IDE_PM_START_RESUME) {
|
||||
/*
|
||||
* The first thing we do on wakeup is to wait for BSY bit to
|
||||
* go away (with a looong timeout) as a drive on this hwif may
|
||||
* just be POSTing itself.
|
||||
* We do that before even selecting as the "other" device on
|
||||
* the bus may be broken enough to walk on our toes at this
|
||||
* point.
|
||||
*/
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
int rc;
|
||||
#ifdef DEBUG_PM
|
||||
printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
|
||||
#endif
|
||||
rc = ide_wait_not_busy(hwif, 35000);
|
||||
if (rc)
|
||||
printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
|
||||
SELECT_DRIVE(drive);
|
||||
hwif->tp_ops->set_irq(hwif, 1);
|
||||
rc = ide_wait_not_busy(hwif, 100000);
|
||||
if (rc)
|
||||
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
|
||||
}
|
||||
}
|
@ -110,20 +110,22 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
|
||||
* read and parse the results. This function is run with
|
||||
* interrupts disabled.
|
||||
*/
|
||||
|
||||
static inline void do_identify (ide_drive_t *drive, u8 cmd)
|
||||
|
||||
static void do_identify(ide_drive_t *drive, u8 cmd)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
u16 *id = drive->id;
|
||||
char *m = (char *)&id[ATA_ID_PROD];
|
||||
unsigned long flags;
|
||||
int bswap = 1, is_cfa;
|
||||
|
||||
/* local CPU only; some systems need this */
|
||||
local_irq_save(flags);
|
||||
/* read 512 bytes of id info */
|
||||
hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
|
||||
local_irq_restore(flags);
|
||||
|
||||
drive->dev_flags |= IDE_DFLAG_ID_READ;
|
||||
|
||||
local_irq_enable();
|
||||
#ifdef DEBUG
|
||||
printk(KERN_INFO "%s: dumping identify data\n", drive->name);
|
||||
ide_dump_identify((u8 *)id);
|
||||
@ -306,17 +308,12 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
|
||||
s = tp_ops->read_status(hwif);
|
||||
|
||||
if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
|
||||
unsigned long flags;
|
||||
|
||||
/* local CPU only; some systems need this */
|
||||
local_irq_save(flags);
|
||||
/* drive returned ID */
|
||||
do_identify(drive, cmd);
|
||||
/* drive responded with ID */
|
||||
rc = 0;
|
||||
/* clear drive IRQ */
|
||||
(void)tp_ops->read_status(hwif);
|
||||
local_irq_restore(flags);
|
||||
} else {
|
||||
/* drive refused ID */
|
||||
rc = 2;
|
||||
@ -554,8 +551,8 @@ static void enable_nest (ide_drive_t *drive)
|
||||
* 1 device was found
|
||||
* (note: IDE_DFLAG_PRESENT might still be not set)
|
||||
*/
|
||||
|
||||
static inline u8 probe_for_drive (ide_drive_t *drive)
|
||||
|
||||
static u8 probe_for_drive(ide_drive_t *drive)
|
||||
{
|
||||
char *m;
|
||||
|
||||
@ -642,7 +639,7 @@ static int ide_register_port(ide_hwif_t *hwif)
|
||||
int ret;
|
||||
|
||||
/* register with global device tree */
|
||||
strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE);
|
||||
dev_set_name(&hwif->gendev, hwif->name);
|
||||
hwif->gendev.driver_data = hwif;
|
||||
if (hwif->gendev.parent == NULL) {
|
||||
if (hwif->dev)
|
||||
@ -863,31 +860,6 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* save_match() is used to simplify logic in init_irq() below.
|
||||
*
|
||||
* A loophole here is that we may not know about a particular
|
||||
* hwif's irq until after that hwif is actually probed/initialized..
|
||||
* This could be a problem for the case where an hwif is on a
|
||||
* dual interface that requires serialization (eg. cmd640) and another
|
||||
* hwif using one of the same irqs is initialized beforehand.
|
||||
*
|
||||
* This routine detects and reports such situations, but does not fix them.
|
||||
*/
|
||||
static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
|
||||
{
|
||||
ide_hwif_t *m = *match;
|
||||
|
||||
if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
|
||||
if (!new->hwgroup)
|
||||
return;
|
||||
printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n",
|
||||
hwif->name, new->name, m->name);
|
||||
}
|
||||
if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
|
||||
*match = new;
|
||||
}
|
||||
|
||||
/*
|
||||
* init request queue
|
||||
*/
|
||||
@ -906,7 +878,8 @@ static int ide_init_queue(ide_drive_t *drive)
|
||||
* do not.
|
||||
*/
|
||||
|
||||
q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif));
|
||||
q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock,
|
||||
hwif_to_node(hwif));
|
||||
if (!q)
|
||||
return 1;
|
||||
|
||||
@ -947,7 +920,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
|
||||
{
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
if (!hwgroup->drive) {
|
||||
/* first drive for hwgroup. */
|
||||
drive->next = drive;
|
||||
@ -957,7 +930,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
|
||||
drive->next = hwgroup->drive->next;
|
||||
hwgroup->drive->next = drive;
|
||||
}
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1002,7 +975,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
|
||||
|
||||
ide_ports[hwif->index] = NULL;
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
/*
|
||||
* Remove us from the hwgroup, and free
|
||||
* the hwgroup if we were the only member
|
||||
@ -1030,7 +1003,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
|
||||
}
|
||||
BUG_ON(hwgroup->hwif == hwif);
|
||||
}
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1051,27 +1024,13 @@ static int init_irq (ide_hwif_t *hwif)
|
||||
mutex_lock(&ide_cfg_mtx);
|
||||
hwif->hwgroup = NULL;
|
||||
|
||||
/*
|
||||
* Group up with any other hwifs that share our irq(s).
|
||||
*/
|
||||
for (index = 0; index < MAX_HWIFS; index++) {
|
||||
ide_hwif_t *h = ide_ports[index];
|
||||
|
||||
if (h && h->hwgroup) { /* scan only initialized ports */
|
||||
if (hwif->irq == h->irq) {
|
||||
hwif->sharing_irq = h->sharing_irq = 1;
|
||||
if (hwif->chipset != ide_pci ||
|
||||
h->chipset != ide_pci) {
|
||||
save_match(hwif, h, &match);
|
||||
}
|
||||
}
|
||||
if (hwif->serialized) {
|
||||
if (hwif->mate && hwif->mate->irq == h->irq)
|
||||
save_match(hwif, h, &match);
|
||||
}
|
||||
if (h->serialized) {
|
||||
if (h->mate && hwif->irq == h->mate->irq)
|
||||
save_match(hwif, h, &match);
|
||||
if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) {
|
||||
if (hwif->host == h->host)
|
||||
match = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1092,17 +1051,19 @@ static int init_irq (ide_hwif_t *hwif)
|
||||
* linked list, the first entry is the hwif that owns
|
||||
* hwgroup->handler - do not change that.
|
||||
*/
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
hwif->next = hwgroup->hwif->next;
|
||||
hwgroup->hwif->next = hwif;
|
||||
BUG_ON(hwif->next == hwif);
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
} else {
|
||||
hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO,
|
||||
hwif_to_node(hwif));
|
||||
if (hwgroup == NULL)
|
||||
goto out_up;
|
||||
|
||||
spin_lock_init(&hwgroup->lock);
|
||||
|
||||
hwif->hwgroup = hwgroup;
|
||||
hwgroup->hwif = hwif->next = hwif;
|
||||
|
||||
@ -1122,8 +1083,7 @@ static int init_irq (ide_hwif_t *hwif)
|
||||
sa = IRQF_SHARED;
|
||||
#endif /* __mc68000__ */
|
||||
|
||||
if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 ||
|
||||
hwif->chipset == ide_ali14xx)
|
||||
if (hwif->chipset == ide_pci)
|
||||
sa = IRQF_SHARED;
|
||||
|
||||
if (io_ports->ctl_addr)
|
||||
@ -1150,8 +1110,7 @@ static int init_irq (ide_hwif_t *hwif)
|
||||
io_ports->data_addr, hwif->irq);
|
||||
#endif /* __mc68000__ */
|
||||
if (match)
|
||||
printk(KERN_CONT " (%sed with %s)",
|
||||
hwif->sharing_irq ? "shar" : "serializ", match->name);
|
||||
printk(KERN_CONT " (serialized with %s)", match->name);
|
||||
printk(KERN_CONT "\n");
|
||||
|
||||
mutex_unlock(&ide_cfg_mtx);
|
||||
@ -1263,20 +1222,21 @@ static void ide_remove_drive_from_hwgroup(ide_drive_t *drive)
|
||||
static void drive_release_dev (struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
|
||||
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
|
||||
|
||||
ide_proc_unregister_device(drive);
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
ide_remove_drive_from_hwgroup(drive);
|
||||
kfree(drive->id);
|
||||
drive->id = NULL;
|
||||
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
|
||||
/* Messed up locking ... */
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
blk_cleanup_queue(drive->queue);
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
drive->queue = NULL;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
|
||||
complete(&drive->gendev_rel_comp);
|
||||
}
|
||||
@ -1352,7 +1312,7 @@ static void hwif_register_devices(ide_hwif_t *hwif)
|
||||
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
|
||||
continue;
|
||||
|
||||
snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
|
||||
dev_set_name(dev, "%u.%u", hwif->index, i);
|
||||
dev->parent = &hwif->gendev;
|
||||
dev->bus = &ide_bus_type;
|
||||
dev->driver_data = drive;
|
||||
@ -1436,13 +1396,11 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
|
||||
}
|
||||
|
||||
if ((d->host_flags & IDE_HFLAG_SERIALIZE) ||
|
||||
((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) {
|
||||
if (hwif->mate)
|
||||
hwif->mate->serialized = hwif->serialized = 1;
|
||||
}
|
||||
((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base))
|
||||
hwif->host->host_flags |= IDE_HFLAG_SERIALIZE;
|
||||
|
||||
if (d->host_flags & IDE_HFLAG_RQSIZE_256)
|
||||
hwif->rqsize = 256;
|
||||
if (d->max_sectors)
|
||||
hwif->rqsize = d->max_sectors;
|
||||
|
||||
/* call chipset specific routine for each enabled port */
|
||||
if (d->init_hwif)
|
||||
@ -1794,59 +1752,3 @@ void ide_port_scan(ide_hwif_t *hwif)
|
||||
ide_proc_port_register_devices(hwif);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_port_scan);
|
||||
|
||||
static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
|
||||
u8 port_no, const struct ide_port_info *d,
|
||||
unsigned long config)
|
||||
{
|
||||
unsigned long base, ctl;
|
||||
int irq;
|
||||
|
||||
if (port_no == 0) {
|
||||
base = 0x1f0;
|
||||
ctl = 0x3f6;
|
||||
irq = 14;
|
||||
} else {
|
||||
base = 0x170;
|
||||
ctl = 0x376;
|
||||
irq = 15;
|
||||
}
|
||||
|
||||
if (!request_region(base, 8, d->name)) {
|
||||
printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
|
||||
d->name, base, base + 7);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!request_region(ctl, 1, d->name)) {
|
||||
printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
|
||||
d->name, ctl);
|
||||
release_region(base, 8);
|
||||
return;
|
||||
}
|
||||
|
||||
ide_std_init_ports(hw, base, ctl);
|
||||
hw->irq = irq;
|
||||
hw->chipset = d->chipset;
|
||||
hw->config = config;
|
||||
|
||||
hws[port_no] = hw;
|
||||
}
|
||||
|
||||
int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
|
||||
{
|
||||
hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
|
||||
|
||||
memset(&hw, 0, sizeof(hw));
|
||||
|
||||
if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
|
||||
ide_legacy_init_one(hws, &hw[0], 0, d, config);
|
||||
ide_legacy_init_one(hws, &hw[1], 1, d, config);
|
||||
|
||||
if (hws[0] == NULL && hws[1] == NULL &&
|
||||
(d->host_flags & IDE_HFLAG_SINGLE))
|
||||
return -ENOENT;
|
||||
|
||||
return ide_host_add(d, hws, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_legacy_device_add);
|
||||
|
@ -46,10 +46,6 @@ static int proc_ide_read_imodel
|
||||
case ide_qd65xx: name = "qd65xx"; break;
|
||||
case ide_umc8672: name = "umc8672"; break;
|
||||
case ide_ht6560b: name = "ht6560b"; break;
|
||||
case ide_rz1000: name = "rz1000"; break;
|
||||
case ide_trm290: name = "trm290"; break;
|
||||
case ide_cmd646: name = "cmd646"; break;
|
||||
case ide_cy82c693: name = "cy82c693"; break;
|
||||
case ide_4drives: name = "4drives"; break;
|
||||
case ide_pmac: name = "mac-io"; break;
|
||||
case ide_au1xxx: name = "au1xxx"; break;
|
||||
@ -155,13 +151,8 @@ static int ide_read_setting(ide_drive_t *drive,
|
||||
const struct ide_devset *ds = setting->setting;
|
||||
int val = -EINVAL;
|
||||
|
||||
if (ds->get) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
if (ds->get)
|
||||
val = ds->get(drive);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
@ -583,31 +574,19 @@ EXPORT_SYMBOL(ide_proc_register_driver);
|
||||
* Clean up the driver specific /proc files and IDE settings
|
||||
* for a given drive.
|
||||
*
|
||||
* Takes ide_setting_mtx and ide_lock.
|
||||
* Caller must hold none of the locks.
|
||||
* Takes ide_setting_mtx.
|
||||
*/
|
||||
|
||||
void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
ide_remove_proc_entries(drive->proc, driver->proc_entries(drive));
|
||||
|
||||
mutex_lock(&ide_setting_mtx);
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
/*
|
||||
* ide_setting_mtx protects the settings list
|
||||
* ide_lock protects the use of settings
|
||||
*
|
||||
* so we need to hold both, ide_settings_sem because we want to
|
||||
* modify the settings list, and ide_lock because we cannot take
|
||||
* a setting out that is being used.
|
||||
*
|
||||
* OTOH both ide_{read,write}_setting are only ever used under
|
||||
* ide_setting_mtx.
|
||||
* ide_setting_mtx protects both the settings list and the use
|
||||
* of settings (we cannot take a setting out that is being used).
|
||||
*/
|
||||
drive->settings = NULL;
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
mutex_unlock(&ide_setting_mtx);
|
||||
}
|
||||
EXPORT_SYMBOL(ide_proc_unregister_driver);
|
||||
|
@ -74,9 +74,6 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
|
||||
|
||||
DEFINE_MUTEX(ide_cfg_mtx);
|
||||
|
||||
__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
|
||||
EXPORT_SYMBOL(ide_lock);
|
||||
|
||||
static void ide_port_init_devices_data(ide_hwif_t *);
|
||||
|
||||
/*
|
||||
@ -130,7 +127,6 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
|
||||
}
|
||||
}
|
||||
|
||||
/* Called with ide_lock held. */
|
||||
static void __ide_port_unregister_devices(ide_hwif_t *hwif)
|
||||
{
|
||||
int i;
|
||||
@ -139,10 +135,8 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
|
||||
ide_drive_t *drive = &hwif->drives[i];
|
||||
|
||||
if (drive->dev_flags & IDE_DFLAG_PRESENT) {
|
||||
spin_unlock_irq(&ide_lock);
|
||||
device_unregister(&drive->gendev);
|
||||
wait_for_completion(&drive->gendev_rel_comp);
|
||||
spin_lock_irq(&ide_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,11 +144,9 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
|
||||
void ide_port_unregister_devices(ide_hwif_t *hwif)
|
||||
{
|
||||
mutex_lock(&ide_cfg_mtx);
|
||||
spin_lock_irq(&ide_lock);
|
||||
__ide_port_unregister_devices(hwif);
|
||||
hwif->present = 0;
|
||||
ide_port_init_devices_data(hwif);
|
||||
spin_unlock_irq(&ide_lock);
|
||||
mutex_unlock(&ide_cfg_mtx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
|
||||
@ -192,12 +184,10 @@ void ide_unregister(ide_hwif_t *hwif)
|
||||
|
||||
mutex_lock(&ide_cfg_mtx);
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
if (hwif->present) {
|
||||
__ide_port_unregister_devices(hwif);
|
||||
hwif->present = 0;
|
||||
}
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
ide_proc_unregister_port(hwif);
|
||||
|
||||
@ -340,6 +330,7 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
|
||||
static int set_pio_mode(ide_drive_t *drive, int arg)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
ide_hwgroup_t *hwgroup = hwif->hwgroup;
|
||||
const struct ide_port_ops *port_ops = hwif->port_ops;
|
||||
|
||||
if (arg < 0 || arg > 255)
|
||||
@ -354,9 +345,9 @@ static int set_pio_mode(ide_drive_t *drive, int arg)
|
||||
unsigned long flags;
|
||||
|
||||
/* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
spin_lock_irqsave(&hwgroup->lock, flags);
|
||||
port_ops->set_pio_mode(drive, arg);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
spin_unlock_irqrestore(&hwgroup->lock, flags);
|
||||
} else
|
||||
port_ops->set_pio_mode(drive, arg);
|
||||
} else {
|
||||
@ -397,80 +388,6 @@ ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
|
||||
ide_ext_devset_rw_sync(using_dma, using_dma);
|
||||
__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
|
||||
|
||||
static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
|
||||
{
|
||||
ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct request *rq;
|
||||
struct request_pm_state rqpm;
|
||||
ide_task_t args;
|
||||
int ret;
|
||||
|
||||
/* call ACPI _GTM only once */
|
||||
if ((drive->dn & 1) == 0 || pair == NULL)
|
||||
ide_acpi_get_timing(hwif);
|
||||
|
||||
memset(&rqpm, 0, sizeof(rqpm));
|
||||
memset(&args, 0, sizeof(args));
|
||||
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
|
||||
rq->cmd_type = REQ_TYPE_PM_SUSPEND;
|
||||
rq->special = &args;
|
||||
rq->data = &rqpm;
|
||||
rqpm.pm_step = IDE_PM_START_SUSPEND;
|
||||
if (mesg.event == PM_EVENT_PRETHAW)
|
||||
mesg.event = PM_EVENT_FREEZE;
|
||||
rqpm.pm_state = mesg.event;
|
||||
|
||||
ret = blk_execute_rq(drive->queue, NULL, rq, 0);
|
||||
blk_put_request(rq);
|
||||
|
||||
/* call ACPI _PS3 only after both devices are suspended */
|
||||
if (ret == 0 && ((drive->dn & 1) || pair == NULL))
|
||||
ide_acpi_set_state(hwif, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int generic_ide_resume(struct device *dev)
|
||||
{
|
||||
ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
struct request *rq;
|
||||
struct request_pm_state rqpm;
|
||||
ide_task_t args;
|
||||
int err;
|
||||
|
||||
/* call ACPI _PS0 / _STM only once */
|
||||
if ((drive->dn & 1) == 0 || pair == NULL) {
|
||||
ide_acpi_set_state(hwif, 1);
|
||||
ide_acpi_push_timing(hwif);
|
||||
}
|
||||
|
||||
ide_acpi_exec_tfs(drive);
|
||||
|
||||
memset(&rqpm, 0, sizeof(rqpm));
|
||||
memset(&args, 0, sizeof(args));
|
||||
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
|
||||
rq->cmd_type = REQ_TYPE_PM_RESUME;
|
||||
rq->cmd_flags |= REQ_PREEMPT;
|
||||
rq->special = &args;
|
||||
rq->data = &rqpm;
|
||||
rqpm.pm_step = IDE_PM_START_RESUME;
|
||||
rqpm.pm_state = PM_EVENT_ON;
|
||||
|
||||
err = blk_execute_rq(drive->queue, NULL, rq, 1);
|
||||
blk_put_request(rq);
|
||||
|
||||
if (err == 0 && dev->driver) {
|
||||
ide_driver_t *drv = to_ide_driver(dev->driver);
|
||||
|
||||
if (drv->resume)
|
||||
drv->resume(drive);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_device_get - get an additional reference to a ide_drive_t
|
||||
* @drive: device to get a reference to
|
||||
|
@ -350,16 +350,17 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
|
||||
.dma_timeout = pdc202xx_dma_timeout,
|
||||
};
|
||||
|
||||
#define DECLARE_PDC2026X_DEV(udma, extra_flags) \
|
||||
#define DECLARE_PDC2026X_DEV(udma, sectors) \
|
||||
{ \
|
||||
.name = DRV_NAME, \
|
||||
.init_chipset = init_chipset_pdc202xx, \
|
||||
.port_ops = &pdc2026x_port_ops, \
|
||||
.dma_ops = &pdc2026x_dma_ops, \
|
||||
.host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \
|
||||
.host_flags = IDE_HFLAGS_PDC202XX, \
|
||||
.pio_mask = ATA_PIO4, \
|
||||
.mwdma_mask = ATA_MWDMA2, \
|
||||
.udma_mask = udma, \
|
||||
.max_sectors = sectors, \
|
||||
}
|
||||
|
||||
static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
|
||||
@ -376,8 +377,8 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
|
||||
|
||||
/* 1: PDC2026{2,3} */
|
||||
DECLARE_PDC2026X_DEV(ATA_UDMA4, 0),
|
||||
/* 2: PDC2026{5,7} */
|
||||
DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
|
||||
/* 2: PDC2026{5,7}: UDMA5, limit LBA48 requests to 256 sectors */
|
||||
DECLARE_PDC2026X_DEV(ATA_UDMA5, 256),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -22,34 +22,48 @@
|
||||
|
||||
#define DRV_NAME "rz1000"
|
||||
|
||||
static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
|
||||
static int __devinit rz1000_disable_readahead(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *dev = to_pci_dev(hwif->dev);
|
||||
u16 reg;
|
||||
|
||||
if (!pci_read_config_word (dev, 0x40, ®) &&
|
||||
!pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
|
||||
printk(KERN_INFO "%s: disabled chipset read-ahead "
|
||||
"(buggy RZ1000/RZ1001)\n", hwif->name);
|
||||
"(buggy RZ1000/RZ1001)\n", pci_name(dev));
|
||||
return 0;
|
||||
} else {
|
||||
if (hwif->mate)
|
||||
hwif->mate->serialized = hwif->serialized = 1;
|
||||
hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
|
||||
printk(KERN_INFO "%s: serialized, disabled unmasking "
|
||||
"(buggy RZ1000/RZ1001)\n", hwif->name);
|
||||
"(buggy RZ1000/RZ1001)\n", pci_name(dev));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct ide_port_info rz1000_chipset __devinitdata = {
|
||||
.name = DRV_NAME,
|
||||
.init_hwif = init_hwif_rz1000,
|
||||
.chipset = ide_rz1000,
|
||||
.host_flags = IDE_HFLAG_NO_DMA,
|
||||
};
|
||||
|
||||
static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
return ide_pci_init_one(dev, &rz1000_chipset, NULL);
|
||||
struct ide_port_info d = rz1000_chipset;
|
||||
int rc;
|
||||
|
||||
rc = pci_enable_device(dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (rz1000_disable_readahead(dev)) {
|
||||
d.host_flags |= IDE_HFLAG_SERIALIZE;
|
||||
d.host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
|
||||
}
|
||||
|
||||
return ide_pci_init_one(dev, &d, NULL);
|
||||
}
|
||||
|
||||
static void rz1000_remove(struct pci_dev *dev)
|
||||
{
|
||||
ide_pci_remove(dev);
|
||||
pci_disable_device(dev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id rz1000_pci_tbl[] = {
|
||||
@ -63,7 +77,7 @@ static struct pci_driver rz1000_pci_driver = {
|
||||
.name = "RZ1000_IDE",
|
||||
.id_table = rz1000_pci_tbl,
|
||||
.probe = rz1000_init_one,
|
||||
.remove = ide_pci_remove,
|
||||
.remove = rz1000_remove,
|
||||
};
|
||||
|
||||
static int __init rz1000_ide_init(void)
|
||||
|
@ -328,10 +328,10 @@ static struct ide_dma_ops trm290_dma_ops = {
|
||||
static const struct ide_port_info trm290_chipset __devinitdata = {
|
||||
.name = DRV_NAME,
|
||||
.init_hwif = init_hwif_trm290,
|
||||
.chipset = ide_trm290,
|
||||
.port_ops = &trm290_port_ops,
|
||||
.dma_ops = &trm290_dma_ops,
|
||||
.host_flags = IDE_HFLAG_NO_ATAPI_DMA |
|
||||
.host_flags = IDE_HFLAG_TRM290 |
|
||||
IDE_HFLAG_NO_ATAPI_DMA |
|
||||
#if 0 /* play it safe for now */
|
||||
IDE_HFLAG_TRUST_BIOS_FOR_DMA |
|
||||
#endif
|
||||
|
@ -181,7 +181,7 @@ static void tx4938ide_input_data_swap(ide_drive_t *drive, struct request *rq,
|
||||
|
||||
while (count--)
|
||||
*ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port));
|
||||
__ide_flush_dcache_range((unsigned long)buf, count * 2);
|
||||
__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
|
||||
}
|
||||
|
||||
static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq,
|
||||
@ -195,7 +195,7 @@ static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq,
|
||||
__raw_writew(le16_to_cpu(*ptr), (void __iomem *)port);
|
||||
ptr++;
|
||||
}
|
||||
__ide_flush_dcache_range((unsigned long)buf, count * 2);
|
||||
__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
|
||||
}
|
||||
|
||||
static const struct ide_tp_ops tx4938ide_tp_ops = {
|
||||
|
@ -259,6 +259,12 @@ static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq)
|
||||
bcount = 0x10000 - (cur_addr & 0xffff);
|
||||
if (bcount > cur_len)
|
||||
bcount = cur_len;
|
||||
/*
|
||||
* This workaround for zero count seems required.
|
||||
* (standard ide_build_dmatable do it too)
|
||||
*/
|
||||
if ((bcount & 0xffff) == 0x0000)
|
||||
bcount = 0x8000;
|
||||
*table++ = bcount & 0xffff;
|
||||
*table++ = cur_addr;
|
||||
cur_addr += bcount;
|
||||
@ -558,7 +564,7 @@ static void tx4939ide_input_data_swap(ide_drive_t *drive, struct request *rq,
|
||||
|
||||
while (count--)
|
||||
*ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port));
|
||||
__ide_flush_dcache_range((unsigned long)buf, count * 2);
|
||||
__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
|
||||
}
|
||||
|
||||
static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq,
|
||||
@ -572,7 +578,7 @@ static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq,
|
||||
__raw_writew(le16_to_cpu(*ptr), (void __iomem *)port);
|
||||
ptr++;
|
||||
}
|
||||
__ide_flush_dcache_range((unsigned long)buf, count * 2);
|
||||
__ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
|
||||
}
|
||||
|
||||
static const struct ide_tp_ops tx4939ide_tp_ops = {
|
||||
|
@ -107,18 +107,21 @@ static void umc_set_speeds(u8 speeds[])
|
||||
static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
|
||||
{
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
unsigned long flags;
|
||||
ide_hwgroup_t *mate_hwgroup = hwif->mate ? hwif->mate->hwgroup : NULL;
|
||||
unsigned long uninitialized_var(flags);
|
||||
|
||||
printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
|
||||
drive->name, pio, pio_to_umc[pio]);
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
if (hwif->mate && hwif->mate->hwgroup->handler) {
|
||||
if (mate_hwgroup)
|
||||
spin_lock_irqsave(&mate_hwgroup->lock, flags);
|
||||
if (mate_hwgroup && mate_hwgroup->handler) {
|
||||
printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
|
||||
} else {
|
||||
current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
|
||||
umc_set_speeds(current_speeds);
|
||||
}
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
if (mate_hwgroup)
|
||||
spin_unlock_irqrestore(&mate_hwgroup->lock, flags);
|
||||
}
|
||||
|
||||
static const struct ide_port_ops umc8672_port_ops = {
|
||||
|
@ -578,6 +578,8 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
|
||||
{
|
||||
idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);
|
||||
ide_drive_t *drive = scsi->drive;
|
||||
ide_hwif_t *hwif;
|
||||
ide_hwgroup_t *hwgroup;
|
||||
int busy;
|
||||
int ret = FAILED;
|
||||
|
||||
@ -594,13 +596,16 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
|
||||
goto no_drive;
|
||||
}
|
||||
|
||||
/* First give it some more time, how much is "right" is hard to say :-( */
|
||||
hwif = drive->hwif;
|
||||
hwgroup = hwif->hwgroup;
|
||||
|
||||
busy = ide_wait_not_busy(HWIF(drive), 100); /* FIXME - uses mdelay which causes latency? */
|
||||
/* First give it some more time, how much is "right" is hard to say :-(
|
||||
FIXME - uses mdelay which causes latency? */
|
||||
busy = ide_wait_not_busy(hwif, 100);
|
||||
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
|
||||
printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
spin_lock_irq(&hwgroup->lock);
|
||||
|
||||
/* If there is no pc running we're done (our interrupt took care of it) */
|
||||
pc = drive->pc;
|
||||
@ -629,7 +634,7 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
|
||||
}
|
||||
|
||||
ide_unlock:
|
||||
spin_unlock_irq(&ide_lock);
|
||||
spin_unlock_irq(&hwgroup->lock);
|
||||
no_drive:
|
||||
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
|
||||
printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");
|
||||
@ -642,6 +647,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
|
||||
struct request *req;
|
||||
idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);
|
||||
ide_drive_t *drive = scsi->drive;
|
||||
ide_hwgroup_t *hwgroup;
|
||||
int ready = 0;
|
||||
int ret = SUCCESS;
|
||||
|
||||
@ -658,14 +664,18 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
hwgroup = drive->hwif->hwgroup;
|
||||
|
||||
spin_lock_irq(cmd->device->host->host_lock);
|
||||
spin_lock(&ide_lock);
|
||||
spin_lock(&hwgroup->lock);
|
||||
|
||||
pc = drive->pc;
|
||||
if (pc)
|
||||
req = pc->rq;
|
||||
|
||||
if (pc == NULL || (req = pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
|
||||
if (pc == NULL || req != hwgroup->rq || hwgroup->handler == NULL) {
|
||||
printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
|
||||
spin_unlock(&ide_lock);
|
||||
spin_unlock(&hwgroup->lock);
|
||||
spin_unlock_irq(cmd->device->host->host_lock);
|
||||
return FAILED;
|
||||
}
|
||||
@ -685,10 +695,10 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
|
||||
BUG();
|
||||
}
|
||||
|
||||
HWGROUP(drive)->rq = NULL;
|
||||
HWGROUP(drive)->handler = NULL;
|
||||
HWGROUP(drive)->busy = 1; /* will set this to zero when ide reset finished */
|
||||
spin_unlock(&ide_lock);
|
||||
hwgroup->rq = NULL;
|
||||
hwgroup->handler = NULL;
|
||||
hwgroup->busy = 1; /* will set this to zero when ide reset finished */
|
||||
spin_unlock(&hwgroup->lock);
|
||||
|
||||
ide_do_reset(drive);
|
||||
|
||||
|
@ -122,8 +122,6 @@ struct ide_io_ports {
|
||||
#define MAX_DRIVES 2 /* per interface; 2 assumed by lots of code */
|
||||
#define SECTOR_SIZE 512
|
||||
|
||||
#define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
|
||||
|
||||
/*
|
||||
* Timeouts for various operations:
|
||||
*/
|
||||
@ -172,9 +170,7 @@ typedef int (ide_ack_intr_t)(struct hwif_s *);
|
||||
enum { ide_unknown, ide_generic, ide_pci,
|
||||
ide_cmd640, ide_dtc2278, ide_ali14xx,
|
||||
ide_qd65xx, ide_umc8672, ide_ht6560b,
|
||||
ide_rz1000, ide_trm290,
|
||||
ide_cmd646, ide_cy82c693, ide_4drives,
|
||||
ide_pmac, ide_acorn,
|
||||
ide_4drives, ide_pmac, ide_acorn,
|
||||
ide_au1xxx, ide_palm3710
|
||||
};
|
||||
|
||||
@ -496,8 +492,6 @@ enum {
|
||||
* when more than one interrupt is needed.
|
||||
*/
|
||||
IDE_AFLAG_LIMIT_NFRAMES = (1 << 7),
|
||||
/* Seeking in progress. */
|
||||
IDE_AFLAG_SEEKING = (1 << 8),
|
||||
/* Saved TOC information is current. */
|
||||
IDE_AFLAG_TOC_VALID = (1 << 9),
|
||||
/* We think that the drive door is locked. */
|
||||
@ -845,8 +839,6 @@ typedef struct hwif_s {
|
||||
unsigned extra_ports; /* number of extra dma ports */
|
||||
|
||||
unsigned present : 1; /* this interface exists */
|
||||
unsigned serialized : 1; /* serialized all channel operation */
|
||||
unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
|
||||
unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */
|
||||
|
||||
struct device gendev;
|
||||
@ -909,6 +901,8 @@ typedef struct hwgroup_s {
|
||||
|
||||
int req_gen;
|
||||
int req_gen_timer;
|
||||
|
||||
spinlock_t lock;
|
||||
} ide_hwgroup_t;
|
||||
|
||||
typedef struct ide_driver_s ide_driver_t;
|
||||
@ -1122,6 +1116,14 @@ enum {
|
||||
IDE_PM_COMPLETED,
|
||||
};
|
||||
|
||||
int generic_ide_suspend(struct device *, pm_message_t);
|
||||
int generic_ide_resume(struct device *);
|
||||
|
||||
void ide_complete_power_step(ide_drive_t *, struct request *);
|
||||
ide_startstop_t ide_start_power_step(ide_drive_t *, struct request *);
|
||||
void ide_complete_pm_request(ide_drive_t *, struct request *);
|
||||
void ide_check_pm_state(ide_drive_t *, struct request *);
|
||||
|
||||
/*
|
||||
* Subdrivers support.
|
||||
*
|
||||
@ -1376,8 +1378,8 @@ enum {
|
||||
IDE_HFLAG_LEGACY_IRQS = (1 << 21),
|
||||
/* force use of legacy IRQs */
|
||||
IDE_HFLAG_FORCE_LEGACY_IRQS = (1 << 22),
|
||||
/* limit LBA48 requests to 256 sectors */
|
||||
IDE_HFLAG_RQSIZE_256 = (1 << 23),
|
||||
/* host is TRM290 */
|
||||
IDE_HFLAG_TRM290 = (1 << 23),
|
||||
/* use 32-bit I/O ops */
|
||||
IDE_HFLAG_IO_32BIT = (1 << 24),
|
||||
/* unmask IRQs */
|
||||
@ -1415,6 +1417,9 @@ struct ide_port_info {
|
||||
|
||||
ide_pci_enablebit_t enablebits[2];
|
||||
hwif_chipset_t chipset;
|
||||
|
||||
u16 max_sectors; /* if < than the default one */
|
||||
|
||||
u32 host_flags;
|
||||
u8 pio_mask;
|
||||
u8 swdma_mask;
|
||||
@ -1610,13 +1615,13 @@ extern struct mutex ide_cfg_mtx;
|
||||
/*
|
||||
* Structure locking:
|
||||
*
|
||||
* ide_cfg_mtx and ide_lock together protect changes to
|
||||
* ide_hwif_t->{next,hwgroup}
|
||||
* ide_cfg_mtx and hwgroup->lock together protect changes to
|
||||
* ide_hwif_t->next
|
||||
* ide_drive_t->next
|
||||
*
|
||||
* ide_hwgroup_t->busy: ide_lock
|
||||
* ide_hwgroup_t->hwif: ide_lock
|
||||
* ide_hwif_t->mate: constant, no locking
|
||||
* ide_hwgroup_t->busy: hwgroup->lock
|
||||
* ide_hwgroup_t->hwif: hwgroup->lock
|
||||
* ide_hwif_t->{hwgroup,mate}: constant, no locking
|
||||
* ide_drive_t->hwif: constant, no locking
|
||||
*/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user