Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c09b663 authored by Xiaofei Tan's avatar Xiaofei Tan Committed by Martin K. Petersen
Browse files

scsi: hisi_sas: add memory barrier in task delivery function



In task start delivery function, we need to add a memory barrier to prevent
re-ordering of reading memory by hardware. Because the slot data is set in
task prepare function and it could be running in another CPU.

This patch adds an memory barrier after s->ready is read in the task start
delivery function, and uses WRITE_ONCE() in the places where s->ready is
set to ensure that the compiler does not re-order.

Signed-off-by: default avatarXiaofei Tan <tanxiaofei@huawei.com>
Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 6cca51ee
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -446,7 +446,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
	spin_unlock_irqrestore(&task->task_state_lock, flags);

	++(*pass);
	slot->ready = 1;
	WRITE_ONCE(slot->ready, 1);

	return 0;

@@ -1749,7 +1749,7 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
	task->task_state_flags |= SAS_TASK_AT_INITIATOR;
	spin_unlock_irqrestore(&task->task_state_lock, flags);

	slot->ready = 1;
	WRITE_ONCE(slot->ready, 1);
	/* send abort command to the chip */
	spin_lock_irqsave(&dq->lock, flags);
	list_add_tail(&slot->entry, &sas_dev->list);
+10 −5
Original line number Diff line number Diff line
@@ -903,23 +903,28 @@ get_free_slot_v1_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
static void start_delivery_v1_hw(struct hisi_sas_dq *dq)
{
	struct hisi_hba *hisi_hba = dq->hisi_hba;
	struct hisi_sas_slot *s, *s1;
	struct hisi_sas_slot *s, *s1, *s2 = NULL;
	struct list_head *dq_list;
	int dlvry_queue = dq->id;
	int wp, count = 0;
	int wp;

	dq_list = &dq->list;
	list_for_each_entry_safe(s, s1, &dq->list, delivery) {
		if (!s->ready)
			break;
		count++;
		wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
		s2 = s;
		list_del(&s->delivery);
	}

	if (!count)
	if (!s2)
		return;

	/*
	 * Ensure that memories for slots built on other CPUs is observed.
	 */
	smp_rmb();
	wp = (s2->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;

	hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
}

+10 −5
Original line number Diff line number Diff line
@@ -1665,23 +1665,28 @@ get_free_slot_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
static void start_delivery_v2_hw(struct hisi_sas_dq *dq)
{
	struct hisi_hba *hisi_hba = dq->hisi_hba;
	struct hisi_sas_slot *s, *s1;
	struct hisi_sas_slot *s, *s1, *s2 = NULL;
	struct list_head *dq_list;
	int dlvry_queue = dq->id;
	int wp, count = 0;
	int wp;

	dq_list = &dq->list;
	list_for_each_entry_safe(s, s1, &dq->list, delivery) {
		if (!s->ready)
			break;
		count++;
		wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
		s2 = s;
		list_del(&s->delivery);
	}

	if (!count)
	if (!s2)
		return;

	/*
	 * Ensure that memories for slots built on other CPUs is observed.
	 */
	smp_rmb();
	wp = (s2->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;

	hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
}

+10 −5
Original line number Diff line number Diff line
@@ -882,23 +882,28 @@ get_free_slot_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
static void start_delivery_v3_hw(struct hisi_sas_dq *dq)
{
	struct hisi_hba *hisi_hba = dq->hisi_hba;
	struct hisi_sas_slot *s, *s1;
	struct hisi_sas_slot *s, *s1, *s2 = NULL;
	struct list_head *dq_list;
	int dlvry_queue = dq->id;
	int wp, count = 0;
	int wp;

	dq_list = &dq->list;
	list_for_each_entry_safe(s, s1, &dq->list, delivery) {
		if (!s->ready)
			break;
		count++;
		wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
		s2 = s;
		list_del(&s->delivery);
	}

	if (!count)
	if (!s2)
		return;

	/*
	 * Ensure that memories for slots built on other CPUs is observed.
	 */
	smp_rmb();
	wp = (s2->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;

	hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
}