|
@@ -75,8 +75,6 @@ struct virtio_scsi {
|
|
|
|
|
|
/* Get some buffers ready for event vq */
|
|
|
struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
|
|
|
-
|
|
|
- struct virtio_scsi_target_state *tgt[];
|
|
|
};
|
|
|
|
|
|
static struct kmem_cache *virtscsi_cmd_cache;
|
|
@@ -530,6 +528,25 @@ static int virtscsi_abort(struct scsi_cmnd *sc)
|
|
|
return virtscsi_tmf(vscsi, cmd);
|
|
|
}
|
|
|
|
|
|
+static int virtscsi_target_alloc(struct scsi_target *starget)
|
|
|
+{
|
|
|
+ struct virtio_scsi_target_state *tgt =
|
|
|
+ kmalloc(sizeof(*tgt), GFP_KERNEL);
|
|
|
+ if (!tgt)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ spin_lock_init(&tgt->tgt_lock);
|
|
|
+
|
|
|
+ starget->hostdata = tgt;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void virtscsi_target_destroy(struct scsi_target *starget)
|
|
|
+{
|
|
|
+ struct virtio_scsi_target_state *tgt = starget->hostdata;
|
|
|
+ kfree(tgt);
|
|
|
+}
|
|
|
+
|
|
|
static struct scsi_host_template virtscsi_host_template = {
|
|
|
.module = THIS_MODULE,
|
|
|
.name = "Virtio SCSI HBA",
|
|
@@ -542,6 +559,8 @@ static struct scsi_host_template virtscsi_host_template = {
|
|
|
.can_queue = 1024,
|
|
|
.dma_boundary = UINT_MAX,
|
|
|
.use_clustering = ENABLE_CLUSTERING,
|
|
|
+ .target_alloc = virtscsi_target_alloc,
|
|
|
+ .target_destroy = virtscsi_target_destroy,
|
|
|
};
|
|
|
|
|
|
#define virtscsi_config_get(vdev, fld) \
|
|
@@ -568,20 +587,6 @@ static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq,
|
|
|
virtscsi_vq->vq = vq;
|
|
|
}
|
|
|
|
|
|
-static struct virtio_scsi_target_state *virtscsi_alloc_tgt(
|
|
|
- struct virtio_device *vdev)
|
|
|
-{
|
|
|
- struct virtio_scsi_target_state *tgt;
|
|
|
- gfp_t gfp_mask = GFP_KERNEL;
|
|
|
-
|
|
|
- tgt = kmalloc(sizeof(*tgt), gfp_mask);
|
|
|
- if (!tgt)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- spin_lock_init(&tgt->tgt_lock);
|
|
|
- return tgt;
|
|
|
-}
|
|
|
-
|
|
|
static void virtscsi_scan(struct virtio_device *vdev)
|
|
|
{
|
|
|
struct Scsi_Host *shost = (struct Scsi_Host *)vdev->priv;
|
|
@@ -591,28 +596,17 @@ static void virtscsi_scan(struct virtio_device *vdev)
|
|
|
|
|
|
static void virtscsi_remove_vqs(struct virtio_device *vdev)
|
|
|
{
|
|
|
- struct Scsi_Host *sh = virtio_scsi_host(vdev);
|
|
|
- struct virtio_scsi *vscsi = shost_priv(sh);
|
|
|
- u32 i, num_targets;
|
|
|
-
|
|
|
/* Stop all the virtqueues. */
|
|
|
vdev->config->reset(vdev);
|
|
|
|
|
|
- num_targets = sh->max_id;
|
|
|
- for (i = 0; i < num_targets; i++) {
|
|
|
- kfree(vscsi->tgt[i]);
|
|
|
- vscsi->tgt[i] = NULL;
|
|
|
- }
|
|
|
-
|
|
|
vdev->config->del_vqs(vdev);
|
|
|
}
|
|
|
|
|
|
static int virtscsi_init(struct virtio_device *vdev,
|
|
|
- struct virtio_scsi *vscsi, int num_targets)
|
|
|
+ struct virtio_scsi *vscsi)
|
|
|
{
|
|
|
int err;
|
|
|
struct virtqueue *vqs[3];
|
|
|
- u32 i;
|
|
|
|
|
|
vq_callback_t *callbacks[] = {
|
|
|
virtscsi_ctrl_done,
|
|
@@ -640,18 +634,6 @@ static int virtscsi_init(struct virtio_device *vdev,
|
|
|
if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG))
|
|
|
virtscsi_kick_event_all(vscsi);
|
|
|
|
|
|
- for (i = 0; i < num_targets; i++) {
|
|
|
- vscsi->tgt[i] = virtscsi_alloc_tgt(vdev);
|
|
|
- if (!vscsi->tgt[i]) {
|
|
|
- err = -ENOMEM;
|
|
|
- goto out;
|
|
|
- }
|
|
|
- }
|
|
|
- err = 0;
|
|
|
-
|
|
|
-out:
|
|
|
- if (err)
|
|
|
- virtscsi_remove_vqs(vdev);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -663,12 +645,9 @@ static int virtscsi_probe(struct virtio_device *vdev)
|
|
|
u32 sg_elems, num_targets;
|
|
|
u32 cmd_per_lun;
|
|
|
|
|
|
- /* Allocate memory and link the structs together. */
|
|
|
num_targets = virtscsi_config_get(vdev, max_target) + 1;
|
|
|
- shost = scsi_host_alloc(&virtscsi_host_template,
|
|
|
- sizeof(*vscsi)
|
|
|
- + num_targets * sizeof(struct virtio_scsi_target_state));
|
|
|
|
|
|
+ shost = scsi_host_alloc(&virtscsi_host_template, sizeof(*vscsi));
|
|
|
if (!shost)
|
|
|
return -ENOMEM;
|
|
|
|
|
@@ -678,7 +657,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
|
|
|
vscsi->vdev = vdev;
|
|
|
vdev->priv = shost;
|
|
|
|
|
|
- err = virtscsi_init(vdev, vscsi, num_targets);
|
|
|
+ err = virtscsi_init(vdev, vscsi);
|
|
|
if (err)
|
|
|
goto virtscsi_init_failed;
|
|
|
|
|
@@ -735,7 +714,7 @@ static int virtscsi_restore(struct virtio_device *vdev)
|
|
|
struct Scsi_Host *sh = virtio_scsi_host(vdev);
|
|
|
struct virtio_scsi *vscsi = shost_priv(sh);
|
|
|
|
|
|
- return virtscsi_init(vdev, vscsi, sh->max_id);
|
|
|
+ return virtscsi_init(vdev, vscsi);
|
|
|
}
|
|
|
#endif
|
|
|
|