diff options
author | Quinn Tran <quinn.tran@qlogic.com> | 2017-08-30 13:16:49 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-08-30 22:15:00 -0400 |
commit | b5d1531260b9e5819edcaed8b549859e582e4ca4 (patch) | |
tree | a7d479b1e30264d7ceab544e71f57a8787a25076 | |
parent | 1a28faa01074f1cacc029bcb611690f086b11de2 (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.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 33 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 2 |
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); | |||
113 | extern char qla2x00_version_str[]; | 113 | extern char qla2x00_version_str[]; |
114 | 114 | ||
115 | extern struct kmem_cache *srb_cachep; | 115 | extern struct kmem_cache *srb_cachep; |
116 | extern struct kmem_cache *qla_tgt_plogi_cachep; | ||
116 | 117 | ||
117 | extern int ql2xlogintimeout; | 118 | extern int ql2xlogintimeout; |
118 | extern int qlport_down_retry; | 119 | extern 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 | |||
4677 | void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) | 4677 | void 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 | ||
4725 | void | 4756 | void |
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 | */ |
147 | static struct kmem_cache *qla_tgt_mgmt_cmd_cachep; | 147 | static struct kmem_cache *qla_tgt_mgmt_cmd_cachep; |
148 | static struct kmem_cache *qla_tgt_plogi_cachep; | 148 | struct kmem_cache *qla_tgt_plogi_cachep; |
149 | static mempool_t *qla_tgt_mgmt_cmd_mempool; | 149 | static mempool_t *qla_tgt_mgmt_cmd_mempool; |
150 | static struct workqueue_struct *qla_tgt_wq; | 150 | static struct workqueue_struct *qla_tgt_wq; |
151 | static DEFINE_MUTEX(qla_tgt_mutex); | 151 | static DEFINE_MUTEX(qla_tgt_mutex); |