Thread (27 messages) 27 messages, 2 authors, 2015-08-30

Re: [PATCH v1 14/15] scsi: ufs: commit descriptors before setting the doorbell

From: <hidden>
Date: 2015-08-27 12:11:40
Also in: linux-arm-msm, lkml

On Tue, Aug 25, 2015 at 7:36 AM,  [off-list ref] wrote:
quoted
quoted
On Aug 21, 2015 3:10 PM, "Yaniv Gardi" [off-list ref] wrote:
quoted
Add a write memory barrier to make sure descriptors prepared are
actually
written to memory before ringing the doorbell. We have also added the
write memory barrier after ringing the doorbell register so that
controller sees the new request immediately.

Signed-off-by: Yaniv Gardi <redacted>

---
 drivers/scsi/ufs/ufshcd.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index fef0660..876148b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -833,6 +833,8 @@ void ufshcd_send_command(struct ufs_hba *hba,
unsigned int task_tag)
        ufshcd_clk_scaling_start_busy(hba);
        __set_bit(task_tag, &hba->outstanding_reqs);
        ufshcd_writel(hba, 1 << task_tag,
REG_UTP_TRANSFER_REQ_DOOR_BELL);
+       /* Make sure that doorbell is committed immediately */
+       wmb();
Is this really necessary? Is there a measurable difference?
I'm not sure if there is a measurable difference, but as the Door-Bell
register is the one that actually responsible for the HW execution of
the
requests, anyhow, it's recommended to its value will be written
instantly to the memory.
A barrier doesn't guarantee speed, only ordering. Unless you can
measure the difference, you should not have it.
Rob,
let me have an example:
context#1 updates outstanding_reqs variable and write(DOOR_BELL)
context#2 upon interrupt of a request completion the following happens:
  report completion on each one of the bits in:
  outstanding_reqs ^ read(DOOR_BELL);

0. let's assume the DOOR_BELL = 0x1 (which means 1 active request in slot 0)
1. context#1: update the DOOR_BELL to be 0x3; (2 active requests: in slot
0 and 1)
2. the new value 0x3 is still not written to the DR so DORR_BELL is still
0x1, but outstanding_reqs is already updated = 0x3
3. the request in slot 0 just completed, and interrupt happens, so
DORR_BELL is now 0 (request in slot 0 completed)
4. context#2: outstanding_reqs ^ read(DOOR_BELL) = 0x3 ^ 0x0 = 0x3 =>
wrong conclusion since the request in slot 1 never completed, and actually
never started.

quoted
Also, as the Interrupt context reads this register, and compare it to
the
SW mirroring value (hba->outstanding_reqs) in order to realize what
requests are already completed, it's important to get the correct value
by reading this register, otherwise we might realize a request
completion
while it was never even submitted.
If a register read can pass a register write out of order, then your
h/w is broken. Plus what if the interrupt occurs before the barrier.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help