1*29c8d9ebSAdit Ranadive /* 2*29c8d9ebSAdit Ranadive * Copyright (c) 2012-2016 VMware, Inc. All rights reserved. 3*29c8d9ebSAdit Ranadive * 4*29c8d9ebSAdit Ranadive * This program is free software; you can redistribute it and/or 5*29c8d9ebSAdit Ranadive * modify it under the terms of EITHER the GNU General Public License 6*29c8d9ebSAdit Ranadive * version 2 as published by the Free Software Foundation or the BSD 7*29c8d9ebSAdit Ranadive * 2-Clause License. This program is distributed in the hope that it 8*29c8d9ebSAdit Ranadive * will be useful, but WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED 9*29c8d9ebSAdit Ranadive * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 10*29c8d9ebSAdit Ranadive * See the GNU General Public License version 2 for more details at 11*29c8d9ebSAdit Ranadive * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html. 12*29c8d9ebSAdit Ranadive * 13*29c8d9ebSAdit Ranadive * You should have received a copy of the GNU General Public License 14*29c8d9ebSAdit Ranadive * along with this program available in the file COPYING in the main 15*29c8d9ebSAdit Ranadive * directory of this source tree. 16*29c8d9ebSAdit Ranadive * 17*29c8d9ebSAdit Ranadive * The BSD 2-Clause License 18*29c8d9ebSAdit Ranadive * 19*29c8d9ebSAdit Ranadive * Redistribution and use in source and binary forms, with or 20*29c8d9ebSAdit Ranadive * without modification, are permitted provided that the following 21*29c8d9ebSAdit Ranadive * conditions are met: 22*29c8d9ebSAdit Ranadive * 23*29c8d9ebSAdit Ranadive * - Redistributions of source code must retain the above 24*29c8d9ebSAdit Ranadive * copyright notice, this list of conditions and the following 25*29c8d9ebSAdit Ranadive * disclaimer. 26*29c8d9ebSAdit Ranadive * 27*29c8d9ebSAdit Ranadive * - Redistributions in binary form must reproduce the above 28*29c8d9ebSAdit Ranadive * copyright notice, this list of conditions and the following 29*29c8d9ebSAdit Ranadive * disclaimer in the documentation and/or other materials 30*29c8d9ebSAdit Ranadive * provided with the distribution. 31*29c8d9ebSAdit Ranadive * 32*29c8d9ebSAdit Ranadive * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33*29c8d9ebSAdit Ranadive * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34*29c8d9ebSAdit Ranadive * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 35*29c8d9ebSAdit Ranadive * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 36*29c8d9ebSAdit Ranadive * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 37*29c8d9ebSAdit Ranadive * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 38*29c8d9ebSAdit Ranadive * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 39*29c8d9ebSAdit Ranadive * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40*29c8d9ebSAdit Ranadive * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 41*29c8d9ebSAdit Ranadive * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42*29c8d9ebSAdit Ranadive * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 43*29c8d9ebSAdit Ranadive * OF THE POSSIBILITY OF SUCH DAMAGE. 44*29c8d9ebSAdit Ranadive */ 45*29c8d9ebSAdit Ranadive 46*29c8d9ebSAdit Ranadive #include <linux/list.h> 47*29c8d9ebSAdit Ranadive 48*29c8d9ebSAdit Ranadive #include "pvrdma.h" 49*29c8d9ebSAdit Ranadive 50*29c8d9ebSAdit Ranadive #define PVRDMA_CMD_TIMEOUT 10000 /* ms */ 51*29c8d9ebSAdit Ranadive 52*29c8d9ebSAdit Ranadive static inline int pvrdma_cmd_recv(struct pvrdma_dev *dev, 53*29c8d9ebSAdit Ranadive union pvrdma_cmd_resp *resp, 54*29c8d9ebSAdit Ranadive unsigned resp_code) 55*29c8d9ebSAdit Ranadive { 56*29c8d9ebSAdit Ranadive int err; 57*29c8d9ebSAdit Ranadive 58*29c8d9ebSAdit Ranadive dev_dbg(&dev->pdev->dev, "receive response from device\n"); 59*29c8d9ebSAdit Ranadive 60*29c8d9ebSAdit Ranadive err = wait_for_completion_interruptible_timeout(&dev->cmd_done, 61*29c8d9ebSAdit Ranadive msecs_to_jiffies(PVRDMA_CMD_TIMEOUT)); 62*29c8d9ebSAdit Ranadive if (err == 0 || err == -ERESTARTSYS) { 63*29c8d9ebSAdit Ranadive dev_warn(&dev->pdev->dev, 64*29c8d9ebSAdit Ranadive "completion timeout or interrupted\n"); 65*29c8d9ebSAdit Ranadive return -ETIMEDOUT; 66*29c8d9ebSAdit Ranadive } 67*29c8d9ebSAdit Ranadive 68*29c8d9ebSAdit Ranadive spin_lock(&dev->cmd_lock); 69*29c8d9ebSAdit Ranadive memcpy(resp, dev->resp_slot, sizeof(*resp)); 70*29c8d9ebSAdit Ranadive spin_unlock(&dev->cmd_lock); 71*29c8d9ebSAdit Ranadive 72*29c8d9ebSAdit Ranadive if (resp->hdr.ack != resp_code) { 73*29c8d9ebSAdit Ranadive dev_warn(&dev->pdev->dev, 74*29c8d9ebSAdit Ranadive "unknown response %#x expected %#x\n", 75*29c8d9ebSAdit Ranadive resp->hdr.ack, resp_code); 76*29c8d9ebSAdit Ranadive return -EFAULT; 77*29c8d9ebSAdit Ranadive } 78*29c8d9ebSAdit Ranadive 79*29c8d9ebSAdit Ranadive return 0; 80*29c8d9ebSAdit Ranadive } 81*29c8d9ebSAdit Ranadive 82*29c8d9ebSAdit Ranadive int 83*29c8d9ebSAdit Ranadive pvrdma_cmd_post(struct pvrdma_dev *dev, union pvrdma_cmd_req *req, 84*29c8d9ebSAdit Ranadive union pvrdma_cmd_resp *resp, unsigned resp_code) 85*29c8d9ebSAdit Ranadive { 86*29c8d9ebSAdit Ranadive int err; 87*29c8d9ebSAdit Ranadive 88*29c8d9ebSAdit Ranadive dev_dbg(&dev->pdev->dev, "post request to device\n"); 89*29c8d9ebSAdit Ranadive 90*29c8d9ebSAdit Ranadive /* Serializiation */ 91*29c8d9ebSAdit Ranadive down(&dev->cmd_sema); 92*29c8d9ebSAdit Ranadive 93*29c8d9ebSAdit Ranadive BUILD_BUG_ON(sizeof(union pvrdma_cmd_req) != 94*29c8d9ebSAdit Ranadive sizeof(struct pvrdma_cmd_modify_qp)); 95*29c8d9ebSAdit Ranadive 96*29c8d9ebSAdit Ranadive spin_lock(&dev->cmd_lock); 97*29c8d9ebSAdit Ranadive memcpy(dev->cmd_slot, req, sizeof(*req)); 98*29c8d9ebSAdit Ranadive spin_unlock(&dev->cmd_lock); 99*29c8d9ebSAdit Ranadive 100*29c8d9ebSAdit Ranadive init_completion(&dev->cmd_done); 101*29c8d9ebSAdit Ranadive pvrdma_write_reg(dev, PVRDMA_REG_REQUEST, 0); 102*29c8d9ebSAdit Ranadive 103*29c8d9ebSAdit Ranadive /* Make sure the request is written before reading status. */ 104*29c8d9ebSAdit Ranadive mb(); 105*29c8d9ebSAdit Ranadive 106*29c8d9ebSAdit Ranadive err = pvrdma_read_reg(dev, PVRDMA_REG_ERR); 107*29c8d9ebSAdit Ranadive if (err == 0) { 108*29c8d9ebSAdit Ranadive if (resp != NULL) 109*29c8d9ebSAdit Ranadive err = pvrdma_cmd_recv(dev, resp, resp_code); 110*29c8d9ebSAdit Ranadive } else { 111*29c8d9ebSAdit Ranadive dev_warn(&dev->pdev->dev, 112*29c8d9ebSAdit Ranadive "failed to write request error reg: %d\n", err); 113*29c8d9ebSAdit Ranadive err = -EFAULT; 114*29c8d9ebSAdit Ranadive } 115*29c8d9ebSAdit Ranadive 116*29c8d9ebSAdit Ranadive up(&dev->cmd_sema); 117*29c8d9ebSAdit Ranadive 118*29c8d9ebSAdit Ranadive return err; 119*29c8d9ebSAdit Ranadive } 120