Re: [PATCH v5 04/31] elx: libefc_sli: queue create/destroy/parse routines
From: Daniel Wagner <hidden>
Date: 2021-01-04 13:41:37
Hi James, On Sun, Jan 03, 2021 at 09:11:07AM -0800, James Smart wrote:
+int
+sli_fc_rq_alloc(struct sli4 *sli4, struct sli4_queue *q,
+ u32 n_entries, u32 buffer_size,
+ struct sli4_queue *cq, bool is_hdr)
+{
+ if (__sli_queue_init(sli4, q, SLI4_QTYPE_RQ, SLI4_RQE_SIZE,
+ n_entries, SLI_PAGE_SIZE))
+ return EFC_FAIL;
+
+ if (!sli_cmd_rq_create_v1(sli4, sli4->bmbx.virt, &q->dma, cq->id,
+ buffer_size)) {
+ if (__sli_create_queue(sli4, q)) {
+ efc_log_info(sli4, "Create queue failed %d\n", q->id);
+ goto error;
+ }
+ if (is_hdr && q->id & 1) {
+ efc_log_info(sli4, "bad header RQ_ID %d\n", q->id);
+ goto error;
+ } else if (!is_hdr && (q->id & 1) == 0) {
+ efc_log_info(sli4, "bad data RQ_ID %d\n", q->id);
+ goto error;
+ }
+ } else {
+ goto error;
+ }
This could be written as
if (sli_cmd_rq_create_v1())
goto error;
if (__sli_create_queue())
goto error;
+ if (is_hdr)
+ q->u.flag |= SLI4_QUEUE_FLAG_HDR;
+ else
+ q->u.flag &= ~SLI4_QUEUE_FLAG_HDR;
+ return EFC_SUCCESS;
+error:
+ __sli_queue_destroy(sli4, q);
+ return EFC_FAIL;
+}
+
+int
+sli_fc_rq_set_alloc(struct sli4 *sli4, u32 num_rq_pairs,
+ struct sli4_queue *qs[], u32 base_cq_id,
+ u32 n_entries, u32 header_buffer_size,
+ u32 payload_buffer_size)
+{
+ u32 i;
+ struct efc_dma dma = {0};
+ struct sli4_rsp_cmn_create_queue_set *rsp = NULL;
+ void __iomem *db_regaddr = NULL;
+ u32 num_rqs = num_rq_pairs * 2;
+
+ for (i = 0; i < num_rqs; i++) {
+ if (__sli_queue_init(sli4, qs[i], SLI4_QTYPE_RQ,
+ SLI4_RQE_SIZE, n_entries,
+ SLI_PAGE_SIZE)) {
+ goto error;
+ }
+ }
+
+ if (sli_cmd_rq_create_v2(sli4, num_rqs, qs, base_cq_id,
+ header_buffer_size, payload_buffer_size, &dma)) {
+ goto error;
+ }
+
+ if (sli_bmbx_command(sli4)) {
+ efc_log_err(sli4, "bootstrap mailbox write failed RQSet\n");
+ goto error;
+ }
+
+ if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
+ db_regaddr = sli4->reg[1] + SLI4_IF6_RQ_DB_REG;
+ else
+ db_regaddr = sli4->reg[0] + SLI4_RQ_DB_REG;
+
+ rsp = dma.virt;
+ if (rsp->hdr.status) {
+ efc_log_err(sli4, "bad create RQSet status=%#x addl=%#x\n",
+ rsp->hdr.status, rsp->hdr.additional_status);
+ goto error;
+ } else {
+ for (i = 0; i < num_rqs; i++) {
+ qs[i]->id = i + le16_to_cpu(rsp->q_id);
+ if ((qs[i]->id & 1) == 0)
+ qs[i]->u.flag |= SLI4_QUEUE_FLAG_HDR;
+ else
+ qs[i]->u.flag &= ~SLI4_QUEUE_FLAG_HDR;
+
+ qs[i]->db_regaddr = db_regaddr;
+ }
+ }With the goto in first block you don't need the else block.
+ + dma_free_coherent(&sli4->pci->dev, dma.size, dma.virt, dma.phys); + + return EFC_SUCCESS; + +error: + for (i = 0; i < num_rqs; i++) + __sli_queue_destroy(sli4, qs[i]); + + if (dma.virt) + dma_free_coherent(&sli4->pci->dev, dma.size, dma.virt, + dma.phys); + + return EFC_FAIL; +}
[...]
+int
+sli_cq_alloc_set(struct sli4 *sli4, struct sli4_queue *qs[],
+ u32 num_cqs, u32 n_entries, struct sli4_queue *eqs[])
+{
+ u32 i;
+ struct efc_dma dma = {0};
+ struct sli4_rsp_cmn_create_queue_set *res;
+ void __iomem *db_regaddr;
+
+ /* Align the queue DMA memory */
+ for (i = 0; i < num_cqs; i++) {
+ if (__sli_queue_init(sli4, qs[i], SLI4_QTYPE_CQ,
+ SLI4_CQE_BYTES, n_entries, SLI_PAGE_SIZE))
+ goto error;
+ }
+
+ if (sli_cmd_cq_set_create(sli4, qs, num_cqs, eqs, &dma))
+ goto error;
+
+ if (sli_bmbx_command(sli4))
+ goto error;
+
+ if (sli4->if_type == SLI4_INTF_IF_TYPE_6)
+ db_regaddr = sli4->reg[1] + SLI4_IF6_CQ_DB_REG;
+ else
+ db_regaddr = sli4->reg[0] + SLI4_EQCQ_DB_REG;
+
+ res = dma.virt;
+ if (res->hdr.status) {
+ efc_log_err(sli4, "bad create CQSet status=%#x addl=%#x\n",
+ res->hdr.status, res->hdr.additional_status);
+ goto error;
+ } else {
+ /* Check if we got all requested CQs. */
+ if (le16_to_cpu(res->num_q_allocated) != num_cqs) {
+ efc_log_crit(sli4, "Requested count CQs doesn't match.\n");
+ goto error;
+ }
+ /* Fill the resp cq ids. */
+ for (i = 0; i < num_cqs; i++) {
+ qs[i]->id = le16_to_cpu(res->q_id) + i;
+ qs[i]->db_regaddr = db_regaddr;
+ }
+ }With the goto in the true block the else block is not needed.
+ + dma_free_coherent(&sli4->pci->dev, dma.size, dma.virt, dma.phys); + + return EFC_SUCCESS; + +error: + for (i = 0; i < num_cqs; i++) + __sli_queue_destroy(sli4, qs[i]); + + if (dma.virt) + dma_free_coherent(&sli4->pci->dev, dma.size, dma.virt, + dma.phys); + + return EFC_FAIL; +}
[...]
+int
+sli_eq_read(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
+{
+ u8 *qe = q->dma.virt;
+ u32 *qindex = NULL;
+ unsigned long flags = 0;
+ u8 clear = false, valid = false;
+ u16 wflags = 0;
+
+ clear = (sli4->if_type == SLI4_INTF_IF_TYPE_6) ? false : true;
+
+ qindex = &q->index;
+
+ spin_lock_irqsave(&q->lock, flags);First, why does the q->index access not be protected by the lock and second, why do you need the variable anyway? Can't you just use q->index directly?
+
+ qe += *qindex * q->size;
+
+ /* Check if eqe is valid */
+ wflags = le16_to_cpu(((struct sli4_eqe *)qe)->dw0w0_flags);
+ valid = ((wflags & SLI4_EQE_VALID) == q->phase);
+ if (!valid) {valid is not used anywhere else. It could be avoided.
+ spin_unlock_irqrestore(&q->lock, flags);
+ return EFC_FAIL;
+ }
+
+ if (clear) {Clear is a local variable only used once here. And why do the comparison right here where it's needed?
+ wflags &= ~SLI4_EQE_VALID;
+ ((struct sli4_eqe *)qe)->dw0w0_flags =
+ cpu_to_le16(wflags);
+ }
+
+ memcpy(entry, qe, q->size);
+ *qindex = (*qindex + 1) & (q->length - 1);
+ q->n_posted++;
+ /*
+ * For prism, the phase value will be used
+ * to check the validity of eq/cq entries.
+ * The value toggles after a complete sweep
+ * through the queue.
+ */
+
+ if (sli4->if_type == SLI4_INTF_IF_TYPE_6 && *qindex == 0)
+ q->phase ^= (u16)0x1;
+
+ spin_unlock_irqrestore(&q->lock, flags);
+
+ return EFC_SUCCESS;
+}
+
+int
+sli_cq_read(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
+{
+ u8 *qe = q->dma.virt;
+ u32 *qindex = NULL;
+ unsigned long flags = 0;
+ u8 clear = false;
+ u32 dwflags = 0;
+ bool valid_bit_set;
+
+ clear = (sli4->if_type == SLI4_INTF_IF_TYPE_6) ? false : true;
+
+ qindex = &q->index;
+
+ spin_lock_irqsave(&q->lock, flags);The same question as above about q->index.
+
+ qe += *qindex * q->size;
+
+ /* Check if cqe is valid */
+ dwflags = le32_to_cpu(((struct sli4_mcqe *)qe)->dw3_flags);
+ valid_bit_set = (dwflags & SLI4_MCQE_VALID) != 0;
+
+ if (valid_bit_set != q->phase) {
+ spin_unlock_irqrestore(&q->lock, flags);
+ return EFC_FAIL;
+ }
+
+ if (clear) {Same comment as in the above function on 'clear'.
+ dwflags &= ~SLI4_MCQE_VALID;
+ ((struct sli4_mcqe *)qe)->dw3_flags =
+ cpu_to_le32(dwflags);
+ }
+
+ memcpy(entry, qe, q->size);
+ *qindex = (*qindex + 1) & (q->length - 1);
+ q->n_posted++;
+ /*
+ * For prism, the phase value will be used
+ * to check the validity of eq/cq entries.
+ * The value toggles after a complete sweep
+ * through the queue.
+ */
+
+ if (sli4->if_type == SLI4_INTF_IF_TYPE_6 && *qindex == 0)
+ q->phase ^= (u16)0x1;
+
+ spin_unlock_irqrestore(&q->lock, flags);
+
+ return EFC_SUCCESS;
+}
+
+int
+sli_mq_read(struct sli4 *sli4, struct sli4_queue *q, u8 *entry)
+{
+ u8 *qe = q->dma.virt;
+ u32 *qindex = NULL;
+ unsigned long flags = 0;
+
+ qindex = &q->u.r_idx;
+
+ spin_lock_irqsave(&q->lock, flags);qindex again.
+
+ qe += *qindex * q->size;
+
+ /* Check if mqe is valid */
+ if (q->index == q->u.r_idx) {
+ spin_unlock_irqrestore(&q->lock, flags);
+ return EFC_FAIL;
+ }
+
+ memcpy(entry, qe, q->size);
+ *qindex = (*qindex + 1) & (q->length - 1);
+
+ spin_unlock_irqrestore(&q->lock, flags);
+
+ return EFC_SUCCESS;
+}Thanks, Daniel