linux/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cmd.c
<<
>>
Prefs
   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
  52static 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
  82int
  83pvrdma_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