blk_add_timer(rq);
 
-       /*
-        * Ensure that ->deadline is visible before set the started
-        * flag and clear the completed flag.
-        */
-       smp_mb__before_atomic();
+       WARN_ON_ONCE(test_bit(REQ_ATOM_STARTED, &rq->atomic_flags));
 
        /*
         * Mark us as started and clear complete. Complete might have been
         * set if requeue raced with timeout, which then marked it as
         * complete. So be sure to clear complete again when we start
         * the request, otherwise we'll ignore the completion event.
+        *
+        * Ensure that ->deadline is visible before we set STARTED, such that
+        * blk_mq_check_expired() is guaranteed to observe our ->deadline when
+        * it observes STARTED.
         */
-       if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags))
-               set_bit(REQ_ATOM_STARTED, &rq->atomic_flags);
-       if (test_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags))
+       smp_wmb();
+       set_bit(REQ_ATOM_STARTED, &rq->atomic_flags);
+       if (test_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags)) {
+               /*
+                * Coherence order guarantees these consecutive stores to a
+                * single variable propagate in the specified order. Thus the
+                * clear_bit() is ordered _after_ the set bit. See
+                * blk_mq_check_expired().
+                *
+                * (the bits must be part of the same byte for this to be
+                * true).
+                */
                clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
+       }
 
        if (q->dma_drain_size && blk_rq_bytes(rq)) {
                /*
                struct request *rq, void *priv, bool reserved)
 {
        struct blk_mq_timeout_data *data = priv;
+       unsigned long deadline;
 
        if (!test_bit(REQ_ATOM_STARTED, &rq->atomic_flags))
                return;
 
+       /*
+        * Ensures that if we see STARTED we must also see our
+        * up-to-date deadline, see blk_mq_start_request().
+        */
+       smp_rmb();
+
+       deadline = READ_ONCE(rq->deadline);
+
        /*
         * The rq being checked may have been freed and reallocated
         * out already here, we avoid this race by checking rq->deadline
         *   and clearing the flag in blk_mq_start_request(), so
         *   this rq won't be timed out too.
         */
-       if (time_after_eq(jiffies, rq->deadline)) {
-               if (!blk_mark_rq_complete(rq))
+       if (time_after_eq(jiffies, deadline)) {
+               if (!blk_mark_rq_complete(rq)) {
+                       /*
+                        * Again coherence order ensures that consecutive reads
+                        * from the same variable must be in that order. This
+                        * ensures that if we see COMPLETE clear, we must then
+                        * see STARTED set and we'll ignore this timeout.
+                        *
+                        * (There's also the MB implied by the test_and_clear())
+                        */
                        blk_mq_rq_timed_out(rq, reserved);
-       } else if (!data->next_set || time_after(data->next, rq->deadline)) {
-               data->next = rq->deadline;
+               }
+       } else if (!data->next_set || time_after(data->next, deadline)) {
+               data->next = deadline;
                data->next_set = 1;
        }
 }