Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca7d5e42 authored by Jeff Garzik's avatar Jeff Garzik
Browse files

Merge branch 'upstream'

parents a0819750 cc9278ed
Loading
Loading
Loading
Loading
+27 −30
Original line number Diff line number Diff line
@@ -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);

	pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16);
	/*
	 * 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;

	ahci_fill_cmd_slot(ap, opts);
}

static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
@@ -676,18 +679,12 @@ static void ahci_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);
	} else {
	ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
	qc = ata_qc_from_tag(ap, ap->active_tag);
	qc->err_mask |= AC_ERR_TIMEOUT;
	}

	spin_unlock_irqrestore(&host_set->lock, flags);

	if (qc)
	ata_eh_qc_complete(qc);
}

+1 −0
Original line number Diff line number Diff line
@@ -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,
+22 −24
Original line number Diff line number Diff line
@@ -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);
+43 −1
Original line number Diff line number Diff line
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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);
Loading