|
@@ -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)
|
|
static void start_delivery_v2_hw(struct hisi_sas_dq *dq)
|
|
{
|
|
{
|
|
struct hisi_hba *hisi_hba = dq->hisi_hba;
|
|
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;
|
|
struct list_head *dq_list;
|
|
int dlvry_queue = dq->id;
|
|
int dlvry_queue = dq->id;
|
|
- int wp, count = 0;
|
|
|
|
|
|
+ int wp;
|
|
|
|
|
|
dq_list = &dq->list;
|
|
dq_list = &dq->list;
|
|
list_for_each_entry_safe(s, s1, &dq->list, delivery) {
|
|
list_for_each_entry_safe(s, s1, &dq->list, delivery) {
|
|
if (!s->ready)
|
|
if (!s->ready)
|
|
break;
|
|
break;
|
|
- count++;
|
|
|
|
- wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
|
|
|
|
|
|
+ s2 = s;
|
|
list_del(&s->delivery);
|
|
list_del(&s->delivery);
|
|
}
|
|
}
|
|
|
|
|
|
- if (!count)
|
|
|
|
|
|
+ if (!s2)
|
|
return;
|
|
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);
|
|
hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
|
|
}
|
|
}
|
|
|
|
|