@@ -143,6 +143,7 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *,
extern int ql_dm_tgt_ex_pct;
extern struct workqueue_struct *qla_wq;
extern int ql2xmvasynctoatio;
+extern struct kmem_cache *qla_tgt_plogi_cachep;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
@@ -4486,8 +4486,9 @@ int qla24xx_post_upd_fcport_work(struct scsi_qla_host *vha, fc_port_t *fcport)
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;
qlt_plogi_ack_t *pla = (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);
@@ -4502,6 +4503,8 @@ 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;
@@ -4511,6 +4514,30 @@ 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) {
@@ -4527,6 +4554,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
@@ -49,13 +49,12 @@
module_param(qlop_mode, charp, S_IRUGO);
MODULE_PARM_DESC(qlop_mode,
"Determines operating mode. Possible values: "
- "\"exclusive\" - initiator mode will be enabled on load, "
- "disabled on enabling target mode and then on disabling target mode "
- "enabled back; "
+ "\"exclusive\" - Initiator Mode will be enabled on load. "
+ " Target Mode can be activated when ready. Only one mode can be active at a time; "
"\"tgt_mode\" - Target mode only. Initiator mode will never be enabled; "
- "\"dual_mode\" - Initiator Modes will be enabled. Target Mode can be "
+ "\"dual_mode\" - Initiator Modes will be enabled on load. Target Mode can be "
"activated when ready; "
- "\"ini_mode\" (default) - initiator mode will always stay enabled.");
+ "\"ini_mode\" (default) - Initiator mode will always stay enabled.");
int ql_dm_tgt_ex_pct = 50;
module_param(ql_dm_tgt_ex_pct, int, S_IRUGO|S_IWUSR);
@@ -133,7 +132,7 @@ static struct fc_port *qlt_create_sess(struct scsi_qla_host *vha,
/*
* Global Variables
*/
-static struct kmem_cache *qla_tgt_plogi_cachep;
+struct kmem_cache *qla_tgt_plogi_cachep;
static struct workqueue_struct *qla_tgt_wq;
static DEFINE_MUTEX(qla_tgt_mutex);
LIST_HEAD(qla_tgt_glist);