Commit 295ab1b5 authored by Karen Xie's avatar Karen Xie Committed by James Bottomley

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: default avatarKaren Xie <kxie@chelsio.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent d11b6916
...@@ -598,22 +598,24 @@ int cxgb3i_adapter_ddp_info(struct t3cdev *tdev, ...@@ -598,22 +598,24 @@ int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,
* release all the resource held by the ddp pagepod manager for a given * release all the resource held by the ddp pagepod manager for a given
* adapter if needed * 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; int i = 0;
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); ddp_log_info("kref release ddp 0x%p, t3dev 0x%p.\n", ddp, ddp->tdev);
if (ddp) { ddp->tdev->ulp_iscsi = NULL;
tdev->ulp_iscsi = NULL;
while (i < ddp->nppods) { while (i < ddp->nppods) {
struct cxgb3i_gather_list *gl = ddp->gl_map[i]; struct cxgb3i_gather_list *gl = ddp->gl_map[i];
if (gl) { if (gl) {
int npods = (gl->nelem + PPOD_PAGES_MAX - 1) int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
>> PPOD_PAGES_SHIFT; >> PPOD_PAGES_SHIFT;
ddp_log_info("t3dev 0x%p, ddp %d + %d.\n", ddp_log_info("t3dev 0x%p, ddp %d + %d.\n",
tdev, i, npods); ddp->tdev, i, npods);
kfree(gl); kfree(gl);
ddp_free_gl_skb(ddp, i, npods); ddp_free_gl_skb(ddp, i, npods);
i += npods; i += npods;
...@@ -621,7 +623,15 @@ void cxgb3i_ddp_cleanup(struct t3cdev *tdev) ...@@ -621,7 +623,15 @@ void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
i++; i++;
} }
cxgb3i_free_big_mem(ddp); 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)
kref_put(&ddp->refcnt, ddp_cleanup);
} }
/** /**
...@@ -631,12 +641,13 @@ void cxgb3i_ddp_cleanup(struct t3cdev *tdev) ...@@ -631,12 +641,13 @@ void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
*/ */
static void ddp_init(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; struct ulp_iscsi_info uinfo;
unsigned int ppmax, bits; unsigned int ppmax, bits;
int i, err; 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", ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
tdev, tdev->ulp_iscsi); tdev, tdev->ulp_iscsi);
return; return;
...@@ -670,6 +681,7 @@ static void ddp_init(struct t3cdev *tdev) ...@@ -670,6 +681,7 @@ static void ddp_init(struct t3cdev *tdev)
ppmax * ppmax *
sizeof(struct cxgb3i_gather_list *)); sizeof(struct cxgb3i_gather_list *));
spin_lock_init(&ddp->map_lock); spin_lock_init(&ddp->map_lock);
kref_init(&ddp->refcnt);
ddp->tdev = tdev; ddp->tdev = tdev;
ddp->pdev = uinfo.pdev; ddp->pdev = uinfo.pdev;
......
...@@ -54,6 +54,7 @@ struct cxgb3i_gather_list { ...@@ -54,6 +54,7 @@ struct cxgb3i_gather_list {
* struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload
* *
* @list: list head to link elements * @list: list head to link elements
* @refcnt: ref. count
* @tdev: pointer to t3cdev used by cxgb3 driver * @tdev: pointer to t3cdev used by cxgb3 driver
* @max_txsz: max tx packet size for ddp * @max_txsz: max tx packet size for ddp
* @max_rxsz: max rx packet size for ddp * @max_rxsz: max rx packet size for ddp
...@@ -70,6 +71,7 @@ struct cxgb3i_gather_list { ...@@ -70,6 +71,7 @@ struct cxgb3i_gather_list {
*/ */
struct cxgb3i_ddp_info { struct cxgb3i_ddp_info {
struct list_head list; struct list_head list;
struct kref refcnt;
struct t3cdev *tdev; struct t3cdev *tdev;
struct pci_dev *pdev; struct pci_dev *pdev;
unsigned int max_txsz; unsigned int max_txsz;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment