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