Implement qlini_mode qla2xxx module parameter with ini_mode_force_reverse sysfs attribute instead of CONFIG_SCSI_QLA2XXX_TARGET_DISABLE_INI_MODE compile-time option for better flexibility.

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1781 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2010-06-24 18:03:27 +00:00
parent 78edc5afb9
commit eb16bf9163
9 changed files with 230 additions and 48 deletions

View File

@@ -31,20 +31,8 @@ config SCSI_QLA2XXX_TARGET
depends on SCSI_QLA_FC
default y
---help---
This option enables target mode hooks used by the SCST QLA2x00tgt driver.
Once the qla2x00tgt module is loaded, target mode can be enable via a
sysfs interface under scsi_host, thus enabling target mode for specific
cards.
You will also need the SCST middle level drivers from
http://scst.sourceforge.net/.
This option enables target mode hooks used by the SCST qla2x00t
driver. Once qla2x00tgt module is loaded, target mode for each
port can be enable via sysfs interface.
config SCSI_QLA2XXX_TARGET_DISABLE_INI_MODE
bool "Disable initiator mode for ports with enabled target mode"
depends on SCSI_QLA2XXX_TARGET
default y
---help---
This option disables initiator mode for hosts for which target mode was
enabled. In other words, it disables possibility to use both target and
initiator mode simultaneously on the same host. It is needed, because
some switches don't handle well ports with both target and initiator
modes enabled.
You will also need the SCST middle level for qla2x00t.

View File

@@ -107,6 +107,37 @@ http://sourceforge.net/mailarchive/forum.php?thread_name=4B4CD39F.6020401%40vlnb
for more details why.
Initiator and target modes
--------------------------
When qla2xxx compiled with CONFIG_SCSI_QLA2XXX_TARGET enabled, it has
parameter "ini_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 remote for your target initiators, which if they 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.
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.
You can always see which modes are currently active in active_mode sysfs
attribute.
Explicit conformation
---------------------

View File

@@ -34,31 +34,27 @@ extern request_t *qla2x00_req_pkt(scsi_qla_host_t *ha);
extern struct qla_tgt_data qla_target;
/* Called under HW lock */
static inline void qla_set_tgt_mode(scsi_qla_host_t *ha)
{
#ifdef CONFIG_SCSI_QLA2XXX_TARGET_DISABLE_INI_MODE
ha->host->active_mode = MODE_TARGET;
#else
ha->host->active_mode |= MODE_TARGET;
#endif
}
/* Called under HW lock */
static inline void qla_clear_tgt_mode(scsi_qla_host_t *ha)
{
#ifdef CONFIG_SCSI_QLA2XXX_TARGET_DISABLE_INI_MODE
ha->host->active_mode = MODE_INITIATOR;
#else
ha->host->active_mode &= ~MODE_TARGET;
#endif
}
void qla_set_tgt_mode(scsi_qla_host_t *ha);
void qla_clear_tgt_mode(scsi_qla_host_t *ha);
static inline bool qla_tgt_mode_enabled(scsi_qla_host_t *ha)
{
return ha->host->active_mode & MODE_TARGET;
}
static inline bool qla_ini_mode_enabled(scsi_qla_host_t *ha)
{
return ha->host->active_mode & MODE_INITIATOR;
}
static inline void qla_reverse_ini_mode(scsi_qla_host_t *ha)
{
if (ha->host->active_mode & MODE_INITIATOR)
ha->host->active_mode &= ~MODE_INITIATOR;
else
ha->host->active_mode |= MODE_INITIATOR;
}
/********************************************************************\
* ISP Queue types left out of new QLogic driver (from old version)
\********************************************************************/

View File

@@ -44,13 +44,21 @@
* Must be changed on any change in any initiator visible interfaces or
* data in the target add-on
*/
#define QLA2X_TARGET_MAGIC 265
#define QLA2X_TARGET_MAGIC 267
/*
* Must be changed on any change in any target visible interfaces or
* data in the initiator
*/
#define QLA2X_INITIATOR_MAGIC 57218
#define QLA2X_INITIATOR_MAGIC 57219
#define QLA2X_INI_MODE_STR_EXCLUSIVE "exclusive"
#define QLA2X_INI_MODE_STR_DISABLED "disabled"
#define QLA2X_INI_MODE_STR_ENABLED "enabled"
#define QLA2X_INI_MODE_EXCLUSIVE 0
#define QLA2X_INI_MODE_DISABLED 1
#define QLA2X_INI_MODE_ENABLED 2
#define QLA2X00_COMMAND_COUNT_INIT 250
#define QLA2X00_IMMED_NOTIFY_COUNT_INIT 250

View File

@@ -214,6 +214,75 @@ static DEVICE_ATTR(explicit_conform_enabled,
#endif /* CONFIG_SCST_PROC */
static ssize_t
qla2x00_show_ini_mode_force_reverse(struct device *dev,
struct device_attribute *attr, char *buffer)
{
scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
ulong max_size = PAGE_SIZE;
ulong size;
size = scnprintf(buffer, max_size, "%x\n", ha->ini_mode_force_reverse);
return size;
}
static ssize_t
qla2x00_store_ini_mode_force_reverse(struct device *dev,
struct device_attribute *attr, const char *buffer, size_t size)
{
struct scsi_qla_host *ha = shost_priv(class_to_shost(dev));
unsigned long flags;
if (buffer == NULL)
return size;
spin_lock_irqsave(&ha->hardware_lock, flags);
switch (buffer[0]) {
case '0':
if (!ha->ini_mode_force_reverse)
goto out_unlock;
ha->ini_mode_force_reverse = 0;
qla_printk(KERN_INFO, ha, "qla2xxx(%ld): initiator mode force "
"reverse disabled\n", ha->instance);
qla_reverse_ini_mode(ha);
break;
case '1':
if (ha->ini_mode_force_reverse)
goto out_unlock;
ha->ini_mode_force_reverse = 1;
qla_printk(KERN_INFO, ha, "qla2xxx(%ld): initiator mode force "
"reverse enabled\n", ha->instance);
qla_reverse_ini_mode(ha);
break;
default:
#if defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_11)
qla_printk(KERN_ERR, ha, "%s: Requested action not understood: "
"%s\n", __func__, buffer);
#endif
break;
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
qla2xxx_wake_dpc(ha);
qla2x00_wait_for_hba_online(ha);
out:
return size;
out_unlock:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
goto out;
}
static DEVICE_ATTR(ini_mode_force_reverse,
S_IRUGO|S_IWUSR,
qla2x00_show_ini_mode_force_reverse,
qla2x00_store_ini_mode_force_reverse);
static ssize_t
qla2x00_show_resource_counts(struct device *dev,
struct device_attribute *attr, char *buffer)
@@ -1338,6 +1407,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_target_mode_enabled,
&dev_attr_explicit_conform_enabled,
#endif
&dev_attr_ini_mode_force_reverse,
&dev_attr_resource_counts,
&dev_attr_port_database,
#endif

View File

@@ -2352,6 +2352,7 @@ typedef struct scsi_qla_host {
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
unsigned int enable_explicit_conf :1;
unsigned int host_shutting_down :1;
unsigned int ini_mode_force_reverse :1;
dma_addr_t atio_dma; /* Physical address. */
atio_t *atio_ring; /* Base virtual address */

View File

@@ -546,11 +546,10 @@ qla2x00_rff_id(scsi_qla_host_t *ha)
* FC-4 Feature bit 0 indicates target functionality to the name server.
*/
if (qla_tgt_mode_enabled(ha)) {
#ifdef CONFIG_SCSI_QLA2XXX_TARGET_DISABLE_INI_MODE
ct_req->req.rff_id.fc4_feature = BIT_0;
#else
ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1;
#endif
if (qla_ini_mode_enabled(ha))
ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1;
else
ct_req->req.rff_id.fc4_feature = BIT_0;
} else
#endif
ct_req->req.rff_id.fc4_feature = BIT_1;

View File

@@ -1754,9 +1754,10 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
/* Enable target mode */
nv->firmware_options[0] |= BIT_4;
#ifdef CONFIG_SCSI_QLA2XXX_TARGET_DISABLE_INI_MODE
nv->firmware_options[0] |= BIT_5;
#endif
/* Disable ini mode, if requested */
if (!qla_ini_mode_enabled(ha))
nv->firmware_options[0] |= BIT_5;
/* Disable Full Login after LIP */
nv->firmware_options[1] &= ~BIT_5;
@@ -3745,9 +3746,10 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
/* Enable target mode */
nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_4);
#ifdef CONFIG_SCSI_QLA2XXX_TARGET_DISABLE_INI_MODE
nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_5);
#endif
/* Disable ini mode, if requested */
if (!qla_ini_mode_enabled(ha))
nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_5);
/* Disable Full Login after LIP */
nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13);

View File

@@ -36,6 +36,18 @@ struct qla_tgt_data qla_target;
*/
static LIST_HEAD(qla_ha_list);
static DEFINE_MUTEX(qla_ha_list_mutex);
static char *qlini_mode = QLA2X_INI_MODE_STR_EXCLUSIVE;
module_param(qlini_mode, charp, S_IRUGO);
MODULE_PARM_DESC(qlini_mode,
"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.");
static int ql2x_ini_mode = QLA2X_INI_MODE_EXCLUSIVE;
#endif
/*
@@ -3073,6 +3085,76 @@ static struct pci_driver qla2xxx_pci_driver = {
.err_handler = &qla2xxx_err_handler,
};
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
/* Must be called under HW lock */
void qla_set_tgt_mode(scsi_qla_host_t *ha)
{
switch (ql2x_ini_mode) {
case QLA2X_INI_MODE_DISABLED:
case QLA2X_INI_MODE_EXCLUSIVE:
ha->host->active_mode = MODE_TARGET;
break;
case QLA2X_INI_MODE_ENABLED:
ha->host->active_mode |= MODE_TARGET;
break;
default:
BUG();
break;
}
if (ha->ini_mode_force_reverse)
qla_reverse_ini_mode(ha);
return;
}
EXPORT_SYMBOL(qla_set_tgt_mode);
/* Must be called under HW lock */
void qla_clear_tgt_mode(scsi_qla_host_t *ha)
{
switch (ql2x_ini_mode) {
case QLA2X_INI_MODE_DISABLED:
ha->host->active_mode = MODE_UNKNOWN;
break;
case QLA2X_INI_MODE_EXCLUSIVE:
ha->host->active_mode = MODE_INITIATOR;
break;
case QLA2X_INI_MODE_ENABLED:
ha->host->active_mode &= ~MODE_TARGET;
break;
default:
BUG();
break;
}
if (ha->ini_mode_force_reverse)
qla_reverse_ini_mode(ha);
return;
}
EXPORT_SYMBOL(qla_clear_tgt_mode);
static bool __init qla2x00_parse_ini_mode(void)
{
if (strcasecmp(qlini_mode, QLA2X_INI_MODE_STR_EXCLUSIVE) == 0)
ql2x_ini_mode = QLA2X_INI_MODE_EXCLUSIVE;
else if (strcasecmp(qlini_mode, QLA2X_INI_MODE_STR_DISABLED) == 0)
ql2x_ini_mode = QLA2X_INI_MODE_DISABLED;
else if (strcasecmp(qlini_mode, QLA2X_INI_MODE_STR_ENABLED) == 0)
ql2x_ini_mode = QLA2X_INI_MODE_ENABLED;
else
return false;
return true;
}
#else
static inline bool qla2x00_parse_ini_mode(void)
{
return true;
}
#endif
/**
* qla2x00_module_init - Module initialization.
**/
@@ -3100,6 +3182,11 @@ qla2x00_module_init(void)
ql2xextended_error_logging = 1;
#endif
if (!qla2x00_parse_ini_mode()) {
printk("Wrong qlini_mode value %s\n", qlini_mode);
return -EINVAL;
}
/* Allocate cache for SRBs. */
srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
SLAB_HWCACHE_ALIGN, NULL);