Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 212806
b: refs/heads/master
c: 1aadf5c
h: refs/heads/master
v: v3
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Oct 22, 2010
1 parent d92ac89 commit 4984312
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 66 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d9027470b88631d0956ac37cdadfdeb9cdcf2c99
refs/heads/master: 1aadf5c3bbbbb0db09dcb5aa26c61326e0d3e9e7
13 changes: 11 additions & 2 deletions trunk/drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4943,8 +4943,13 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
*
* Indicate to the mid and upper layers that an ATA
* command has completed, with either an ok or not-ok status.
* Indicate to the mid and upper layers that an ATA command has
* completed, with either an ok or not-ok status.
*
* Refrain from calling this function multiple times when
* successfully completing multiple NCQ commands.
* ata_qc_complete_multiple() should be used instead, which will
* properly update IRQ expect state.
*
* LOCKING:
* spin_lock_irqsave(host lock)
Expand Down Expand Up @@ -5037,6 +5042,10 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
* requests normally. ap->qc_active and @qc_active is compared
* and commands are completed accordingly.
*
* Always use this function when completing multiple NCQ commands
* from IRQ handlers instead of calling ata_qc_complete()
* multiple times to keep IRQ expect status properly in sync.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*
Expand Down
8 changes: 2 additions & 6 deletions trunk/drivers/ata/sata_fsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1137,17 +1137,13 @@ static void sata_fsl_host_intr(struct ata_port *ap)
ioread32(hcr_base + CE));

for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
if (done_mask & (1 << i)) {
qc = ata_qc_from_tag(ap, i);
if (qc) {
ata_qc_complete(qc);
}
if (done_mask & (1 << i))
DPRINTK
("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
i, ioread32(hcr_base + CC),
ioread32(hcr_base + CA));
}
}
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
return;

} else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) {
Expand Down
25 changes: 12 additions & 13 deletions trunk/drivers/ata/sata_mv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2743,18 +2743,11 @@ static void mv_err_intr(struct ata_port *ap)
}
}

static void mv_process_crpb_response(struct ata_port *ap,
static bool mv_process_crpb_response(struct ata_port *ap,
struct mv_crpb *response, unsigned int tag, int ncq_enabled)
{
u8 ata_status;
u16 edma_status = le16_to_cpu(response->flags);
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);

if (unlikely(!qc)) {
ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
__func__, tag);
return;
}

/*
* edma_status from a response queue entry:
Expand All @@ -2768,13 +2761,14 @@ static void mv_process_crpb_response(struct ata_port *ap,
* Error will be seen/handled by
* mv_err_intr(). So do nothing at all here.
*/
return;
return false;
}
}
ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
if (!ac_err_mask(ata_status))
ata_qc_complete(qc);
return true;
/* else: leave it for mv_err_intr() */
return false;
}

static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp)
Expand All @@ -2783,6 +2777,7 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
struct mv_host_priv *hpriv = ap->host->private_data;
u32 in_index;
bool work_done = false;
u32 done_mask = 0;
int ncq_enabled = (pp->pp_flags & MV_PP_FLAG_NCQ_EN);

/* Get the hardware queue position index */
Expand All @@ -2803,15 +2798,19 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
/* Gen II/IIE: get command tag from CRPB entry */
tag = le16_to_cpu(response->id) & 0x1f;
}
mv_process_crpb_response(ap, response, tag, ncq_enabled);
if (mv_process_crpb_response(ap, response, tag, ncq_enabled))
done_mask |= 1 << tag;
work_done = true;
}

/* Update the software queue position index in hardware */
if (work_done)
if (work_done) {
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);

/* Update the software queue position index in hardware */
writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
(pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
port_mmio + EDMA_RSP_Q_OUT_PTR);
}
}

static void mv_port_intr(struct ata_port *ap, u32 port_cause)
Expand Down
57 changes: 13 additions & 44 deletions trunk/drivers/ata/sata_nv.c
Original file line number Diff line number Diff line change
Expand Up @@ -873,29 +873,11 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
ata_port_freeze(ap);
else
ata_port_abort(ap);
return 1;
return -1;
}

if (likely(flags & NV_CPB_RESP_DONE)) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
VPRINTK("CPB flags done, flags=0x%x\n", flags);
if (likely(qc)) {
DPRINTK("Completing qc from tag %d\n", cpb_num);
ata_qc_complete(qc);
} else {
struct ata_eh_info *ehi = &ap->link.eh_info;
/* Notifier bits set without a command may indicate the drive
is misbehaving. Raise host state machine violation on this
condition. */
ata_port_printk(ap, KERN_ERR,
"notifier for tag %d with no cmd?\n",
cpb_num);
ehi->err_mask |= AC_ERR_HSM;
ehi->action |= ATA_EH_RESET;
ata_port_freeze(ap);
return 1;
}
}
if (likely(flags & NV_CPB_RESP_DONE))
return 1;
return 0;
}

Expand Down Expand Up @@ -1018,6 +1000,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
NV_ADMA_STAT_CPBERR |
NV_ADMA_STAT_CMD_COMPLETE)) {
u32 check_commands = notifier_clears[i];
u32 done_mask = 0;
int pos, rc;

if (status & NV_ADMA_STAT_CPBERR) {
Expand All @@ -1034,10 +1017,13 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
pos--;
rc = nv_adma_check_cpb(ap, pos,
notifier_error & (1 << pos));
if (unlikely(rc))
if (rc > 0)
done_mask |= 1 << pos;
else if (unlikely(rc < 0))
check_commands = 0;
check_commands &= ~(1 << pos);
}
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
}
}

Expand Down Expand Up @@ -2132,7 +2118,6 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
struct ata_eh_info *ehi = &ap->link.eh_info;
u32 sactive;
u32 done_mask;
int i;
u8 host_stat;
u8 lack_dhfis = 0;

Expand All @@ -2152,27 +2137,11 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
sactive = readl(pp->sactive_block);
done_mask = pp->qc_active ^ sactive;

if (unlikely(done_mask & sactive)) {
ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
"(%08x->%08x)", pp->qc_active, sactive);
ehi->err_mask |= AC_ERR_HSM;
ehi->action |= ATA_EH_RESET;
return -EINVAL;
}
for (i = 0; i < ATA_MAX_QUEUE; i++) {
if (!(done_mask & (1 << i)))
continue;

qc = ata_qc_from_tag(ap, i);
if (qc) {
ata_qc_complete(qc);
pp->qc_active &= ~(1 << i);
pp->dhfis_bits &= ~(1 << i);
pp->dmafis_bits &= ~(1 << i);
pp->sdbfis_bits |= (1 << i);
}
}
pp->qc_active &= ~done_mask;
pp->dhfis_bits &= ~done_mask;
pp->dmafis_bits &= ~done_mask;
pp->sdbfis_bits |= done_mask;
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);

if (!ap->qc_active) {
DPRINTK("over\n");
Expand Down

0 comments on commit 4984312

Please sign in to comment.