aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/virtio_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/virtio_scsi.c')
-rw-r--r--drivers/scsi/virtio_scsi.c71
1 files changed, 25 insertions, 46 deletions
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index b53ba9e18f47..ffa03e8cb19c 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -75,8 +75,6 @@ struct virtio_scsi {
75 75
76 /* Get some buffers ready for event vq */ 76 /* Get some buffers ready for event vq */
77 struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; 77 struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN];
78
79 struct virtio_scsi_target_state *tgt[];
80}; 78};
81 79
82static struct kmem_cache *virtscsi_cmd_cache; 80static struct kmem_cache *virtscsi_cmd_cache;
@@ -530,6 +528,25 @@ static int virtscsi_abort(struct scsi_cmnd *sc)
530 return virtscsi_tmf(vscsi, cmd); 528 return virtscsi_tmf(vscsi, cmd);
531} 529}
532 530
531static int virtscsi_target_alloc(struct scsi_target *starget)
532{
533 struct virtio_scsi_target_state *tgt =
534 kmalloc(sizeof(*tgt), GFP_KERNEL);
535 if (!tgt)
536 return -ENOMEM;
537
538 spin_lock_init(&tgt->tgt_lock);
539
540 starget->hostdata = tgt;
541 return 0;
542}
543
544static void virtscsi_target_destroy(struct scsi_target *starget)
545{
546 struct virtio_scsi_target_state *tgt = starget->hostdata;
547 kfree(tgt);
548}
549
533static struct scsi_host_template virtscsi_host_template = { 550static struct scsi_host_template virtscsi_host_template = {
534 .module = THIS_MODULE, 551 .module = THIS_MODULE,
535 .name = "Virtio SCSI HBA", 552 .name = "Virtio SCSI HBA",
@@ -542,6 +559,8 @@ static struct scsi_host_template virtscsi_host_template = {
542 .can_queue = 1024, 559 .can_queue = 1024,
543 .dma_boundary = UINT_MAX, 560 .dma_boundary = UINT_MAX,
544 .use_clustering = ENABLE_CLUSTERING, 561 .use_clustering = ENABLE_CLUSTERING,
562 .target_alloc = virtscsi_target_alloc,
563 .target_destroy = virtscsi_target_destroy,
545}; 564};
546 565
547#define virtscsi_config_get(vdev, fld) \ 566#define virtscsi_config_get(vdev, fld) \
@@ -568,20 +587,6 @@ static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq,
568 virtscsi_vq->vq = vq; 587 virtscsi_vq->vq = vq;
569} 588}
570 589
571static struct virtio_scsi_target_state *virtscsi_alloc_tgt(
572 struct virtio_device *vdev)
573{
574 struct virtio_scsi_target_state *tgt;
575 gfp_t gfp_mask = GFP_KERNEL;
576
577 tgt = kmalloc(sizeof(*tgt), gfp_mask);
578 if (!tgt)
579 return NULL;
580
581 spin_lock_init(&tgt->tgt_lock);
582 return tgt;
583}
584
585static void virtscsi_scan(struct virtio_device *vdev) 590static void virtscsi_scan(struct virtio_device *vdev)
586{ 591{
587 struct Scsi_Host *shost = (struct Scsi_Host *)vdev->priv; 592 struct Scsi_Host *shost = (struct Scsi_Host *)vdev->priv;
@@ -591,28 +596,17 @@ static void virtscsi_scan(struct virtio_device *vdev)
591 596
592static void virtscsi_remove_vqs(struct virtio_device *vdev) 597static void virtscsi_remove_vqs(struct virtio_device *vdev)
593{ 598{
594 struct Scsi_Host *sh = virtio_scsi_host(vdev);
595 struct virtio_scsi *vscsi = shost_priv(sh);
596 u32 i, num_targets;
597
598 /* Stop all the virtqueues. */ 599 /* Stop all the virtqueues. */
599 vdev->config->reset(vdev); 600 vdev->config->reset(vdev);
600 601
601 num_targets = sh->max_id;
602 for (i = 0; i < num_targets; i++) {
603 kfree(vscsi->tgt[i]);
604 vscsi->tgt[i] = NULL;
605 }
606
607 vdev->config->del_vqs(vdev); 602 vdev->config->del_vqs(vdev);
608} 603}
609 604
610static int virtscsi_init(struct virtio_device *vdev, 605static int virtscsi_init(struct virtio_device *vdev,
611 struct virtio_scsi *vscsi, int num_targets) 606 struct virtio_scsi *vscsi)
612{ 607{
613 int err; 608 int err;
614 struct virtqueue *vqs[3]; 609 struct virtqueue *vqs[3];
615 u32 i;
616 610
617 vq_callback_t *callbacks[] = { 611 vq_callback_t *callbacks[] = {
618 virtscsi_ctrl_done, 612 virtscsi_ctrl_done,
@@ -640,18 +634,6 @@ static int virtscsi_init(struct virtio_device *vdev,
640 if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) 634 if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG))
641 virtscsi_kick_event_all(vscsi); 635 virtscsi_kick_event_all(vscsi);
642 636
643 for (i = 0; i < num_targets; i++) {
644 vscsi->tgt[i] = virtscsi_alloc_tgt(vdev);
645 if (!vscsi->tgt[i]) {
646 err = -ENOMEM;
647 goto out;
648 }
649 }
650 err = 0;
651
652out:
653 if (err)
654 virtscsi_remove_vqs(vdev);
655 return err; 637 return err;
656} 638}
657 639
@@ -663,12 +645,9 @@ static int virtscsi_probe(struct virtio_device *vdev)
663 u32 sg_elems, num_targets; 645 u32 sg_elems, num_targets;
664 u32 cmd_per_lun; 646 u32 cmd_per_lun;
665 647
666 /* Allocate memory and link the structs together. */
667 num_targets = virtscsi_config_get(vdev, max_target) + 1; 648 num_targets = virtscsi_config_get(vdev, max_target) + 1;
668 shost = scsi_host_alloc(&virtscsi_host_template,
669 sizeof(*vscsi)
670 + num_targets * sizeof(struct virtio_scsi_target_state));
671 649
650 shost = scsi_host_alloc(&virtscsi_host_template, sizeof(*vscsi));
672 if (!shost) 651 if (!shost)
673 return -ENOMEM; 652 return -ENOMEM;
674 653
@@ -678,7 +657,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
678 vscsi->vdev = vdev; 657 vscsi->vdev = vdev;
679 vdev->priv = shost; 658 vdev->priv = shost;
680 659
681 err = virtscsi_init(vdev, vscsi, num_targets); 660 err = virtscsi_init(vdev, vscsi);
682 if (err) 661 if (err)
683 goto virtscsi_init_failed; 662 goto virtscsi_init_failed;
684 663
@@ -735,7 +714,7 @@ static int virtscsi_restore(struct virtio_device *vdev)
735 struct Scsi_Host *sh = virtio_scsi_host(vdev); 714 struct Scsi_Host *sh = virtio_scsi_host(vdev);
736 struct virtio_scsi *vscsi = shost_priv(sh); 715 struct virtio_scsi *vscsi = shost_priv(sh);
737 716
738 return virtscsi_init(vdev, vscsi, sh->max_id); 717 return virtscsi_init(vdev, vscsi);
739} 718}
740#endif 719#endif
741 720