linux/drivers/scsi/storvsc_drv.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2009, Microsoft Corporation.
 *
 * Authors:
 *   Haiyang Zhang <[email protected]>
 *   Hank Janssen  <[email protected]>
 *   K. Y. Srinivasan <[email protected]>
 */

#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/hyperv.h>
#include <linux/blkdev.h>
#include <linux/dma-mapping.h>

#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_devinfo.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_transport.h>

/*
 * All wire protocol details (storage protocol between the guest and the host)
 * are consolidated here.
 *
 * Begin protocol definitions.
 */

/*
 * Version history:
 * V1 Beta: 0.1
 * V1 RC < 2008/1/31: 1.0
 * V1 RC > 2008/1/31:  2.0
 * Win7: 4.2
 * Win8: 5.1
 * Win8.1: 6.0
 * Win10: 6.2
 */

#define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_)
#define VMSTOR_PROTO_VERSION_WIN6
#define VMSTOR_PROTO_VERSION_WIN7
#define VMSTOR_PROTO_VERSION_WIN8
#define VMSTOR_PROTO_VERSION_WIN8_1
#define VMSTOR_PROTO_VERSION_WIN10

/* channel callback timeout in ms */
#define CALLBACK_TIMEOUT

/*  Packet structure describing virtual storage requests. */
enum vstor_packet_operation {};

/*
 * WWN packet for Fibre Channel HBA
 */

struct hv_fc_wwn_packet {};



/*
 * SRB Flag Bits
 */

#define SRB_FLAGS_QUEUE_ACTION_ENABLE
#define SRB_FLAGS_DISABLE_DISCONNECT
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
#define SRB_FLAGS_BYPASS_FROZEN_QUEUE
#define SRB_FLAGS_DISABLE_AUTOSENSE
#define SRB_FLAGS_DATA_IN
#define SRB_FLAGS_DATA_OUT
#define SRB_FLAGS_NO_DATA_TRANSFER
#define SRB_FLAGS_UNSPECIFIED_DIRECTION
#define SRB_FLAGS_NO_QUEUE_FREEZE
#define SRB_FLAGS_ADAPTER_CACHE_ENABLE
#define SRB_FLAGS_FREE_SENSE_BUFFER

/*
 * This flag indicates the request is part of the workflow for processing a D3.
 */
#define SRB_FLAGS_D3_PROCESSING
#define SRB_FLAGS_IS_ACTIVE
#define SRB_FLAGS_ALLOCATED_FROM_ZONE
#define SRB_FLAGS_SGLIST_FROM_POOL
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
#define SRB_FLAGS_NO_KEEP_AWAKE
#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE
#define SRB_FLAGS_PORT_DRIVER_SENSEHASPORT
#define SRB_FLAGS_DONT_START_NEXT_PACKET
#define SRB_FLAGS_PORT_DRIVER_RESERVED
#define SRB_FLAGS_CLASS_DRIVER_RESERVED

#define SP_UNTAGGED
#define SRB_SIMPLE_TAG_REQUEST

/*
 * Platform neutral description of a scsi request -
 * this remains the same across the write regardless of 32/64 bit
 * note: it's patterned off the SCSI_PASS_THROUGH structure
 */
#define STORVSC_MAX_CMD_LEN

/* Sense buffer size is the same for all versions since Windows 8 */
#define STORVSC_SENSE_BUFFER_SIZE
#define STORVSC_MAX_BUF_LEN_WITH_PADDING

/*
 * The storage protocol version is determined during the
 * initial exchange with the host.  It will indicate which
 * storage functionality is available in the host.
*/
static int vmstor_proto_version;

#define STORVSC_LOGGING_NONE
#define STORVSC_LOGGING_ERROR
#define STORVSC_LOGGING_WARN

static int logging_level =;
module_param(logging_level, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

static inline bool do_logging(int level)
{}

#define storvsc_log(dev, level, fmt, ...)

struct vmscsi_request {} __attribute((packed));

/*
 * The list of windows version in order of preference.
 */

static const int protocol_version[] =;


/*
 * This structure is sent during the initialization phase to get the different
 * properties of the channel.
 */

#define STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL

struct vmstorage_channel_properties {} __packed;

/*  This structure is sent during the storage protocol negotiations. */
struct vmstorage_protocol_version {} __packed;

/* Channel Property Flags */
#define STORAGE_CHANNEL_REMOVABLE_FLAG
#define STORAGE_CHANNEL_EMULATED_IDE_FLAG

struct vstor_packet {} __packed;

/*
 * Packet Flags:
 *
 * This flag indicates that the server should send back a completion for this
 * packet.
 */

#define REQUEST_COMPLETION_FLAG

/* Matches Windows-end */
enum storvsc_request_type {};

/*
 * SRB status codes and masks. In the 8-bit field, the two high order bits
 * are flags, while the remaining 6 bits are an integer status code.  The
 * definitions here include only the subset of the integer status codes that
 * are tested for in this driver.
 */
#define SRB_STATUS_AUTOSENSE_VALID
#define SRB_STATUS_QUEUE_FROZEN

/* SRB status integer codes */
#define SRB_STATUS_SUCCESS
#define SRB_STATUS_ABORTED
#define SRB_STATUS_ERROR
#define SRB_STATUS_INVALID_REQUEST
#define SRB_STATUS_TIMEOUT
#define SRB_STATUS_SELECTION_TIMEOUT
#define SRB_STATUS_BUS_RESET
#define SRB_STATUS_DATA_OVERRUN
#define SRB_STATUS_INVALID_LUN
#define SRB_STATUS_INTERNAL_ERROR

#define SRB_STATUS(status)
/*
 * This is the end of Protocol specific defines.
 */

static int storvsc_ringbuffer_size =;
static int aligned_ringbuffer_size;
static u32 max_outstanding_req_per_channel;
static int storvsc_change_queue_depth(struct scsi_device *sdev, int queue_depth);

static int storvsc_vcpus_per_sub_channel =;
static unsigned int storvsc_max_hw_queues;

module_param(storvsc_ringbuffer_size, int, S_IRUGO);
MODULE_PARM_DESC();

module_param(storvsc_max_hw_queues, uint, 0644);
MODULE_PARM_DESC();

module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO);
MODULE_PARM_DESC();

static int ring_avail_percent_lowater =;
module_param(ring_avail_percent_lowater, int, S_IRUGO);
MODULE_PARM_DESC();

/*
 * Timeout in seconds for all devices managed by this driver.
 */
static int storvsc_timeout =;

#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
static struct scsi_transport_template *fc_transport_template;
#endif

static struct scsi_host_template scsi_driver;
static void storvsc_on_channel_callback(void *context);

#define STORVSC_MAX_LUNS_PER_TARGET
#define STORVSC_MAX_TARGETS
#define STORVSC_MAX_CHANNELS

#define STORVSC_FC_MAX_LUNS_PER_TARGET
#define STORVSC_FC_MAX_TARGETS
#define STORVSC_FC_MAX_CHANNELS
#define STORVSC_FC_MAX_XFER_SIZE

#define STORVSC_IDE_MAX_LUNS_PER_TARGET
#define STORVSC_IDE_MAX_TARGETS
#define STORVSC_IDE_MAX_CHANNELS

/*
 * Upper bound on the size of a storvsc packet.
 */
#define STORVSC_MAX_PKT_SIZE

struct storvsc_cmd_request {};


/* A storvsc device is a device object that contains a vmbus channel */
struct storvsc_device {};

struct hv_host_device {};

struct storvsc_scan_work {};

static void storvsc_device_scan(struct work_struct *work)
{}

static void storvsc_host_scan(struct work_struct *work)
{}

static void storvsc_remove_lun(struct work_struct *work)
{}


/*
 * We can get incoming messages from the host that are not in response to
 * messages that we have sent out. An example of this would be messages
 * received by the guest to notify dynamic addition/removal of LUNs. To
 * deal with potential race conditions where the driver may be in the
 * midst of being unloaded when we might receive an unsolicited message
 * from the host, we have implemented a mechanism to gurantee sequential
 * consistency:
 *
 * 1) Once the device is marked as being destroyed, we will fail all
 *    outgoing messages.
 * 2) We permit incoming messages when the device is being destroyed,
 *    only to properly account for messages already sent out.
 */

static inline struct storvsc_device *get_out_stor_device(
					struct hv_device *device)
{}


static inline void storvsc_wait_to_drain(struct storvsc_device *dev)
{}

static inline struct storvsc_device *get_in_stor_device(
					struct hv_device *device)
{}

static void storvsc_change_target_cpu(struct vmbus_channel *channel, u32 old,
				      u32 new)
{}

static u64 storvsc_next_request_id(struct vmbus_channel *channel, u64 rqst_addr)
{}

static void handle_sc_creation(struct vmbus_channel *new_sc)
{}

static void  handle_multichannel_storage(struct hv_device *device, int max_chns)
{}

static void cache_wwn(struct storvsc_device *stor_device,
		      struct vstor_packet *vstor_packet)
{}


static int storvsc_execute_vstor_op(struct hv_device *device,
				    struct storvsc_cmd_request *request,
				    bool status_check)
{}

static int storvsc_channel_init(struct hv_device *device, bool is_fc)
{}

static void storvsc_handle_error(struct vmscsi_request *vm_srb,
				struct scsi_cmnd *scmnd,
				struct Scsi_Host *host,
				u8 asc, u8 ascq)
{}


static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request,
				       struct storvsc_device *stor_dev)
{}

static void storvsc_on_io_completion(struct storvsc_device *stor_device,
				  struct vstor_packet *vstor_packet,
				  struct storvsc_cmd_request *request)
{}

static void storvsc_on_receive(struct storvsc_device *stor_device,
			     struct vstor_packet *vstor_packet,
			     struct storvsc_cmd_request *request)
{}

static void storvsc_on_channel_callback(void *context)
{}

static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size,
				  bool is_fc)
{}

static int storvsc_dev_remove(struct hv_device *device)
{}

static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device,
					u16 q_num)
{}


static int storvsc_do_io(struct hv_device *device,
			 struct storvsc_cmd_request *request, u16 q_num)
{}

static int storvsc_device_alloc(struct scsi_device *sdevice)
{}

static int storvsc_device_configure(struct scsi_device *sdevice)
{}

static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
			   sector_t capacity, int *info)
{}

static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
{}

/*
 * The host guarantees to respond to each command, although I/O latencies might
 * be unbounded on Azure.  Reset the timer unconditionally to give the host a
 * chance to perform EH.
 */
static enum scsi_timeout_action storvsc_eh_timed_out(struct scsi_cmnd *scmnd)
{}

static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd)
{}

static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
{}

static struct scsi_host_template scsi_driver =;

enum {};

static const struct hv_vmbus_device_id id_table[] =;

MODULE_DEVICE_TABLE(vmbus, id_table);

static const struct {} fc_guid =;

static bool hv_dev_is_fc(struct hv_device *hv_dev)
{}

static int storvsc_probe(struct hv_device *device,
			const struct hv_vmbus_device_id *dev_id)
{}

/* Change a scsi target's queue depth */
static int storvsc_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{}

static void storvsc_remove(struct hv_device *dev)
{}

static int storvsc_suspend(struct hv_device *hv_dev)
{}

static int storvsc_resume(struct hv_device *hv_dev)
{}

static struct hv_driver storvsc_drv =;

#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
static struct fc_function_template fc_transport_functions =;
#endif

static int __init storvsc_drv_init(void)
{}

static void __exit storvsc_drv_exit(void)
{}

MODULE_LICENSE();
MODULE_DESCRIPTION();
module_init();
module_exit(storvsc_drv_exit);