cxgb3i -- use kref to track ddp usage
PATCH v2 1/2 cxgb3i -- use kref to track ddp usage
[PATCH 1/2 2.6.30-rc v2] cxgb3i -- use kref to track ddp usage
From: Karen Xie <[email protected]>
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 <[email protected]>
---
drivers/scsi/cxgb3i/cxgb3i_ddp.c | 54 +++++++++++++++++++++++--------------- drivers/scsi/cxgb3i/cxgb3i_ddp.h | 2 + 2 files changed, 35 insertions(+), 21 deletions(-)
drivers/scsi/cxgb3i/cxgb3i_ddp.c +33 -21
@@ -598,30 +598,40 @@ int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,* release all the resource held by the ddp pagepod manager for a given * adapter if needed */ -void cxgb3i_ddp_cleanup (struct t3cdev *tdev) + +static void ddp_cleanup (struct kref *kref) { +struct cxgb3i_ddp_info *ddp =container_of (kref, + struct cxgb3i_ddp_info, + refcnt);int i =0 ; + +ddp_log_info ("kref release ddp 0x%p, t3dev 0x%p.\n" , ddp, ddp->tdev); + + ddp->tdev->ulp_iscsi =NULL ; +while (i < ddp->nppods) { +struct cxgb3i_gather_list *gl = ddp->gl_map[i]; +if (gl) { +int npods = (gl->nelem +PPOD_PAGES_MAX -1 ) + >>PPOD_PAGES_SHIFT ; +ddp_log_info ("t3dev 0x%p, ddp %d + %d.\n" , + ddp->tdev, i, npods); +kfree (gl); +ddp_free_gl_skb (ddp, i, npods); + i += npods; + }else + i++; + } +cxgb3i_free_big_mem (ddp); +} + +void cxgb3i_ddp_cleanup (struct t3cdev *tdev) +{struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;ddp_log_info ("t3dev 0x%p, release ddp 0x%p.\n" , tdev, ddp); - -if (ddp) { - tdev->ulp_iscsi =NULL ; -while (i < ddp->nppods) { -struct cxgb3i_gather_list *gl = ddp->gl_map[i]; -if (gl) { -int npods = (gl->nelem +PPOD_PAGES_MAX -1 ) - >>PPOD_PAGES_SHIFT ; -ddp_log_info ("t3dev 0x%p, ddp %d + %d.\n" , - tdev, i, npods); -kfree (gl); -ddp_free_gl_skb (ddp, i, npods); - i += npods; - }else - i++; - } -cxgb3i_free_big_mem (ddp); - } +if (ddp) +kref_put (&ddp->refcnt, ddp_cleanup); }/**
@@ -631,12 +641,13 @@ void cxgb3i_ddp_cleanup(struct t3cdev *tdev)*/ static void ddp_init (struct t3cdev *tdev) { -struct cxgb3i_ddp_info *ddp; +struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;struct ulp_iscsi_info uinfo;unsigned int ppmax, bits;int i, err; -if (tdev->ulp_iscsi) { +if (ddp) { +kref_get (&ddp->refcnt);ddp_log_warn ("t3dev 0x%p, ddp 0x%p already set up.\n" , tdev, tdev->ulp_iscsi);return ;
@@ -670,6 +681,7 @@ static void ddp_init(struct t3cdev *tdev)ppmax * sizeof(struct cxgb3i_gather_list *));spin_lock_init (&ddp->map_lock); +kref_init (&ddp->refcnt); ddp->tdev = tdev; ddp->pdev = uinfo.pdev;
drivers/scsi/cxgb3i/cxgb3i_ddp.h +2 -0
@@ -54,6 +54,7 @@ struct cxgb3i_gather_list {* struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload * * @list: list head to link elements +* @refcnt: ref. count * @tdev: pointer to t3cdev used by cxgb3 driver * @max_txsz: max tx packet size for ddp * @max_rxsz: max rx packet size for ddp
@@ -70,6 +71,7 @@ struct cxgb3i_gather_list {*/ struct cxgb3i_ddp_info {struct list_head list; +struct kref refcnt;struct t3cdev *tdev;struct pci_dev *pdev;unsigned int max_txsz;