14fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini/* 24fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * Virtio SCSI HBA driver 34fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * 44fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * Copyright IBM Corp. 2010 54fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * Copyright Red Hat, Inc. 2011 64fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * 74fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * Authors: 84fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> 94fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * Paolo Bonzini <pbonzini@redhat.com> 104fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * 114fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * This work is licensed under the terms of the GNU GPL, version 2 or later. 124fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * See the COPYING file in the top-level directory. 134fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * 144fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini */ 154fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 164fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <linux/module.h> 174fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <linux/slab.h> 184fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <linux/mempool.h> 194fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <linux/virtio.h> 204fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <linux/virtio_ids.h> 214fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <linux/virtio_config.h> 224fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <linux/virtio_scsi.h> 234fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <scsi/scsi_host.h> 244fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <scsi/scsi_device.h> 254fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#include <scsi/scsi_cmnd.h> 264fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 274fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#define VIRTIO_SCSI_MEMPOOL_SZ 64 284fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 294fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini/* Command queue element */ 304fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistruct virtio_scsi_cmd { 314fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct scsi_cmnd *sc; 324fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct completion *comp; 334fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini union { 344fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd_req cmd; 354fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_ctrl_tmf_req tmf; 364fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_ctrl_an_req an; 374fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } req; 384fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini union { 394fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd_resp cmd; 404fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_ctrl_tmf_resp tmf; 414fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_ctrl_an_resp an; 424fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_event evt; 434fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } resp; 444fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} ____cacheline_aligned_in_smp; 454fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 464fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini/* Driver instance state */ 474fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistruct virtio_scsi { 484fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Protects ctrl_vq, req_vq and sg[] */ 494fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini spinlock_t vq_lock; 504fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 514fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_device *vdev; 524fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtqueue *ctrl_vq; 534fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtqueue *event_vq; 544fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtqueue *req_vq; 554fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 564fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* For sglist construction when adding commands to the virtqueue. */ 574fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct scatterlist sg[]; 584fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini}; 594fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 604fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic struct kmem_cache *virtscsi_cmd_cache; 614fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic mempool_t *virtscsi_cmd_pool; 624fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 634fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic inline struct Scsi_Host *virtio_scsi_host(struct virtio_device *vdev) 644fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 654fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return vdev->priv; 664fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 674fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 684fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_compute_resid(struct scsi_cmnd *sc, u32 resid) 694fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 704fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (!resid) 714fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return; 724fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 734fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (!scsi_bidi_cmnd(sc)) { 744fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scsi_set_resid(sc, resid); 754fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return; 764fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } 774fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 784fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scsi_in(sc)->resid = min(resid, scsi_in(sc)->length); 794fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scsi_out(sc)->resid = resid - scsi_in(sc)->resid; 804fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 814fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 824fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini/** 834fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * virtscsi_complete_cmd - finish a scsi_cmd and invoke scsi_done 844fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * 854fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * Called with vq_lock held. 864fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini */ 874fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_complete_cmd(void *buf) 884fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 894fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd *cmd = buf; 904fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct scsi_cmnd *sc = cmd->sc; 914fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd_resp *resp = &cmd->resp.cmd; 924fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 934fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini dev_dbg(&sc->device->sdev_gendev, 944fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini "cmd %p response %u status %#02x sense_len %u\n", 954fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sc, resp->response, resp->status, resp->sense_len); 964fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 974fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sc->result = resp->status; 984fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_compute_resid(sc, resp->resid); 994fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini switch (resp->response) { 1004fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_OK: 1014fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_OK); 1024fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1034fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_OVERRUN: 1044fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_ERROR); 1054fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1064fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_ABORTED: 1074fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_ABORT); 1084fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1094fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_BAD_TARGET: 1104fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_BAD_TARGET); 1114fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1124fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_RESET: 1134fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_RESET); 1144fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1154fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_BUSY: 1164fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_BUS_BUSY); 1174fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1184fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_TRANSPORT_FAILURE: 1194fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_TRANSPORT_DISRUPTED); 1204fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1214fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_TARGET_FAILURE: 1224fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_TARGET_FAILURE); 1234fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1244fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_NEXUS_FAILURE: 1254fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_NEXUS_FAILURE); 1264fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1274fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini default: 1284fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scmd_printk(KERN_WARNING, sc, "Unknown response %d", 1294fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini resp->response); 1304fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* fall through */ 1314fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini case VIRTIO_SCSI_S_FAILURE: 1324fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_host_byte(sc, DID_ERROR); 1334fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini break; 1344fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } 1354fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1364fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini WARN_ON(resp->sense_len > VIRTIO_SCSI_SENSE_SIZE); 1374fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (sc->sense_buffer) { 1384fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini memcpy(sc->sense_buffer, resp->sense, 1394fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini min_t(u32, resp->sense_len, VIRTIO_SCSI_SENSE_SIZE)); 1404fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (resp->sense_len) 1414fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini set_driver_byte(sc, DRIVER_SENSE); 1424fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } 1434fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1444fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini mempool_free(cmd, virtscsi_cmd_pool); 1454fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sc->scsi_done(sc); 1464fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 1474fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1484fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_vq_done(struct virtqueue *vq, void (*fn)(void *buf)) 1494fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 1504fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); 1514fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi *vscsi = shost_priv(sh); 1524fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini void *buf; 1534fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini unsigned long flags; 1544fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini unsigned int len; 1554fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1564fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini spin_lock_irqsave(&vscsi->vq_lock, flags); 1574fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1584fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini do { 1594fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtqueue_disable_cb(vq); 1604fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini while ((buf = virtqueue_get_buf(vq, &len)) != NULL) 1614fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini fn(buf); 1624fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } while (!virtqueue_enable_cb(vq)); 1634fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1644fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini spin_unlock_irqrestore(&vscsi->vq_lock, flags); 1654fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 1664fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1674fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_req_done(struct virtqueue *vq) 1684fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 1694fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_vq_done(vq, virtscsi_complete_cmd); 1704fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini}; 1714fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1724fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_complete_free(void *buf) 1734fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 1744fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd *cmd = buf; 1754fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1764fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (cmd->comp) 1774fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini complete_all(cmd->comp); 178e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini else 179e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini mempool_free(cmd, virtscsi_cmd_pool); 1804fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 1814fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1824fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_ctrl_done(struct virtqueue *vq) 1834fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 1844fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_vq_done(vq, virtscsi_complete_free); 1854fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini}; 1864fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1874fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_event_done(struct virtqueue *vq) 1884fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 1894fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_vq_done(vq, virtscsi_complete_free); 1904fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini}; 1914fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 1924fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx, 1934fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct scsi_data_buffer *sdb) 1944fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 1954fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct sg_table *table = &sdb->table; 1964fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct scatterlist *sg_elem; 1974fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini unsigned int idx = *p_idx; 1984fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini int i; 1994fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2004fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini for_each_sg(table->sgl, sg_elem, table->nents, i) 2014fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sg_set_buf(&sg[idx++], sg_virt(sg_elem), sg_elem->length); 2024fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2034fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini *p_idx = idx; 2044fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 2054fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2064fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini/** 2074fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * virtscsi_map_cmd - map a scsi_cmd to a virtqueue scatterlist 2084fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * @vscsi : virtio_scsi state 2094fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * @cmd : command structure 2104fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * @out_num : number of read-only elements 2114fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * @in_num : number of write-only elements 2124fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * @req_size : size of the request buffer 2134fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * @resp_size : size of the response buffer 2144fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * 2154fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * Called with vq_lock held. 2164fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini */ 2174fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_map_cmd(struct virtio_scsi *vscsi, 2184fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd *cmd, 2194fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini unsigned *out_num, unsigned *in_num, 2204fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini size_t req_size, size_t resp_size) 2214fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 2224fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct scsi_cmnd *sc = cmd->sc; 2234fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct scatterlist *sg = vscsi->sg; 2244fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini unsigned int idx = 0; 2254fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2264fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (sc) { 2274fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); 2284fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); 2294fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2304fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* TODO: check feature bit and fail if unsupported? */ 2314fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini BUG_ON(sc->sc_data_direction == DMA_BIDIRECTIONAL); 2324fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } 2334fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2344fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Request header. */ 2354fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sg_set_buf(&sg[idx++], &cmd->req, req_size); 2364fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2374fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Data-out buffer. */ 2384fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (sc && sc->sc_data_direction != DMA_FROM_DEVICE) 2394fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_map_sgl(sg, &idx, scsi_out(sc)); 2404fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2414fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini *out_num = idx; 2424fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2434fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Response header. */ 2444fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sg_set_buf(&sg[idx++], &cmd->resp, resp_size); 2454fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2464fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Data-in buffer */ 2474fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (sc && sc->sc_data_direction != DMA_TO_DEVICE) 2484fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_map_sgl(sg, &idx, scsi_in(sc)); 2494fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2504fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini *in_num = idx - *out_num; 2514fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 2524fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2534fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int virtscsi_kick_cmd(struct virtio_scsi *vscsi, struct virtqueue *vq, 2544fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd *cmd, 2554fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini size_t req_size, size_t resp_size, gfp_t gfp) 2564fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 2574fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini unsigned int out_num, in_num; 2584fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini unsigned long flags; 2594fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini int ret; 2604fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2614fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini spin_lock_irqsave(&vscsi->vq_lock, flags); 2624fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2634fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_map_cmd(vscsi, cmd, &out_num, &in_num, req_size, resp_size); 2644fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2654fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini ret = virtqueue_add_buf(vq, vscsi->sg, out_num, in_num, cmd, gfp); 2664fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (ret >= 0) 2674fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtqueue_kick(vq); 2684fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2694fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini spin_unlock_irqrestore(&vscsi->vq_lock, flags); 2704fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return ret; 2714fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 2724fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2734fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) 2744fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 2754fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi *vscsi = shost_priv(sh); 2764fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd *cmd; 2774fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini int ret; 2784fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2794fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini dev_dbg(&sc->device->sdev_gendev, 2804fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini "cmd %p CDB: %#02x\n", sc, sc->cmnd[0]); 2814fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2824fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini ret = SCSI_MLQUEUE_HOST_BUSY; 2834fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd = mempool_alloc(virtscsi_cmd_pool, GFP_ATOMIC); 2844fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (!cmd) 2854fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini goto out; 2864fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 2874fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini memset(cmd, 0, sizeof(*cmd)); 2884fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd->sc = sc; 2894fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd->req.cmd = (struct virtio_scsi_cmd_req){ 2904fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[0] = 1, 2914fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[1] = sc->device->id, 2924fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[2] = (sc->device->lun >> 8) | 0x40, 2934fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[3] = sc->device->lun & 0xff, 2944fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .tag = (unsigned long)sc, 2954fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .task_attr = VIRTIO_SCSI_S_SIMPLE, 2964fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .prio = 0, 2974fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .crn = 0, 2984fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini }; 2994fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3004fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); 3014fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); 3024fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3034fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (virtscsi_kick_cmd(vscsi, vscsi->req_vq, cmd, 3044fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sizeof cmd->req.cmd, sizeof cmd->resp.cmd, 3054fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini GFP_ATOMIC) >= 0) 3064fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini ret = 0; 3074fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3084fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonziniout: 3094fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return ret; 3104fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 3114fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3124fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd) 3134fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 3144fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini DECLARE_COMPLETION_ONSTACK(comp); 315e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini int ret = FAILED; 3164fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3174fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd->comp = ∁ 318e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini if (virtscsi_kick_cmd(vscsi, vscsi->ctrl_vq, cmd, 319e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini sizeof cmd->req.tmf, sizeof cmd->resp.tmf, 320e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini GFP_NOIO) < 0) 321e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini goto out; 3224fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3234fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini wait_for_completion(&comp); 324e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini if (cmd->resp.tmf.response == VIRTIO_SCSI_S_OK || 325e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini cmd->resp.tmf.response == VIRTIO_SCSI_S_FUNCTION_SUCCEEDED) 326e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini ret = SUCCESS; 3274fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 328e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonziniout: 329e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini mempool_free(cmd, virtscsi_cmd_pool); 330e4594bb50518eb89c447be97dabd5bd99f405d71Paolo Bonzini return ret; 3314fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 3324fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3334fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int virtscsi_device_reset(struct scsi_cmnd *sc) 3344fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 3354fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi *vscsi = shost_priv(sc->device->host); 3364fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd *cmd; 3374fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3384fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sdev_printk(KERN_INFO, sc->device, "device reset\n"); 3394fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO); 3404fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (!cmd) 3414fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return FAILED; 3424fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3434fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini memset(cmd, 0, sizeof(*cmd)); 3444fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd->sc = sc; 3454fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ 3464fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .type = VIRTIO_SCSI_T_TMF, 3474fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .subtype = VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET, 3484fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[0] = 1, 3494fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[1] = sc->device->id, 3504fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[2] = (sc->device->lun >> 8) | 0x40, 3514fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[3] = sc->device->lun & 0xff, 3524fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini }; 3534fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return virtscsi_tmf(vscsi, cmd); 3544fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 3554fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3564fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int virtscsi_abort(struct scsi_cmnd *sc) 3574fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 3584fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi *vscsi = shost_priv(sc->device->host); 3594fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi_cmd *cmd; 3604fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3614fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scmd_printk(KERN_INFO, sc, "abort\n"); 3624fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO); 3634fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (!cmd) 3644fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return FAILED; 3654fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3664fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini memset(cmd, 0, sizeof(*cmd)); 3674fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd->sc = sc; 3684fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ 3694fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .type = VIRTIO_SCSI_T_TMF, 3704fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .subtype = VIRTIO_SCSI_T_TMF_ABORT_TASK, 3714fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[0] = 1, 3724fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[1] = sc->device->id, 3734fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[2] = (sc->device->lun >> 8) | 0x40, 3744fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .lun[3] = sc->device->lun & 0xff, 3754fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .tag = (unsigned long)sc, 3764fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini }; 3774fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return virtscsi_tmf(vscsi, cmd); 3784fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 3794fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3804fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic struct scsi_host_template virtscsi_host_template = { 3814fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .module = THIS_MODULE, 3824fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .name = "Virtio SCSI HBA", 3834fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .proc_name = "virtio_scsi", 3844fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .queuecommand = virtscsi_queuecommand, 3854fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .this_id = -1, 3864fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .eh_abort_handler = virtscsi_abort, 3874fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .eh_device_reset_handler = virtscsi_device_reset, 3884fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3894fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .can_queue = 1024, 3904fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .dma_boundary = UINT_MAX, 3914fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .use_clustering = ENABLE_CLUSTERING, 3924fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini}; 3934fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 3944fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#define virtscsi_config_get(vdev, fld) \ 3954fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini ({ \ 3964fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini typeof(((struct virtio_scsi_config *)0)->fld) __val; \ 3974fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vdev->config->get(vdev, \ 3984fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini offsetof(struct virtio_scsi_config, fld), \ 3994fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini &__val, sizeof(__val)); \ 4004fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini __val; \ 4014fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini }) 4024fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4034fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#define virtscsi_config_set(vdev, fld, val) \ 4044fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini (void)({ \ 4054fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \ 4064fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vdev->config->set(vdev, \ 4074fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini offsetof(struct virtio_scsi_config, fld), \ 4084fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini &__val, sizeof(__val)); \ 4094fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini }) 4104fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4114fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int virtscsi_init(struct virtio_device *vdev, 4124fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi *vscsi) 4134fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 4144fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini int err; 4154fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtqueue *vqs[3]; 4164fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vq_callback_t *callbacks[] = { 4174fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_ctrl_done, 4184fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_event_done, 4194fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_req_done 4204fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini }; 4214fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini const char *names[] = { 4224fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini "control", 4234fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini "event", 4244fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini "request" 4254fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini }; 4264fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4274fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Discover virtqueues and write information to configuration. */ 4284fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini err = vdev->config->find_vqs(vdev, 3, vqs, callbacks, names); 4294fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (err) 4304fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return err; 4314fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4324fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vscsi->ctrl_vq = vqs[0]; 4334fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vscsi->event_vq = vqs[1]; 4344fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vscsi->req_vq = vqs[2]; 4354fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4364fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE); 4374fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE); 4384fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return 0; 4394fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 4404fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4414fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int __devinit virtscsi_probe(struct virtio_device *vdev) 4424fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 4434fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct Scsi_Host *shost; 4444fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi *vscsi; 4454fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini int err; 4464fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini u32 sg_elems; 4474fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini u32 cmd_per_lun; 4484fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4494fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* We need to know how many segments before we allocate. 4504fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini * We need an extra sg elements at head and tail. 4514fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini */ 4524fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1; 4534fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4544fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Allocate memory and link the structs together. */ 4554fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini shost = scsi_host_alloc(&virtscsi_host_template, 4564fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sizeof(*vscsi) + sizeof(vscsi->sg[0]) * (sg_elems + 2)); 4574fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4584fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (!shost) 4594fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return -ENOMEM; 4604fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4614fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini shost->sg_tablesize = sg_elems; 4624fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vscsi = shost_priv(shost); 4634fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vscsi->vdev = vdev; 4644fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vdev->priv = shost; 4654fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4664fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Random initializations. */ 4674fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini spin_lock_init(&vscsi->vq_lock); 4684fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini sg_init_table(vscsi->sg, sg_elems + 2); 4694fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4704fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini err = virtscsi_init(vdev, vscsi); 4714fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (err) 4724fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini goto virtscsi_init_failed; 4734fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4744fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1; 4754fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue); 4764fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0xFFFF; 4774fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini shost->max_lun = virtscsi_config_get(vdev, max_lun) + 1; 4784fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini shost->max_id = virtscsi_config_get(vdev, max_target) + 1; 4794fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini shost->max_channel = 0; 4804fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE; 4814fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini err = scsi_add_host(shost, &vdev->dev); 4824fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (err) 4834fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini goto scsi_add_host_failed; 4844fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4854fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scsi_scan_host(shost); 4864fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4874fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return 0; 4884fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4894fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonziniscsi_add_host_failed: 4904fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vdev->config->del_vqs(vdev); 4914fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinivirtscsi_init_failed: 4924fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scsi_host_put(shost); 4934fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return err; 4944fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 4954fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 4964fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void virtscsi_remove_vqs(struct virtio_device *vdev) 4974fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 4984fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini /* Stop all the virtqueues. */ 4994fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vdev->config->reset(vdev); 5004fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5014fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini vdev->config->del_vqs(vdev); 5024fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 5034fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5044fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void __devexit virtscsi_remove(struct virtio_device *vdev) 5054fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 5064fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct Scsi_Host *shost = virtio_scsi_host(vdev); 5074fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5084fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scsi_remove_host(shost); 5094fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5104fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_remove_vqs(vdev); 5114fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini scsi_host_put(shost); 5124fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 5134fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5144fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#ifdef CONFIG_PM 5154fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int virtscsi_freeze(struct virtio_device *vdev) 5164fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 5174fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_remove_vqs(vdev); 5184fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return 0; 5194fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 5204fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5214fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int virtscsi_restore(struct virtio_device *vdev) 5224fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 5234fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct Scsi_Host *sh = virtio_scsi_host(vdev); 5244fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini struct virtio_scsi *vscsi = shost_priv(sh); 5254fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5264fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return virtscsi_init(vdev, vscsi); 5274fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 5284fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#endif 5294fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5304fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic struct virtio_device_id id_table[] = { 5314fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini { VIRTIO_ID_SCSI, VIRTIO_DEV_ANY_ID }, 5324fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini { 0 }, 5334fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini}; 5344fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5354fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic struct virtio_driver virtio_scsi_driver = { 5364fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .driver.name = KBUILD_MODNAME, 5374fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .driver.owner = THIS_MODULE, 5384fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .id_table = id_table, 5394fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .probe = virtscsi_probe, 5404fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#ifdef CONFIG_PM 5414fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .freeze = virtscsi_freeze, 5424fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .restore = virtscsi_restore, 5434fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini#endif 5444fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini .remove = __devexit_p(virtscsi_remove), 5454fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini}; 5464fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5474fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic int __init init(void) 5484fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 5494fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini int ret = -ENOMEM; 5504fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5514fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_cmd_cache = KMEM_CACHE(virtio_scsi_cmd, 0); 5524fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (!virtscsi_cmd_cache) { 5534fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini printk(KERN_ERR "kmem_cache_create() for " 5544fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini "virtscsi_cmd_cache failed\n"); 5554fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini goto error; 5564fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } 5574fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5584fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5594fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_cmd_pool = 5604fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini mempool_create_slab_pool(VIRTIO_SCSI_MEMPOOL_SZ, 5614fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_cmd_cache); 5624fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (!virtscsi_cmd_pool) { 5634fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini printk(KERN_ERR "mempool_create() for" 5644fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini "virtscsi_cmd_pool failed\n"); 5654fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini goto error; 5664fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } 5674fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini ret = register_virtio_driver(&virtio_scsi_driver); 5684fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (ret < 0) 5694fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini goto error; 5704fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5714fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return 0; 5724fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5734fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinierror: 5744fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (virtscsi_cmd_pool) { 5754fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini mempool_destroy(virtscsi_cmd_pool); 5764fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_cmd_pool = NULL; 5774fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } 5784fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini if (virtscsi_cmd_cache) { 5794fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini kmem_cache_destroy(virtscsi_cmd_cache); 5804fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini virtscsi_cmd_cache = NULL; 5814fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini } 5824fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini return ret; 5834fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 5844fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5854fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinistatic void __exit fini(void) 5864fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini{ 5874fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini unregister_virtio_driver(&virtio_scsi_driver); 5884fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini mempool_destroy(virtscsi_cmd_pool); 5894fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini kmem_cache_destroy(virtscsi_cmd_cache); 5904fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini} 5914fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinimodule_init(init); 5924fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzinimodule_exit(fini); 5934fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo Bonzini 5944fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo BonziniMODULE_DEVICE_TABLE(virtio, id_table); 5954fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo BonziniMODULE_DESCRIPTION("Virtio SCSI HBA driver"); 5964fe74b1cb051dc9d47a80e263c388cf1651783d4Paolo BonziniMODULE_LICENSE("GPL"); 597