aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@qlogic.com>2017-08-30 13:16:49 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2017-08-30 22:15:00 -0400
commitb5d1531260b9e5819edcaed8b549859e582e4ca4 (patch)
treea7d479b1e30264d7ceab544e71f57a8787a25076
parent1a28faa01074f1cacc029bcb611690f086b11de2 (diff)
scsi: qla2xxx: Fix slow mem alloc behind lock
Call Trace: [<ffffffff81341687>] dump_stack+0x6b/0xa4 [<ffffffff810c3e30>] ? print_irqtrace_events+0xd0/0xe0 [<ffffffff8109e3c3>] ___might_sleep+0x183/0x240 [<ffffffff8109e4d2>] __might_sleep+0x52/0x90 [<ffffffff811fe17b>] kmem_cache_alloc_trace+0x5b/0x300 [<ffffffff810c666b>] ? __lock_acquired+0x30b/0x420 [<ffffffffa0733c28>] qla2x00_alloc_fcport+0x38/0x2a0 [qla2xxx] [<ffffffffa07217f4>] ? qla2x00_do_work+0x34/0x2b0 [qla2xxx] [<ffffffff816cc82b>] ? _raw_spin_lock_irqsave+0x7b/0x90 [<ffffffffa072169a>] ? qla24xx_create_new_sess+0x3a/0x160 [qla2xxx] [<ffffffffa0721723>] qla24xx_create_new_sess+0xc3/0x160 [qla2xxx] [<ffffffff810c91ed>] ? trace_hardirqs_on+0xd/0x10 [<ffffffffa07218f8>] qla2x00_do_work+0x138/0x2b0 [qla2xxx] Signed-off-by: Quinn Tran <quinn.tran@qlogic.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c33
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c2
3 files changed, 34 insertions, 2 deletions
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 0b219b3ca653..f852ca60c49f 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -113,6 +113,7 @@ int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
113extern char qla2x00_version_str[]; 113extern char qla2x00_version_str[];
114 114
115extern struct kmem_cache *srb_cachep; 115extern struct kmem_cache *srb_cachep;
116extern struct kmem_cache *qla_tgt_plogi_cachep;
116 117
117extern int ql2xlogintimeout; 118extern int ql2xlogintimeout;
118extern int qlport_down_retry; 119extern int qlport_down_retry;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 56bd086b79ea..5b2437a5ea44 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4677,9 +4677,10 @@ static
4677void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) 4677void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
4678{ 4678{
4679 unsigned long flags; 4679 unsigned long flags;
4680 fc_port_t *fcport = NULL; 4680 fc_port_t *fcport = NULL, *tfcp;
4681 struct qlt_plogi_ack_t *pla = 4681 struct qlt_plogi_ack_t *pla =
4682 (struct qlt_plogi_ack_t *)e->u.new_sess.pla; 4682 (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
4683 uint8_t free_fcport = 0;
4683 4684
4684 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); 4685 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
4685 fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1); 4686 fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1);
@@ -4694,6 +4695,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
4694 pla->ref_count--; 4695 pla->ref_count--;
4695 } 4696 }
4696 } else { 4697 } else {
4698 spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
4697 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); 4699 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
4698 if (fcport) { 4700 if (fcport) {
4699 fcport->d_id = e->u.new_sess.id; 4701 fcport->d_id = e->u.new_sess.id;
@@ -4703,6 +4705,29 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
4703 4705
4704 memcpy(fcport->port_name, e->u.new_sess.port_name, 4706 memcpy(fcport->port_name, e->u.new_sess.port_name,
4705 WWN_SIZE); 4707 WWN_SIZE);
4708 } else {
4709 ql_dbg(ql_dbg_disc, vha, 0xffff,
4710 "%s %8phC mem alloc fail.\n",
4711 __func__, e->u.new_sess.port_name);
4712
4713 if (pla)
4714 kmem_cache_free(qla_tgt_plogi_cachep, pla);
4715 return;
4716 }
4717
4718 spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
4719 /* search again to make sure one else got ahead */
4720 tfcp = qla2x00_find_fcport_by_wwpn(vha,
4721 e->u.new_sess.port_name, 1);
4722 if (tfcp) {
4723 /* should rarily happen */
4724 ql_dbg(ql_dbg_disc, vha, 0xffff,
4725 "%s %8phC found existing fcport b4 add. DS %d LS %d\n",
4726 __func__, tfcp->port_name, tfcp->disc_state,
4727 tfcp->fw_login_state);
4728
4729 free_fcport = 1;
4730 } else {
4706 list_add_tail(&fcport->list, &vha->vp_fcports); 4731 list_add_tail(&fcport->list, &vha->vp_fcports);
4707 4732
4708 if (pla) { 4733 if (pla) {
@@ -4720,6 +4745,12 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
4720 else 4745 else
4721 qla24xx_async_gnl(vha, fcport); 4746 qla24xx_async_gnl(vha, fcport);
4722 } 4747 }
4748
4749 if (free_fcport) {
4750 qla2x00_free_fcport(fcport);
4751 if (pla)
4752 kmem_cache_free(qla_tgt_plogi_cachep, pla);
4753 }
4723} 4754}
4724 4755
4725void 4756void
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 43113d52893b..192554b1536f 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -145,7 +145,7 @@ static void qlt_send_busy(struct qla_qpair *, struct atio_from_isp *,
145 * Global Variables 145 * Global Variables
146 */ 146 */
147static struct kmem_cache *qla_tgt_mgmt_cmd_cachep; 147static struct kmem_cache *qla_tgt_mgmt_cmd_cachep;
148static struct kmem_cache *qla_tgt_plogi_cachep; 148struct kmem_cache *qla_tgt_plogi_cachep;
149static mempool_t *qla_tgt_mgmt_cmd_mempool; 149static mempool_t *qla_tgt_mgmt_cmd_mempool;
150static struct workqueue_struct *qla_tgt_wq; 150static struct workqueue_struct *qla_tgt_wq;
151static DEFINE_MUTEX(qla_tgt_mutex); 151static DEFINE_MUTEX(qla_tgt_mutex);