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

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
......@@ -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);
......
......@@ -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);
......
......@@ -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 @@ static int init_eq(struct hinic_eq *eq, struct hinic_hwif *hwif,
**/
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);
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -45,7 +45,7 @@
#define HW_CONS_IDX(sq) be16_to_cpu(*(u16 *)((sq)->hw_ci_addr))
#define MIN_SKB_LEN 17
#define MIN_SKB_LEN 32
#define MAX_PAYLOAD_OFFSET 221
#define TRANSPORT_OFFSET(l4_hdr, skb) ((u32)((l4_hdr) - (skb)->data))
......@@ -622,6 +622,8 @@ static int free_tx_poll(struct napi_struct *napi, int budget)
do {
hw_ci = HW_CONS_IDX(sq) & wq->mask;
dma_rmb();
/* Reading a WQEBB to get real WQE size and consumer index. */
sq_wqe = hinic_sq_read_wqebb(sq, &skb, &wqe_size, &sw_ci);
if ((!sq_wqe) ||
......
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