qed: Register slowpath queue doorbell with doorbell overflow recovery mechanism
authorAriel Elior <Ariel.Elior@cavium.com>
Wed, 28 Nov 2018 16:16:04 +0000 (18:16 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 30 Nov 2018 21:45:13 +0000 (13:45 -0800)
Slow path queue is a doorbelling entity. Register it with the overflow mechanism.

Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
Signed-off-by: Tomer Tayar <Tomer.Tayar@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qed/qed_sp.h
drivers/net/ethernet/qlogic/qed/qed_spq.c

index 3157c0d9944177e784a62ef983dd2adc3b5c0f11..4179c9013fc65fea92c132c927cdaf5bc5637fe4 100644 (file)
@@ -227,7 +227,9 @@ struct qed_spq {
        u32                     comp_count;
 
        u32                     cid;
-       qed_spq_async_comp_cb async_comp_cb[MAX_PROTOCOL_TYPE];
+       u32                     db_addr_offset;
+       struct core_db_data     db_data;
+       qed_spq_async_comp_cb   async_comp_cb[MAX_PROTOCOL_TYPE];
 };
 
 /**
index 0a9c5bb0fa486658a23132680a1aeddb9a72b518..eb88bbc6b1931adfa1c5d5760739fa0702e90dee 100644 (file)
@@ -252,9 +252,9 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
                           struct qed_spq *p_spq, struct qed_spq_entry *p_ent)
 {
        struct qed_chain *p_chain = &p_hwfn->p_spq->chain;
+       struct core_db_data *p_db_data = &p_spq->db_data;
        u16 echo = qed_chain_get_prod_idx(p_chain);
        struct slow_path_element        *elem;
-       struct core_db_data             db;
 
        p_ent->elem.hdr.echo    = cpu_to_le16(echo);
        elem = qed_chain_produce(p_chain);
@@ -266,27 +266,22 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
        *elem = p_ent->elem; /* struct assignment */
 
        /* send a doorbell on the slow hwfn session */
-       memset(&db, 0, sizeof(db));
-       SET_FIELD(db.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
-       SET_FIELD(db.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);
-       SET_FIELD(db.params, CORE_DB_DATA_AGG_VAL_SEL,
-                 DQ_XCM_CORE_SPQ_PROD_CMD);
-       db.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
-       db.spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
+       p_db_data->spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain));
 
        /* make sure the SPQE is updated before the doorbell */
        wmb();
 
-       DOORBELL(p_hwfn, qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY), *(u32 *)&db);
+       DOORBELL(p_hwfn, p_spq->db_addr_offset, *(u32 *)p_db_data);
 
        /* make sure doorbell is rang */
        wmb();
 
        DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
                   "Doorbelled [0x%08x, CID 0x%08x] with Flags: %02x agg_params: %02x, prod: %04x\n",
-                  qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY),
-                  p_spq->cid, db.params, db.agg_flags,
-                  qed_chain_get_prod_idx(p_chain));
+                  p_spq->db_addr_offset,
+                  p_spq->cid,
+                  p_db_data->params,
+                  p_db_data->agg_flags, qed_chain_get_prod_idx(p_chain));
 
        return 0;
 }
@@ -490,8 +485,11 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 {
        struct qed_spq *p_spq = p_hwfn->p_spq;
        struct qed_spq_entry *p_virt = NULL;
+       struct core_db_data *p_db_data;
+       void __iomem *db_addr;
        dma_addr_t p_phys = 0;
        u32 i, capacity;
+       int rc;
 
        INIT_LIST_HEAD(&p_spq->pending);
        INIT_LIST_HEAD(&p_spq->completion_pending);
@@ -528,6 +526,25 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
 
        /* reset the chain itself */
        qed_chain_reset(&p_spq->chain);
+
+       /* Initialize the address/data of the SPQ doorbell */
+       p_spq->db_addr_offset = qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY);
+       p_db_data = &p_spq->db_data;
+       memset(p_db_data, 0, sizeof(*p_db_data));
+       SET_FIELD(p_db_data->params, CORE_DB_DATA_DEST, DB_DEST_XCM);
+       SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_MAX);
+       SET_FIELD(p_db_data->params, CORE_DB_DATA_AGG_VAL_SEL,
+                 DQ_XCM_CORE_SPQ_PROD_CMD);
+       p_db_data->agg_flags = DQ_XCM_CORE_DQ_CF_CMD;
+
+       /* Register the SPQ doorbell with the doorbell recovery mechanism */
+       db_addr = (void __iomem *)((u8 __iomem *)p_hwfn->doorbells +
+                                  p_spq->db_addr_offset);
+       rc = qed_db_recovery_add(p_hwfn->cdev, db_addr, &p_spq->db_data,
+                                DB_REC_WIDTH_32B, DB_REC_KERNEL);
+       if (rc)
+               DP_INFO(p_hwfn,
+                       "Failed to register the SPQ doorbell with the doorbell recovery mechanism\n");
 }
 
 int qed_spq_alloc(struct qed_hwfn *p_hwfn)
@@ -575,11 +592,17 @@ spq_allocate_fail:
 void qed_spq_free(struct qed_hwfn *p_hwfn)
 {
        struct qed_spq *p_spq = p_hwfn->p_spq;
+       void __iomem *db_addr;
        u32 capacity;
 
        if (!p_spq)
                return;
 
+       /* Delete the SPQ doorbell from the doorbell recovery mechanism */
+       db_addr = (void __iomem *)((u8 __iomem *)p_hwfn->doorbells +
+                                  p_spq->db_addr_offset);
+       qed_db_recovery_del(p_hwfn->cdev, db_addr, &p_spq->db_data);
+
        if (p_spq->p_virt) {
                capacity = qed_chain_get_capacity(&p_spq->chain);
                dma_free_coherent(&p_hwfn->cdev->pdev->dev,