Commit d177c408 authored by John Garry's avatar John Garry Committed by Martin K. Petersen

scsi: hisi_sas: service v2 hw CQ ISR with tasklet

Currently the all the slot processing for the completion queue is done
in ISR context. It is judged that the slot processing can take a long
time, especially when a SATA NCQ completes (upto 32 slots).

So, as a solution, defer the bulk of the ISR processing to tasklet
context. Each CQ will have its down tasklet.
Signed-off-by: default avatarJohn Garry <john.garry@huawei.com>
Reviewed-by: default avatarXiang Chen <chenxiang66@hisilicon.com>
Reviewed-by: default avatarZhangfei Gao <zhangfei.gao@linaro.org>
Tested-by: default avatarHanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent ab3dabb3
...@@ -95,6 +95,7 @@ struct hisi_sas_port { ...@@ -95,6 +95,7 @@ struct hisi_sas_port {
struct hisi_sas_cq { struct hisi_sas_cq {
struct hisi_hba *hisi_hba; struct hisi_hba *hisi_hba;
struct tasklet_struct tasklet;
int rd_point; int rd_point;
int id; int id;
}; };
......
...@@ -2481,20 +2481,17 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p) ...@@ -2481,20 +2481,17 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) static void cq_tasklet_v2_hw(unsigned long val)
{ {
struct hisi_sas_cq *cq = p; struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val;
struct hisi_hba *hisi_hba = cq->hisi_hba; struct hisi_hba *hisi_hba = cq->hisi_hba;
struct hisi_sas_slot *slot; struct hisi_sas_slot *slot;
struct hisi_sas_itct *itct; struct hisi_sas_itct *itct;
struct hisi_sas_complete_v2_hdr *complete_queue; struct hisi_sas_complete_v2_hdr *complete_queue;
u32 irq_value, rd_point = cq->rd_point, wr_point, dev_id; u32 rd_point = cq->rd_point, wr_point, dev_id;
int queue = cq->id; int queue = cq->id;
complete_queue = hisi_hba->complete_hdr[queue]; complete_queue = hisi_hba->complete_hdr[queue];
irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR + wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
(0x14 * queue)); (0x14 * queue));
...@@ -2545,6 +2542,18 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) ...@@ -2545,6 +2542,18 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
/* update rd_point */ /* update rd_point */
cq->rd_point = rd_point; cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
}
static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
{
struct hisi_sas_cq *cq = p;
struct hisi_hba *hisi_hba = cq->hisi_hba;
int queue = cq->id;
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
tasklet_schedule(&cq->tasklet);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2726,6 +2735,8 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) ...@@ -2726,6 +2735,8 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
for (i = 0; i < hisi_hba->queue_count; i++) { for (i = 0; i < hisi_hba->queue_count; i++) {
int idx = i + 96; /* First cq interrupt is irq96 */ int idx = i + 96; /* First cq interrupt is irq96 */
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
struct tasklet_struct *t = &cq->tasklet;
irq = irq_map[idx]; irq = irq_map[idx];
if (!irq) { if (!irq) {
...@@ -2742,6 +2753,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba) ...@@ -2742,6 +2753,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
irq, rc); irq, rc);
return -ENOENT; return -ENOENT;
} }
tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment