18c2ecf20Sopenharmony_ci/**********************************************************************
28c2ecf20Sopenharmony_ci * Author: Cavium, Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Contact: support@cavium.com
58c2ecf20Sopenharmony_ci *          Please include "LiquidIO" in the subject.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
118c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
168c2ecf20Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more details.
178c2ecf20Sopenharmony_ci ***********************************************************************/
188c2ecf20Sopenharmony_ci#include <linux/pci.h>
198c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
208c2ecf20Sopenharmony_ci#include "liquidio_common.h"
218c2ecf20Sopenharmony_ci#include "octeon_droq.h"
228c2ecf20Sopenharmony_ci#include "octeon_iq.h"
238c2ecf20Sopenharmony_ci#include "response_manager.h"
248c2ecf20Sopenharmony_ci#include "octeon_device.h"
258c2ecf20Sopenharmony_ci#include "octeon_main.h"
268c2ecf20Sopenharmony_ci#include "octeon_mailbox.h"
278c2ecf20Sopenharmony_ci#include "cn23xx_pf_device.h"
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/**
308c2ecf20Sopenharmony_ci * octeon_mbox_read:
318c2ecf20Sopenharmony_ci * @mbox: Pointer mailbox
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci * Reads the 8-bytes of data from the mbox register
348c2ecf20Sopenharmony_ci * Writes back the acknowldgement inidcating completion of read
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ciint octeon_mbox_read(struct octeon_mbox *mbox)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	union octeon_mbox_message msg;
398c2ecf20Sopenharmony_ci	int ret = 0;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	spin_lock(&mbox->lock);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	msg.u64 = readq(mbox->mbox_read_reg);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	if ((msg.u64 == OCTEON_PFVFACK) || (msg.u64 == OCTEON_PFVFSIG)) {
468c2ecf20Sopenharmony_ci		spin_unlock(&mbox->lock);
478c2ecf20Sopenharmony_ci		return 0;
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
518c2ecf20Sopenharmony_ci		mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] = msg.u64;
528c2ecf20Sopenharmony_ci		mbox->mbox_req.recv_len++;
538c2ecf20Sopenharmony_ci	} else {
548c2ecf20Sopenharmony_ci		if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
558c2ecf20Sopenharmony_ci			mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] =
568c2ecf20Sopenharmony_ci				msg.u64;
578c2ecf20Sopenharmony_ci			mbox->mbox_resp.recv_len++;
588c2ecf20Sopenharmony_ci		} else {
598c2ecf20Sopenharmony_ci			if ((mbox->state & OCTEON_MBOX_STATE_IDLE) &&
608c2ecf20Sopenharmony_ci			    (msg.s.type == OCTEON_MBOX_REQUEST)) {
618c2ecf20Sopenharmony_ci				mbox->state &= ~OCTEON_MBOX_STATE_IDLE;
628c2ecf20Sopenharmony_ci				mbox->state |=
638c2ecf20Sopenharmony_ci				    OCTEON_MBOX_STATE_REQUEST_RECEIVING;
648c2ecf20Sopenharmony_ci				mbox->mbox_req.msg.u64 = msg.u64;
658c2ecf20Sopenharmony_ci				mbox->mbox_req.q_no = mbox->q_no;
668c2ecf20Sopenharmony_ci				mbox->mbox_req.recv_len = 1;
678c2ecf20Sopenharmony_ci			} else {
688c2ecf20Sopenharmony_ci				if ((mbox->state &
698c2ecf20Sopenharmony_ci				     OCTEON_MBOX_STATE_RESPONSE_PENDING) &&
708c2ecf20Sopenharmony_ci				    (msg.s.type == OCTEON_MBOX_RESPONSE)) {
718c2ecf20Sopenharmony_ci					mbox->state &=
728c2ecf20Sopenharmony_ci					    ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
738c2ecf20Sopenharmony_ci					mbox->state |=
748c2ecf20Sopenharmony_ci					    OCTEON_MBOX_STATE_RESPONSE_RECEIVING
758c2ecf20Sopenharmony_ci					    ;
768c2ecf20Sopenharmony_ci					mbox->mbox_resp.msg.u64 = msg.u64;
778c2ecf20Sopenharmony_ci					mbox->mbox_resp.q_no = mbox->q_no;
788c2ecf20Sopenharmony_ci					mbox->mbox_resp.recv_len = 1;
798c2ecf20Sopenharmony_ci				} else {
808c2ecf20Sopenharmony_ci					writeq(OCTEON_PFVFERR,
818c2ecf20Sopenharmony_ci					       mbox->mbox_read_reg);
828c2ecf20Sopenharmony_ci					mbox->state |= OCTEON_MBOX_STATE_ERROR;
838c2ecf20Sopenharmony_ci					spin_unlock(&mbox->lock);
848c2ecf20Sopenharmony_ci					return 1;
858c2ecf20Sopenharmony_ci				}
868c2ecf20Sopenharmony_ci			}
878c2ecf20Sopenharmony_ci		}
888c2ecf20Sopenharmony_ci	}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
918c2ecf20Sopenharmony_ci		if (mbox->mbox_req.recv_len < mbox->mbox_req.msg.s.len) {
928c2ecf20Sopenharmony_ci			ret = 0;
938c2ecf20Sopenharmony_ci		} else {
948c2ecf20Sopenharmony_ci			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVING;
958c2ecf20Sopenharmony_ci			mbox->state |= OCTEON_MBOX_STATE_REQUEST_RECEIVED;
968c2ecf20Sopenharmony_ci			ret = 1;
978c2ecf20Sopenharmony_ci		}
988c2ecf20Sopenharmony_ci	} else {
998c2ecf20Sopenharmony_ci		if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
1008c2ecf20Sopenharmony_ci			if (mbox->mbox_resp.recv_len <
1018c2ecf20Sopenharmony_ci			    mbox->mbox_resp.msg.s.len) {
1028c2ecf20Sopenharmony_ci				ret = 0;
1038c2ecf20Sopenharmony_ci			} else {
1048c2ecf20Sopenharmony_ci				mbox->state &=
1058c2ecf20Sopenharmony_ci				    ~OCTEON_MBOX_STATE_RESPONSE_RECEIVING;
1068c2ecf20Sopenharmony_ci				mbox->state |=
1078c2ecf20Sopenharmony_ci				    OCTEON_MBOX_STATE_RESPONSE_RECEIVED;
1088c2ecf20Sopenharmony_ci				ret = 1;
1098c2ecf20Sopenharmony_ci			}
1108c2ecf20Sopenharmony_ci		} else {
1118c2ecf20Sopenharmony_ci			WARN_ON(1);
1128c2ecf20Sopenharmony_ci		}
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	writeq(OCTEON_PFVFACK, mbox->mbox_read_reg);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	spin_unlock(&mbox->lock);
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	return ret;
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci/**
1238c2ecf20Sopenharmony_ci * octeon_mbox_write:
1248c2ecf20Sopenharmony_ci * @oct: Pointer Octeon Device
1258c2ecf20Sopenharmony_ci * @mbox_cmd: Cmd to send to mailbox.
1268c2ecf20Sopenharmony_ci *
1278c2ecf20Sopenharmony_ci * Populates the queue specific mbox structure
1288c2ecf20Sopenharmony_ci * with cmd information.
1298c2ecf20Sopenharmony_ci * Write the cmd to mbox register
1308c2ecf20Sopenharmony_ci */
1318c2ecf20Sopenharmony_ciint octeon_mbox_write(struct octeon_device *oct,
1328c2ecf20Sopenharmony_ci		      struct octeon_mbox_cmd *mbox_cmd)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	struct octeon_mbox *mbox = oct->mbox[mbox_cmd->q_no];
1358c2ecf20Sopenharmony_ci	u32 count, i, ret = OCTEON_MBOX_STATUS_SUCCESS;
1368c2ecf20Sopenharmony_ci	long timeout = LIO_MBOX_WRITE_WAIT_TIME;
1378c2ecf20Sopenharmony_ci	unsigned long flags;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	spin_lock_irqsave(&mbox->lock, flags);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	if ((mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) &&
1428c2ecf20Sopenharmony_ci	    !(mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED)) {
1438c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
1448c2ecf20Sopenharmony_ci		return OCTEON_MBOX_STATUS_FAILED;
1458c2ecf20Sopenharmony_ci	}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	if ((mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) &&
1488c2ecf20Sopenharmony_ci	    !(mbox->state & OCTEON_MBOX_STATE_IDLE)) {
1498c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
1508c2ecf20Sopenharmony_ci		return OCTEON_MBOX_STATUS_BUSY;
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	if (mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) {
1548c2ecf20Sopenharmony_ci		memcpy(&mbox->mbox_resp, mbox_cmd,
1558c2ecf20Sopenharmony_ci		       sizeof(struct octeon_mbox_cmd));
1568c2ecf20Sopenharmony_ci		mbox->state = OCTEON_MBOX_STATE_RESPONSE_PENDING;
1578c2ecf20Sopenharmony_ci	}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&mbox->lock, flags);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	count = 0;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	while (readq(mbox->mbox_write_reg) != OCTEON_PFVFSIG) {
1648c2ecf20Sopenharmony_ci		schedule_timeout_uninterruptible(timeout);
1658c2ecf20Sopenharmony_ci		if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
1668c2ecf20Sopenharmony_ci			ret = OCTEON_MBOX_STATUS_FAILED;
1678c2ecf20Sopenharmony_ci			break;
1688c2ecf20Sopenharmony_ci		}
1698c2ecf20Sopenharmony_ci	}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (ret == OCTEON_MBOX_STATUS_SUCCESS) {
1728c2ecf20Sopenharmony_ci		writeq(mbox_cmd->msg.u64, mbox->mbox_write_reg);
1738c2ecf20Sopenharmony_ci		for (i = 0; i < (u32)(mbox_cmd->msg.s.len - 1); i++) {
1748c2ecf20Sopenharmony_ci			count = 0;
1758c2ecf20Sopenharmony_ci			while (readq(mbox->mbox_write_reg) !=
1768c2ecf20Sopenharmony_ci			       OCTEON_PFVFACK) {
1778c2ecf20Sopenharmony_ci				schedule_timeout_uninterruptible(timeout);
1788c2ecf20Sopenharmony_ci				if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
1798c2ecf20Sopenharmony_ci					ret = OCTEON_MBOX_STATUS_FAILED;
1808c2ecf20Sopenharmony_ci					break;
1818c2ecf20Sopenharmony_ci				}
1828c2ecf20Sopenharmony_ci			}
1838c2ecf20Sopenharmony_ci			if (ret == OCTEON_MBOX_STATUS_SUCCESS)
1848c2ecf20Sopenharmony_ci				writeq(mbox_cmd->data[i], mbox->mbox_write_reg);
1858c2ecf20Sopenharmony_ci			else
1868c2ecf20Sopenharmony_ci				break;
1878c2ecf20Sopenharmony_ci		}
1888c2ecf20Sopenharmony_ci	}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	spin_lock_irqsave(&mbox->lock, flags);
1918c2ecf20Sopenharmony_ci	if (mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) {
1928c2ecf20Sopenharmony_ci		mbox->state = OCTEON_MBOX_STATE_IDLE;
1938c2ecf20Sopenharmony_ci		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
1948c2ecf20Sopenharmony_ci	} else {
1958c2ecf20Sopenharmony_ci		if ((!mbox_cmd->msg.s.resp_needed) ||
1968c2ecf20Sopenharmony_ci		    (ret == OCTEON_MBOX_STATUS_FAILED)) {
1978c2ecf20Sopenharmony_ci			mbox->state &= ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
1988c2ecf20Sopenharmony_ci			if (!(mbox->state &
1998c2ecf20Sopenharmony_ci			      (OCTEON_MBOX_STATE_REQUEST_RECEIVING |
2008c2ecf20Sopenharmony_ci			       OCTEON_MBOX_STATE_REQUEST_RECEIVED)))
2018c2ecf20Sopenharmony_ci				mbox->state = OCTEON_MBOX_STATE_IDLE;
2028c2ecf20Sopenharmony_ci		}
2038c2ecf20Sopenharmony_ci	}
2048c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&mbox->lock, flags);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	return ret;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistatic void get_vf_stats(struct octeon_device *oct,
2108c2ecf20Sopenharmony_ci			 struct oct_vf_stats *stats)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	int i;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	for (i = 0; i < oct->num_iqs; i++) {
2158c2ecf20Sopenharmony_ci		if (!oct->instr_queue[i])
2168c2ecf20Sopenharmony_ci			continue;
2178c2ecf20Sopenharmony_ci		stats->tx_packets += oct->instr_queue[i]->stats.tx_done;
2188c2ecf20Sopenharmony_ci		stats->tx_bytes += oct->instr_queue[i]->stats.tx_tot_bytes;
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	for (i = 0; i < oct->num_oqs; i++) {
2228c2ecf20Sopenharmony_ci		if (!oct->droq[i])
2238c2ecf20Sopenharmony_ci			continue;
2248c2ecf20Sopenharmony_ci		stats->rx_packets += oct->droq[i]->stats.rx_pkts_received;
2258c2ecf20Sopenharmony_ci		stats->rx_bytes += oct->droq[i]->stats.rx_bytes_received;
2268c2ecf20Sopenharmony_ci	}
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci/**
2308c2ecf20Sopenharmony_ci * octeon_mbox_process_cmd:
2318c2ecf20Sopenharmony_ci * @mbox: Pointer mailbox
2328c2ecf20Sopenharmony_ci * @mbox_cmd: Pointer to command received
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * Process the cmd received in mbox
2358c2ecf20Sopenharmony_ci */
2368c2ecf20Sopenharmony_cistatic int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
2378c2ecf20Sopenharmony_ci				   struct octeon_mbox_cmd *mbox_cmd)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	struct octeon_device *oct = mbox->oct_dev;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	switch (mbox_cmd->msg.s.cmd) {
2428c2ecf20Sopenharmony_ci	case OCTEON_VF_ACTIVE:
2438c2ecf20Sopenharmony_ci		dev_dbg(&oct->pci_dev->dev, "got vfactive sending data back\n");
2448c2ecf20Sopenharmony_ci		mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
2458c2ecf20Sopenharmony_ci		mbox_cmd->msg.s.resp_needed = 1;
2468c2ecf20Sopenharmony_ci		mbox_cmd->msg.s.len = 2;
2478c2ecf20Sopenharmony_ci		mbox_cmd->data[0] = 0; /* VF version is in mbox_cmd->data[0] */
2488c2ecf20Sopenharmony_ci		((struct lio_version *)&mbox_cmd->data[0])->major =
2498c2ecf20Sopenharmony_ci			LIQUIDIO_BASE_MAJOR_VERSION;
2508c2ecf20Sopenharmony_ci		((struct lio_version *)&mbox_cmd->data[0])->minor =
2518c2ecf20Sopenharmony_ci			LIQUIDIO_BASE_MINOR_VERSION;
2528c2ecf20Sopenharmony_ci		((struct lio_version *)&mbox_cmd->data[0])->micro =
2538c2ecf20Sopenharmony_ci			LIQUIDIO_BASE_MICRO_VERSION;
2548c2ecf20Sopenharmony_ci		memcpy(mbox_cmd->msg.s.params, (uint8_t *)&oct->pfvf_hsword, 6);
2558c2ecf20Sopenharmony_ci		/* Sending core cofig info to the corresponding active VF.*/
2568c2ecf20Sopenharmony_ci		octeon_mbox_write(oct, mbox_cmd);
2578c2ecf20Sopenharmony_ci		break;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	case OCTEON_VF_FLR_REQUEST:
2608c2ecf20Sopenharmony_ci		dev_info(&oct->pci_dev->dev,
2618c2ecf20Sopenharmony_ci			 "got a request for FLR from VF that owns DPI ring %u\n",
2628c2ecf20Sopenharmony_ci			 mbox->q_no);
2638c2ecf20Sopenharmony_ci		pcie_flr(oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no]);
2648c2ecf20Sopenharmony_ci		break;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	case OCTEON_PF_CHANGED_VF_MACADDR:
2678c2ecf20Sopenharmony_ci		if (OCTEON_CN23XX_VF(oct))
2688c2ecf20Sopenharmony_ci			octeon_pf_changed_vf_macaddr(oct,
2698c2ecf20Sopenharmony_ci						     mbox_cmd->msg.s.params);
2708c2ecf20Sopenharmony_ci		break;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	case OCTEON_GET_VF_STATS:
2738c2ecf20Sopenharmony_ci		dev_dbg(&oct->pci_dev->dev, "Got VF stats request. Sending data back\n");
2748c2ecf20Sopenharmony_ci		mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
2758c2ecf20Sopenharmony_ci		mbox_cmd->msg.s.resp_needed = 1;
2768c2ecf20Sopenharmony_ci		mbox_cmd->msg.s.len = 1 +
2778c2ecf20Sopenharmony_ci			sizeof(struct oct_vf_stats) / sizeof(u64);
2788c2ecf20Sopenharmony_ci		get_vf_stats(oct, (struct oct_vf_stats *)mbox_cmd->data);
2798c2ecf20Sopenharmony_ci		octeon_mbox_write(oct, mbox_cmd);
2808c2ecf20Sopenharmony_ci		break;
2818c2ecf20Sopenharmony_ci	default:
2828c2ecf20Sopenharmony_ci		break;
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci	return 0;
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci/**
2888c2ecf20Sopenharmony_ci * octeon_mbox_process_message
2898c2ecf20Sopenharmony_ci * @mbox: mailbox
2908c2ecf20Sopenharmony_ci *
2918c2ecf20Sopenharmony_ci * Process the received mbox message.
2928c2ecf20Sopenharmony_ci */
2938c2ecf20Sopenharmony_ciint octeon_mbox_process_message(struct octeon_mbox *mbox)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	struct octeon_mbox_cmd mbox_cmd;
2968c2ecf20Sopenharmony_ci	unsigned long flags;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	spin_lock_irqsave(&mbox->lock, flags);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_ERROR) {
3018c2ecf20Sopenharmony_ci		if (mbox->state & (OCTEON_MBOX_STATE_RESPONSE_PENDING |
3028c2ecf20Sopenharmony_ci				   OCTEON_MBOX_STATE_RESPONSE_RECEIVING)) {
3038c2ecf20Sopenharmony_ci			memcpy(&mbox_cmd, &mbox->mbox_resp,
3048c2ecf20Sopenharmony_ci			       sizeof(struct octeon_mbox_cmd));
3058c2ecf20Sopenharmony_ci			mbox->state = OCTEON_MBOX_STATE_IDLE;
3068c2ecf20Sopenharmony_ci			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
3078c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&mbox->lock, flags);
3088c2ecf20Sopenharmony_ci			mbox_cmd.recv_status = 1;
3098c2ecf20Sopenharmony_ci			if (mbox_cmd.fn)
3108c2ecf20Sopenharmony_ci				mbox_cmd.fn(mbox->oct_dev, &mbox_cmd,
3118c2ecf20Sopenharmony_ci					    mbox_cmd.fn_arg);
3128c2ecf20Sopenharmony_ci			return 0;
3138c2ecf20Sopenharmony_ci		}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		mbox->state = OCTEON_MBOX_STATE_IDLE;
3168c2ecf20Sopenharmony_ci		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
3178c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
3188c2ecf20Sopenharmony_ci		return 0;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVED) {
3228c2ecf20Sopenharmony_ci		memcpy(&mbox_cmd, &mbox->mbox_resp,
3238c2ecf20Sopenharmony_ci		       sizeof(struct octeon_mbox_cmd));
3248c2ecf20Sopenharmony_ci		mbox->state = OCTEON_MBOX_STATE_IDLE;
3258c2ecf20Sopenharmony_ci		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
3268c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
3278c2ecf20Sopenharmony_ci		mbox_cmd.recv_status = 0;
3288c2ecf20Sopenharmony_ci		if (mbox_cmd.fn)
3298c2ecf20Sopenharmony_ci			mbox_cmd.fn(mbox->oct_dev, &mbox_cmd, mbox_cmd.fn_arg);
3308c2ecf20Sopenharmony_ci		return 0;
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED) {
3348c2ecf20Sopenharmony_ci		memcpy(&mbox_cmd, &mbox->mbox_req,
3358c2ecf20Sopenharmony_ci		       sizeof(struct octeon_mbox_cmd));
3368c2ecf20Sopenharmony_ci		if (!mbox_cmd.msg.s.resp_needed) {
3378c2ecf20Sopenharmony_ci			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVED;
3388c2ecf20Sopenharmony_ci			if (!(mbox->state &
3398c2ecf20Sopenharmony_ci			      OCTEON_MBOX_STATE_RESPONSE_PENDING))
3408c2ecf20Sopenharmony_ci				mbox->state = OCTEON_MBOX_STATE_IDLE;
3418c2ecf20Sopenharmony_ci			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
3428c2ecf20Sopenharmony_ci		}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
3458c2ecf20Sopenharmony_ci		octeon_mbox_process_cmd(mbox, &mbox_cmd);
3468c2ecf20Sopenharmony_ci		return 0;
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&mbox->lock, flags);
3508c2ecf20Sopenharmony_ci	WARN_ON(1);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	return 0;
3538c2ecf20Sopenharmony_ci}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ciint octeon_mbox_cancel(struct octeon_device *oct, int q_no)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	struct octeon_mbox *mbox = oct->mbox[q_no];
3588c2ecf20Sopenharmony_ci	struct octeon_mbox_cmd *mbox_cmd;
3598c2ecf20Sopenharmony_ci	unsigned long flags = 0;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	spin_lock_irqsave(&mbox->lock, flags);
3628c2ecf20Sopenharmony_ci	mbox_cmd = &mbox->mbox_resp;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	if (!(mbox->state & OCTEON_MBOX_STATE_RESPONSE_PENDING)) {
3658c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&mbox->lock, flags);
3668c2ecf20Sopenharmony_ci		return 1;
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	mbox->state = OCTEON_MBOX_STATE_IDLE;
3708c2ecf20Sopenharmony_ci	memset(mbox_cmd, 0, sizeof(*mbox_cmd));
3718c2ecf20Sopenharmony_ci	writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
3728c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&mbox->lock, flags);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	return 0;
3758c2ecf20Sopenharmony_ci}
376