Skip to content

Commit c2130f6

Browse files
nehebdamien-lemoal
authored andcommitted
ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning
The hand-rolled bit-scanning loop in the NCQ completion path has an infinite loop bug. When tag_mask has only high bits set (e.g. 0x80000000), the inner while loop left-shifts tag_mask until it overflows to 0. At that point !(0 & 1) is always true and 0 <<= 1 stays 0, causing an infinite loop in hardirq context with a spinlock held. Replace the open-coded bit-scanning with __ffs() which correctly finds the least significant set bit and is bounded by the width of the argument. Fixes: 6293600 ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev <rosenp@gmail.com> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
1 parent 66c4e31 commit c2130f6

1 file changed

Lines changed: 2 additions & 7 deletions

File tree

drivers/ata/sata_dwc_460ex.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -607,14 +607,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
607607
status = ap->ops->sff_check_status(ap);
608608
dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status);
609609

610-
tag = 0;
611610
while (tag_mask) {
612-
while (!(tag_mask & 0x00000001)) {
613-
tag++;
614-
tag_mask <<= 1;
615-
}
616-
617-
tag_mask &= (~0x00000001);
611+
tag = __ffs(tag_mask);
612+
tag_mask &= ~(1U << tag);
618613
qc = ata_qc_from_tag(ap, tag);
619614
if (unlikely(!qc)) {
620615
dev_err(ap->dev, "failed to get qc");

0 commit comments

Comments
 (0)