162306a36Sopenharmony_ci/**********************************************************************
262306a36Sopenharmony_ci * Author: Cavium, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Contact: support@cavium.com
562306a36Sopenharmony_ci *          Please include "LiquidIO" in the subject.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
1162306a36Sopenharmony_ci * published by the Free Software Foundation.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
1662306a36Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more details.
1762306a36Sopenharmony_ci ***********************************************************************/
1862306a36Sopenharmony_ci#include <linux/pci.h>
1962306a36Sopenharmony_ci#include <linux/netdevice.h>
2062306a36Sopenharmony_ci#include "liquidio_common.h"
2162306a36Sopenharmony_ci#include "octeon_droq.h"
2262306a36Sopenharmony_ci#include "octeon_iq.h"
2362306a36Sopenharmony_ci#include "response_manager.h"
2462306a36Sopenharmony_ci#include "octeon_device.h"
2562306a36Sopenharmony_ci#include "octeon_main.h"
2662306a36Sopenharmony_ci#include "octeon_mailbox.h"
2762306a36Sopenharmony_ci#include "cn23xx_pf_device.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/**
3062306a36Sopenharmony_ci * octeon_mbox_read:
3162306a36Sopenharmony_ci * @mbox: Pointer mailbox
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * Reads the 8-bytes of data from the mbox register
3462306a36Sopenharmony_ci * Writes back the acknowldgement inidcating completion of read
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_ciint octeon_mbox_read(struct octeon_mbox *mbox)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	union octeon_mbox_message msg;
3962306a36Sopenharmony_ci	int ret = 0;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	spin_lock(&mbox->lock);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	msg.u64 = readq(mbox->mbox_read_reg);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	if ((msg.u64 == OCTEON_PFVFACK) || (msg.u64 == OCTEON_PFVFSIG)) {
4662306a36Sopenharmony_ci		spin_unlock(&mbox->lock);
4762306a36Sopenharmony_ci		return 0;
4862306a36Sopenharmony_ci	}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
5162306a36Sopenharmony_ci		mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] = msg.u64;
5262306a36Sopenharmony_ci		mbox->mbox_req.recv_len++;
5362306a36Sopenharmony_ci	} else {
5462306a36Sopenharmony_ci		if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
5562306a36Sopenharmony_ci			mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] =
5662306a36Sopenharmony_ci				msg.u64;
5762306a36Sopenharmony_ci			mbox->mbox_resp.recv_len++;
5862306a36Sopenharmony_ci		} else {
5962306a36Sopenharmony_ci			if ((mbox->state & OCTEON_MBOX_STATE_IDLE) &&
6062306a36Sopenharmony_ci			    (msg.s.type == OCTEON_MBOX_REQUEST)) {
6162306a36Sopenharmony_ci				mbox->state &= ~OCTEON_MBOX_STATE_IDLE;
6262306a36Sopenharmony_ci				mbox->state |=
6362306a36Sopenharmony_ci				    OCTEON_MBOX_STATE_REQUEST_RECEIVING;
6462306a36Sopenharmony_ci				mbox->mbox_req.msg.u64 = msg.u64;
6562306a36Sopenharmony_ci				mbox->mbox_req.q_no = mbox->q_no;
6662306a36Sopenharmony_ci				mbox->mbox_req.recv_len = 1;
6762306a36Sopenharmony_ci			} else {
6862306a36Sopenharmony_ci				if ((mbox->state &
6962306a36Sopenharmony_ci				     OCTEON_MBOX_STATE_RESPONSE_PENDING) &&
7062306a36Sopenharmony_ci				    (msg.s.type == OCTEON_MBOX_RESPONSE)) {
7162306a36Sopenharmony_ci					mbox->state &=
7262306a36Sopenharmony_ci					    ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
7362306a36Sopenharmony_ci					mbox->state |=
7462306a36Sopenharmony_ci					    OCTEON_MBOX_STATE_RESPONSE_RECEIVING
7562306a36Sopenharmony_ci					    ;
7662306a36Sopenharmony_ci					mbox->mbox_resp.msg.u64 = msg.u64;
7762306a36Sopenharmony_ci					mbox->mbox_resp.q_no = mbox->q_no;
7862306a36Sopenharmony_ci					mbox->mbox_resp.recv_len = 1;
7962306a36Sopenharmony_ci				} else {
8062306a36Sopenharmony_ci					writeq(OCTEON_PFVFERR,
8162306a36Sopenharmony_ci					       mbox->mbox_read_reg);
8262306a36Sopenharmony_ci					mbox->state |= OCTEON_MBOX_STATE_ERROR;
8362306a36Sopenharmony_ci					spin_unlock(&mbox->lock);
8462306a36Sopenharmony_ci					return 1;
8562306a36Sopenharmony_ci				}
8662306a36Sopenharmony_ci			}
8762306a36Sopenharmony_ci		}
8862306a36Sopenharmony_ci	}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
9162306a36Sopenharmony_ci		if (mbox->mbox_req.recv_len < mbox->mbox_req.msg.s.len) {
9262306a36Sopenharmony_ci			ret = 0;
9362306a36Sopenharmony_ci		} else {
9462306a36Sopenharmony_ci			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVING;
9562306a36Sopenharmony_ci			mbox->state |= OCTEON_MBOX_STATE_REQUEST_RECEIVED;
9662306a36Sopenharmony_ci			ret = 1;
9762306a36Sopenharmony_ci		}
9862306a36Sopenharmony_ci	} else {
9962306a36Sopenharmony_ci		if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
10062306a36Sopenharmony_ci			if (mbox->mbox_resp.recv_len <
10162306a36Sopenharmony_ci			    mbox->mbox_resp.msg.s.len) {
10262306a36Sopenharmony_ci				ret = 0;
10362306a36Sopenharmony_ci			} else {
10462306a36Sopenharmony_ci				mbox->state &=
10562306a36Sopenharmony_ci				    ~OCTEON_MBOX_STATE_RESPONSE_RECEIVING;
10662306a36Sopenharmony_ci				mbox->state |=
10762306a36Sopenharmony_ci				    OCTEON_MBOX_STATE_RESPONSE_RECEIVED;
10862306a36Sopenharmony_ci				ret = 1;
10962306a36Sopenharmony_ci			}
11062306a36Sopenharmony_ci		} else {
11162306a36Sopenharmony_ci			WARN_ON(1);
11262306a36Sopenharmony_ci		}
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	writeq(OCTEON_PFVFACK, mbox->mbox_read_reg);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	spin_unlock(&mbox->lock);
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	return ret;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/**
12362306a36Sopenharmony_ci * octeon_mbox_write:
12462306a36Sopenharmony_ci * @oct: Pointer Octeon Device
12562306a36Sopenharmony_ci * @mbox_cmd: Cmd to send to mailbox.
12662306a36Sopenharmony_ci *
12762306a36Sopenharmony_ci * Populates the queue specific mbox structure
12862306a36Sopenharmony_ci * with cmd information.
12962306a36Sopenharmony_ci * Write the cmd to mbox register
13062306a36Sopenharmony_ci */
13162306a36Sopenharmony_ciint octeon_mbox_write(struct octeon_device *oct,
13262306a36Sopenharmony_ci		      struct octeon_mbox_cmd *mbox_cmd)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	struct octeon_mbox *mbox = oct->mbox[mbox_cmd->q_no];
13562306a36Sopenharmony_ci	u32 count, i, ret = OCTEON_MBOX_STATUS_SUCCESS;
13662306a36Sopenharmony_ci	long timeout = LIO_MBOX_WRITE_WAIT_TIME;
13762306a36Sopenharmony_ci	unsigned long flags;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	spin_lock_irqsave(&mbox->lock, flags);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	if ((mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) &&
14262306a36Sopenharmony_ci	    !(mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED)) {
14362306a36Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
14462306a36Sopenharmony_ci		return OCTEON_MBOX_STATUS_FAILED;
14562306a36Sopenharmony_ci	}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	if ((mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) &&
14862306a36Sopenharmony_ci	    !(mbox->state & OCTEON_MBOX_STATE_IDLE)) {
14962306a36Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
15062306a36Sopenharmony_ci		return OCTEON_MBOX_STATUS_BUSY;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) {
15462306a36Sopenharmony_ci		memcpy(&mbox->mbox_resp, mbox_cmd,
15562306a36Sopenharmony_ci		       sizeof(struct octeon_mbox_cmd));
15662306a36Sopenharmony_ci		mbox->state = OCTEON_MBOX_STATE_RESPONSE_PENDING;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	spin_unlock_irqrestore(&mbox->lock, flags);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	count = 0;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	while (readq(mbox->mbox_write_reg) != OCTEON_PFVFSIG) {
16462306a36Sopenharmony_ci		schedule_timeout_uninterruptible(timeout);
16562306a36Sopenharmony_ci		if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
16662306a36Sopenharmony_ci			ret = OCTEON_MBOX_STATUS_FAILED;
16762306a36Sopenharmony_ci			break;
16862306a36Sopenharmony_ci		}
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	if (ret == OCTEON_MBOX_STATUS_SUCCESS) {
17262306a36Sopenharmony_ci		writeq(mbox_cmd->msg.u64, mbox->mbox_write_reg);
17362306a36Sopenharmony_ci		for (i = 0; i < (u32)(mbox_cmd->msg.s.len - 1); i++) {
17462306a36Sopenharmony_ci			count = 0;
17562306a36Sopenharmony_ci			while (readq(mbox->mbox_write_reg) !=
17662306a36Sopenharmony_ci			       OCTEON_PFVFACK) {
17762306a36Sopenharmony_ci				schedule_timeout_uninterruptible(timeout);
17862306a36Sopenharmony_ci				if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
17962306a36Sopenharmony_ci					ret = OCTEON_MBOX_STATUS_FAILED;
18062306a36Sopenharmony_ci					break;
18162306a36Sopenharmony_ci				}
18262306a36Sopenharmony_ci			}
18362306a36Sopenharmony_ci			if (ret == OCTEON_MBOX_STATUS_SUCCESS)
18462306a36Sopenharmony_ci				writeq(mbox_cmd->data[i], mbox->mbox_write_reg);
18562306a36Sopenharmony_ci			else
18662306a36Sopenharmony_ci				break;
18762306a36Sopenharmony_ci		}
18862306a36Sopenharmony_ci	}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	spin_lock_irqsave(&mbox->lock, flags);
19162306a36Sopenharmony_ci	if (mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) {
19262306a36Sopenharmony_ci		mbox->state = OCTEON_MBOX_STATE_IDLE;
19362306a36Sopenharmony_ci		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
19462306a36Sopenharmony_ci	} else {
19562306a36Sopenharmony_ci		if ((!mbox_cmd->msg.s.resp_needed) ||
19662306a36Sopenharmony_ci		    (ret == OCTEON_MBOX_STATUS_FAILED)) {
19762306a36Sopenharmony_ci			mbox->state &= ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
19862306a36Sopenharmony_ci			if (!(mbox->state &
19962306a36Sopenharmony_ci			      (OCTEON_MBOX_STATE_REQUEST_RECEIVING |
20062306a36Sopenharmony_ci			       OCTEON_MBOX_STATE_REQUEST_RECEIVED)))
20162306a36Sopenharmony_ci				mbox->state = OCTEON_MBOX_STATE_IDLE;
20262306a36Sopenharmony_ci		}
20362306a36Sopenharmony_ci	}
20462306a36Sopenharmony_ci	spin_unlock_irqrestore(&mbox->lock, flags);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	return ret;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic void get_vf_stats(struct octeon_device *oct,
21062306a36Sopenharmony_ci			 struct oct_vf_stats *stats)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	int i;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	for (i = 0; i < oct->num_iqs; i++) {
21562306a36Sopenharmony_ci		if (!oct->instr_queue[i])
21662306a36Sopenharmony_ci			continue;
21762306a36Sopenharmony_ci		stats->tx_packets += oct->instr_queue[i]->stats.tx_done;
21862306a36Sopenharmony_ci		stats->tx_bytes += oct->instr_queue[i]->stats.tx_tot_bytes;
21962306a36Sopenharmony_ci	}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	for (i = 0; i < oct->num_oqs; i++) {
22262306a36Sopenharmony_ci		if (!oct->droq[i])
22362306a36Sopenharmony_ci			continue;
22462306a36Sopenharmony_ci		stats->rx_packets += oct->droq[i]->stats.rx_pkts_received;
22562306a36Sopenharmony_ci		stats->rx_bytes += oct->droq[i]->stats.rx_bytes_received;
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci/**
23062306a36Sopenharmony_ci * octeon_mbox_process_cmd:
23162306a36Sopenharmony_ci * @mbox: Pointer mailbox
23262306a36Sopenharmony_ci * @mbox_cmd: Pointer to command received
23362306a36Sopenharmony_ci *
23462306a36Sopenharmony_ci * Process the cmd received in mbox
23562306a36Sopenharmony_ci */
23662306a36Sopenharmony_cistatic int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
23762306a36Sopenharmony_ci				   struct octeon_mbox_cmd *mbox_cmd)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	struct octeon_device *oct = mbox->oct_dev;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	switch (mbox_cmd->msg.s.cmd) {
24262306a36Sopenharmony_ci	case OCTEON_VF_ACTIVE:
24362306a36Sopenharmony_ci		dev_dbg(&oct->pci_dev->dev, "got vfactive sending data back\n");
24462306a36Sopenharmony_ci		mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
24562306a36Sopenharmony_ci		mbox_cmd->msg.s.resp_needed = 1;
24662306a36Sopenharmony_ci		mbox_cmd->msg.s.len = 2;
24762306a36Sopenharmony_ci		mbox_cmd->data[0] = 0; /* VF version is in mbox_cmd->data[0] */
24862306a36Sopenharmony_ci		((struct lio_version *)&mbox_cmd->data[0])->major =
24962306a36Sopenharmony_ci			LIQUIDIO_BASE_MAJOR_VERSION;
25062306a36Sopenharmony_ci		((struct lio_version *)&mbox_cmd->data[0])->minor =
25162306a36Sopenharmony_ci			LIQUIDIO_BASE_MINOR_VERSION;
25262306a36Sopenharmony_ci		((struct lio_version *)&mbox_cmd->data[0])->micro =
25362306a36Sopenharmony_ci			LIQUIDIO_BASE_MICRO_VERSION;
25462306a36Sopenharmony_ci		memcpy(mbox_cmd->msg.s.params, (uint8_t *)&oct->pfvf_hsword, 6);
25562306a36Sopenharmony_ci		/* Sending core cofig info to the corresponding active VF.*/
25662306a36Sopenharmony_ci		octeon_mbox_write(oct, mbox_cmd);
25762306a36Sopenharmony_ci		break;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	case OCTEON_VF_FLR_REQUEST:
26062306a36Sopenharmony_ci		dev_info(&oct->pci_dev->dev,
26162306a36Sopenharmony_ci			 "got a request for FLR from VF that owns DPI ring %u\n",
26262306a36Sopenharmony_ci			 mbox->q_no);
26362306a36Sopenharmony_ci		pcie_flr(oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no]);
26462306a36Sopenharmony_ci		break;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	case OCTEON_PF_CHANGED_VF_MACADDR:
26762306a36Sopenharmony_ci		if (OCTEON_CN23XX_VF(oct))
26862306a36Sopenharmony_ci			octeon_pf_changed_vf_macaddr(oct,
26962306a36Sopenharmony_ci						     mbox_cmd->msg.s.params);
27062306a36Sopenharmony_ci		break;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	case OCTEON_GET_VF_STATS:
27362306a36Sopenharmony_ci		dev_dbg(&oct->pci_dev->dev, "Got VF stats request. Sending data back\n");
27462306a36Sopenharmony_ci		mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
27562306a36Sopenharmony_ci		mbox_cmd->msg.s.resp_needed = 1;
27662306a36Sopenharmony_ci		mbox_cmd->msg.s.len = 1 +
27762306a36Sopenharmony_ci			sizeof(struct oct_vf_stats) / sizeof(u64);
27862306a36Sopenharmony_ci		get_vf_stats(oct, (struct oct_vf_stats *)mbox_cmd->data);
27962306a36Sopenharmony_ci		octeon_mbox_write(oct, mbox_cmd);
28062306a36Sopenharmony_ci		break;
28162306a36Sopenharmony_ci	default:
28262306a36Sopenharmony_ci		break;
28362306a36Sopenharmony_ci	}
28462306a36Sopenharmony_ci	return 0;
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci/**
28862306a36Sopenharmony_ci * octeon_mbox_process_message
28962306a36Sopenharmony_ci * @mbox: mailbox
29062306a36Sopenharmony_ci *
29162306a36Sopenharmony_ci * Process the received mbox message.
29262306a36Sopenharmony_ci */
29362306a36Sopenharmony_ciint octeon_mbox_process_message(struct octeon_mbox *mbox)
29462306a36Sopenharmony_ci{
29562306a36Sopenharmony_ci	struct octeon_mbox_cmd mbox_cmd;
29662306a36Sopenharmony_ci	unsigned long flags;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	spin_lock_irqsave(&mbox->lock, flags);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_ERROR) {
30162306a36Sopenharmony_ci		if (mbox->state & (OCTEON_MBOX_STATE_RESPONSE_PENDING |
30262306a36Sopenharmony_ci				   OCTEON_MBOX_STATE_RESPONSE_RECEIVING)) {
30362306a36Sopenharmony_ci			memcpy(&mbox_cmd, &mbox->mbox_resp,
30462306a36Sopenharmony_ci			       sizeof(struct octeon_mbox_cmd));
30562306a36Sopenharmony_ci			mbox->state = OCTEON_MBOX_STATE_IDLE;
30662306a36Sopenharmony_ci			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
30762306a36Sopenharmony_ci			spin_unlock_irqrestore(&mbox->lock, flags);
30862306a36Sopenharmony_ci			mbox_cmd.recv_status = 1;
30962306a36Sopenharmony_ci			if (mbox_cmd.fn)
31062306a36Sopenharmony_ci				mbox_cmd.fn(mbox->oct_dev, &mbox_cmd,
31162306a36Sopenharmony_ci					    mbox_cmd.fn_arg);
31262306a36Sopenharmony_ci			return 0;
31362306a36Sopenharmony_ci		}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci		mbox->state = OCTEON_MBOX_STATE_IDLE;
31662306a36Sopenharmony_ci		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
31762306a36Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
31862306a36Sopenharmony_ci		return 0;
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVED) {
32262306a36Sopenharmony_ci		memcpy(&mbox_cmd, &mbox->mbox_resp,
32362306a36Sopenharmony_ci		       sizeof(struct octeon_mbox_cmd));
32462306a36Sopenharmony_ci		mbox->state = OCTEON_MBOX_STATE_IDLE;
32562306a36Sopenharmony_ci		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
32662306a36Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
32762306a36Sopenharmony_ci		mbox_cmd.recv_status = 0;
32862306a36Sopenharmony_ci		if (mbox_cmd.fn)
32962306a36Sopenharmony_ci			mbox_cmd.fn(mbox->oct_dev, &mbox_cmd, mbox_cmd.fn_arg);
33062306a36Sopenharmony_ci		return 0;
33162306a36Sopenharmony_ci	}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED) {
33462306a36Sopenharmony_ci		memcpy(&mbox_cmd, &mbox->mbox_req,
33562306a36Sopenharmony_ci		       sizeof(struct octeon_mbox_cmd));
33662306a36Sopenharmony_ci		if (!mbox_cmd.msg.s.resp_needed) {
33762306a36Sopenharmony_ci			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVED;
33862306a36Sopenharmony_ci			if (!(mbox->state &
33962306a36Sopenharmony_ci			      OCTEON_MBOX_STATE_RESPONSE_PENDING))
34062306a36Sopenharmony_ci				mbox->state = OCTEON_MBOX_STATE_IDLE;
34162306a36Sopenharmony_ci			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
34262306a36Sopenharmony_ci		}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
34562306a36Sopenharmony_ci		octeon_mbox_process_cmd(mbox, &mbox_cmd);
34662306a36Sopenharmony_ci		return 0;
34762306a36Sopenharmony_ci	}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	spin_unlock_irqrestore(&mbox->lock, flags);
35062306a36Sopenharmony_ci	WARN_ON(1);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	return 0;
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ciint octeon_mbox_cancel(struct octeon_device *oct, int q_no)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci	struct octeon_mbox *mbox = oct->mbox[q_no];
35862306a36Sopenharmony_ci	struct octeon_mbox_cmd *mbox_cmd;
35962306a36Sopenharmony_ci	unsigned long flags = 0;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	spin_lock_irqsave(&mbox->lock, flags);
36262306a36Sopenharmony_ci	mbox_cmd = &mbox->mbox_resp;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	if (!(mbox->state & OCTEON_MBOX_STATE_RESPONSE_PENDING)) {
36562306a36Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
36662306a36Sopenharmony_ci		return 1;
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	mbox->state = OCTEON_MBOX_STATE_IDLE;
37062306a36Sopenharmony_ci	memset(mbox_cmd, 0, sizeof(*mbox_cmd));
37162306a36Sopenharmony_ci	writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
37262306a36Sopenharmony_ci	spin_unlock_irqrestore(&mbox->lock, flags);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	return 0;
37562306a36Sopenharmony_ci}
376