From 3911ff6e8ff2ef51c0e5c26f1b42b3f8564c507a Mon Sep 17 00:00:00 2001 From: Hillf Danton Date: Tue, 30 Nov 2010 16:18:17 -0800 Subject: [PATCH] --- yaml --- r: 226787 b: refs/heads/master c: 2034c19ce8f8503aa14cb1e763fbfe60316aaa8e h: refs/heads/master i: 226785: 9c260ffb60aca1681a3215e6ad3d128d43d8b6d8 226783: 9d26d2ac3b1fe9137a933cea5be69f910db2e7a2 v: v3 --- [refs] | 2 +- trunk/drivers/scsi/libfc/fc_exch.c | 36 +++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 834e0816ab16..e81ff83696b5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8236554a27af870ecd1cd588d9558ccdc212037b +refs/heads/master: 2034c19ce8f8503aa14cb1e763fbfe60316aaa8e diff --git a/trunk/drivers/scsi/libfc/fc_exch.c b/trunk/drivers/scsi/libfc/fc_exch.c index d0df1b2faf25..46973d6618d0 100644 --- a/trunk/drivers/scsi/libfc/fc_exch.c +++ b/trunk/drivers/scsi/libfc/fc_exch.c @@ -67,6 +67,11 @@ struct workqueue_struct *fc_exch_workqueue; struct fc_exch_pool { u16 next_index; u16 total_exches; + + /* two cache of free slot in exch array */ + u16 left; + u16 right; + spinlock_t lock; struct list_head ex_list; }; @@ -396,13 +401,23 @@ static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index, static void fc_exch_delete(struct fc_exch *ep) { struct fc_exch_pool *pool; + u16 index; pool = ep->pool; spin_lock_bh(&pool->lock); WARN_ON(pool->total_exches <= 0); pool->total_exches--; - fc_exch_ptr_set(pool, (ep->xid - ep->em->min_xid) >> fc_cpu_order, - NULL); + + /* update cache of free slot */ + index = (ep->xid - ep->em->min_xid) >> fc_cpu_order; + if (pool->left == FC_XID_UNKNOWN) + pool->left = index; + else if (pool->right == FC_XID_UNKNOWN) + pool->right = index; + else + pool->next_index = index; + + fc_exch_ptr_set(pool, index, NULL); list_del(&ep->ex_list); spin_unlock_bh(&pool->lock); fc_exch_release(ep); /* drop hold for exch in mp */ @@ -678,6 +693,19 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, pool = per_cpu_ptr(mp->pool, cpu); spin_lock_bh(&pool->lock); put_cpu(); + + /* peek cache of free slot */ + if (pool->left != FC_XID_UNKNOWN) { + index = pool->left; + pool->left = FC_XID_UNKNOWN; + goto hit; + } + if (pool->right != FC_XID_UNKNOWN) { + index = pool->right; + pool->right = FC_XID_UNKNOWN; + goto hit; + } + index = pool->next_index; /* allocate new exch from pool */ while (fc_exch_ptr_get(pool, index)) { @@ -686,7 +714,7 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport, goto err; } pool->next_index = index == mp->pool_max_index ? 0 : index + 1; - +hit: fc_exch_hold(ep); /* hold for exch in mp */ spin_lock_init(&ep->ex_lock); /* @@ -2180,6 +2208,8 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport, goto free_mempool; for_each_possible_cpu(cpu) { pool = per_cpu_ptr(mp->pool, cpu); + pool->left = FC_XID_UNKNOWN; + pool->right = FC_XID_UNKNOWN; spin_lock_init(&pool->lock); INIT_LIST_HEAD(&pool->ex_list); }