Received: by 10.213.65.68 with SMTP id h4csp448116imn; Tue, 13 Mar 2018 09:21:31 -0700 (PDT) X-Google-Smtp-Source: AG47ELs71z5QGSTd8xCO5DNKkCYlt21EYGuG/Axx4RrmPfYZCtzVh8Sl87vo9ydE/O92iBqcqhku X-Received: by 2002:a17:902:24:: with SMTP id 33-v6mr1052986pla.341.1520958091719; Tue, 13 Mar 2018 09:21:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1520958091; cv=none; d=google.com; s=arc-20160816; b=Z3wjFllSLS4viOjG/JEFDBmOXeZ/oQya46313wkRC4etAhw4wbnIHrEQGLDdSk7UTL VPW6BnkdjTVBPlepm1uNPK0kfZp4ZsIEZR9itg+yFgzezZBJ+JpizDVVvGcx3ysp2nFC 4NDX/+xAvX7XUioim6QpaT6M4mf5L9RHLtwI2bMmEuCCCz7a2GdUVVpoGaVdimosP/Q2 PNv8qiLEhO/qHVF4482B7uHRJ0YnUAM098NrdYlJuyZfGtB1lStLFeyD39Mo1aXTTDv4 08SjU/TYQmlbcz0ZZltUZW5NhVGCst8H16ibUA2IfyKuDg2F8vmlINIvAgmMg/KT2w9O /7fw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=jr0aH38fQUb5Crd72Nj0eAL7aUVFL1aSto/HHnkoa9E=; b=zkzM9JtFnEkDo8DFg8n8So78WOTkUq+F1DTZN2Ghihu5afWuAATFD7i9feiHrWdZie asAIiAXjjkIa1b6t3jp+KZR6O/Z2cbduDxHENIb7+5+aamuwQwAo+ZK9KbMZ6Jn2HQWw kz5DMr3ftOeQVqlB8gFpbAU3xI1jX7xiwe7Ug+kWlU0XvfFjyV8hki3+F/uEDfqf7WYk tQp6UnbchDq996bYZ3xuHGOLAsiN3qCSEywN8VUzUMEIHgeS7BUEZFyQTtpdRZiB9Jda TFBgi71ImzXDFw8zhKhs+fr4Xh9/h5p17ahZiT/j4Bp65kA39sqeEeQfh79u14pgkUeG OSCA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n25si308758pgc.87.2018.03.13.09.21.17; Tue, 13 Mar 2018 09:21:31 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933844AbeCMPet (ORCPT + 99 others); Tue, 13 Mar 2018 11:34:49 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:32920 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933833AbeCMPeq (ORCPT ); Tue, 13 Mar 2018 11:34:46 -0400 Received: from localhost (LFbn-1-12258-90.w90-92.abo.wanadoo.fr [90.92.71.90]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 2322510A1; Tue, 13 Mar 2018 15:34:45 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Quinn Tran , Himanshu Madhani , Hannes Reinecke , "Martin K. Petersen" Subject: [PATCH 4.15 133/146] scsi: qla2xxx: Relogin to target port on a cable swap Date: Tue, 13 Mar 2018 16:25:00 +0100 Message-Id: <20180313152330.400128363@linuxfoundation.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180313152320.439085687@linuxfoundation.org> References: <20180313152320.439085687@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.15-stable review patch. If anyone has any objections, please let me know. ------------------ From: Quinn Tran commit 5ef696aa9f3ccf999552d924c4e21a348f2bbea9 upstream. If user swaps one target port for another target port for same switch port, the new target port is not being recognized by the driver. Current code assumes that old Target port has recovered from link down. The fix will ask switch what is the WWPN of a specific NportID (GPNID) rather than assuming it's the same Target port which has came back. Fixes: 726b85487067d ("qla2xxx: Add framework for async fabric discovery") Cc: # 4.10+ Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_gs.c | 170 +++++++++++++++++++++++++++++--------- drivers/scsi/qla2xxx/qla_init.c | 6 - drivers/scsi/qla2xxx/qla_os.c | 35 +++++++ drivers/scsi/qla2xxx/qla_target.c | 35 ++++++- 4 files changed, 197 insertions(+), 49 deletions(-) --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3171,43 +3171,136 @@ void qla24xx_async_gpnid_done(scsi_qla_h void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea) { - fc_port_t *fcport; - unsigned long flags; + fc_port_t *fcport, *conflict, *t; - spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); - fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1); - spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); - - if (fcport) { - /* cable moved. just plugged in */ - fcport->rscn_gen++; - fcport->d_id = ea->id; - fcport->scan_state = QLA_FCPORT_FOUND; - fcport->flags |= FCF_FABRIC_DEVICE; - - switch (fcport->disc_state) { - case DSC_DELETED: - ql_dbg(ql_dbg_disc, vha, 0x210d, - "%s %d %8phC login\n", __func__, __LINE__, - fcport->port_name); - qla24xx_fcport_handle_login(vha, fcport); - break; - case DSC_DELETE_PEND: - break; - default: - ql_dbg(ql_dbg_disc, vha, 0x2064, - "%s %d %8phC post del sess\n", - __func__, __LINE__, fcport->port_name); - qlt_schedule_sess_for_deletion_lock(fcport); - break; + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %d port_id: %06x\n", + __func__, __LINE__, ea->id.b24); + + if (ea->rc) { + /* cable is disconnected */ + list_for_each_entry_safe(fcport, t, &vha->vp_fcports, list) { + if (fcport->d_id.b24 == ea->id.b24) { + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %d %8phC DS %d\n", + __func__, __LINE__, + fcport->port_name, + fcport->disc_state); + fcport->scan_state = QLA_FCPORT_SCAN; + switch (fcport->disc_state) { + case DSC_DELETED: + case DSC_DELETE_PEND: + break; + default: + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %d %8phC post del sess\n", + __func__, __LINE__, + fcport->port_name); + qlt_schedule_sess_for_deletion_lock + (fcport); + break; + } + } } } else { - /* create new fcport */ - ql_dbg(ql_dbg_disc, vha, 0x2065, - "%s %d %8phC post new sess\n", - __func__, __LINE__, ea->port_name); - - qla24xx_post_newsess_work(vha, &ea->id, ea->port_name, NULL); + /* cable is connected */ + fcport = qla2x00_find_fcport_by_wwpn(vha, ea->port_name, 1); + if (fcport) { + list_for_each_entry_safe(conflict, t, &vha->vp_fcports, + list) { + if ((conflict->d_id.b24 == ea->id.b24) && + (fcport != conflict)) { + /* 2 fcports with conflict Nport ID or + * an existing fcport is having nport ID + * conflict with new fcport. + */ + + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %d %8phC DS %d\n", + __func__, __LINE__, + conflict->port_name, + conflict->disc_state); + conflict->scan_state = QLA_FCPORT_SCAN; + switch (conflict->disc_state) { + case DSC_DELETED: + case DSC_DELETE_PEND: + break; + default: + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %d %8phC post del sess\n", + __func__, __LINE__, + conflict->port_name); + qlt_schedule_sess_for_deletion_lock + (conflict); + break; + } + } + } + + fcport->rscn_gen++; + fcport->scan_state = QLA_FCPORT_FOUND; + fcport->flags |= FCF_FABRIC_DEVICE; + switch (fcport->disc_state) { + case DSC_LOGIN_COMPLETE: + /* recheck session is still intact. */ + ql_dbg(ql_dbg_disc, vha, 0x210d, + "%s %d %8phC revalidate session with ADISC\n", + __func__, __LINE__, fcport->port_name); + qla24xx_post_gpdb_work(vha, fcport, + PDO_FORCE_ADISC); + break; + case DSC_DELETED: + ql_dbg(ql_dbg_disc, vha, 0x210d, + "%s %d %8phC login\n", __func__, __LINE__, + fcport->port_name); + fcport->d_id = ea->id; + qla24xx_fcport_handle_login(vha, fcport); + break; + case DSC_DELETE_PEND: + fcport->d_id = ea->id; + break; + default: + fcport->d_id = ea->id; + break; + } + } else { + list_for_each_entry_safe(conflict, t, &vha->vp_fcports, + list) { + if (conflict->d_id.b24 == ea->id.b24) { + /* 2 fcports with conflict Nport ID or + * an existing fcport is having nport ID + * conflict with new fcport. + */ + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %d %8phC DS %d\n", + __func__, __LINE__, + conflict->port_name, + conflict->disc_state); + + conflict->scan_state = QLA_FCPORT_SCAN; + switch (conflict->disc_state) { + case DSC_DELETED: + case DSC_DELETE_PEND: + break; + default: + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %d %8phC post del sess\n", + __func__, __LINE__, + conflict->port_name); + qlt_schedule_sess_for_deletion_lock + (conflict); + break; + } + } + } + + /* create new fcport */ + ql_dbg(ql_dbg_disc, vha, 0x2065, + "%s %d %8phC post new sess\n", + __func__, __LINE__, ea->port_name); + qla24xx_post_newsess_work(vha, &ea->id, + ea->port_name, NULL); + } } } @@ -3248,12 +3341,13 @@ static void qla2x00_async_gpnid_sp_done( spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); if (res) { - if (res == QLA_FUNCTION_TIMEOUT) + if (res == QLA_FUNCTION_TIMEOUT) { qla24xx_post_gpnid_work(sp->vha, &ea.id); - sp->free(sp); - return; + sp->free(sp); + return; + } } else if (sp->gen1) { - /* There was anoter RSNC for this Nport ID */ + /* There was another RSCN for this Nport ID */ qla24xx_post_gpnid_work(sp->vha, &ea.id); sp->free(sp); return; --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -925,6 +925,9 @@ void qla24xx_handle_gpdb_event(scsi_qla_ * must have triggered the session to be re-validate. * session is still valid. */ + ql_dbg(ql_dbg_disc, vha, 0x20d6, + "%s %d %8phC session revalidate success\n", + __func__, __LINE__, fcport->port_name); fcport->disc_state = DSC_LOGIN_COMPLETE; } spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); @@ -1049,9 +1052,8 @@ void qla24xx_handle_rscn_event(fc_port_t switch (fcport->disc_state) { case DSC_DELETED: case DSC_LOGIN_COMPLETE: - qla24xx_post_gidpn_work(fcport->vha, fcport); + qla24xx_post_gpnid_work(fcport->vha, &ea->id); break; - default: break; } --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -4760,10 +4760,39 @@ void qla24xx_create_new_sess(struct scsi spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); if (fcport) { - if (pla) + if (pla) { qlt_plogi_ack_unref(vha, pla); - else - qla24xx_async_gffid(vha, fcport); + } else { + spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); + tfcp = qla2x00_find_fcport_by_nportid(vha, + &e->u.new_sess.id, 1); + if (tfcp && (tfcp != fcport)) { + /* + * We have a conflict fcport with same NportID. + */ + ql_dbg(ql_dbg_disc, vha, 0xffff, + "%s %8phC found conflict b4 add. DS %d LS %d\n", + __func__, tfcp->port_name, tfcp->disc_state, + tfcp->fw_login_state); + + switch (tfcp->disc_state) { + case DSC_DELETED: + break; + case DSC_DELETE_PEND: + fcport->login_pause = 1; + tfcp->conflict = fcport; + break; + default: + fcport->login_pause = 1; + tfcp->conflict = fcport; + qlt_schedule_sess_for_deletion_lock + (tfcp); + break; + } + } + spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + qla24xx_async_gnl(vha, fcport); + } } if (free_fcport) { --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -890,6 +890,17 @@ qlt_plogi_ack_link(struct scsi_qla_host iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[0], pla->ref_count, pla, link); + if (link == QLT_PLOGI_LINK_CONFLICT) { + switch (sess->disc_state) { + case DSC_DELETED: + case DSC_DELETE_PEND: + pla->ref_count--; + return; + default: + break; + } + } + if (sess->plogi_link[link]) qlt_plogi_ack_unref(vha, sess->plogi_link[link]); @@ -4737,6 +4748,10 @@ static int qlt_24xx_handle_els(struct sc sess->d_id = port_id; sess->login_gen++; + ql_dbg(ql_dbg_disc, vha, 0x20f9, + "%s %d %8phC DS %d\n", + __func__, __LINE__, sess->port_name, sess->disc_state); + switch (sess->disc_state) { case DSC_DELETED: qlt_plogi_ack_unref(vha, pla); @@ -4786,12 +4801,20 @@ static int qlt_24xx_handle_els(struct sc } if (conflict_sess) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09b, - "PRLI with conflicting sess %p port %8phC\n", - conflict_sess, conflict_sess->port_name); - qlt_send_term_imm_notif(vha, iocb, 1); - res = 0; - break; + switch (conflict_sess->disc_state) { + case DSC_DELETED: + case DSC_DELETE_PEND: + break; + default: + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf09b, + "PRLI with conflicting sess %p port %8phC\n", + conflict_sess, conflict_sess->port_name); + conflict_sess->fw_login_state = + DSC_LS_PORT_UNAVAIL; + qlt_send_term_imm_notif(vha, iocb, 1); + res = 0; + break; + } } if (sess != NULL) {