linux/drivers/scsi/vmw_pvscsi.c

/*
 * Linux driver for VMware's para-virtualized SCSI HBA.
 *
 * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; version 2 of the License and no later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/pci.h>

#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>

#include "vmw_pvscsi.h"

#define PVSCSI_LINUX_DRIVER_DESC

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_VERSION();

#define PVSCSI_DEFAULT_NUM_PAGES_PER_RING
#define PVSCSI_DEFAULT_NUM_PAGES_MSG_RING
#define PVSCSI_DEFAULT_QUEUE_DEPTH
#define SGL_SIZE

struct pvscsi_sg_list {};

struct pvscsi_ctx {};

struct pvscsi_adapter {};


/* Command line parameters */
static int pvscsi_ring_pages;
static int pvscsi_msg_ring_pages =;
static int pvscsi_cmd_per_lun    =;
static bool pvscsi_disable_msi;
static bool pvscsi_disable_msix;
static bool pvscsi_use_msg       =;
static bool pvscsi_use_req_threshold =;

#define PVSCSI_RW

module_param_named(ring_pages, pvscsi_ring_pages, int, PVSCSI_RW);
MODULE_PARM_DESC();

module_param_named(msg_ring_pages, pvscsi_msg_ring_pages, int, PVSCSI_RW);
MODULE_PARM_DESC();

module_param_named(cmd_per_lun, pvscsi_cmd_per_lun, int, PVSCSI_RW);
MODULE_PARM_DESC();

module_param_named(disable_msi, pvscsi_disable_msi, bool, PVSCSI_RW);
MODULE_PARM_DESC();

module_param_named(disable_msix, pvscsi_disable_msix, bool, PVSCSI_RW);
MODULE_PARM_DESC();

module_param_named(use_msg, pvscsi_use_msg, bool, PVSCSI_RW);
MODULE_PARM_DESC();

module_param_named(use_req_threshold, pvscsi_use_req_threshold,
		   bool, PVSCSI_RW);
MODULE_PARM_DESC();

static const struct pci_device_id pvscsi_pci_tbl[] =;

MODULE_DEVICE_TABLE(pci, pvscsi_pci_tbl);

static struct device *
pvscsi_dev(const struct pvscsi_adapter *adapter)
{}

static struct pvscsi_ctx *
pvscsi_find_context(const struct pvscsi_adapter *adapter, struct scsi_cmnd *cmd)
{}

static struct pvscsi_ctx *
pvscsi_acquire_context(struct pvscsi_adapter *adapter, struct scsi_cmnd *cmd)
{}

static void pvscsi_release_context(struct pvscsi_adapter *adapter,
				   struct pvscsi_ctx *ctx)
{}

/*
 * Map a pvscsi_ctx struct to a context ID field value; we map to a simple
 * non-zero integer. ctx always points to an entry in cmd_map array, hence
 * the return value is always >=1.
 */
static u64 pvscsi_map_context(const struct pvscsi_adapter *adapter,
			      const struct pvscsi_ctx *ctx)
{}

static struct pvscsi_ctx *
pvscsi_get_context(const struct pvscsi_adapter *adapter, u64 context)
{}

static void pvscsi_reg_write(const struct pvscsi_adapter *adapter,
			     u32 offset, u32 val)
{}

static u32 pvscsi_reg_read(const struct pvscsi_adapter *adapter, u32 offset)
{}

static u32 pvscsi_read_intr_status(const struct pvscsi_adapter *adapter)
{}

static void pvscsi_write_intr_status(const struct pvscsi_adapter *adapter,
				     u32 val)
{}

static void pvscsi_unmask_intr(const struct pvscsi_adapter *adapter)
{}

static void pvscsi_mask_intr(const struct pvscsi_adapter *adapter)
{}

static void pvscsi_write_cmd_desc(const struct pvscsi_adapter *adapter,
				  u32 cmd, const void *desc, size_t len)
{}

static void pvscsi_abort_cmd(const struct pvscsi_adapter *adapter,
			     const struct pvscsi_ctx *ctx)
{}

static void pvscsi_kick_rw_io(const struct pvscsi_adapter *adapter)
{}

static void pvscsi_process_request_ring(const struct pvscsi_adapter *adapter)
{}

static int scsi_is_rw(unsigned char op)
{}

static void pvscsi_kick_io(const struct pvscsi_adapter *adapter,
			   unsigned char op)
{}

static void ll_adapter_reset(const struct pvscsi_adapter *adapter)
{}

static void ll_bus_reset(const struct pvscsi_adapter *adapter)
{}

static void ll_device_reset(const struct pvscsi_adapter *adapter, u32 target)
{}

static void pvscsi_create_sg(struct pvscsi_ctx *ctx,
			     struct scatterlist *sg, unsigned count)
{}

/*
 * Map all data buffers for a command into PCI space and
 * setup the scatter/gather list if needed.
 */
static int pvscsi_map_buffers(struct pvscsi_adapter *adapter,
			      struct pvscsi_ctx *ctx, struct scsi_cmnd *cmd,
			      struct PVSCSIRingReqDesc *e)
{}

/*
 * The device incorrectly doesn't clear the first byte of the sense
 * buffer in some cases. We have to do it ourselves.
 * Otherwise we run into trouble when SWIOTLB is forced.
 */
static void pvscsi_patch_sense(struct scsi_cmnd *cmd)
{}

static void pvscsi_unmap_buffers(const struct pvscsi_adapter *adapter,
				 struct pvscsi_ctx *ctx)
{}

static int pvscsi_allocate_rings(struct pvscsi_adapter *adapter)
{}

static void pvscsi_setup_all_rings(const struct pvscsi_adapter *adapter)
{}

static int pvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
{}

/*
 * Pull a completion descriptor off and pass the completion back
 * to the SCSI mid layer.
 */
static void pvscsi_complete_request(struct pvscsi_adapter *adapter,
				    const struct PVSCSIRingCmpDesc *e)
{}

/*
 * barrier usage : Since the PVSCSI device is emulated, there could be cases
 * where we may want to serialize some accesses between the driver and the
 * emulation layer. We use compiler barriers instead of the more expensive
 * memory barriers because PVSCSI is only supported on X86 which has strong
 * memory access ordering.
 */
static void pvscsi_process_completion_ring(struct pvscsi_adapter *adapter)
{}

/*
 * Translate a Linux SCSI request into a request ring entry.
 */
static int pvscsi_queue_ring(struct pvscsi_adapter *adapter,
			     struct pvscsi_ctx *ctx, struct scsi_cmnd *cmd)
{}

static int pvscsi_queue_lck(struct scsi_cmnd *cmd)
{}

static DEF_SCSI_QCMD(pvscsi_queue)

static int pvscsi_abort(struct scsi_cmnd *cmd)
{}

/*
 * Abort all outstanding requests.  This is only safe to use if the completion
 * ring will never be walked again or the device has been reset, because it
 * destroys the 1-1 mapping between context field passed to emulation and our
 * request structure.
 */
static void pvscsi_reset_all(struct pvscsi_adapter *adapter)
{}

static int pvscsi_host_reset(struct scsi_cmnd *cmd)
{}

static int pvscsi_bus_reset(struct scsi_cmnd *cmd)
{}

static int pvscsi_device_reset(struct scsi_cmnd *cmd)
{}

static struct scsi_host_template pvscsi_template;

static const char *pvscsi_info(struct Scsi_Host *host)
{}

static struct scsi_host_template pvscsi_template =;

static void pvscsi_process_msg(const struct pvscsi_adapter *adapter,
			       const struct PVSCSIRingMsgDesc *e)
{}

static int pvscsi_msg_pending(const struct pvscsi_adapter *adapter)
{}

static void pvscsi_process_msg_ring(const struct pvscsi_adapter *adapter)
{}

static void pvscsi_msg_workqueue_handler(struct work_struct *data)
{}

static int pvscsi_setup_msg_workqueue(struct pvscsi_adapter *adapter)
{}

static bool pvscsi_setup_req_threshold(struct pvscsi_adapter *adapter,
				      bool enable)
{}

static irqreturn_t pvscsi_isr(int irq, void *devp)
{}

static irqreturn_t pvscsi_shared_isr(int irq, void *devp)
{}

static void pvscsi_free_sgls(const struct pvscsi_adapter *adapter)
{}

static void pvscsi_shutdown_intr(struct pvscsi_adapter *adapter)
{}

static void pvscsi_release_resources(struct pvscsi_adapter *adapter)
{}

/*
 * Allocate scatter gather lists.
 *
 * These are statically allocated.  Trying to be clever was not worth it.
 *
 * Dynamic allocation can fail, and we can't go deep into the memory
 * allocator, since we're a SCSI driver, and trying too hard to allocate
 * memory might generate disk I/O.  We also don't want to fail disk I/O
 * in that case because we can't get an allocation - the I/O could be
 * trying to swap out data to free memory.  Since that is pathological,
 * just use a statically allocated scatter list.
 *
 */
static int pvscsi_allocate_sg(struct pvscsi_adapter *adapter)
{}

/*
 * Query the device, fetch the config info and return the
 * maximum number of targets on the adapter. In case of
 * failure due to any reason return default i.e. 16.
 */
static u32 pvscsi_get_max_targets(struct pvscsi_adapter *adapter)
{}

static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{}

static void __pvscsi_shutdown(struct pvscsi_adapter *adapter)
{}

static void pvscsi_shutdown(struct pci_dev *dev)
{}

static void pvscsi_remove(struct pci_dev *pdev)
{}

static struct pci_driver pvscsi_pci_driver =;

static int __init pvscsi_init(void)
{}

static void __exit pvscsi_exit(void)
{}

module_init();
module_exit(pvscsi_exit);