mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
Unsupported (yet) patch making QLA adapters behave in the target mode from the very beginning with description from Bryan Mesich <bryan.mesi
ch@ndsu.edu>. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2360 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -137,6 +137,10 @@ of the initiator mode from enabled to disabled and vice versa.
|
||||
You can always see which modes are currently active in active_mode sysfs
|
||||
attribute.
|
||||
|
||||
Also if the "disabled" mode isn't sufficiently strong for you, you can
|
||||
consider using patch unsupported-patches/qla_delayed_hw_init_tgt_mode_from_the_beginning.diff.
|
||||
See description of it inside it.
|
||||
|
||||
|
||||
Explicit conformation
|
||||
---------------------
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
The below patch fixes a problem that RHEL 5 initiators encounter when
|
||||
the target is running SCST + qla2x00tgt. The qla2xxx driver that is
|
||||
shipped with Red Hat supplied kernels for RHEL 5 does not handle
|
||||
fc_remote_port role changes. Specifically, a role change of:
|
||||
|
||||
FCP Target -> unknown -> FCP Initiator -> FCP Target
|
||||
|
||||
results in the fc_remote_port failing to transition to FCP Target.
|
||||
The above role change is usually triggered by a reboot of the FC
|
||||
target. After the target comes up after its reboot, the initiator(s)
|
||||
will be unable to re-attach their storage without a reboot of their
|
||||
own (or possibly an unload/reload of the qla2xxx driver).
|
||||
|
||||
The problem lies in the initiator briefly seeing the target as a FCP
|
||||
Initiator, an artifact from the qla2xxx and qla2x00tgt modules loading on
|
||||
the target. This patch fixes the problem by delaying firmware loading
|
||||
until the qla2x00tgt module is loaded. When the qla2x00tgt is loaded,
|
||||
it is forced into target mode (i.e. target_mode_enabled = 1). This
|
||||
requires that SCST have its configuration loaded _before_ qla2x00tgt
|
||||
is loaded. Otherwise the initiators will log into the target without
|
||||
security groups in place, etc... The qla2xxx driver needs to be loaded
|
||||
with the parameter "qlini_mode=disabled" to postpone the firmware load
|
||||
until qla2x00tgt is loaded. See below for loading example:
|
||||
|
||||
1. modprobe scst
|
||||
2. modprobe scst_vdisk
|
||||
3. modprobe qla2xxx qlini_mode=disabled
|
||||
(NOTE: You should see that firmware initialization
|
||||
was posponed by looking at the output of dmesg.)
|
||||
4. Load SCST configuration (scstadmin or other utility)
|
||||
5. modprobe qla2x00tgt
|
||||
|
||||
Also required is that SCST and qla2x00tgt be compiled with PROCFS
|
||||
support enabled (see below why). Starting at version 2.0.0, SCST
|
||||
defaults to SYSFS, so make sure "make enable_procfs" is run before
|
||||
building.
|
||||
|
||||
With the patch applied, the resulting role change will be the
|
||||
following during a target reboot:
|
||||
|
||||
FCP Target -> unknown -> FCP Target
|
||||
|
||||
The isp_mod target driver does not have this problem since the card
|
||||
stays uninitialized until target mode in enabled. It is, however, still
|
||||
possible to have problems during role transitioning with both isp_mod
|
||||
and qla2x00tgt modules. This occurs if the Qlogic HBA is configured to
|
||||
load BIOS during boot. This is typically used for SAN booting and
|
||||
probably should be disabled on the target to keep things simple.
|
||||
|
||||
Andrew Vasquez <andrew.vasquez@qlogic.com> fixed this issue for the
|
||||
main line kernels and was added in 2.6.27. RHEL 5 initiators running
|
||||
kernels >= 2.6.27 do not need this patch applied.
|
||||
|
||||
commit 6390d1f33faecf48e31f27dd7dbe928540f8acfc
|
||||
Author: Andrew Vasquez <andrew.vasquez@qlogic.com>
|
||||
Date: Wed Aug 13 21:36:56 2008 -0700
|
||||
|
||||
[SCSI] qla2xxx: Correct synchronization of software/firmware fcport states.
|
||||
|
||||
Greg Wettstein (greg@enjellic.com) noted:
|
||||
http://article.gmane.org/gmane.linux.scsi/43409
|
||||
|
||||
on a reboot of a previously recognized SCST target, the initiator
|
||||
driver would be unable to re-recognize the device as a target.
|
||||
It turns out that prior to the SCST software reloading and
|
||||
returning it's "target-capable" abilities in the PRLI payload,
|
||||
the HBA would be re-initialized as an initiator-only type port.
|
||||
Since initiators typically classify themselves as an FCP-2
|
||||
capable device, both software and firmware do not perform an
|
||||
explicit logout during port-loss. Unfortunately, as can be seen
|
||||
by the failure case, when the port (now target-capable) returns,
|
||||
firmware performs an ADISC without a follow-on PRLI, leaving
|
||||
stale 'initiator-only' data in the firmware's port database.
|
||||
|
||||
Correct the discrepancy by performing the explicit logout during
|
||||
the transport's request to terminate-rport-io, thus synchronizing
|
||||
port states and ensuring a follow-on PRLI is performed.
|
||||
|
||||
Reported-by: Greg Wettstein <greg@enjellic.com>
|
||||
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
|
||||
Cc: Stable Tree <stable@kernel.org>
|
||||
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
|
||||
|
||||
|
||||
This patch wasn't applied to the qla2x00t, because it can work only with
|
||||
the obsolete procfs-based interface, where LUNs initialization for the
|
||||
QLA targets happens before the corresponding SCST targets created. With
|
||||
the sysfs-based interface it isn't possible, because in it all LUNs are
|
||||
bound to target. It's so, at least, until SCST has persistent LUN
|
||||
groups, so each target immediately after it's created would have all its
|
||||
LUNs configured from the corresponding persistent group.
|
||||
|
||||
--
|
||||
|
||||
Index: qla_init.c
|
||||
===================================================================
|
||||
--- qla_init.c (revision 2148)
|
||||
+++ qla_init.c (working copy)
|
||||
@@ -4202,6 +4202,10 @@ int qla2xxx_tgt_register_driver(struct q
|
||||
|
||||
memcpy(&qla_target, tgt_data, sizeof(qla_target));
|
||||
|
||||
+ res = qla2xxx_check_init_hardware();
|
||||
+ if (res != 0)
|
||||
+ goto out;
|
||||
+
|
||||
res = QLA2X_INITIATOR_MAGIC;
|
||||
|
||||
out:
|
||||
Index: qla_gbl.h
|
||||
===================================================================
|
||||
--- qla_gbl.h (revision 2148)
|
||||
+++ qla_gbl.h (working copy)
|
||||
@@ -82,6 +82,8 @@ extern int qla2x00_post_hwe_work(struct
|
||||
|
||||
extern void qla2x00_abort_fcport_cmds(fc_port_t *);
|
||||
|
||||
+extern int qla2xxx_check_init_hardware(void);
|
||||
+
|
||||
/*
|
||||
* Global Functions in qla_mid.c source file.
|
||||
*/
|
||||
Index: qla2x_tgt.h
|
||||
===================================================================
|
||||
--- qla2x_tgt.h (revision 2148)
|
||||
+++ qla2x_tgt.h (working copy)
|
||||
@@ -34,6 +34,8 @@ extern request_t *qla2x00_req_pkt(scsi_q
|
||||
|
||||
extern struct qla_tgt_data qla_target;
|
||||
|
||||
+extern bool ql2x_hardware_initialized;
|
||||
+
|
||||
void qla_set_tgt_mode(scsi_qla_host_t *ha);
|
||||
void qla_clear_tgt_mode(scsi_qla_host_t *ha);
|
||||
|
||||
Index: qla_os.c
|
||||
===================================================================
|
||||
--- qla_os.c (revision 2148)
|
||||
+++ qla_os.c (working copy)
|
||||
@@ -50,6 +50,9 @@ MODULE_PARM_DESC(qlini_mode,
|
||||
static int ql2x_ini_mode = QLA2X_INI_MODE_EXCLUSIVE;
|
||||
#endif
|
||||
|
||||
+bool ql2x_hardware_initialized;
|
||||
+EXPORT_SYMBOL(ql2x_hardware_initialized);
|
||||
+
|
||||
/*
|
||||
* SRB allocation cache
|
||||
*/
|
||||
@@ -3124,7 +3127,7 @@ void qla_clear_tgt_mode(scsi_qla_host_t
|
||||
{
|
||||
switch (ql2x_ini_mode) {
|
||||
case QLA2X_INI_MODE_DISABLED:
|
||||
- ha->host->active_mode = MODE_UNKNOWN;
|
||||
+ ha->host->active_mode = MODE_TARGET;
|
||||
break;
|
||||
case QLA2X_INI_MODE_EXCLUSIVE:
|
||||
ha->host->active_mode = MODE_INITIATOR;
|
||||
@@ -3157,6 +3160,22 @@ static bool __init qla2x00_parse_ini_mod
|
||||
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+int qla2xxx_check_init_hardware(void)
|
||||
+{
|
||||
+ int res = 0;
|
||||
+
|
||||
+ if (!ql2x_hardware_initialized) {
|
||||
+ res = pci_register_driver(&qla2xxx_pci_driver);
|
||||
+ if (res != 0)
|
||||
+ goto out;
|
||||
+ ql2x_hardware_initialized = true;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
#else
|
||||
static inline bool qla2x00_parse_ini_mode(void)
|
||||
{
|
||||
@@ -3193,7 +3212,8 @@ qla2x00_module_init(void)
|
||||
|
||||
if (!qla2x00_parse_ini_mode()) {
|
||||
printk("Wrong qlini_mode value %s\n", qlini_mode);
|
||||
- return -EINVAL;
|
||||
+ ret = -EINVAL;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* Allocate cache for SRBs. */
|
||||
@@ -3202,7 +3222,8 @@ qla2x00_module_init(void)
|
||||
if (srb_cachep == NULL) {
|
||||
printk(KERN_ERR
|
||||
"qla2xxx: Unable to allocate SRB cache...Failing load!\n");
|
||||
- return -ENOMEM;
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* Derive version string. */
|
||||
@@ -3213,26 +3234,46 @@ qla2x00_module_init(void)
|
||||
qla2xxx_transport_template =
|
||||
fc_attach_transport(&qla2xxx_transport_functions);
|
||||
if (!qla2xxx_transport_template) {
|
||||
- kmem_cache_destroy(srb_cachep);
|
||||
- return -ENODEV;
|
||||
+ ret = -ENODEV;
|
||||
+ goto out_cache_destroy;
|
||||
}
|
||||
qla2xxx_transport_vport_template =
|
||||
fc_attach_transport(&qla2xxx_transport_vport_functions);
|
||||
if (!qla2xxx_transport_vport_template) {
|
||||
- kmem_cache_destroy(srb_cachep);
|
||||
- fc_release_transport(qla2xxx_transport_template);
|
||||
- return -ENODEV;
|
||||
+ ret = -ENODEV;
|
||||
+ goto out_fc_release_transport_template;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "QLogic Fibre Channel HBA Driver: %s\n",
|
||||
qla2x00_version_str);
|
||||
- ret = pci_register_driver(&qla2xxx_pci_driver);
|
||||
- if (ret) {
|
||||
- kmem_cache_destroy(srb_cachep);
|
||||
- fc_release_transport(qla2xxx_transport_template);
|
||||
- fc_release_transport(qla2xxx_transport_vport_template);
|
||||
+
|
||||
+#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
+ if (ql2x_ini_mode == QLA2X_INI_MODE_DISABLED) {
|
||||
+ printk(KERN_INFO "qlini_mode disabled (%d), delaying hardware "
|
||||
+ "initialization until target mode add-on load\n",
|
||||
+ QLA2X_INI_MODE_DISABLED);
|
||||
+ goto out;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+ ret = pci_register_driver(&qla2xxx_pci_driver);
|
||||
+ if (ret)
|
||||
+ goto out_fc_release_vport_template;
|
||||
+
|
||||
+ ql2x_hardware_initialized = true;
|
||||
+
|
||||
+out:
|
||||
return ret;
|
||||
+
|
||||
+out_fc_release_vport_template:
|
||||
+ fc_release_transport(qla2xxx_transport_vport_template);
|
||||
+
|
||||
+out_fc_release_transport_template:
|
||||
+ fc_release_transport(qla2xxx_transport_template);
|
||||
+
|
||||
+out_cache_destroy:
|
||||
+ kmem_cache_destroy(srb_cachep);
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3241,8 +3282,10 @@ qla2x00_module_init(void)
|
||||
static void __exit
|
||||
qla2x00_module_exit(void)
|
||||
{
|
||||
- pci_unregister_driver(&qla2xxx_pci_driver);
|
||||
- qla2x00_release_firmware();
|
||||
+ if (ql2x_hardware_initialized) {
|
||||
+ pci_unregister_driver(&qla2xxx_pci_driver);
|
||||
+ qla2x00_release_firmware();
|
||||
+ }
|
||||
kmem_cache_destroy(srb_cachep);
|
||||
fc_release_transport(qla2xxx_transport_template);
|
||||
fc_release_transport(qla2xxx_transport_vport_template);
|
||||
Index: qla2x00-target/qla2x00t.c
|
||||
===================================================================
|
||||
--- qla2x00-target/qla2x00t.c (revision 2148)
|
||||
+++ qla2x00-target/qla2x00t.c (working copy)
|
||||
@@ -314,7 +314,8 @@ static int q2t_target_detect(struct scst
|
||||
goto out;
|
||||
}
|
||||
|
||||
- qla2xxx_add_targets();
|
||||
+ if (ql2x_hardware_initialized)
|
||||
+ qla2xxx_add_targets();
|
||||
|
||||
res = 0;
|
||||
|
||||
@@ -5000,9 +5001,12 @@ static int q2t_add_target(scsi_qla_host_
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
- TRACE_DBG("Registering target for host %ld(%p)", ha->host_no, ha);
|
||||
+ if ((ha->q2t_tgt != NULL) || (ha->tgt != NULL)) {
|
||||
+ res = 0;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- sBUG_ON((ha->q2t_tgt != NULL) || (ha->tgt != NULL));
|
||||
+ TRACE_DBG("Registering target for host %ld(%p)", ha->host_no, ha);
|
||||
|
||||
tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
|
||||
if (tgt == NULL) {
|
||||
@@ -5029,7 +5033,8 @@ static int q2t_add_target(scsi_qla_host_
|
||||
|
||||
ha->q2t_tgt = tgt;
|
||||
|
||||
- if (q2t_get_target_name(ha, &wwn) != 0)
|
||||
+ res = q2t_get_target_name(ha, &wwn);
|
||||
+ if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
tgt->scst_tgt = scst_register_target(&tgt2x_template, wwn);
|
||||
@@ -5084,6 +5089,13 @@ static int q2t_add_target(scsi_qla_host_
|
||||
scst_tgt_set_sg_tablesize(tgt->scst_tgt, sg_tablesize);
|
||||
scst_tgt_set_tgt_priv(tgt->scst_tgt, tgt);
|
||||
|
||||
+ if (qla_tgt_mode_enabled(ha)) {
|
||||
+ ha->tgt = ha->q2t_tgt;
|
||||
+ ha->tgt->tgt_stop = 0;
|
||||
+ }
|
||||
+
|
||||
+ res = 0;
|
||||
+
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
Reference in New Issue
Block a user