Skip to content

Commit 1aadf5c

Browse files
htejunJeff Garzik
authored andcommitted
libata: always use ata_qc_complete_multiple() for NCQ command completions
Currently, sata_fsl, mv and nv call ata_qc_complete() multiple times from their interrupt handlers to indicate completion of NCQ commands. This limits the visibility the libata core layer has into how commands are being executed and completed, which is necessary to support IRQ expecting in generic way. libata already has an interface to complete multiple commands at once - ata_qc_complete_multiple() which ahci and sata_sil24 already use. This patch updates the three drivers to use ata_qc_complete_multiple() too and updates comments on ata_qc_complete[_multiple]() regarding their usages with NCQ completions. This change not only provides better visibility into command execution to the core layer but also simplifies low level drivers. * sata_fsl: It already builds done_mask. Conversion is straight forward. * sata_mv: mv_process_crpb_response() no longer checks for illegal completions, it just returns whether the tag is completed or not. mv_process_crpb_entries() builds done_mask from it and passes it to ata_qc_complete_multiple() which will check for illegal completions. * sata_nv adma: Similar to sata_mv. nv_adma_check_cpb() now just returns the tag status and nv_adma_interrupt() builds done_mask from it and passes it to ata_qc_complete_multiple(). * sata_nv swncq: It already builds done_mask. Drop unnecessary illegal transition checks and call ata_qc_complete_multiple(). In the long run, it might be a good idea to make ata_qc_complete() whine if called when multiple NCQ commands are in flight. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Ashish Kalra <ashish.kalra@freescale.com> Cc: Saeed Bishara <saeed@marvell.com> Cc: Mark Lord <liml@rtr.ca> Cc: Robert Hancock <hancockr@shaw.ca> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
1 parent d902747 commit 1aadf5c

File tree

4 files changed

+38
-65
lines changed

4 files changed

+38
-65
lines changed

drivers/ata/libata-core.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4943,8 +4943,13 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
49434943
* ata_qc_complete - Complete an active ATA command
49444944
* @qc: Command to complete
49454945
*
4946-
* Indicate to the mid and upper layers that an ATA
4947-
* command has completed, with either an ok or not-ok status.
4946+
* Indicate to the mid and upper layers that an ATA command has
4947+
* completed, with either an ok or not-ok status.
4948+
*
4949+
* Refrain from calling this function multiple times when
4950+
* successfully completing multiple NCQ commands.
4951+
* ata_qc_complete_multiple() should be used instead, which will
4952+
* properly update IRQ expect state.
49484953
*
49494954
* LOCKING:
49504955
* spin_lock_irqsave(host lock)
@@ -5037,6 +5042,10 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
50375042
* requests normally. ap->qc_active and @qc_active is compared
50385043
* and commands are completed accordingly.
50395044
*
5045+
* Always use this function when completing multiple NCQ commands
5046+
* from IRQ handlers instead of calling ata_qc_complete()
5047+
* multiple times to keep IRQ expect status properly in sync.
5048+
*
50405049
* LOCKING:
50415050
* spin_lock_irqsave(host lock)
50425051
*

drivers/ata/sata_fsl.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,17 +1137,13 @@ static void sata_fsl_host_intr(struct ata_port *ap)
11371137
ioread32(hcr_base + CE));
11381138

11391139
for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
1140-
if (done_mask & (1 << i)) {
1141-
qc = ata_qc_from_tag(ap, i);
1142-
if (qc) {
1143-
ata_qc_complete(qc);
1144-
}
1140+
if (done_mask & (1 << i))
11451141
DPRINTK
11461142
("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
11471143
i, ioread32(hcr_base + CC),
11481144
ioread32(hcr_base + CA));
1149-
}
11501145
}
1146+
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
11511147
return;
11521148

11531149
} else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) {

drivers/ata/sata_mv.c

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2743,18 +2743,11 @@ static void mv_err_intr(struct ata_port *ap)
27432743
}
27442744
}
27452745

2746-
static void mv_process_crpb_response(struct ata_port *ap,
2746+
static bool mv_process_crpb_response(struct ata_port *ap,
27472747
struct mv_crpb *response, unsigned int tag, int ncq_enabled)
27482748
{
27492749
u8 ata_status;
27502750
u16 edma_status = le16_to_cpu(response->flags);
2751-
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
2752-
2753-
if (unlikely(!qc)) {
2754-
ata_port_printk(ap, KERN_ERR, "%s: no qc for tag=%d\n",
2755-
__func__, tag);
2756-
return;
2757-
}
27582751

27592752
/*
27602753
* edma_status from a response queue entry:
@@ -2768,13 +2761,14 @@ static void mv_process_crpb_response(struct ata_port *ap,
27682761
* Error will be seen/handled by
27692762
* mv_err_intr(). So do nothing at all here.
27702763
*/
2771-
return;
2764+
return false;
27722765
}
27732766
}
27742767
ata_status = edma_status >> CRPB_FLAG_STATUS_SHIFT;
27752768
if (!ac_err_mask(ata_status))
2776-
ata_qc_complete(qc);
2769+
return true;
27772770
/* else: leave it for mv_err_intr() */
2771+
return false;
27782772
}
27792773

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

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

2810-
/* Update the software queue position index in hardware */
2811-
if (work_done)
2806+
if (work_done) {
2807+
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
2808+
2809+
/* Update the software queue position index in hardware */
28122810
writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
28132811
(pp->resp_idx << EDMA_RSP_Q_PTR_SHIFT),
28142812
port_mmio + EDMA_RSP_Q_OUT_PTR);
2813+
}
28152814
}
28162815

28172816
static void mv_port_intr(struct ata_port *ap, u32 port_cause)

drivers/ata/sata_nv.c

Lines changed: 13 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -873,29 +873,11 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
873873
ata_port_freeze(ap);
874874
else
875875
ata_port_abort(ap);
876-
return 1;
876+
return -1;
877877
}
878878

879-
if (likely(flags & NV_CPB_RESP_DONE)) {
880-
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
881-
VPRINTK("CPB flags done, flags=0x%x\n", flags);
882-
if (likely(qc)) {
883-
DPRINTK("Completing qc from tag %d\n", cpb_num);
884-
ata_qc_complete(qc);
885-
} else {
886-
struct ata_eh_info *ehi = &ap->link.eh_info;
887-
/* Notifier bits set without a command may indicate the drive
888-
is misbehaving. Raise host state machine violation on this
889-
condition. */
890-
ata_port_printk(ap, KERN_ERR,
891-
"notifier for tag %d with no cmd?\n",
892-
cpb_num);
893-
ehi->err_mask |= AC_ERR_HSM;
894-
ehi->action |= ATA_EH_RESET;
895-
ata_port_freeze(ap);
896-
return 1;
897-
}
898-
}
879+
if (likely(flags & NV_CPB_RESP_DONE))
880+
return 1;
899881
return 0;
900882
}
901883

@@ -1018,6 +1000,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
10181000
NV_ADMA_STAT_CPBERR |
10191001
NV_ADMA_STAT_CMD_COMPLETE)) {
10201002
u32 check_commands = notifier_clears[i];
1003+
u32 done_mask = 0;
10211004
int pos, rc;
10221005

10231006
if (status & NV_ADMA_STAT_CPBERR) {
@@ -1034,10 +1017,13 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
10341017
pos--;
10351018
rc = nv_adma_check_cpb(ap, pos,
10361019
notifier_error & (1 << pos));
1037-
if (unlikely(rc))
1020+
if (rc > 0)
1021+
done_mask |= 1 << pos;
1022+
else if (unlikely(rc < 0))
10381023
check_commands = 0;
10391024
check_commands &= ~(1 << pos);
10401025
}
1026+
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
10411027
}
10421028
}
10431029

@@ -2132,7 +2118,6 @@ static int nv_swncq_sdbfis(struct ata_port *ap)
21322118
struct ata_eh_info *ehi = &ap->link.eh_info;
21332119
u32 sactive;
21342120
u32 done_mask;
2135-
int i;
21362121
u8 host_stat;
21372122
u8 lack_dhfis = 0;
21382123

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

2155-
if (unlikely(done_mask & sactive)) {
2156-
ata_ehi_clear_desc(ehi);
2157-
ata_ehi_push_desc(ehi, "illegal SWNCQ:qc_active transition"
2158-
"(%08x->%08x)", pp->qc_active, sactive);
2159-
ehi->err_mask |= AC_ERR_HSM;
2160-
ehi->action |= ATA_EH_RESET;
2161-
return -EINVAL;
2162-
}
2163-
for (i = 0; i < ATA_MAX_QUEUE; i++) {
2164-
if (!(done_mask & (1 << i)))
2165-
continue;
2166-
2167-
qc = ata_qc_from_tag(ap, i);
2168-
if (qc) {
2169-
ata_qc_complete(qc);
2170-
pp->qc_active &= ~(1 << i);
2171-
pp->dhfis_bits &= ~(1 << i);
2172-
pp->dmafis_bits &= ~(1 << i);
2173-
pp->sdbfis_bits |= (1 << i);
2174-
}
2175-
}
2140+
pp->qc_active &= ~done_mask;
2141+
pp->dhfis_bits &= ~done_mask;
2142+
pp->dmafis_bits &= ~done_mask;
2143+
pp->sdbfis_bits |= done_mask;
2144+
ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
21762145

21772146
if (!ap->qc_active) {
21782147
DPRINTK("over\n");

0 commit comments

Comments
 (0)