|
@@ -4677,9 +4677,10 @@ static
|
|
|
void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
|
|
|
{
|
|
|
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 *)e->u.new_sess.pla;
|
|
|
+ uint8_t free_fcport = 0;
|
|
|
|
|
|
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
|
|
|
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)
|
|
|
pla->ref_count--;
|
|
|
}
|
|
|
} else {
|
|
|
+ spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
|
|
|
fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
|
|
|
if (fcport) {
|
|
|
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)
|
|
|
|
|
|
memcpy(fcport->port_name, e->u.new_sess.port_name,
|
|
|
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);
|
|
|
|
|
|
if (pla) {
|
|
@@ -4720,6 +4745,12 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
|
|
|
else
|
|
|
qla24xx_async_gnl(vha, fcport);
|
|
|
}
|
|
|
+
|
|
|
+ if (free_fcport) {
|
|
|
+ qla2x00_free_fcport(fcport);
|
|
|
+ if (pla)
|
|
|
+ kmem_cache_free(qla_tgt_plogi_cachep, pla);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void
|