#define pr_fmt(fmt) …
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mempool.h>
#include <linux/interrupt.h>
#include <linux/virtio.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
#include <linux/virtio_scsi.h>
#include <linux/cpu.h>
#include <linux/blkdev.h>
#include <linux/blk-integrity.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_devinfo.h>
#include <linux/seqlock.h>
#include <linux/blk-mq-virtio.h>
#include "sd.h"
#define VIRTIO_SCSI_MEMPOOL_SZ …
#define VIRTIO_SCSI_EVENT_LEN …
#define VIRTIO_SCSI_VQ_BASE …
static unsigned int virtscsi_poll_queues;
module_param(virtscsi_poll_queues, uint, 0644);
MODULE_PARM_DESC(…) …;
struct virtio_scsi_cmd { … } ____cacheline_aligned_in_smp;
struct virtio_scsi_event_node { … };
struct virtio_scsi_vq { … };
struct virtio_scsi { … };
static struct kmem_cache *virtscsi_cmd_cache;
static mempool_t *virtscsi_cmd_pool;
static inline struct Scsi_Host *virtio_scsi_host(struct virtio_device *vdev)
{ … }
static void virtscsi_compute_resid(struct scsi_cmnd *sc, u32 resid)
{ … }
static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf)
{ … }
static void virtscsi_vq_done(struct virtio_scsi *vscsi,
struct virtio_scsi_vq *virtscsi_vq,
void (*fn)(struct virtio_scsi *vscsi, void *buf))
{ … }
static void virtscsi_req_done(struct virtqueue *vq)
{
struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
int index = vq->index - VIRTIO_SCSI_VQ_BASE;
struct virtio_scsi_vq *req_vq = &vscsi->req_vqs[index];
virtscsi_vq_done(vscsi, req_vq, virtscsi_complete_cmd);
};
static void virtscsi_poll_requests(struct virtio_scsi *vscsi)
{ … }
static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf)
{ … }
static void virtscsi_ctrl_done(struct virtqueue *vq)
{
struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
virtscsi_vq_done(vscsi, &vscsi->ctrl_vq, virtscsi_complete_free);
};
static void virtscsi_handle_event(struct work_struct *work);
static int virtscsi_kick_event(struct virtio_scsi *vscsi,
struct virtio_scsi_event_node *event_node)
{ … }
static int virtscsi_kick_event_all(struct virtio_scsi *vscsi)
{ … }
static void virtscsi_cancel_event_work(struct virtio_scsi *vscsi)
{ … }
static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
struct virtio_scsi_event *event)
{ … }
static void virtscsi_handle_param_change(struct virtio_scsi *vscsi,
struct virtio_scsi_event *event)
{ … }
static int virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi)
{ … }
static void virtscsi_handle_event(struct work_struct *work)
{ … }
static void virtscsi_complete_event(struct virtio_scsi *vscsi, void *buf)
{ … }
static void virtscsi_event_done(struct virtqueue *vq)
{
struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
virtscsi_vq_done(vscsi, &vscsi->event_vq, virtscsi_complete_event);
};
static int __virtscsi_add_cmd(struct virtqueue *vq,
struct virtio_scsi_cmd *cmd,
size_t req_size, size_t resp_size)
{ … }
static void virtscsi_kick_vq(struct virtio_scsi_vq *vq)
{ … }
static int virtscsi_add_cmd(struct virtio_scsi_vq *vq,
struct virtio_scsi_cmd *cmd,
size_t req_size, size_t resp_size,
bool kick)
{ … }
static void virtio_scsi_init_hdr(struct virtio_device *vdev,
struct virtio_scsi_cmd_req *cmd,
struct scsi_cmnd *sc)
{ … }
#ifdef CONFIG_BLK_DEV_INTEGRITY
static void virtio_scsi_init_hdr_pi(struct virtio_device *vdev,
struct virtio_scsi_cmd_req_pi *cmd_pi,
struct scsi_cmnd *sc)
{ … }
#endif
static struct virtio_scsi_vq *virtscsi_pick_vq_mq(struct virtio_scsi *vscsi,
struct scsi_cmnd *sc)
{ … }
static int virtscsi_queuecommand(struct Scsi_Host *shost,
struct scsi_cmnd *sc)
{ … }
static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd)
{ … }
static int virtscsi_device_reset(struct scsi_cmnd *sc)
{ … }
static int virtscsi_device_alloc(struct scsi_device *sdevice)
{ … }
static int virtscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
{ … }
static int virtscsi_abort(struct scsi_cmnd *sc)
{ … }
static void virtscsi_map_queues(struct Scsi_Host *shost)
{ … }
static int virtscsi_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
{ … }
static void virtscsi_commit_rqs(struct Scsi_Host *shost, u16 hwq)
{ … }
static enum scsi_timeout_action virtscsi_eh_timed_out(struct scsi_cmnd *scmnd)
{ … }
static const struct scsi_host_template virtscsi_host_template = …;
#define virtscsi_config_get(vdev, fld) …
#define virtscsi_config_set(vdev, fld, val) …
static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq,
struct virtqueue *vq)
{ … }
static void virtscsi_remove_vqs(struct virtio_device *vdev)
{ … }
static int virtscsi_init(struct virtio_device *vdev,
struct virtio_scsi *vscsi)
{ … }
static int virtscsi_probe(struct virtio_device *vdev)
{ … }
static void virtscsi_remove(struct virtio_device *vdev)
{ … }
#ifdef CONFIG_PM_SLEEP
static int virtscsi_freeze(struct virtio_device *vdev)
{ … }
static int virtscsi_restore(struct virtio_device *vdev)
{ … }
#endif
static struct virtio_device_id id_table[] = …;
static unsigned int features[] = …;
static struct virtio_driver virtio_scsi_driver = …;
static int __init virtio_scsi_init(void)
{ … }
static void __exit virtio_scsi_fini(void)
{ … }
module_init(…) …;
module_exit(virtio_scsi_fini);
MODULE_DEVICE_TABLE(virtio, id_table);
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;