/*
* 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 "VMware PVSCSI driver"
MODULE_DESCRIPTION(PVSCSI_LINUX_DRIVER_DESC);
MODULE_AUTHOR("VMware, Inc.");
MODULE_LICENSE("GPL");
MODULE_VERSION(PVSCSI_DRIVER_VERSION_STRING);
#define PVSCSI_DEFAULT_NUM_PAGES_PER_RING 8
#define PVSCSI_DEFAULT_NUM_PAGES_MSG_RING 1
#define PVSCSI_DEFAULT_QUEUE_DEPTH 254
#define SGL_SIZE PAGE_SIZE
struct pvscsi_sg_list {
struct PVSCSISGElement sge[PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT];
};
struct pvscsi_ctx {
/*
* The index of the context in cmd_map serves as the context ID for a
* 1-to-1 mapping completions back to requests.
*/
struct scsi_cmnd *cmd;
struct pvscsi_sg_list *sgl;
struct list_head list;
dma_addr_t dataPA;
dma_addr_t sensePA;
dma_addr_t sglPA;
struct completion *abort_cmp;
};
struct pvscsi_adapter {
char *mmioBase;
u8 rev;
bool use_msg;
bool use_req_threshold;
spinlock_t hw_lock;
struct workqueue_struct *workqueue;
struct work_struct work;
struct PVSCSIRingReqDesc *req_ring;
unsigned req_pages;
unsigned req_depth;
dma_addr_t reqRingPA;
struct PVSCSIRingCmpDesc *cmp_ring;
unsigned cmp_pages;
dma_addr_t cmpRingPA;
struct PVSCSIRingMsgDesc *msg_ring;
unsigned msg_pages;
dma_addr_t msgRingPA;
struct PVSCSIRingsState *rings_state;
dma_addr_t ringStatePA;
struct pci_dev *dev;
struct Scsi_Host *host;
struct list_head cmd_pool;
struct pvscsi_ctx *cmd_map;
};
/* Command line parameters */
static int pvscsi_ring_pages;
static int pvscsi_msg_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_MSG_RING;
static int pvscsi_cmd_per_lun = PVSCSI_DEFAULT_QUEUE_DEPTH;
static bool pvscsi_disable_msi;
static bool pvscsi_disable_msix;
static bool pvscsi_use_msg = true;
static bool pvscsi_use_req_threshold = true;
#define PVSCSI_RW (S_IRUSR | S_IWUSR)
module_param_named(ring_pages, pvscsi_ring_pages, int, PVSCSI_RW);
MODULE_PARM_DESC(ring_pages, "Number of pages per req/cmp ring - (default="
__stringify(PVSCSI_DEFAULT_NUM_PAGES_PER_RING)
"[up to 16 targets],"
__stringify(PVSCSI_SETUP_RINGS_MAX_NUM_PAGES)
"[for 16+ targets])");
module_param_named(msg_ring_pages, pvscsi_msg_ring_pages, int, PVSCSI_RW);
MODULE_PARM_DESC(msg_ring_pages, "Number of pages for the msg ring - (default="
__stringify(PVSCSI_DEFAULT_NUM_PAGES_MSG_RING) ")");
module_param_named(cmd_per_lun, pvscsi_cmd_per_lun, int, PVSCSI_RW);
MODULE_PARM_DESC(cmd_per_lun, "Maximum commands per lun - (default="
__stringify(PVSCSI_DEFAULT_QUEUE_DEPTH) ")");
module_param_named(disable_msi, pvscsi_disable_msi, bool, PVSCSI_RW);
MODULE_PARM_DESC(disable_msi, "Disable MSI use in driver - (default=0)");
module_param_named(disable_msix, pvscsi_disable_msix, bool, PVSCSI_RW);
MODULE_PARM_DESC(disable_msix, "Disable MSI-X use in driver - (default=0)");
module_param_name
|