From: Bart Van Assche Date: Thu, 21 May 2026 17:33:29 +0000 (-0700) Subject: ata: libata: Fix ata_exec_internal() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aa0ae1c35f7b3e9afed2324bed5f5c87ad55b92c;p=thirdparty%2Fkernel%2Flinux.git ata: libata: Fix ata_exec_internal() Some but not all ata_exec_internal() calls happen from the context of the ATA error handler. Commit c0c362b60e25 ("libata: implement cross-port EH exclusion") added ata_eh_release() and ata_eh_acquire() calls in ata_exec_internal(). Calling these functions is necessary if the caller holds the eh_mutex but is not allowed if the caller doesn't hold that mutex. Fix this by only calling ata_eh_release() and ata_eh_acquire() if the caller holds the eh_mutex. An example of an indirect caller of ata_exec_internal() that does not hold the eh_mutex is ata_host_register(). Fixes: c0c362b60e25 ("libata: implement cross-port EH exclusion") Signed-off-by: Bart Van Assche Reviewed-by: Niklas Cassel Reviewed-by: Damien Le Moal Reviewed-by: Hannes Reinecke Signed-off-by: Niklas Cassel --- diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3d0027ec33c2a..3e19a00a92393 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1540,6 +1540,7 @@ unsigned int ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, { struct ata_link *link = dev->link; struct ata_port *ap = link->ap; + const bool owns_eh_mutex = ap->host->eh_owner == current; u8 command = tf->command; struct ata_queued_cmd *qc; struct scatterlist sgl; @@ -1617,11 +1618,25 @@ unsigned int ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, } } - ata_eh_release(ap); + if (owns_eh_mutex) { + /* + * To prevent that the compiler complains about the + * ata_eh_release() call below. + */ + __acquire(&ap->host->eh_mutex); + ata_eh_release(ap); + } rc = wait_for_completion_timeout(&wait, msecs_to_jiffies(timeout)); - ata_eh_acquire(ap); + if (owns_eh_mutex) { + ata_eh_acquire(ap); + /* + * To prevent that the compiler complains about the above + * ata_eh_acquire() call. + */ + __release(&ap->host->eh_mutex); + } ata_sff_flush_pio_task(ap);