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