aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/virtio_scsi.c
diff options
context:
space:
mode:
authorWanlong Gao <gaowanlong@cn.fujitsu.com>2013-04-08 09:31:16 -0400
committerRusty Russell <rusty@rustcorp.com.au>2013-04-08 09:36:47 -0400
commit5c370194df9a97248ca69e05bfbd2d21b4886fe5 (patch)
tree068f626733a03d5100f6c32a7a8bf44bd23b109a /drivers/scsi/virtio_scsi.c
parent3826835ab8bb7eac47f14f279df2bd58ec2bb279 (diff)
virtio-scsi: redo allocation of target data
virtio_scsi_target_state is now empty. We will find new uses for it in the next few patches, so this patch does not drop it completely. And as James suggested, we use entries target_alloc and target_destroy in the host template to allocate and destroy the virtio_scsi_target_state of each target, attach this struct to scsi_target->hostdata. Now we can get at it from the sdev with scsi_target(sdev)->hostdata. No messing around with fixed size arrays and bulk memory allocation and no need to pass in the maximum target size as a parameter because everything should now happen dynamically. Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: linux-scsi@vger.kernel.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com> Reviewed-by: Asias He <asias@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
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