Merge branch 'upstream'

This commit is contained in:
Jeff Garzik 2006-02-10 07:09:37 -05:00
commit ca7d5e42d7
19 changed files with 113 additions and 83 deletions

View File

@ -206,6 +206,7 @@ static struct scsi_host_template ahci_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
@ -506,6 +507,15 @@ static unsigned int ahci_dev_classify(struct ata_port *ap)
return ata_dev_classify(&tf);
}
static void ahci_fill_cmd_slot(struct ata_port *ap, u32 opts)
{
struct ahci_port_priv *pp = ap->private_data;
pp->cmd_slot[0].opts = cpu_to_le32(opts);
pp->cmd_slot[0].status = 0;
pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
}
static void ahci_phy_reset(struct ata_port *ap)
{
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
@ -584,42 +594,35 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct ahci_port_priv *pp = ap->private_data;
int is_atapi = is_atapi_taskfile(&qc->tf);
u32 opts;
const u32 cmd_fis_len = 5; /* five dwords */
unsigned int n_elem;
/*
* Fill in command slot information (currently only one slot,
* slot 0, is currently since we don't do queueing)
*/
opts = cmd_fis_len;
if (qc->tf.flags & ATA_TFLAG_WRITE)
opts |= AHCI_CMD_WRITE;
if (is_atapi_taskfile(&qc->tf))
opts |= AHCI_CMD_ATAPI;
pp->cmd_slot[0].opts = cpu_to_le32(opts);
pp->cmd_slot[0].status = 0;
pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
/*
* Fill in command table information. First, the header,
* a SATA Register - Host to Device command FIS.
*/
ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
if (opts & AHCI_CMD_ATAPI) {
if (is_atapi) {
memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len);
}
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
return;
n_elem = 0;
if (qc->flags & ATA_QCFLAG_DMAMAP)
n_elem = ahci_fill_sg(qc);
n_elem = ahci_fill_sg(qc);
/*
* Fill in command slot information.
*/
opts = cmd_fis_len | n_elem << 16;
if (qc->tf.flags & ATA_TFLAG_WRITE)
opts |= AHCI_CMD_WRITE;
if (is_atapi)
opts |= AHCI_CMD_ATAPI;
pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16);
ahci_fill_cmd_slot(ap, opts);
}
static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
@ -676,19 +679,13 @@ static void ahci_eng_timeout(struct ata_port *ap)
spin_lock_irqsave(&host_set->lock, flags);
ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
} else {
ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
qc->err_mask |= AC_ERR_TIMEOUT;
}
qc->err_mask |= AC_ERR_TIMEOUT;
spin_unlock_irqrestore(&host_set->lock, flags);
if (qc)
ata_eh_qc_complete(qc);
ata_eh_qc_complete(qc);
}
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)

View File

@ -180,6 +180,7 @@ static struct scsi_host_template piix_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -3702,20 +3702,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
void ata_eng_timeout(struct ata_port *ap)
{
struct ata_queued_cmd *qc;
DPRINTK("ENTER\n");
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc)
ata_qc_timeout(qc);
else {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
goto out;
}
ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
out:
DPRINTK("EXIT\n");
}
@ -3798,19 +3788,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
}
}
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
* @err_mask: ATA Status register contents
*
* Indicate to the mid and upper layers that an ATA
* command has completed, with either an ok or not-ok status.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_qc_complete(struct ata_queued_cmd *qc)
inline void __ata_qc_complete(struct ata_queued_cmd *qc)
{
assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
assert(qc->flags & ATA_QCFLAG_ACTIVE);
@ -3828,6 +3806,25 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
qc->complete_fn(qc);
}
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
* @err_mask: ATA Status register contents
*
* Indicate to the mid and upper layers that an ATA
* command has completed, with either an ok or not-ok status.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_qc_complete(struct ata_queued_cmd *qc)
{
if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
return;
__ata_qc_complete(qc);
}
static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
@ -5183,6 +5180,7 @@ EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_timed_out);
EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_release);

View File

@ -716,6 +716,47 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
return 0; /* scsi layer doesn't check return value, sigh */
}
/**
* ata_scsi_timed_out - SCSI layer time out callback
* @cmd: timed out SCSI command
*
* Handles SCSI layer timeout. We race with normal completion of
* the qc for @cmd. If the qc is already gone, we lose and let
* the scsi command finish (EH_HANDLED). Otherwise, the qc has
* timed out and EH should be invoked. Prevent ata_qc_complete()
* from finishing it by setting EH_SCHEDULED and return
* EH_NOT_HANDLED.
*
* LOCKING:
* Called from timer context
*
* RETURNS:
* EH_HANDLED or EH_NOT_HANDLED
*/
enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
unsigned long flags;
struct ata_queued_cmd *qc;
enum scsi_eh_timer_return ret = EH_HANDLED;
DPRINTK("ENTER\n");
spin_lock_irqsave(&ap->host_set->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc) {
assert(qc->scsicmd == cmd);
qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
qc->err_mask |= AC_ERR_TIMEOUT;
ret = EH_NOT_HANDLED;
}
spin_unlock_irqrestore(&ap->host_set->lock, flags);
DPRINTK("EXIT, ret=%d\n", ret);
return ret;
}
/**
* ata_scsi_error - SCSI layer error handler callback
* @host: SCSI host on which error occurred
@ -741,6 +782,7 @@ int ata_scsi_error(struct Scsi_Host *host)
spin_lock_irqsave(&ap->host_set->lock, flags);
assert(!(ap->flags & ATA_FLAG_IN_EH));
ap->flags |= ATA_FLAG_IN_EH;
assert(ata_qc_from_tag(ap, ap->active_tag) != NULL);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
ap->ops->eng_timeout(ap);
@ -770,7 +812,7 @@ static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
spin_lock_irqsave(&ap->host_set->lock, flags);
qc->scsidone = ata_eh_scsidone;
ata_qc_complete(qc);
__ata_qc_complete(qc);
assert(!ata_tag_valid(qc->tag));
spin_unlock_irqrestore(&ap->host_set->lock, flags);

View File

@ -46,6 +46,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc);
extern void __ata_qc_complete(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep);

View File

@ -143,6 +143,7 @@ static struct scsi_host_template adma_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -378,6 +378,7 @@ static struct scsi_host_template mv_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = MV_USE_Q_DEPTH,
.this_id = ATA_SHT_THIS_ID,
@ -2025,13 +2026,8 @@ static void mv_eng_timeout(struct ata_port *ap)
mv_err_intr(ap);
mv_stop_and_reset(ap);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
} else {
qc->err_mask |= AC_ERR_TIMEOUT;
ata_eh_qc_complete(qc);
}
qc->err_mask |= AC_ERR_TIMEOUT;
ata_eh_qc_complete(qc);
}
/**

View File

@ -229,6 +229,7 @@ static struct scsi_host_template nv_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -112,6 +112,7 @@ static struct scsi_host_template pdc_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
@ -432,11 +433,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
spin_lock_irqsave(&host_set->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
goto out;
}
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
@ -456,10 +452,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
break;
}
out:
spin_unlock_irqrestore(&host_set->lock, flags);
if (qc)
ata_eh_qc_complete(qc);
ata_eh_qc_complete(qc);
DPRINTK("EXIT\n");
}

View File

@ -132,6 +132,7 @@ static struct scsi_host_template qs_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -135,6 +135,7 @@ static struct scsi_host_template sil_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -280,6 +280,7 @@ static struct scsi_host_template sil24_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
@ -638,11 +639,6 @@ static void sil24_eng_timeout(struct ata_port *ap)
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
return;
}
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
qc->err_mask |= AC_ERR_TIMEOUT;

View File

@ -87,6 +87,7 @@ static struct scsi_host_template sis_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -288,6 +288,7 @@ static struct scsi_host_template k2_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -182,6 +182,7 @@ static struct scsi_host_template pdc_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
@ -866,11 +867,6 @@ static void pdc_eng_timeout(struct ata_port *ap)
spin_lock_irqsave(&host_set->lock, flags);
qc = ata_qc_from_tag(ap, ap->active_tag);
if (!qc) {
printk(KERN_ERR "ata%u: BUG: timeout without command\n",
ap->id);
goto out;
}
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
@ -889,10 +885,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
break;
}
out:
spin_unlock_irqrestore(&host_set->lock, flags);
if (qc)
ata_eh_qc_complete(qc);
ata_eh_qc_complete(qc);
DPRINTK("EXIT\n");
}

View File

@ -75,6 +75,7 @@ static struct scsi_host_template uli_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -94,6 +94,7 @@ static struct scsi_host_template svia_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -223,6 +223,7 @@ static struct scsi_host_template vsc_sata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_timed_out = ata_scsi_timed_out,
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,

View File

@ -170,6 +170,7 @@ enum {
ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */
ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
/* various lengths of time */
ATA_TMOUT_EDD = 5 * HZ, /* heuristic */
@ -511,6 +512,7 @@ extern void ata_host_set_remove(struct ata_host_set *host_set);
extern int ata_scsi_detect(struct scsi_host_template *sht);
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern int ata_scsi_error(struct Scsi_Host *host);
extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);