Target driver for QLogic Fibre Channel adapters
================================================

Version 3.11.0-pre, 29 December 2025
----------------------------

This is the legacy target driver for the QLogic Fibre Channel adapters
matched by qla2xxx_pci_tbl[] in ../qla_os.c. It should also support
FCoE, but that has never been verified. It has passed intensive internal
SanDisk tests. It is stable and production ready. This driver is in
stable maintenance mode in favor of the default qla2x00t-32gbit tree,
which supports newer QLogic adapters.

This driver consists from two parts: the target mode driver itself and
the changed initiator driver from Linux kernel, which is, particularly,
intended to perform all the initialization and shutdown tasks. The
initiator driver was changed to provide the target mode support and all
necessary callbacks, but it's still capable to work as initiator only.
Mode, when a host acts as the initiator and the target simultaneously,
is supported as well.

This source is maintained and tested with the SCST core in this
repository. The current supported and tested kernel set is maintained
in ../../nightly/conf/nightly.conf; do not infer current support from
historical minimum-version statements.

See also "ToDo" file for list of known issues and unimplemented
features.


Installation
------------

Follow ../../INSTALL.md for prerequisites and source or package
workflows. This legacy tree is not selected by default. For a source
build from the repository root, select it together with the matching
out-of-tree initiator driver:

BUILD_2X_MODULE=y CONFIG_SCSI_QLA_FC=y \
CONFIG_SCSI_QLA2XXX_TARGET=y QLA_32GBIT=no make all

The build produces the matching qla2xxx_scst initiator/HBA module and
qla2x00tgt target adapter with the required SCST symbol dependencies.
Do not copy these sources into a kernel tree or edit Makefile include
paths. Installation is a separate privileged operation; use
../../INSTALL.md for the current procedure.


Usage
-----

WARNING: The commands in this section act on live kernel, HBA, Fibre
Channel fabric and storage state. Do not run them until the exact host,
ports, initiators and backing devices have been identified and approved.
The examples load or reload modules, issue a LIP, write sysfs, enable a
target and export writable storage; they are not safe production
defaults.

After the drivers are loaded and adapters successfully initialized by
the initiator driver, including firmware image load, you should
configure exported devices using the corresponding interface of SCST
core. It is highly recommended to use scstadmin utility for that
purpose.

Then target mode should be enabled via a sysfs interface on a per card
basis, like:

echo "1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled

See below for full description of the driver's sysfs interface.

See ../doc/qla2x00t-howto.html for the in-tree installation and
configuration HOWTO.


IMPORTANT USAGE NOTES
---------------------

1. Obtain firmware from current vendor or distribution support for the
exact board model. The ql2xfwloadbin module parameter and the
FW_FILE_* definitions in ../qla_os.c describe the driver's firmware
source selection and exact request_firmware() names. See the in-tree
HOWTO for the safety requirements.

2. The qla2x00tgt target adapter and qla2xxx_scst initiator/HBA module
are a matched pair. Do not reload only one of them. Unloading either
module is a live storage operation and requires all affected targets,
sessions and initiator use to be stopped first.

3. If a target is enabled after its initiators have started, use the
discovery procedure for the initiator driver and exact fabric port. A
LIP is a live fabric operation, not a safe generic discovery command.


Initiator and target modes
--------------------------

When qla2xxx compiled with CONFIG_SCSI_QLA2XXX_TARGET enabled, it has
parameter "qlini_mode", which determines when initiator mode will be
enabled. Possible values:

 - "exclusive" (default) - initiator mode will be enabled on load,
disabled on enabling target mode and then on disabling target mode
enabled back.

 - "disabled" - initiator mode will never be enabled.

 - "enabled" - initiator mode will always stay enabled.

Usage of mode "disabled" is recommended, if you have incorrectly
functioning your target's initiators, which if once seen a port in
initiator mode, later refuse to see it as a target.

Use mode "enabled" if you need your QLA adapters to work in both
initiator and target modes at the same time.

You can always see which modes are currently active in active_mode sysfs
attribute.

In all the modes you can at any time use sysfs attribute
ini_mode_force_reverse to force enable or disable initiator mode on any
particular port. Setting this attribute to 1 will reverse current status
of the initiator mode from enabled to disabled and vice versa.
Changing this attribute requests an ISP abort and waits for the HBA to
return online.


Explicit confirmation
---------------------

This option should (actually, almost always must) be enabled by writing
"1" to the explicit_confirmation attribute in the target port
subdirectory under /sys/kernel/scst_tgt/targets/qla2x00t if a target
card exports at least one stateful SCSI device, like tape,
and class 2 isn't used, otherwise link-level errors could lead to loss
of the target/initiator state synchronization. Also check if initiator
supports this feature, it is reported in the kernel logs ("confirmed
completion supported" or not). No major performance degradation was
noticed, if it is enabled. Supported only for 23xx+. Disabled by
default. Changing this attribute requests an ISP abort and waits for the
HBA to return online.

Class 2
-------

Class 2 is the close equivalent of TCP in the network world. If you
enable it, all the Fibre Channel packets will be acknowledged. By
default, class 3 is used, which is UDP-like. Enable class 2 by writing
"1" to class2_enabled through the target's host link. This option needs
a special firmware with class 2 support. Disabled by default. Changing
it requests an ISP abort.


N_Port ID Virtualization
------------------------

NPIV target mode is disabled in this driver. The target template does not
register add_target or del_target callbacks, and no qla2x00t management file
for virtual targets is created. Do not use instructions from older releases
to create NPIV targets with this driver.


Compilation options
-------------------

CONFIG_SCST_DEBUG and CONFIG_SCST_TRACING are selected consistently for
the core and its consumers by the repository build mode; use the
top-level 2debug, 2release or 2perf target instead of editing this
driver's Makefile. The QLogic-only options below are disabled ccflags-y
definitions in qla2x00-target/Kbuild and require an intentional source
configuration change and rebuild.

 - CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD - makes SCST process incoming
   commands from the qla2x00t target driver and call the driver's
   callbacks in internal SCST threads context instead of SIRQ context,
   where those commands were received. Useful for debugging and lead to
   some performance loss.

 - CONFIG_QLA_TGT_DEBUG_SRR - turns on retransmitting packets (SRR)
   debugging. In this mode some CTIOs will be "broken" to force the
   initiator to issue a retransmit request.


Sysfs interface
---------------

Starting from 2.0.0 this driver has sysfs interface.

Root of SCST sysfs interface is /sys/kernel/scst_tgt. Root of this
driver is /sys/kernel/scst_tgt/targets/qla2x00t. It has the following
entries:

 - None, one or more subdirectories for targets with name equal to port
   names of the corresponding targets.

 - trace_level - when tracing or debugging support is built, allows
   tracing facilities to be changed. Read the file for usage help.

 - version - read-only attribute, which allows to see version of
   this driver and enabled optional features.

Each target subdirectory contains selected entries described below.
The complete common target interface is defined by ../../scst/SysfsRules
and the current SCST sysfs implementation.

 - host - link pointing on the corresponding scsi_host of the initiator
   driver

 - hw_target - read-only attribute with value 1. It identifies a
   hardware target.

 - ini_groups - subdirectory defining initiator groups for this target,
   used to define per-initiator access control. See SCST core README for
   more details.

 - luns - subdirectory defining LUNs of this target. See SCST core
   README for more details.

 - sessions - subdirectory containing connected to this target sessions.

 - enabled - using this attribute you can enable or disable target mode
   of this FC port. It allows to finish configuring it before it starts
   accepting new connections. 0 by default.

 - explicit_confirmation - allows to enable explicit confirmations, see
   above.

 - abort_isp - write-only recovery attribute. Any write requests an ISP
   abort and waits for the HBA to return online. This can disrupt live
   Fibre Channel traffic.

 - node_name and port_name - read or override the hardware target WWNs.
   Changing either while the target is enabled requests an ISP abort and
   HBA reinitialization.

 - rel_tgt_id - allows to read or write SCSI Relative Target Port
   Identifier attribute. This identifier is used to identify SCSI Target
   Ports by some SCSI commands, mainly by Persistent Reservations
   commands. This identifier must be unique among all SCST targets, but
   for convenience SCST allows disabled targets to have not unique
   rel_tgt_id. In this case SCST will not allow to enable this target
   until rel_tgt_id becomes unique. This attribute initialized unique by
   SCST by default.

Subdirectory "sessions" contains one subdirectory for each connected
session with name equal to port name of the connected initiator.

Each session subdirectory contains the following entries:

 - initiator_name - contains initiator's port name

 - active_commands - contains number of active, i.e. not yet or being
   executed, SCSI commands in this session.

 - commands - contains overall number of SCSI commands in this session.

WARNING: The scripts below perform live module and sysfs operations,
enable an FC target and export hard-coded SCSI devices, backing paths
and WWNs. They are interface examples, not runnable defaults. Do not
use them without substituting an approved test configuration and
following the scstadmin workflow referenced above.

Below is another sample script, which configures 1 real local SCSI disk
0:0:1:0 for usage with 25:00:00:f0:98:87:92:f3 target:

#!/bin/bash

modprobe scst
modprobe scst_disk

echo "add_device 0:0:1:0" >/sys/kernel/scst_tgt/handlers/dev_disk/mgmt

modprobe qla2x00tgt

echo "add 0:0:1:0 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled

Below is an advanced sample script, which configures more virtual
devices of various types, including virtual CDROM. In this script
initiator 25:00:00:f0:99:87:94:a3 will see disk1 and disk2 devices, all
other initiators will see read only blockio, nullio and cdrom devices.

#!/bin/bash

modprobe scst
modprobe scst_vdisk

echo "add_device disk1 filename=/disk1; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device disk2 filename=/disk2; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
echo "add_device nullio" >/sys/kernel/scst_tgt/handlers/vdisk_nullio/mgmt
echo "add_device cdrom" >/sys/kernel/scst_tgt/handlers/vcdrom/mgmt

modprobe qla2x00tgt

echo "add blockio 0 read_only=1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
echo "add nullio 1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
echo "add cdrom 2" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt

echo "create 25:00:00:f0:99:87:94:a3" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/mgmt
echo "add disk1 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/mgmt
echo "add disk2 1" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/mgmt
echo "add 25:00:00:f0:99:87:94:a3" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/initiators/mgmt

echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled

An abridged view of the resulting SCST sysfs hierarchy with initiator
25:00:00:f0:99:87:94:a3 connected looks like:

/sys/kernel/scst_tgt
|-- devices
|   |-- blockio
|   |   |-- blocksize
|   |   |-- exported
|   |   |   `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/0
|   |   |-- filename
|   |   |-- handler -> ../../handlers/vdisk_blockio
|   |   |-- nv_cache
|   |   |-- read_only
|   |   |-- removable
|   |   |-- resync_size
|   |   |-- size_mb
|   |   |-- t10_dev_id
|   |   |-- threads_num
|   |   |-- threads_pool_type
|   |   |-- type
|   |   `-- usn
|   |-- cdrom
|   |   |-- exported
|   |   |   `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/2
|   |   |-- filename
|   |   |-- handler -> ../../handlers/vcdrom
|   |   |-- size_mb
|   |   |-- t10_dev_id
|   |   |-- threads_num
|   |   |-- threads_pool_type
|   |   |-- type
|   |   `-- usn
|   |-- disk1
|   |   |-- blocksize
|   |   |-- exported
|   |   |   `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/0
|   |   |-- filename
|   |   |-- handler -> ../../handlers/vdisk_fileio
|   |   |-- nv_cache
|   |   |-- o_direct
|   |   |-- read_only
|   |   |-- removable
|   |   |-- resync_size
|   |   |-- size_mb
|   |   |-- t10_dev_id
|   |   |-- threads_num
|   |   |-- threads_pool_type
|   |   |-- type
|   |   |-- usn
|   |   `-- write_through
|   |-- disk2
|   |   |-- blocksize
|   |   |-- exported
|   |   |   `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/ini_groups/25:00:00:f0:99:87:94:a3/luns/1
|   |   |-- filename
|   |   |-- handler -> ../../handlers/vdisk_fileio
|   |   |-- nv_cache
|   |   |-- o_direct
|   |   |-- read_only
|   |   |-- removable
|   |   |-- resync_size
|   |   |-- size_mb
|   |   |-- t10_dev_id
|   |   |-- threads_num
|   |   |-- threads_pool_type
|   |   |-- type
|   |   |-- usn
|   |   `-- write_through
|   `-- nullio
|       |-- blocksize
|       |-- exported
|       |   `-- export0 -> ../../../targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/1
|       |-- handler -> ../../handlers/vdisk_nullio
|       |-- read_only
|       |-- removable
|       |-- size_mb
|       |-- t10_dev_id
|       |-- threads_num
|       |-- threads_pool_type
|       |-- type
|       `-- usn
|-- handlers
|   |-- vcdrom
|   |   |-- cdrom -> ../../devices/cdrom
|   |   |-- mgmt
|   |   |-- trace_level
|   |   `-- type
|   |-- vdisk_blockio
|   |   |-- blockio -> ../../devices/blockio
|   |   |-- mgmt
|   |   |-- trace_level
|   |   `-- type
|   |-- vdisk_fileio
|   |   |-- disk1 -> ../../devices/disk1
|   |   |-- disk2 -> ../../devices/disk2
|   |   |-- mgmt
|   |   |-- trace_level
|   |   `-- type
|   `-- vdisk_nullio
|       |-- mgmt
|       |-- nullio -> ../../devices/nullio
|       |-- trace_level
|       `-- type
|-- sgv
|   |-- global_stats
|   |-- sgv
|   |   `-- stats
|   |-- sgv-clust
|   |   `-- stats
|   `-- sgv-dma
|       `-- stats
|-- targets
|   `-- qla2x00t
|       |-- 25:00:00:f0:98:87:92:f3
|       |   |-- abort_isp
|       |   |-- enabled
|       |   |-- explicit_confirmation
|       |   |-- host -> ../../../../../class/scsi_host/host4
|       |   |-- hw_target
|       |   |-- ini_groups
|       |   |   |-- 25:00:00:f0:99:87:94:a3
|       |   |   |   |-- initiators
|       |   |   |   |   |-- 25:00:00:f0:99:87:94:a3
|       |   |   |   |   `-- mgmt
|       |   |   |   `-- luns
|       |   |   |       |-- 0
|       |   |   |       |   |-- device -> ../../../../../../../devices/disk1
|       |   |   |       |   `-- read_only
|       |   |   |       |-- 1
|       |   |   |       |   |-- device -> ../../../../../../../devices/disk2
|       |   |   |       |   `-- read_only
|       |   |   |       `-- mgmt
|       |   |   `-- mgmt
|       |   |-- luns
|       |   |   |-- 0
|       |   |   |   |-- device -> ../../../../../devices/blockio
|       |   |   |   `-- read_only
|       |   |   |-- 1
|       |   |   |   |-- device -> ../../../../../devices/nullio
|       |   |   |   `-- read_only
|       |   |   |-- 2
|       |   |   |   |-- device -> ../../../../../devices/cdrom
|       |   |   |   `-- read_only
|       |   |   `-- mgmt
|       |   |-- node_name
|       |   |-- port_name
|       |   |-- rel_tgt_id
|       |   `-- sessions
|       |       `-- 25:00:00:f0:99:87:94:a3
|       |           |-- active_commands
|       |           |-- commands
|       |           |-- initiator_name
|       |           `-- luns -> ../../ini_groups/25:00:00:f0:99:87:94:a3/luns
|       |-- trace_level
|       |-- version
|-- threads
|-- trace_level
`-- version


Performance advices
-------------------

1. If you are going to use your target in an VM environment, for
instance as a shared storage with VMware, make sure all your VMs
connected to the target via *separate* sessions. You can check it using
the SCST sysfs interface. Use the facilities available in the fabric
and initiators to make separate sessions for each VM; this legacy target
driver does not provide NPIV. Without separate sessions, parallel access
from different VMs can lose considerable performance. This does not
apply when VM hosts using shared storage such as VMFS already connect
through separate sessions.

2. See SCST core's README for more advices. Especially pay attention to
have io_grouping_type option set correctly.


Credits
-------

Thanks to:

 * QLogic support for their invaluable help.

 * Nathaniel Clark <nate@misrule.us> for porting to new 2.6 kernel
initiator driver.

 * Mark Buechler <mark.buechler@gmail.com> for the original
WWN-based authentication, a lot of useful suggestions, bug reports and
help in debugging.

 * Ming Zhang <mingz@ele.uri.edu> for fixes.

 * Uri Yanai <Uri.Yanai@ngsoft.com> and Dorit Halsadi
<Dorit.Halsadi@dothill.com> for adding full NPIV support.

Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
