diff options
author | Karen Xie <kxie@chelsio.com> | 2009-06-15 14:15:16 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-21 11:52:39 -0400 |
commit | 295ab1b54393aec064533fbc5b483844736ccbf0 (patch) | |
tree | d9debe6032b3705dfbfb32e518c953de85dc3977 /drivers | |
parent | d11b6916961d6ec7d7215332cbbe9feec086721d (diff) |
cxgb3i: use kref to track ddp usage
The iscsi ddp functionality could be used by multiple iscsi entities,
add a refcnt to keep track of it, so we would not release it pre-maturely.
Signed-off-by: Karen Xie <kxie@chelsio.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/cxgb3i/cxgb3i_ddp.c | 54 | ||||
-rw-r--r-- | drivers/scsi/cxgb3i/cxgb3i_ddp.h | 2 |
2 files changed, 35 insertions, 21 deletions
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index 99c912547902..8eb2848403f4 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c | |||
@@ -598,30 +598,40 @@ int cxgb3i_adapter_ddp_info(struct t3cdev *tdev, | |||
598 | * release all the resource held by the ddp pagepod manager for a given | 598 | * release all the resource held by the ddp pagepod manager for a given |
599 | * adapter if needed | 599 | * adapter if needed |
600 | */ | 600 | */ |
601 | void cxgb3i_ddp_cleanup(struct t3cdev *tdev) | 601 | |
602 | static void ddp_cleanup(struct kref *kref) | ||
602 | { | 603 | { |
604 | struct cxgb3i_ddp_info *ddp = container_of(kref, | ||
605 | struct cxgb3i_ddp_info, | ||
606 | refcnt); | ||
603 | int i = 0; | 607 | int i = 0; |
608 | |||
609 | ddp_log_info("kref release ddp 0x%p, t3dev 0x%p.\n", ddp, ddp->tdev); | ||
610 | |||
611 | ddp->tdev->ulp_iscsi = NULL; | ||
612 | while (i < ddp->nppods) { | ||
613 | struct cxgb3i_gather_list *gl = ddp->gl_map[i]; | ||
614 | if (gl) { | ||
615 | int npods = (gl->nelem + PPOD_PAGES_MAX - 1) | ||
616 | >> PPOD_PAGES_SHIFT; | ||
617 | ddp_log_info("t3dev 0x%p, ddp %d + %d.\n", | ||
618 | ddp->tdev, i, npods); | ||
619 | kfree(gl); | ||
620 | ddp_free_gl_skb(ddp, i, npods); | ||
621 | i += npods; | ||
622 | } else | ||
623 | i++; | ||
624 | } | ||
625 | cxgb3i_free_big_mem(ddp); | ||
626 | } | ||
627 | |||
628 | void cxgb3i_ddp_cleanup(struct t3cdev *tdev) | ||
629 | { | ||
604 | struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi; | 630 | struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi; |
605 | 631 | ||
606 | ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp); | 632 | ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp); |
607 | 633 | if (ddp) | |
608 | if (ddp) { | 634 | kref_put(&ddp->refcnt, ddp_cleanup); |
609 | tdev->ulp_iscsi = NULL; | ||
610 | while (i < ddp->nppods) { | ||
611 | struct cxgb3i_gather_list *gl = ddp->gl_map[i]; | ||
612 | if (gl) { | ||
613 | int npods = (gl->nelem + PPOD_PAGES_MAX - 1) | ||
614 | >> PPOD_PAGES_SHIFT; | ||
615 | ddp_log_info("t3dev 0x%p, ddp %d + %d.\n", | ||
616 | tdev, i, npods); | ||
617 | kfree(gl); | ||
618 | ddp_free_gl_skb(ddp, i, npods); | ||
619 | i += npods; | ||
620 | } else | ||
621 | i++; | ||
622 | } | ||
623 | cxgb3i_free_big_mem(ddp); | ||
624 | } | ||
625 | } | 635 | } |
626 | 636 | ||
627 | /** | 637 | /** |
@@ -631,12 +641,13 @@ void cxgb3i_ddp_cleanup(struct t3cdev *tdev) | |||
631 | */ | 641 | */ |
632 | static void ddp_init(struct t3cdev *tdev) | 642 | static void ddp_init(struct t3cdev *tdev) |
633 | { | 643 | { |
634 | struct cxgb3i_ddp_info *ddp; | 644 | struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi; |
635 | struct ulp_iscsi_info uinfo; | 645 | struct ulp_iscsi_info uinfo; |
636 | unsigned int ppmax, bits; | 646 | unsigned int ppmax, bits; |
637 | int i, err; | 647 | int i, err; |
638 | 648 | ||
639 | if (tdev->ulp_iscsi) { | 649 | if (ddp) { |
650 | kref_get(&ddp->refcnt); | ||
640 | ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n", | 651 | ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n", |
641 | tdev, tdev->ulp_iscsi); | 652 | tdev, tdev->ulp_iscsi); |
642 | return; | 653 | return; |
@@ -670,6 +681,7 @@ static void ddp_init(struct t3cdev *tdev) | |||
670 | ppmax * | 681 | ppmax * |
671 | sizeof(struct cxgb3i_gather_list *)); | 682 | sizeof(struct cxgb3i_gather_list *)); |
672 | spin_lock_init(&ddp->map_lock); | 683 | spin_lock_init(&ddp->map_lock); |
684 | kref_init(&ddp->refcnt); | ||
673 | 685 | ||
674 | ddp->tdev = tdev; | 686 | ddp->tdev = tdev; |
675 | ddp->pdev = uinfo.pdev; | 687 | ddp->pdev = uinfo.pdev; |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h index 0d296de7cf32..87dd56b422bf 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h | |||
@@ -54,6 +54,7 @@ struct cxgb3i_gather_list { | |||
54 | * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload | 54 | * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload |
55 | * | 55 | * |
56 | * @list: list head to link elements | 56 | * @list: list head to link elements |
57 | * @refcnt: ref. count | ||
57 | * @tdev: pointer to t3cdev used by cxgb3 driver | 58 | * @tdev: pointer to t3cdev used by cxgb3 driver |
58 | * @max_txsz: max tx packet size for ddp | 59 | * @max_txsz: max tx packet size for ddp |
59 | * @max_rxsz: max rx packet size for ddp | 60 | * @max_rxsz: max rx packet size for ddp |
@@ -70,6 +71,7 @@ struct cxgb3i_gather_list { | |||
70 | */ | 71 | */ |
71 | struct cxgb3i_ddp_info { | 72 | struct cxgb3i_ddp_info { |
72 | struct list_head list; | 73 | struct list_head list; |
74 | struct kref refcnt; | ||
73 | struct t3cdev *tdev; | 75 | struct t3cdev *tdev; |
74 | struct pci_dev *pdev; | 76 | struct pci_dev *pdev; |
75 | unsigned int max_txsz; | 77 | unsigned int max_txsz; |