|
@@ -39,72 +39,55 @@
|
|
#include <linux/spinlock.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/prefetch.h>
|
|
#include <linux/prefetch.h>
|
|
|
|
+#include <linux/delay.h>
|
|
|
|
+
|
|
#include "roce_hsi.h"
|
|
#include "roce_hsi.h"
|
|
#include "qplib_res.h"
|
|
#include "qplib_res.h"
|
|
#include "qplib_rcfw.h"
|
|
#include "qplib_rcfw.h"
|
|
static void bnxt_qplib_service_creq(unsigned long data);
|
|
static void bnxt_qplib_service_creq(unsigned long data);
|
|
|
|
|
|
/* Hardware communication channel */
|
|
/* Hardware communication channel */
|
|
-int bnxt_qplib_rcfw_wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
|
|
|
|
|
|
+static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
|
|
{
|
|
{
|
|
u16 cbit;
|
|
u16 cbit;
|
|
int rc;
|
|
int rc;
|
|
|
|
|
|
- cookie &= RCFW_MAX_COOKIE_VALUE;
|
|
|
|
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
|
|
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
|
|
- if (!test_bit(cbit, rcfw->cmdq_bitmap))
|
|
|
|
- dev_warn(&rcfw->pdev->dev,
|
|
|
|
- "QPLIB: CMD bit %d for cookie 0x%x is not set?",
|
|
|
|
- cbit, cookie);
|
|
|
|
-
|
|
|
|
rc = wait_event_timeout(rcfw->waitq,
|
|
rc = wait_event_timeout(rcfw->waitq,
|
|
!test_bit(cbit, rcfw->cmdq_bitmap),
|
|
!test_bit(cbit, rcfw->cmdq_bitmap),
|
|
msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS));
|
|
msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS));
|
|
- if (!rc) {
|
|
|
|
- dev_warn(&rcfw->pdev->dev,
|
|
|
|
- "QPLIB: Bono Error: timeout %d msec, msg {0x%x}\n",
|
|
|
|
- RCFW_CMD_WAIT_TIME_MS, cookie);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return rc;
|
|
|
|
|
|
+ return rc ? 0 : -ETIMEDOUT;
|
|
};
|
|
};
|
|
|
|
|
|
-int bnxt_qplib_rcfw_block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
|
|
|
|
|
|
+static int __block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
|
|
{
|
|
{
|
|
- u32 count = -1;
|
|
|
|
|
|
+ u32 count = RCFW_BLOCKED_CMD_WAIT_COUNT;
|
|
u16 cbit;
|
|
u16 cbit;
|
|
|
|
|
|
- cookie &= RCFW_MAX_COOKIE_VALUE;
|
|
|
|
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
|
|
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
|
|
if (!test_bit(cbit, rcfw->cmdq_bitmap))
|
|
if (!test_bit(cbit, rcfw->cmdq_bitmap))
|
|
goto done;
|
|
goto done;
|
|
do {
|
|
do {
|
|
|
|
+ mdelay(1); /* 1m sec */
|
|
bnxt_qplib_service_creq((unsigned long)rcfw);
|
|
bnxt_qplib_service_creq((unsigned long)rcfw);
|
|
} while (test_bit(cbit, rcfw->cmdq_bitmap) && --count);
|
|
} while (test_bit(cbit, rcfw->cmdq_bitmap) && --count);
|
|
done:
|
|
done:
|
|
- return count;
|
|
|
|
|
|
+ return count ? 0 : -ETIMEDOUT;
|
|
};
|
|
};
|
|
|
|
|
|
-void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
|
|
|
|
- struct cmdq_base *req, void **crsbe,
|
|
|
|
- u8 is_block)
|
|
|
|
|
|
+static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
|
|
|
|
+ struct creq_base *resp, void *sb, u8 is_block)
|
|
{
|
|
{
|
|
- struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
|
|
|
|
struct bnxt_qplib_cmdqe *cmdqe, **cmdq_ptr;
|
|
struct bnxt_qplib_cmdqe *cmdqe, **cmdq_ptr;
|
|
struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
|
|
struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
|
|
- struct bnxt_qplib_hwq *crsb = &rcfw->crsb;
|
|
|
|
- struct bnxt_qplib_crsqe *crsqe = NULL;
|
|
|
|
- struct bnxt_qplib_crsbe **crsb_ptr;
|
|
|
|
|
|
+ struct bnxt_qplib_crsq *crsqe;
|
|
u32 sw_prod, cmdq_prod;
|
|
u32 sw_prod, cmdq_prod;
|
|
- u8 retry_cnt = 0xFF;
|
|
|
|
- dma_addr_t dma_addr;
|
|
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
u32 size, opcode;
|
|
u32 size, opcode;
|
|
u16 cookie, cbit;
|
|
u16 cookie, cbit;
|
|
int pg, idx;
|
|
int pg, idx;
|
|
u8 *preq;
|
|
u8 *preq;
|
|
|
|
|
|
-retry:
|
|
|
|
opcode = req->opcode;
|
|
opcode = req->opcode;
|
|
if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
|
|
if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
|
|
(opcode != CMDQ_BASE_OPCODE_QUERY_FUNC &&
|
|
(opcode != CMDQ_BASE_OPCODE_QUERY_FUNC &&
|
|
@@ -112,63 +95,50 @@ retry:
|
|
dev_err(&rcfw->pdev->dev,
|
|
dev_err(&rcfw->pdev->dev,
|
|
"QPLIB: RCFW not initialized, reject opcode 0x%x",
|
|
"QPLIB: RCFW not initialized, reject opcode 0x%x",
|
|
opcode);
|
|
opcode);
|
|
- return NULL;
|
|
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
if (test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
|
|
if (test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
|
|
opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) {
|
|
opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) {
|
|
dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!");
|
|
dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!");
|
|
- return NULL;
|
|
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
/* Cmdq are in 16-byte units, each request can consume 1 or more
|
|
/* Cmdq are in 16-byte units, each request can consume 1 or more
|
|
* cmdqe
|
|
* cmdqe
|
|
*/
|
|
*/
|
|
spin_lock_irqsave(&cmdq->lock, flags);
|
|
spin_lock_irqsave(&cmdq->lock, flags);
|
|
- if (req->cmd_size > cmdq->max_elements -
|
|
|
|
- ((HWQ_CMP(cmdq->prod, cmdq) - HWQ_CMP(cmdq->cons, cmdq)) &
|
|
|
|
- (cmdq->max_elements - 1))) {
|
|
|
|
|
|
+ if (req->cmd_size >= HWQ_FREE_SLOTS(cmdq)) {
|
|
dev_err(&rcfw->pdev->dev, "QPLIB: RCFW: CMDQ is full!");
|
|
dev_err(&rcfw->pdev->dev, "QPLIB: RCFW: CMDQ is full!");
|
|
spin_unlock_irqrestore(&cmdq->lock, flags);
|
|
spin_unlock_irqrestore(&cmdq->lock, flags);
|
|
-
|
|
|
|
- if (!retry_cnt--)
|
|
|
|
- return NULL;
|
|
|
|
- goto retry;
|
|
|
|
|
|
+ return -EAGAIN;
|
|
}
|
|
}
|
|
|
|
|
|
- retry_cnt = 0xFF;
|
|
|
|
|
|
|
|
- cookie = atomic_inc_return(&rcfw->seq_num) & RCFW_MAX_COOKIE_VALUE;
|
|
|
|
|
|
+ cookie = rcfw->seq_num & RCFW_MAX_COOKIE_VALUE;
|
|
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
|
|
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
|
|
if (is_block)
|
|
if (is_block)
|
|
cookie |= RCFW_CMD_IS_BLOCKING;
|
|
cookie |= RCFW_CMD_IS_BLOCKING;
|
|
|
|
+
|
|
|
|
+ set_bit(cbit, rcfw->cmdq_bitmap);
|
|
req->cookie = cpu_to_le16(cookie);
|
|
req->cookie = cpu_to_le16(cookie);
|
|
- if (test_and_set_bit(cbit, rcfw->cmdq_bitmap)) {
|
|
|
|
- dev_err(&rcfw->pdev->dev,
|
|
|
|
- "QPLIB: RCFW MAX outstanding cmd reached!");
|
|
|
|
- atomic_dec(&rcfw->seq_num);
|
|
|
|
|
|
+ crsqe = &rcfw->crsqe_tbl[cbit];
|
|
|
|
+ if (crsqe->resp) {
|
|
spin_unlock_irqrestore(&cmdq->lock, flags);
|
|
spin_unlock_irqrestore(&cmdq->lock, flags);
|
|
-
|
|
|
|
- if (!retry_cnt--)
|
|
|
|
- return NULL;
|
|
|
|
- goto retry;
|
|
|
|
|
|
+ return -EBUSY;
|
|
}
|
|
}
|
|
- /* Reserve a resp buffer slot if requested */
|
|
|
|
- if (req->resp_size && crsbe) {
|
|
|
|
- spin_lock(&crsb->lock);
|
|
|
|
- sw_prod = HWQ_CMP(crsb->prod, crsb);
|
|
|
|
- crsb_ptr = (struct bnxt_qplib_crsbe **)crsb->pbl_ptr;
|
|
|
|
- *crsbe = (void *)&crsb_ptr[get_crsb_pg(sw_prod)]
|
|
|
|
- [get_crsb_idx(sw_prod)];
|
|
|
|
- bnxt_qplib_crsb_dma_next(crsb->pbl_dma_ptr, sw_prod, &dma_addr);
|
|
|
|
- req->resp_addr = cpu_to_le64(dma_addr);
|
|
|
|
- crsb->prod++;
|
|
|
|
- spin_unlock(&crsb->lock);
|
|
|
|
-
|
|
|
|
- req->resp_size = (sizeof(struct bnxt_qplib_crsbe) +
|
|
|
|
- BNXT_QPLIB_CMDQE_UNITS - 1) /
|
|
|
|
- BNXT_QPLIB_CMDQE_UNITS;
|
|
|
|
|
|
+ memset(resp, 0, sizeof(*resp));
|
|
|
|
+ crsqe->resp = (struct creq_qp_event *)resp;
|
|
|
|
+ crsqe->resp->cookie = req->cookie;
|
|
|
|
+ crsqe->req_size = req->cmd_size;
|
|
|
|
+ if (req->resp_size && sb) {
|
|
|
|
+ struct bnxt_qplib_rcfw_sbuf *sbuf = sb;
|
|
|
|
+
|
|
|
|
+ req->resp_addr = cpu_to_le64(sbuf->dma_addr);
|
|
|
|
+ req->resp_size = (sbuf->size + BNXT_QPLIB_CMDQE_UNITS - 1) /
|
|
|
|
+ BNXT_QPLIB_CMDQE_UNITS;
|
|
}
|
|
}
|
|
|
|
+
|
|
cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
|
|
cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
|
|
preq = (u8 *)req;
|
|
preq = (u8 *)req;
|
|
size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
|
|
size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
|
|
@@ -190,23 +160,24 @@ retry:
|
|
preq += min_t(u32, size, sizeof(*cmdqe));
|
|
preq += min_t(u32, size, sizeof(*cmdqe));
|
|
size -= min_t(u32, size, sizeof(*cmdqe));
|
|
size -= min_t(u32, size, sizeof(*cmdqe));
|
|
cmdq->prod++;
|
|
cmdq->prod++;
|
|
|
|
+ rcfw->seq_num++;
|
|
} while (size > 0);
|
|
} while (size > 0);
|
|
|
|
|
|
|
|
+ rcfw->seq_num++;
|
|
|
|
+
|
|
cmdq_prod = cmdq->prod;
|
|
cmdq_prod = cmdq->prod;
|
|
if (rcfw->flags & FIRMWARE_FIRST_FLAG) {
|
|
if (rcfw->flags & FIRMWARE_FIRST_FLAG) {
|
|
- /* The very first doorbell write is required to set this flag
|
|
|
|
- * which prompts the FW to reset its internal pointers
|
|
|
|
|
|
+ /* The very first doorbell write
|
|
|
|
+ * is required to set this flag
|
|
|
|
+ * which prompts the FW to reset
|
|
|
|
+ * its internal pointers
|
|
*/
|
|
*/
|
|
cmdq_prod |= FIRMWARE_FIRST_FLAG;
|
|
cmdq_prod |= FIRMWARE_FIRST_FLAG;
|
|
rcfw->flags &= ~FIRMWARE_FIRST_FLAG;
|
|
rcfw->flags &= ~FIRMWARE_FIRST_FLAG;
|
|
}
|
|
}
|
|
- sw_prod = HWQ_CMP(crsq->prod, crsq);
|
|
|
|
- crsqe = &crsq->crsq[sw_prod];
|
|
|
|
- memset(crsqe, 0, sizeof(*crsqe));
|
|
|
|
- crsq->prod++;
|
|
|
|
- crsqe->req_size = req->cmd_size;
|
|
|
|
|
|
|
|
/* ring CMDQ DB */
|
|
/* ring CMDQ DB */
|
|
|
|
+ wmb();
|
|
writel(cmdq_prod, rcfw->cmdq_bar_reg_iomem +
|
|
writel(cmdq_prod, rcfw->cmdq_bar_reg_iomem +
|
|
rcfw->cmdq_bar_reg_prod_off);
|
|
rcfw->cmdq_bar_reg_prod_off);
|
|
writel(RCFW_CMDQ_TRIG_VAL, rcfw->cmdq_bar_reg_iomem +
|
|
writel(RCFW_CMDQ_TRIG_VAL, rcfw->cmdq_bar_reg_iomem +
|
|
@@ -214,9 +185,56 @@ retry:
|
|
done:
|
|
done:
|
|
spin_unlock_irqrestore(&cmdq->lock, flags);
|
|
spin_unlock_irqrestore(&cmdq->lock, flags);
|
|
/* Return the CREQ response pointer */
|
|
/* Return the CREQ response pointer */
|
|
- return crsqe ? &crsqe->qp_event : NULL;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
|
|
|
|
+ struct cmdq_base *req,
|
|
|
|
+ struct creq_base *resp,
|
|
|
|
+ void *sb, u8 is_block)
|
|
|
|
+{
|
|
|
|
+ struct creq_qp_event *evnt = (struct creq_qp_event *)resp;
|
|
|
|
+ u16 cookie;
|
|
|
|
+ u8 opcode, retry_cnt = 0xFF;
|
|
|
|
+ int rc = 0;
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ opcode = req->opcode;
|
|
|
|
+ rc = __send_message(rcfw, req, resp, sb, is_block);
|
|
|
|
+ cookie = le16_to_cpu(req->cookie) & RCFW_MAX_COOKIE_VALUE;
|
|
|
|
+ if (!rc)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ if (!retry_cnt || (rc != -EAGAIN && rc != -EBUSY)) {
|
|
|
|
+ /* send failed */
|
|
|
|
+ dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x send failed",
|
|
|
|
+ cookie, opcode);
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
|
|
+ is_block ? mdelay(1) : usleep_range(500, 1000);
|
|
|
|
+
|
|
|
|
+ } while (retry_cnt--);
|
|
|
|
+
|
|
|
|
+ if (is_block)
|
|
|
|
+ rc = __block_for_resp(rcfw, cookie);
|
|
|
|
+ else
|
|
|
|
+ rc = __wait_for_resp(rcfw, cookie);
|
|
|
|
+ if (rc) {
|
|
|
|
+ /* timed out */
|
|
|
|
+ dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x timedout (%d)msec",
|
|
|
|
+ cookie, opcode, RCFW_CMD_WAIT_TIME_MS);
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (evnt->status) {
|
|
|
|
+ /* failed with status */
|
|
|
|
+ dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x status %#x",
|
|
|
|
+ cookie, opcode, evnt->status);
|
|
|
|
+ rc = -EFAULT;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
/* Completions */
|
|
/* Completions */
|
|
static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
|
|
static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
|
|
struct creq_func_event *func_event)
|
|
struct creq_func_event *func_event)
|
|
@@ -260,12 +278,12 @@ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
|
|
static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
|
|
static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
|
|
struct creq_qp_event *qp_event)
|
|
struct creq_qp_event *qp_event)
|
|
{
|
|
{
|
|
- struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
|
|
|
|
struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
|
|
struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
|
|
- struct bnxt_qplib_crsqe *crsqe;
|
|
|
|
- u16 cbit, cookie, blocked = 0;
|
|
|
|
|
|
+ struct bnxt_qplib_crsq *crsqe;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
- u32 sw_cons;
|
|
|
|
|
|
+ u16 cbit, blocked = 0;
|
|
|
|
+ u16 cookie;
|
|
|
|
+ __le16 mcookie;
|
|
|
|
|
|
switch (qp_event->event) {
|
|
switch (qp_event->event) {
|
|
case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION:
|
|
case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION:
|
|
@@ -275,24 +293,31 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
|
|
default:
|
|
default:
|
|
/* Command Response */
|
|
/* Command Response */
|
|
spin_lock_irqsave(&cmdq->lock, flags);
|
|
spin_lock_irqsave(&cmdq->lock, flags);
|
|
- sw_cons = HWQ_CMP(crsq->cons, crsq);
|
|
|
|
- crsqe = &crsq->crsq[sw_cons];
|
|
|
|
- crsq->cons++;
|
|
|
|
- memcpy(&crsqe->qp_event, qp_event, sizeof(crsqe->qp_event));
|
|
|
|
-
|
|
|
|
- cookie = le16_to_cpu(crsqe->qp_event.cookie);
|
|
|
|
|
|
+ cookie = le16_to_cpu(qp_event->cookie);
|
|
|
|
+ mcookie = qp_event->cookie;
|
|
blocked = cookie & RCFW_CMD_IS_BLOCKING;
|
|
blocked = cookie & RCFW_CMD_IS_BLOCKING;
|
|
cookie &= RCFW_MAX_COOKIE_VALUE;
|
|
cookie &= RCFW_MAX_COOKIE_VALUE;
|
|
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
|
|
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
|
|
|
|
+ crsqe = &rcfw->crsqe_tbl[cbit];
|
|
|
|
+ if (crsqe->resp &&
|
|
|
|
+ crsqe->resp->cookie == mcookie) {
|
|
|
|
+ memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
|
|
|
|
+ crsqe->resp = NULL;
|
|
|
|
+ } else {
|
|
|
|
+ dev_err(&rcfw->pdev->dev,
|
|
|
|
+ "QPLIB: CMD %s resp->cookie = %#x, evnt->cookie = %#x",
|
|
|
|
+ crsqe->resp ? "mismatch" : "collision",
|
|
|
|
+ crsqe->resp ? crsqe->resp->cookie : 0, mcookie);
|
|
|
|
+ }
|
|
if (!test_and_clear_bit(cbit, rcfw->cmdq_bitmap))
|
|
if (!test_and_clear_bit(cbit, rcfw->cmdq_bitmap))
|
|
dev_warn(&rcfw->pdev->dev,
|
|
dev_warn(&rcfw->pdev->dev,
|
|
"QPLIB: CMD bit %d was not requested", cbit);
|
|
"QPLIB: CMD bit %d was not requested", cbit);
|
|
-
|
|
|
|
cmdq->cons += crsqe->req_size;
|
|
cmdq->cons += crsqe->req_size;
|
|
- spin_unlock_irqrestore(&cmdq->lock, flags);
|
|
|
|
|
|
+ crsqe->req_size = 0;
|
|
|
|
+
|
|
if (!blocked)
|
|
if (!blocked)
|
|
wake_up(&rcfw->waitq);
|
|
wake_up(&rcfw->waitq);
|
|
- break;
|
|
|
|
|
|
+ spin_unlock_irqrestore(&cmdq->lock, flags);
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -305,12 +330,12 @@ static void bnxt_qplib_service_creq(unsigned long data)
|
|
struct creq_base *creqe, **creq_ptr;
|
|
struct creq_base *creqe, **creq_ptr;
|
|
u32 sw_cons, raw_cons;
|
|
u32 sw_cons, raw_cons;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
- u32 type;
|
|
|
|
|
|
+ u32 type, budget = CREQ_ENTRY_POLL_BUDGET;
|
|
|
|
|
|
- /* Service the CREQ until empty */
|
|
|
|
|
|
+ /* Service the CREQ until budget is over */
|
|
spin_lock_irqsave(&creq->lock, flags);
|
|
spin_lock_irqsave(&creq->lock, flags);
|
|
raw_cons = creq->cons;
|
|
raw_cons = creq->cons;
|
|
- while (1) {
|
|
|
|
|
|
+ while (budget > 0) {
|
|
sw_cons = HWQ_CMP(raw_cons, creq);
|
|
sw_cons = HWQ_CMP(raw_cons, creq);
|
|
creq_ptr = (struct creq_base **)creq->pbl_ptr;
|
|
creq_ptr = (struct creq_base **)creq->pbl_ptr;
|
|
creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)];
|
|
creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)];
|
|
@@ -320,15 +345,9 @@ static void bnxt_qplib_service_creq(unsigned long data)
|
|
type = creqe->type & CREQ_BASE_TYPE_MASK;
|
|
type = creqe->type & CREQ_BASE_TYPE_MASK;
|
|
switch (type) {
|
|
switch (type) {
|
|
case CREQ_BASE_TYPE_QP_EVENT:
|
|
case CREQ_BASE_TYPE_QP_EVENT:
|
|
- if (!bnxt_qplib_process_qp_event
|
|
|
|
- (rcfw, (struct creq_qp_event *)creqe))
|
|
|
|
- rcfw->creq_qp_event_processed++;
|
|
|
|
- else {
|
|
|
|
- dev_warn(&rcfw->pdev->dev, "QPLIB: crsqe with");
|
|
|
|
- dev_warn(&rcfw->pdev->dev,
|
|
|
|
- "QPLIB: type = 0x%x not handled",
|
|
|
|
- type);
|
|
|
|
- }
|
|
|
|
|
|
+ bnxt_qplib_process_qp_event
|
|
|
|
+ (rcfw, (struct creq_qp_event *)creqe);
|
|
|
|
+ rcfw->creq_qp_event_processed++;
|
|
break;
|
|
break;
|
|
case CREQ_BASE_TYPE_FUNC_EVENT:
|
|
case CREQ_BASE_TYPE_FUNC_EVENT:
|
|
if (!bnxt_qplib_process_func_event
|
|
if (!bnxt_qplib_process_func_event
|
|
@@ -346,7 +365,9 @@ static void bnxt_qplib_service_creq(unsigned long data)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
raw_cons++;
|
|
raw_cons++;
|
|
|
|
+ budget--;
|
|
}
|
|
}
|
|
|
|
+
|
|
if (creq->cons != raw_cons) {
|
|
if (creq->cons != raw_cons) {
|
|
creq->cons = raw_cons;
|
|
creq->cons = raw_cons;
|
|
CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, raw_cons,
|
|
CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, raw_cons,
|
|
@@ -375,23 +396,16 @@ static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance)
|
|
/* RCFW */
|
|
/* RCFW */
|
|
int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw)
|
|
int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw)
|
|
{
|
|
{
|
|
- struct creq_deinitialize_fw_resp *resp;
|
|
|
|
struct cmdq_deinitialize_fw req;
|
|
struct cmdq_deinitialize_fw req;
|
|
|
|
+ struct creq_deinitialize_fw_resp resp;
|
|
u16 cmd_flags = 0;
|
|
u16 cmd_flags = 0;
|
|
|
|
+ int rc;
|
|
|
|
|
|
RCFW_CMD_PREP(req, DEINITIALIZE_FW, cmd_flags);
|
|
RCFW_CMD_PREP(req, DEINITIALIZE_FW, cmd_flags);
|
|
- resp = (struct creq_deinitialize_fw_resp *)
|
|
|
|
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
|
|
|
|
- NULL, 0);
|
|
|
|
- if (!resp)
|
|
|
|
- return -EINVAL;
|
|
|
|
-
|
|
|
|
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie)))
|
|
|
|
- return -ETIMEDOUT;
|
|
|
|
-
|
|
|
|
- if (resp->status ||
|
|
|
|
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie))
|
|
|
|
- return -EFAULT;
|
|
|
|
|
|
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
|
|
|
|
+ NULL, 0);
|
|
|
|
+ if (rc)
|
|
|
|
+ return rc;
|
|
|
|
|
|
clear_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
|
|
clear_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
|
|
return 0;
|
|
return 0;
|
|
@@ -417,9 +431,10 @@ static int __get_pbl_pg_idx(struct bnxt_qplib_pbl *pbl)
|
|
int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
|
|
int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
|
|
struct bnxt_qplib_ctx *ctx, int is_virtfn)
|
|
struct bnxt_qplib_ctx *ctx, int is_virtfn)
|
|
{
|
|
{
|
|
- struct creq_initialize_fw_resp *resp;
|
|
|
|
struct cmdq_initialize_fw req;
|
|
struct cmdq_initialize_fw req;
|
|
|
|
+ struct creq_initialize_fw_resp resp;
|
|
u16 cmd_flags = 0, level;
|
|
u16 cmd_flags = 0, level;
|
|
|
|
+ int rc;
|
|
|
|
|
|
RCFW_CMD_PREP(req, INITIALIZE_FW, cmd_flags);
|
|
RCFW_CMD_PREP(req, INITIALIZE_FW, cmd_flags);
|
|
|
|
|
|
@@ -482,37 +497,19 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
|
|
|
|
|
|
skip_ctx_setup:
|
|
skip_ctx_setup:
|
|
req.stat_ctx_id = cpu_to_le32(ctx->stats.fw_id);
|
|
req.stat_ctx_id = cpu_to_le32(ctx->stats.fw_id);
|
|
- resp = (struct creq_initialize_fw_resp *)
|
|
|
|
- bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
|
|
|
|
- NULL, 0);
|
|
|
|
- if (!resp) {
|
|
|
|
- dev_err(&rcfw->pdev->dev,
|
|
|
|
- "QPLIB: RCFW: INITIALIZE_FW send failed");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
- if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
|
|
|
|
- /* Cmd timed out */
|
|
|
|
- dev_err(&rcfw->pdev->dev,
|
|
|
|
- "QPLIB: RCFW: INITIALIZE_FW timed out");
|
|
|
|
- return -ETIMEDOUT;
|
|
|
|
- }
|
|
|
|
- if (resp->status ||
|
|
|
|
- le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
|
|
|
|
- dev_err(&rcfw->pdev->dev,
|
|
|
|
- "QPLIB: RCFW: INITIALIZE_FW failed");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
|
|
+ rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
|
|
|
|
+ NULL, 0);
|
|
|
|
+ if (rc)
|
|
|
|
+ return rc;
|
|
set_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
|
|
set_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
|
|
void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
|
|
{
|
|
{
|
|
- bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->crsb);
|
|
|
|
- kfree(rcfw->crsq.crsq);
|
|
|
|
|
|
+ kfree(rcfw->crsqe_tbl);
|
|
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->cmdq);
|
|
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->cmdq);
|
|
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->creq);
|
|
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->creq);
|
|
-
|
|
|
|
rcfw->pdev = NULL;
|
|
rcfw->pdev = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -539,21 +536,11 @@ int bnxt_qplib_alloc_rcfw_channel(struct pci_dev *pdev,
|
|
goto fail;
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
|
|
- rcfw->crsq.max_elements = rcfw->cmdq.max_elements;
|
|
|
|
- rcfw->crsq.crsq = kcalloc(rcfw->crsq.max_elements,
|
|
|
|
- sizeof(*rcfw->crsq.crsq), GFP_KERNEL);
|
|
|
|
- if (!rcfw->crsq.crsq)
|
|
|
|
|
|
+ rcfw->crsqe_tbl = kcalloc(rcfw->cmdq.max_elements,
|
|
|
|
+ sizeof(*rcfw->crsqe_tbl), GFP_KERNEL);
|
|
|
|
+ if (!rcfw->crsqe_tbl)
|
|
goto fail;
|
|
goto fail;
|
|
|
|
|
|
- rcfw->crsb.max_elements = BNXT_QPLIB_CRSBE_MAX_CNT;
|
|
|
|
- if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->crsb, NULL, 0,
|
|
|
|
- &rcfw->crsb.max_elements,
|
|
|
|
- BNXT_QPLIB_CRSBE_UNITS, 0, PAGE_SIZE,
|
|
|
|
- HWQ_TYPE_CTX)) {
|
|
|
|
- dev_err(&rcfw->pdev->dev,
|
|
|
|
- "QPLIB: HW channel CRSB allocation failed");
|
|
|
|
- goto fail;
|
|
|
|
- }
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
fail:
|
|
fail:
|
|
@@ -606,7 +593,7 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
|
|
int rc;
|
|
int rc;
|
|
|
|
|
|
/* General */
|
|
/* General */
|
|
- atomic_set(&rcfw->seq_num, 0);
|
|
|
|
|
|
+ rcfw->seq_num = 0;
|
|
rcfw->flags = FIRMWARE_FIRST_FLAG;
|
|
rcfw->flags = FIRMWARE_FIRST_FLAG;
|
|
bmap_size = BITS_TO_LONGS(RCFW_MAX_OUTSTANDING_CMD *
|
|
bmap_size = BITS_TO_LONGS(RCFW_MAX_OUTSTANDING_CMD *
|
|
sizeof(unsigned long));
|
|
sizeof(unsigned long));
|
|
@@ -636,10 +623,6 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
|
|
|
|
|
|
rcfw->cmdq_bar_reg_trig_off = RCFW_COMM_TRIG_OFFSET;
|
|
rcfw->cmdq_bar_reg_trig_off = RCFW_COMM_TRIG_OFFSET;
|
|
|
|
|
|
- /* CRSQ */
|
|
|
|
- rcfw->crsq.prod = 0;
|
|
|
|
- rcfw->crsq.cons = 0;
|
|
|
|
-
|
|
|
|
/* CREQ */
|
|
/* CREQ */
|
|
rcfw->creq_bar_reg = RCFW_COMM_CONS_PCI_BAR_REGION;
|
|
rcfw->creq_bar_reg = RCFW_COMM_CONS_PCI_BAR_REGION;
|
|
res_base = pci_resource_start(pdev, rcfw->creq_bar_reg);
|
|
res_base = pci_resource_start(pdev, rcfw->creq_bar_reg);
|
|
@@ -692,3 +675,34 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
|
|
__iowrite32_copy(rcfw->cmdq_bar_reg_iomem, &init, sizeof(init) / 4);
|
|
__iowrite32_copy(rcfw->cmdq_bar_reg_iomem, &init, sizeof(init) / 4);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
|
|
|
|
+ struct bnxt_qplib_rcfw *rcfw,
|
|
|
|
+ u32 size)
|
|
|
|
+{
|
|
|
|
+ struct bnxt_qplib_rcfw_sbuf *sbuf;
|
|
|
|
+
|
|
|
|
+ sbuf = kzalloc(sizeof(*sbuf), GFP_ATOMIC);
|
|
|
|
+ if (!sbuf)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ sbuf->size = size;
|
|
|
|
+ sbuf->sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf->size,
|
|
|
|
+ &sbuf->dma_addr, GFP_ATOMIC);
|
|
|
|
+ if (!sbuf->sb)
|
|
|
|
+ goto bail;
|
|
|
|
+
|
|
|
|
+ return sbuf;
|
|
|
|
+bail:
|
|
|
|
+ kfree(sbuf);
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
|
|
|
|
+ struct bnxt_qplib_rcfw_sbuf *sbuf)
|
|
|
|
+{
|
|
|
|
+ if (sbuf->sb)
|
|
|
|
+ dma_free_coherent(&rcfw->pdev->dev, sbuf->size,
|
|
|
|
+ sbuf->sb, sbuf->dma_addr);
|
|
|
|
+ kfree(sbuf);
|
|
|
|
+}
|