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