Commit 4abe5a1b authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'hinic-BugFixes'



Luo bin says:

====================
hinic: BugFixes

Fix a number of bugs which have been present since the first commit.

The bugs fixed in these patchs are hardly exposed unless given
very specific conditions.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 07f8e4d0 7296695f
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -389,7 +389,8 @@ static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq,

	spin_unlock_bh(&cmdq->cmdq_lock);

	if (!wait_for_completion_timeout(&done, CMDQ_TIMEOUT)) {
	if (!wait_for_completion_timeout(&done,
					 msecs_to_jiffies(CMDQ_TIMEOUT))) {
		spin_lock_bh(&cmdq->cmdq_lock);

		if (cmdq->errcode[curr_prod_idx] == &errcode)
@@ -623,6 +624,8 @@ static int cmdq_cmd_ceq_handler(struct hinic_cmdq *cmdq, u16 ci,
	if (!CMDQ_WQE_COMPLETED(be32_to_cpu(ctrl->ctrl_info)))
		return -EBUSY;

	dma_rmb();

	errcode = CMDQ_WQE_ERRCODE_GET(be32_to_cpu(status->status_info), VAL);

	cmdq_sync_cmd_handler(cmdq, ci, errcode);
+2 −49
Original line number Diff line number Diff line
@@ -360,50 +360,6 @@ static int wait_for_db_state(struct hinic_hwdev *hwdev)
	return -EFAULT;
}

static int wait_for_io_stopped(struct hinic_hwdev *hwdev)
{
	struct hinic_cmd_io_status cmd_io_status;
	struct hinic_hwif *hwif = hwdev->hwif;
	struct pci_dev *pdev = hwif->pdev;
	struct hinic_pfhwdev *pfhwdev;
	unsigned long end;
	u16 out_size;
	int err;

	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
		return -EINVAL;
	}

	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);

	cmd_io_status.func_idx = HINIC_HWIF_FUNC_IDX(hwif);

	end = jiffies + msecs_to_jiffies(IO_STATUS_TIMEOUT);
	do {
		err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
					HINIC_COMM_CMD_IO_STATUS_GET,
					&cmd_io_status, sizeof(cmd_io_status),
					&cmd_io_status, &out_size,
					HINIC_MGMT_MSG_SYNC);
		if ((err) || (out_size != sizeof(cmd_io_status))) {
			dev_err(&pdev->dev, "Failed to get IO status, ret = %d\n",
				err);
			return err;
		}

		if (cmd_io_status.status == IO_STOPPED) {
			dev_info(&pdev->dev, "IO stopped\n");
			return 0;
		}

		msleep(20);
	} while (time_before(jiffies, end));

	dev_err(&pdev->dev, "Wait for IO stopped - Timeout\n");
	return -ETIMEDOUT;
}

/**
 * clear_io_resource - set the IO resources as not active in the NIC
 * @hwdev: the NIC HW device
@@ -423,11 +379,8 @@ static int clear_io_resources(struct hinic_hwdev *hwdev)
		return -EINVAL;
	}

	err = wait_for_io_stopped(hwdev);
	if (err) {
		dev_err(&pdev->dev, "IO has not stopped yet\n");
		return err;
	}
	/* sleep 100ms to wait for firmware stopping I/O */
	msleep(100);

	cmd_clear_io_res.func_idx = HINIC_HWIF_FUNC_IDX(hwif);

+19 −7
Original line number Diff line number Diff line
@@ -188,7 +188,7 @@ static u8 eq_cons_idx_checksum_set(u32 val)
 * eq_update_ci - update the HW cons idx of event queue
 * @eq: the event queue to update the cons idx for
 **/
static void eq_update_ci(struct hinic_eq *eq)
static void eq_update_ci(struct hinic_eq *eq, u32 arm_state)
{
	u32 val, addr = EQ_CONS_IDX_REG_ADDR(eq);

@@ -202,7 +202,7 @@ static void eq_update_ci(struct hinic_eq *eq)

	val |= HINIC_EQ_CI_SET(eq->cons_idx, IDX)    |
	       HINIC_EQ_CI_SET(eq->wrapped, WRAPPED) |
	       HINIC_EQ_CI_SET(EQ_ARMED, INT_ARMED);
	       HINIC_EQ_CI_SET(arm_state, INT_ARMED);

	val |= HINIC_EQ_CI_SET(eq_cons_idx_checksum_set(val), XOR_CHKSUM);

@@ -235,6 +235,8 @@ static void aeq_irq_handler(struct hinic_eq *eq)
		if (HINIC_EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED) == eq->wrapped)
			break;

		dma_rmb();

		event = HINIC_EQ_ELEM_DESC_GET(aeqe_desc, TYPE);
		if (event >= HINIC_MAX_AEQ_EVENTS) {
			dev_err(&pdev->dev, "Unknown AEQ Event %d\n", event);
@@ -347,7 +349,7 @@ static void eq_irq_handler(void *data)
	else if (eq->type == HINIC_CEQ)
		ceq_irq_handler(eq);

	eq_update_ci(eq);
	eq_update_ci(eq, EQ_ARMED);
}

/**
@@ -702,7 +704,7 @@ static int init_eq(struct hinic_eq *eq, struct hinic_hwif *hwif,
	}

	set_eq_ctrls(eq);
	eq_update_ci(eq);
	eq_update_ci(eq, EQ_ARMED);

	err = alloc_eq_pages(eq);
	if (err) {
@@ -752,18 +754,28 @@ err_req_irq:
 **/
static void remove_eq(struct hinic_eq *eq)
{
	struct msix_entry *entry = &eq->msix_entry;

	free_irq(entry->vector, eq);
	hinic_set_msix_state(eq->hwif, eq->msix_entry.entry,
			     HINIC_MSIX_DISABLE);
	free_irq(eq->msix_entry.vector, eq);

	if (eq->type == HINIC_AEQ) {
		struct hinic_eq_work *aeq_work = &eq->aeq_work;

		cancel_work_sync(&aeq_work->work);
		/* clear aeq_len to avoid hw access host memory */
		hinic_hwif_write_reg(eq->hwif,
				     HINIC_CSR_AEQ_CTRL_1_ADDR(eq->q_id), 0);
	} else if (eq->type == HINIC_CEQ) {
		tasklet_kill(&eq->ceq_tasklet);
		/* clear ceq_len to avoid hw access host memory */
		hinic_hwif_write_reg(eq->hwif,
				     HINIC_CSR_CEQ_CTRL_1_ADDR(eq->q_id), 0);
	}

	/* update cons_idx to avoid invalid interrupt */
	eq->cons_idx = hinic_hwif_read_reg(eq->hwif, EQ_PROD_IDX_REG_ADDR(eq));
	eq_update_ci(eq, EQ_NOT_ARMED);

	free_eq_pages(eq);
}

+3 −2
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@

#define MSG_NOT_RESP                    0xFFFF

#define MGMT_MSG_TIMEOUT                1000
#define MGMT_MSG_TIMEOUT                5000

#define mgmt_to_pfhwdev(pf_mgmt)        \
		container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
@@ -267,7 +267,8 @@ static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
		goto unlock_sync_msg;
	}

	if (!wait_for_completion_timeout(recv_done, MGMT_MSG_TIMEOUT)) {
	if (!wait_for_completion_timeout(recv_done,
					 msecs_to_jiffies(MGMT_MSG_TIMEOUT))) {
		dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
		err = -ETIMEDOUT;
		goto unlock_sync_msg;
+3 −0
Original line number Diff line number Diff line
@@ -350,6 +350,9 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget)
		if (!rq_wqe)
			break;

		/* make sure we read rx_done before packet length */
		dma_rmb();

		cqe = rq->cqe[ci];
		status =  be32_to_cpu(cqe->status);
		hinic_rq_get_sge(rxq->rq, rq_wqe, ci, &sge);
Loading