Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 316826
b: refs/heads/master
c: 139fe45
h: refs/heads/master
v: v3
  • Loading branch information
Paolo Bonzini authored and James Bottomley committed Jul 20, 2012
1 parent fb969d1 commit ad988e9
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 26 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b5ee8f2802c559fccb177c0a117f5cd56c1049cc
refs/heads/master: 139fe45abc2234b20fd5ecbcb7ea6d3688fed5e5
77 changes: 52 additions & 25 deletions trunk/drivers/scsi/virtio_scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,22 @@ struct virtio_scsi_cmd {
} resp;
} ____cacheline_aligned_in_smp;

struct virtio_scsi_vq {
/* Protects vq */
spinlock_t vq_lock;

struct virtqueue *vq;
};

/* Driver instance state */
struct virtio_scsi {
/* Protects ctrl_vq, req_vq and sg[] */
spinlock_t vq_lock;
/* Protects sg[]. The lock hierarchy is sg_lock -> vq_lock. */
spinlock_t sg_lock;

struct virtio_device *vdev;
struct virtqueue *ctrl_vq;
struct virtqueue *event_vq;
struct virtqueue *req_vq;
struct virtio_scsi_vq ctrl_vq;
struct virtio_scsi_vq event_vq;
struct virtio_scsi_vq req_vq;

/* For sglist construction when adding commands to the virtqueue. */
struct scatterlist sg[];
Expand Down Expand Up @@ -147,26 +154,25 @@ static void virtscsi_complete_cmd(void *buf)

static void virtscsi_vq_done(struct virtqueue *vq, void (*fn)(void *buf))
{
struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
void *buf;
unsigned long flags;
unsigned int len;

spin_lock_irqsave(&vscsi->vq_lock, flags);

do {
virtqueue_disable_cb(vq);
while ((buf = virtqueue_get_buf(vq, &len)) != NULL)
fn(buf);
} while (!virtqueue_enable_cb(vq));

spin_unlock_irqrestore(&vscsi->vq_lock, flags);
}

static void virtscsi_req_done(struct virtqueue *vq)
{
struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
unsigned long flags;

spin_lock_irqsave(&vscsi->req_vq.vq_lock, flags);
virtscsi_vq_done(vq, virtscsi_complete_cmd);
spin_unlock_irqrestore(&vscsi->req_vq.vq_lock, flags);
};

static void virtscsi_complete_free(void *buf)
Expand All @@ -181,12 +187,24 @@ static void virtscsi_complete_free(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);
unsigned long flags;

spin_lock_irqsave(&vscsi->ctrl_vq.vq_lock, flags);
virtscsi_vq_done(vq, virtscsi_complete_free);
spin_unlock_irqrestore(&vscsi->ctrl_vq.vq_lock, flags);
};

static void virtscsi_event_done(struct virtqueue *vq)
{
struct Scsi_Host *sh = virtio_scsi_host(vq->vdev);
struct virtio_scsi *vscsi = shost_priv(sh);
unsigned long flags;

spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags);
virtscsi_vq_done(vq, virtscsi_complete_free);
spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags);
};

static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,
Expand Down Expand Up @@ -250,25 +268,27 @@ static void virtscsi_map_cmd(struct virtio_scsi *vscsi,
*in_num = idx - *out_num;
}

static int virtscsi_kick_cmd(struct virtio_scsi *vscsi, struct virtqueue *vq,
static int virtscsi_kick_cmd(struct virtio_scsi *vscsi, struct virtio_scsi_vq *vq,
struct virtio_scsi_cmd *cmd,
size_t req_size, size_t resp_size, gfp_t gfp)
{
unsigned int out_num, in_num;
unsigned long flags;
int ret;

spin_lock_irqsave(&vscsi->vq_lock, flags);

spin_lock_irqsave(&vscsi->sg_lock, flags);
virtscsi_map_cmd(vscsi, cmd, &out_num, &in_num, req_size, resp_size);

ret = virtqueue_add_buf(vq, vscsi->sg, out_num, in_num, cmd, gfp);
spin_lock(&vq->vq_lock);
ret = virtqueue_add_buf(vq->vq, vscsi->sg, out_num, in_num, cmd, gfp);
if (ret >= 0)
ret = virtqueue_kick_prepare(vq);
ret = virtqueue_kick_prepare(vq->vq);

spin_unlock(&vq->vq_lock);
spin_unlock_irqrestore(&vscsi->sg_lock, flags);

spin_unlock_irqrestore(&vscsi->vq_lock, flags);
if (ret > 0)
virtqueue_notify(vq);
virtqueue_notify(vq->vq);
return ret;
}

Expand Down Expand Up @@ -302,7 +322,7 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE);
memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);

if (virtscsi_kick_cmd(vscsi, vscsi->req_vq, cmd,
if (virtscsi_kick_cmd(vscsi, &vscsi->req_vq, cmd,
sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
GFP_ATOMIC) >= 0)
ret = 0;
Expand All @@ -317,7 +337,7 @@ static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd)
int ret = FAILED;

cmd->comp = ∁
if (virtscsi_kick_cmd(vscsi, vscsi->ctrl_vq, cmd,
if (virtscsi_kick_cmd(vscsi, &vscsi->ctrl_vq, cmd,
sizeof cmd->req.tmf, sizeof cmd->resp.tmf,
GFP_NOIO) < 0)
goto out;
Expand Down Expand Up @@ -410,6 +430,13 @@ static struct scsi_host_template virtscsi_host_template = {
&__val, sizeof(__val)); \
})

static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq,
struct virtqueue *vq)
{
spin_lock_init(&virtscsi_vq->vq_lock);
virtscsi_vq->vq = vq;
}

static int virtscsi_init(struct virtio_device *vdev,
struct virtio_scsi *vscsi)
{
Expand All @@ -431,9 +458,9 @@ static int virtscsi_init(struct virtio_device *vdev,
if (err)
return err;

vscsi->ctrl_vq = vqs[0];
vscsi->event_vq = vqs[1];
vscsi->req_vq = vqs[2];
virtscsi_init_vq(&vscsi->ctrl_vq, vqs[0]);
virtscsi_init_vq(&vscsi->event_vq, vqs[1]);
virtscsi_init_vq(&vscsi->req_vq, vqs[2]);

virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE);
virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE);
Expand Down Expand Up @@ -466,7 +493,7 @@ static int __devinit virtscsi_probe(struct virtio_device *vdev)
vdev->priv = shost;

/* Random initializations. */
spin_lock_init(&vscsi->vq_lock);
spin_lock_init(&vscsi->sg_lock);
sg_init_table(vscsi->sg, sg_elems + 2);

err = virtscsi_init(vdev, vscsi);
Expand Down

0 comments on commit ad988e9

Please sign in to comment.