]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ata: libata: Document when host->eh_mutex should be held
authorBart Van Assche <bvanassche@acm.org>
Fri, 29 May 2026 18:03:10 +0000 (11:03 -0700)
committerNiklas Cassel <cassel@kernel.org>
Mon, 1 Jun 2026 17:09:08 +0000 (19:09 +0200)
Annotate the following functions with __must_hold(&host->eh_mutex):
 * All ata_port_operations.error_handler() implementations.
 * ata_eh_reset() and ata_eh_recover() because these functions call
   ata_eh_release() and ata_eh_acquire().
 * All callers of ata_eh_reset() and ata_eh_recover().

Enable Clang's context analysis. This will cause the build to fail if
e.g. a locking bug would be introduced in an error path. This patch
should not affect the generated assembler code.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
[cassel: drop note about clang 23 from commit log]
Signed-off-by: Niklas Cassel <cassel@kernel.org>
21 files changed:
drivers/ata/Makefile
drivers/ata/ahci.h
drivers/ata/ahci_imx.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-pmp.c
drivers/ata/libata-sff.c
drivers/ata/libata.h
drivers/ata/pata_arasan_cf.c
drivers/ata/sata_dwc_460ex.c
drivers/ata/sata_fsl.c
drivers/ata/sata_inic162x.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_qstor.c
drivers/ata/sata_sil24.c
drivers/ata/sata_sx4.c
drivers/ata/sata_via.c
include/linux/libata.h

index 20e6645ab737183d92fec21117286c5e354c272f..b96025abd45e36b8a5f07b565afd250c3c2a0bf0 100644 (file)
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
+CONTEXT_ANALYSIS := y
+
 obj-$(CONFIG_ATA)              += libata.o
 
 # non-SFF interface
index 9e8b6319025c440a56bcf6d5096aed48e7535436..b57cca352faa77d7d0c2c2af169df46b4a51f573 100644 (file)
@@ -448,7 +448,8 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv,
 int ahci_reset_em(struct ata_host *host);
 void ahci_print_info(struct ata_host *host, const char *scc_s);
 int ahci_host_activate(struct ata_host *host, const struct scsi_host_template *sht);
-void ahci_error_handler(struct ata_port *ap);
+void ahci_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex);
 u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked);
 
 static inline void __iomem *__ahci_port_base(struct ahci_host_priv *hpriv,
index 3d26595524d3e27343285263a33d12ab596c1ec3..6aaa18e29abc62230a609223381a3a26837d1c87 100644 (file)
@@ -598,6 +598,7 @@ static void imx_sata_disable(struct ahci_host_priv *hpriv)
 }
 
 static void ahci_imx_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        u32 reg_val;
        struct ata_device *dev;
index e0af4b5716b3f2c3859210956f5ee93a2f7061f6..6d72eb017b498796ea465d7ae1846887d22804e2 100644 (file)
@@ -2208,6 +2208,7 @@ static void ahci_thaw(struct ata_port *ap)
 }
 
 void ahci_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ahci_host_priv *hpriv = ap->host->private_data;
 
index 3e19a00a92393fc6134367b2c1f97aa1972e5e1a..f68882706fdca4cb186416fb41f38359e003f948 100644 (file)
@@ -6835,6 +6835,7 @@ EXPORT_SYMBOL_GPL(ata_ratelimit);
  *     Might sleep.
  */
 void ata_msleep(struct ata_port *ap, unsigned int msecs)
+       __context_unsafe(conditional locking)
 {
        bool owns_eh = ap && ap->host->eh_owner == current;
 
@@ -6909,6 +6910,7 @@ static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc)
 }
 
 static void ata_dummy_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        /* truly dummy */
 }
index ecfb9d96249f65894ba20005b1a37f79d4a19724..05df7ea6954a9da69584c4dad618215057d4edf4 100644 (file)
@@ -469,6 +469,7 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev,
  *     EH context.
  */
 void ata_eh_acquire(struct ata_port *ap)
+       __acquires(&ap->host->eh_mutex)
 {
        mutex_lock(&ap->host->eh_mutex);
        WARN_ON_ONCE(ap->host->eh_owner);
@@ -486,6 +487,7 @@ void ata_eh_acquire(struct ata_port *ap)
  *     EH context.
  */
 void ata_eh_release(struct ata_port *ap)
+       __releases(&ap->host->eh_mutex)
 {
        WARN_ON_ONCE(ap->host->eh_owner != current);
        ap->host->eh_owner = NULL;
@@ -2833,6 +2835,7 @@ static bool ata_eh_followup_srst_needed(struct ata_link *link, int rc)
 
 int ata_eh_reset(struct ata_port *ap, struct ata_link *link, int classify,
                 struct ata_reset_operations *reset_ops)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ata_link *slave = ap->slave_link;
        struct ata_eh_context *ehc = &link->eh_context;
@@ -3815,6 +3818,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
  */
 int ata_eh_recover(struct ata_port *ap, struct ata_reset_operations *reset_ops,
                   struct ata_link **r_failed_link)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ata_link *link;
        struct ata_device *dev;
@@ -4112,6 +4116,7 @@ void ata_eh_finish(struct ata_port *ap)
  *     Kernel thread context (may sleep).
  */
 void ata_std_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ata_reset_operations *reset_ops = &ap->ops->reset;
        struct ata_link *link = &ap->link;
index ffd6549960674d28d08a1d8fa1fe69b8e114fef3..736eaf0586f7da3670d91034b653ca6f4451a1b0 100644 (file)
@@ -756,6 +756,7 @@ static int sata_pmp_revalidate_quick(struct ata_device *dev)
  */
 static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
                                   struct ata_reset_operations *reset_ops)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ata_link *link = &ap->link;
        struct ata_eh_context *ehc = &link->eh_context;
@@ -921,6 +922,7 @@ static int sata_pmp_handle_link_fail(struct ata_link *link, int *link_tries)
  *     0 on success, -errno on failure.
  */
 static int sata_pmp_eh_recover(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ata_port_operations *ops = ap->ops;
        int pmp_tries, link_tries[SATA_PMP_MAX_PORTS];
@@ -1098,6 +1100,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
  *     Kernel thread context (may sleep).
  */
 void sata_pmp_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        ata_eh_autopsy(ap);
        ata_eh_report(ap);
index 785b6e371abfb5db9f495b5576c426421aa723d0..734e7c88439a7b9c1a949432a54f35e410cb5e09 100644 (file)
@@ -2053,6 +2053,7 @@ EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
  *     Kernel thread context (may sleep)
  */
 void ata_sff_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ata_queued_cmd *qc;
        unsigned long flags;
@@ -2769,6 +2770,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_interrupt);
  *     Kernel thread context (may sleep)
  */
 void ata_bmdma_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ata_queued_cmd *qc;
        unsigned long flags;
index a5920c10aacaf6d240421476a1ce54f87e37ad8c..d0b0ecd3d086723487dfe5c08987bd7c78ee68d4 100644 (file)
@@ -173,8 +173,10 @@ void ata_scsi_requeue_deferred_qc(struct ata_port *ap);
 /* libata-eh.c */
 extern unsigned int ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
 extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd);
-extern void ata_eh_acquire(struct ata_port *ap);
-extern void ata_eh_release(struct ata_port *ap);
+extern void ata_eh_acquire(struct ata_port *ap)
+       __acquires(&ap->host->eh_mutex);
+extern void ata_eh_release(struct ata_port *ap)
+       __releases(&ap->host->eh_mutex);
 extern void ata_scsi_error(struct Scsi_Host *host);
 extern void ata_eh_fastdrain_timerfn(struct timer_list *t);
 extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
@@ -188,10 +190,12 @@ extern void ata_eh_autopsy(struct ata_port *ap);
 const char *ata_get_cmd_name(u8 command);
 extern void ata_eh_report(struct ata_port *ap);
 extern int ata_eh_reset(struct ata_port *ap, struct ata_link *link,
-                       int classify, struct ata_reset_operations *reset_ops);
+                       int classify, struct ata_reset_operations *reset_ops)
+       __must_hold(&ap->host->eh_mutex);
 extern int ata_eh_recover(struct ata_port *ap,
                          struct ata_reset_operations *reset_ops,
-                         struct ata_link **r_failed_disk);
+                         struct ata_link **r_failed_disk)
+       __must_hold(&ap->host->eh_mutex);
 extern void ata_eh_finish(struct ata_port *ap);
 extern int ata_ering_map(struct ata_ering *ering,
                         int (*map_fn)(struct ata_ering_entry *, void *),
index a77fefd320c26fa54ff05b795febd77a7eaae29a..e05a4847e0371375cb15ac647f1b50b6b4923a53 100644 (file)
@@ -658,6 +658,7 @@ static void arasan_cf_freeze(struct ata_port *ap)
 }
 
 static void arasan_cf_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct arasan_cf_dev *acdev = ap->host->private_data;
 
index 64cb544903d888faf1180d1ec8a0031e248dfa3e..4fc22ce4bd9aa2033edbd5ee1f979f463520cbd6 100644 (file)
@@ -1041,6 +1041,7 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
 }
 
 static void sata_dwc_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        ata_sff_error_handler(ap);
 }
index be829fcc584de2227a01b52f5c057681471c6e8a..70b210afd2911e9a3cc1c335a4feb5ccc41280a4 100644 (file)
@@ -1035,6 +1035,7 @@ err:
 }
 
 static void sata_fsl_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        sata_pmp_error_handler(ap);
 }
index 46a8c20daf18016e13ae0a9b280c4b6541428de7..065408975f5b56e67d265cde1695cb1ad9249e68 100644 (file)
@@ -660,6 +660,7 @@ static int inic_hardreset(struct ata_link *link, unsigned int *class,
 }
 
 static void inic_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        void __iomem *port_base = inic_port_base(ap);
 
index ffb396f61731f1bef7dab2e36c76973ac415f5cf..f6942fd80bae7e72f2677354f23202ceca6fe165 100644 (file)
@@ -2398,6 +2398,7 @@ static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap)
 }
 
 static void mv_pmp_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        unsigned int pmp, pmp_map;
        struct mv_port_priv *pp = ap->private_data;
index 841e7de2bba6ea66eda461ebdfaef1b98fa4da30..19b92706586868ccb84b4e244df9d48ba0023a8f 100644 (file)
@@ -1626,6 +1626,7 @@ static void nv_mcp55_thaw(struct ata_port *ap)
 }
 
 static void nv_adma_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
        if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
@@ -1795,6 +1796,7 @@ static void nv_swncq_ncq_stop(struct ata_port *ap)
 }
 
 static void nv_swncq_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct ata_eh_context *ehc = &ap->link.eh_context;
 
index 2a005aede123dc72dffedc72c6f72eb7ef18b8b4..c5fad448bafcd95b0fa222c428e0719b4088a1c7 100644 (file)
@@ -816,6 +816,7 @@ static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
 }
 
 static void pdc_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        if (!ata_port_is_frozen(ap))
                pdc_reset_port(ap);
index cfb9b5b61cd7ebe8dcb804d5dfed02daa309b1f4..1add7a7d5ff600fc60c6756467b2e6b719879155 100644 (file)
@@ -220,6 +220,7 @@ static int qs_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
 }
 
 static void qs_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        qs_enter_reg_mode(ap);
        ata_sff_error_handler(ap);
index 57f1081b86db3c47c58f9db3f16f050ffa194394..b4549ba968a48bb2d56c5276f9fc20e15d72381e 100644 (file)
@@ -1171,6 +1171,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
 }
 
 static void sil24_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct sil24_port_priv *pp = ap->private_data;
 
index 0986ebd1eb4e59de54101d36e40e2892ace9e72d..227dc1d4e85bd71a58b920a13f2c83e90a815dd1 100644 (file)
@@ -853,6 +853,7 @@ static int pdc_softreset(struct ata_link *link, unsigned int *class,
 }
 
 static void pdc_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        if (!ata_port_is_frozen(ap))
                pdc_reset_port(ap);
index 68e9003ec2d47ba1e60a50a8f427413c539fef87..b672a1e0586742f4fd1367d4beed2ab2785e0845 100644 (file)
@@ -573,6 +573,7 @@ static irqreturn_t vt642x_interrupt(int irq, void *dev_instance)
 }
 
 static void vt6421_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex)
 {
        struct svia_priv *hpriv = ap->host->private_data;
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
index 127229fbd1a632d1ec1216635d64767f11e252e7..7091bc903c05f9f895ce07751e5c93c41fd9ee0d 100644 (file)
@@ -984,7 +984,8 @@ struct ata_port_operations {
        void (*thaw)(struct ata_port *ap);
        struct ata_reset_operations reset;
        struct ata_reset_operations pmp_reset;
-       void (*error_handler)(struct ata_port *ap);
+       void (*error_handler)(struct ata_port *ap)
+               __must_hold(&ap->host->eh_mutex);
        void (*lost_interrupt)(struct ata_port *ap);
        void (*post_internal_cmd)(struct ata_queued_cmd *qc);
        void (*sched_eh)(struct ata_port *ap);
@@ -1419,7 +1420,8 @@ extern void ata_eh_thaw_port(struct ata_port *ap);
 extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
 extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
 
-extern void ata_std_error_handler(struct ata_port *ap);
+extern void ata_std_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex);
 extern void ata_std_sched_eh(struct ata_port *ap);
 extern void ata_std_end_eh(struct ata_port *ap);
 extern int ata_link_nr_enabled(struct ata_link *link);
@@ -1999,7 +2001,8 @@ extern void ata_timing_merge(const struct ata_timing *,
 extern const struct ata_port_operations sata_pmp_port_ops;
 
 extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc);
-extern void sata_pmp_error_handler(struct ata_port *ap);
+extern void sata_pmp_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex);
 
 #else /* CONFIG_SATA_PMP */
 
@@ -2063,7 +2066,8 @@ extern int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
                               unsigned long deadline);
 extern void ata_sff_postreset(struct ata_link *link, unsigned int *classes);
 extern void ata_sff_drain_fifo(struct ata_queued_cmd *qc);
-extern void ata_sff_error_handler(struct ata_port *ap);
+extern void ata_sff_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex);
 extern void ata_sff_std_ports(struct ata_ioports *ioaddr);
 #ifdef CONFIG_PCI
 extern int ata_pci_sff_init_host(struct ata_host *host);
@@ -2093,7 +2097,8 @@ extern enum ata_completion_errors ata_bmdma_dumb_qc_prep(struct ata_queued_cmd *
 extern unsigned int ata_bmdma_port_intr(struct ata_port *ap,
                                      struct ata_queued_cmd *qc);
 extern irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance);
-extern void ata_bmdma_error_handler(struct ata_port *ap);
+extern void ata_bmdma_error_handler(struct ata_port *ap)
+       __must_hold(&ap->host->eh_mutex);
 extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
 extern void ata_bmdma_setup(struct ata_queued_cmd *qc);