Commit b5d15312 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen

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: default avatarQuinn Tran <quinn.tran@qlogic.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 1a28faa0
...@@ -113,6 +113,7 @@ int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8); ...@@ -113,6 +113,7 @@ int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
extern char qla2x00_version_str[]; extern char qla2x00_version_str[];
extern struct kmem_cache *srb_cachep; extern struct kmem_cache *srb_cachep;
extern struct kmem_cache *qla_tgt_plogi_cachep;
extern int ql2xlogintimeout; extern int ql2xlogintimeout;
extern int qlport_down_retry; extern int qlport_down_retry;
......
...@@ -4677,9 +4677,10 @@ static ...@@ -4677,9 +4677,10 @@ static
void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
{ {
unsigned long flags; unsigned long flags;
fc_port_t *fcport = NULL; fc_port_t *fcport = NULL, *tfcp;
struct qlt_plogi_ack_t *pla = struct qlt_plogi_ack_t *pla =
(struct qlt_plogi_ack_t *)e->u.new_sess.pla; (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
uint8_t free_fcport = 0;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1); 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,6 +4695,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
pla->ref_count--; pla->ref_count--;
} }
} else { } else {
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
if (fcport) { if (fcport) {
fcport->d_id = e->u.new_sess.id; 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,6 +4705,29 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
memcpy(fcport->port_name, e->u.new_sess.port_name, memcpy(fcport->port_name, e->u.new_sess.port_name,
WWN_SIZE); WWN_SIZE);
} else {
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %8phC mem alloc fail.\n",
__func__, e->u.new_sess.port_name);
if (pla)
kmem_cache_free(qla_tgt_plogi_cachep, pla);
return;
}
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
/* search again to make sure one else got ahead */
tfcp = qla2x00_find_fcport_by_wwpn(vha,
e->u.new_sess.port_name, 1);
if (tfcp) {
/* should rarily happen */
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s %8phC found existing fcport b4 add. DS %d LS %d\n",
__func__, tfcp->port_name, tfcp->disc_state,
tfcp->fw_login_state);
free_fcport = 1;
} else {
list_add_tail(&fcport->list, &vha->vp_fcports); list_add_tail(&fcport->list, &vha->vp_fcports);
if (pla) { if (pla) {
...@@ -4720,6 +4745,12 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) ...@@ -4720,6 +4745,12 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
else else
qla24xx_async_gnl(vha, fcport); qla24xx_async_gnl(vha, fcport);
} }
if (free_fcport) {
qla2x00_free_fcport(fcport);
if (pla)
kmem_cache_free(qla_tgt_plogi_cachep, pla);
}
} }
void void
......
...@@ -145,7 +145,7 @@ static void qlt_send_busy(struct qla_qpair *, struct atio_from_isp *, ...@@ -145,7 +145,7 @@ static void qlt_send_busy(struct qla_qpair *, struct atio_from_isp *,
* Global Variables * Global Variables
*/ */
static struct kmem_cache *qla_tgt_mgmt_cmd_cachep; static struct kmem_cache *qla_tgt_mgmt_cmd_cachep;
static struct kmem_cache *qla_tgt_plogi_cachep; struct kmem_cache *qla_tgt_plogi_cachep;
static mempool_t *qla_tgt_mgmt_cmd_mempool; static mempool_t *qla_tgt_mgmt_cmd_mempool;
static struct workqueue_struct *qla_tgt_wq; static struct workqueue_struct *qla_tgt_wq;
static DEFINE_MUTEX(qla_tgt_mutex); static DEFINE_MUTEX(qla_tgt_mutex);
......
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