mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-18 03:01:26 +00:00
Patch from Dorit Halsadi <Dorit.Halsadi@dothill.com> and Uri Yanai <Uri.Yanai@ngsoft.com> adding NPIV support to the SCST Target driver for Qlogic 24xx/25xx Fibre Channel cards
with minor fixes. Note: you need NPIV-supporting firmware as well as NPIV-supporting switches to use NPIV. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2408 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -1,8 +1,17 @@
|
||||
Summary of changes between versions 2.0.0 and 2.1.0
|
||||
---------------------------------------------------
|
||||
|
||||
- Complete NPIV support added. Particularly, now SCST core sees
|
||||
all the virtual targets and provide separate target-oriented access
|
||||
control for them. Thanks a lot to Uri Yanai and Dorit
|
||||
Halsadi!
|
||||
|
||||
|
||||
Summary of changes between versions 1.0.2 and 2.0.0
|
||||
---------------------------------------------------
|
||||
|
||||
- Support for 24xx/25xx added
|
||||
|
||||
|
||||
- Disable by default initiator mode if target mode enabled. It can be changed
|
||||
using .config option CONFIG_SCSI_QLA2XXX_TARGET_DISABLE_INI_MODE.
|
||||
|
||||
@@ -17,7 +26,7 @@ Summary of changes between versions 1.0.1 and 1.0.2
|
||||
module unload fixed
|
||||
|
||||
- Implemented abort on timeout of stuck in the firmware commands
|
||||
|
||||
|
||||
|
||||
Summary of changes between versions 1.0.0 and 1.0.1
|
||||
---------------------------------------------------
|
||||
|
||||
@@ -17,14 +17,6 @@ Linux kernel 2.6.26 and higher. Sorry, kernels below 2.6.26 are not
|
||||
supported, because it's too hard to backport used initiator driver to
|
||||
older kernels.
|
||||
|
||||
NPIV is partially supported by this driver. You can create virtual
|
||||
targets using standard Linux interface by echoing wwpn:wwnn into
|
||||
/sys/class/fc_host/hostX/vport_create and work with them, but SCST core
|
||||
will not see those virtual targets and, hence, provide the
|
||||
target-oriented access control for them. However, the initiator-oriented
|
||||
access control will still work very well. Note, you need NPIV-supporting
|
||||
firmware as well as NPIV-supporting switches to use NPIV.
|
||||
|
||||
The original initiator driver was taken from the kernel 2.6.26. Also the
|
||||
following 2.6.26.x commits have been applied to it (upstream ID):
|
||||
048feec5548c0582ee96148c61b87cccbcb5f9be,
|
||||
@@ -167,6 +159,34 @@ option needs a special firmware with class 2 support. Disabled by
|
||||
default.
|
||||
|
||||
|
||||
N_Port ID Virtualization
|
||||
------------------------
|
||||
|
||||
N_Port ID Virtualization(NPIV) is a Fibre Channel facility allowing
|
||||
multiple N_Port IDs to share a single physical N_Port. NPIV is fully
|
||||
supported by this driver. You must have 24xx+ ISPs with NPIV-supporting
|
||||
and NPIV-switches switch(es) to use this facility.
|
||||
|
||||
You can add NPIV targets by echoing
|
||||
|
||||
add_target target_name node_name=node_name_value; parent_host=parent_host_value
|
||||
|
||||
in /sys/kernel/scst_tgt/targets/qla2x00t/mgmt.
|
||||
|
||||
Removing NPIV targets is done by echoing
|
||||
|
||||
del_target target_name
|
||||
|
||||
in/sys/kernel/scst_tgt/targets/qla2x00t/mgmt.
|
||||
|
||||
Also, you can create and remove NPIV targets using the standard Linux
|
||||
interface (i.e. echoing wwpn:wwnn into /sys/class/fc_host/hostX/vport_create
|
||||
and /sys/class/fc_host/hostX/vport_delete).
|
||||
|
||||
It is recommended to use scstadmin utility and its config file to
|
||||
configure virtual NPIV targets instead of the above direct interface.
|
||||
|
||||
|
||||
Compilation options
|
||||
-------------------
|
||||
|
||||
@@ -211,6 +231,12 @@ entries:
|
||||
- version - read-only attribute, which allows to see version of
|
||||
this driver and enabled optional features.
|
||||
|
||||
- mgmt - main management entry, which allows to configure NPIV targets.
|
||||
See content of this file for help how to use it.
|
||||
|
||||
- hw_target (hardware target only) - read-only attribute with value 1.
|
||||
It allows to distinguish hardware and virtual targets.
|
||||
|
||||
Each target subdirectory contains the following entries:
|
||||
|
||||
- host - link pointing on the corresponding scsi_host of the initiator
|
||||
@@ -241,6 +267,12 @@ Each target subdirectory contains the following entries:
|
||||
until rel_tgt_id becomes unique. This attribute initialized unique by
|
||||
SCST by default.
|
||||
|
||||
- node_name (NPIV targets only) - read-only attribute, which allows to see
|
||||
the target World Wide Node Name.
|
||||
|
||||
- parent_host (NPIV target only) - read-only attribute, which allows to see
|
||||
the parent HBA World Wide Port Name (WWPN).
|
||||
|
||||
Subdirectory "sessions" contains one subdirectory for each connected
|
||||
session with name equal to port name of the connected initiator.
|
||||
|
||||
@@ -253,9 +285,10 @@ Each session subdirectory contains the following entries:
|
||||
|
||||
- commands - contains overall number of SCSI commands in this session.
|
||||
|
||||
Below is a sample script, which configures 1 virtual disk "disk1" using
|
||||
/disk1 image for usage with 25:00:00:f0:98:87:92:f3 target. All
|
||||
initiators connected to this target will see this device.
|
||||
Below is a sample script, which configures 2 virtual disk "disk1" using
|
||||
/disk1 image for usage with 25:00:00:f0:98:87:92:f3 hardware target, and
|
||||
"disk2" using /disk2 image for usage with 50:50:00:00:00:00:00:11 NPIV
|
||||
target. All initiators connected to this targets will see those devices.
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
@@ -263,11 +296,17 @@ 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; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt
|
||||
|
||||
modprobe qla2x00tgt
|
||||
|
||||
echo "add_target 50:50:00:00:00:00:00:11 node_name=50:50:00:00:00:00:00:00;parent_host=25:00:00:f0:98:87:92:f3" >\
|
||||
/sys/kernel/scst_tgt/targets/qla2x00t/mgmt
|
||||
|
||||
echo "add disk1 0" >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/luns/mgmt
|
||||
echo "add disk2 0" >/sys/kernel/scst_tgt/targets/qla2x00t/50:50:00:00:00:00:00:11/luns/mgmt
|
||||
echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/25:00:00:f0:98:87:92:f3/enabled
|
||||
echo 1 >/sys/kernel/scst_tgt/targets/qla2x00t/50:50:00:00:00:00:00:11/enabled
|
||||
|
||||
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:
|
||||
@@ -456,6 +495,7 @@ The resulting overall SCST sysfs hierarchy with initiator
|
||||
| | | | `-- read_only
|
||||
| | | `-- mgmt
|
||||
| | |-- rel_tgt_id
|
||||
| | |-- hw_target
|
||||
| | `-- sessions
|
||||
| | `-- 25:00:00:f0:99:87:94:a3
|
||||
| | |-- active_commands
|
||||
@@ -463,7 +503,8 @@ The resulting overall SCST sysfs hierarchy with initiator
|
||||
| | |-- initiator_name
|
||||
| | `-- luns -> ../../ini_groups/25:00:00:f0:99:87:94:a3/luns
|
||||
| |-- trace_level
|
||||
| `-- version
|
||||
| |-- version
|
||||
| `-- mgmt
|
||||
|-- threads
|
||||
|-- trace_level
|
||||
`-- version
|
||||
@@ -503,4 +544,7 @@ 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
|
||||
|
||||
@@ -3,9 +3,6 @@ Known issues and unimplemented features
|
||||
|
||||
- Allow to set port and node names through sysfs.
|
||||
|
||||
- Complete NPIV support. Particularly, SCST core should see all the virtual
|
||||
targets and provide separate target-oriented access control for them.
|
||||
|
||||
- Minor "ToDo"'s spread in the code.
|
||||
|
||||
- If a Linux initiator asks for devices using INQUIRY command too soon
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -126,7 +126,9 @@ qla2x00_send_enable_lun(scsi_qla_host_t *ha, bool enable)
|
||||
}
|
||||
|
||||
extern void qla2xxx_add_targets(void);
|
||||
|
||||
extern size_t
|
||||
qla2xxx_add_vtarget(u64 *port_name, u64 *node_name, u64 *parent_host);
|
||||
extern size_t qla2xxx_del_vtarget(u64 *port_name);
|
||||
#endif /* CONFIG_SCSI_QLA2XXX_TARGET */
|
||||
|
||||
#endif /* __QLA2X_TGT_H */
|
||||
|
||||
@@ -44,13 +44,13 @@
|
||||
* Must be changed on any change in any initiator visible interfaces or
|
||||
* data in the target add-on
|
||||
*/
|
||||
#define QLA2X_TARGET_MAGIC 267
|
||||
#define QLA2X_TARGET_MAGIC 268
|
||||
|
||||
/*
|
||||
* Must be changed on any change in any target visible interfaces or
|
||||
* data in the initiator
|
||||
*/
|
||||
#define QLA2X_INITIATOR_MAGIC 57219
|
||||
#define QLA2X_INITIATOR_MAGIC 57220
|
||||
|
||||
#define QLA2X_INI_MODE_STR_EXCLUSIVE "exclusive"
|
||||
#define QLA2X_INI_MODE_STR_DISABLED "disabled"
|
||||
@@ -508,7 +508,8 @@ typedef struct {
|
||||
uint16_t status;
|
||||
uint16_t timeout;
|
||||
uint16_t dseg_count; /* Data segment count. */
|
||||
uint8_t reserved1[6];
|
||||
uint8_t vp_index;
|
||||
uint8_t reserved1[5];
|
||||
uint32_t exchange_address;
|
||||
uint16_t reserved2;
|
||||
uint16_t flags;
|
||||
@@ -614,7 +615,8 @@ typedef struct {
|
||||
uint8_t entry_status; /* Entry Status. */
|
||||
uint8_t reserved_1[6];
|
||||
uint16_t nport_handle;
|
||||
uint8_t reserved_2[3];
|
||||
uint8_t reserved_2[2];
|
||||
uint8_t vp_index;
|
||||
uint8_t reserved_3:4;
|
||||
uint8_t sof_type:4;
|
||||
uint32_t exchange_address;
|
||||
@@ -656,7 +658,7 @@ typedef struct {
|
||||
uint16_t nport_handle;
|
||||
uint16_t control_flags;
|
||||
#define ABTS_CONTR_FLG_TERM_EXCHG BIT_0
|
||||
uint8_t reserved_2;
|
||||
uint8_t vp_index;
|
||||
uint8_t reserved_3:4;
|
||||
uint8_t sof_type:4;
|
||||
uint32_t exchange_address;
|
||||
|
||||
@@ -1783,6 +1783,26 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
|
||||
fc_host_supported_speeds(vha->host) =
|
||||
fc_host_supported_speeds(ha->host);
|
||||
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
vha->tgt = NULL;
|
||||
vha->q2t_tgt = NULL;
|
||||
mutex_init(&vha->tgt_mutex);
|
||||
mutex_init(&vha->tgt_host_action_mutex);
|
||||
qla_clear_tgt_mode(vha);
|
||||
qla2x00_send_enable_lun(vha, false);
|
||||
if (IS_QLA24XX_TYPE(vha))
|
||||
vha->atio_q_length = ATIO_ENTRY_CNT_24XX;
|
||||
else if (IS_QLA25XX(vha))
|
||||
vha->atio_q_length = ATIO_ENTRY_CNT_24XX;
|
||||
|
||||
if (qla_target.tgt_host_action != NULL)
|
||||
qla_target.tgt_host_action(vha, ADD_TARGET);
|
||||
|
||||
/*
|
||||
* Must be after tgt_host_action() to not race with
|
||||
* qla2xxx_add_targets().
|
||||
*/
|
||||
#endif
|
||||
qla24xx_vport_disable(fc_vport, disable);
|
||||
|
||||
return 0;
|
||||
@@ -1801,6 +1821,11 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
|
||||
scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
|
||||
scsi_qla_host_t *vha = fc_vport->dd_data;
|
||||
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
if (qla_target.tgt_host_action != NULL)
|
||||
qla_target.tgt_host_action(vha, REMOVE_TARGET);
|
||||
#endif
|
||||
|
||||
qla24xx_disable_vp(vha);
|
||||
qla24xx_deallocate_vp_id(vha);
|
||||
|
||||
|
||||
@@ -2626,6 +2626,7 @@ typedef struct scsi_qla_host {
|
||||
uint16_t vp_idx; /* vport ID */
|
||||
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
struct qla_tgt_vp_map *tgt_vp_map;
|
||||
struct mutex tgt_mutex;
|
||||
|
||||
struct mutex tgt_host_action_mutex;
|
||||
@@ -2671,6 +2672,12 @@ typedef struct scsi_qla_host {
|
||||
struct qla_chip_state_84xx *cs84xx;
|
||||
} scsi_qla_host_t;
|
||||
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
struct qla_tgt_vp_map {
|
||||
uint8_t idx;
|
||||
scsi_qla_host_t *vha;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros to help code, maintain, etc.
|
||||
|
||||
@@ -1460,7 +1460,9 @@ qla2x00_configure_hba(scsi_qla_host_t *ha)
|
||||
uint8_t area;
|
||||
uint8_t domain;
|
||||
char connect_type[22];
|
||||
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
scsi_qla_host_t *pha = ha->parent;
|
||||
#endif
|
||||
/* Get host addresses. */
|
||||
rval = qla2x00_get_adapter_id(ha,
|
||||
&loop_id, &al_pa, &area, &domain, &topo, &sw_cap);
|
||||
@@ -1537,7 +1539,10 @@ qla2x00_configure_hba(scsi_qla_host_t *ha)
|
||||
ha->d_id.b.domain = domain;
|
||||
ha->d_id.b.area = area;
|
||||
ha->d_id.b.al_pa = al_pa;
|
||||
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
if (pha)
|
||||
pha->tgt_vp_map[al_pa].idx = ha->vp_idx;
|
||||
#endif
|
||||
if (!ha->flags.init_done)
|
||||
qla_printk(KERN_INFO, ha,
|
||||
"Topology - %s, Host Loop address 0x%x\n",
|
||||
@@ -4139,6 +4144,9 @@ qla2x00_enable_tgt_mode(scsi_qla_host_t *ha)
|
||||
qla_set_tgt_mode(ha);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
|
||||
if (ha->parent)
|
||||
ha = ha->parent;
|
||||
|
||||
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
|
||||
qla2xxx_wake_dpc(ha);
|
||||
qla2x00_wait_for_hba_online(ha);
|
||||
@@ -4154,14 +4162,15 @@ void
|
||||
qla2x00_disable_tgt_mode(scsi_qla_host_t *ha)
|
||||
{
|
||||
unsigned long flags;
|
||||
scsi_qla_host_t *vha = to_qla_parent(ha);
|
||||
|
||||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
spin_lock_irqsave(&vha->hardware_lock, flags);
|
||||
qla_clear_tgt_mode(ha);
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
spin_unlock_irqrestore(&vha->hardware_lock, flags);
|
||||
|
||||
set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
|
||||
qla2xxx_wake_dpc(ha);
|
||||
qla2x00_wait_for_hba_online(ha);
|
||||
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(vha);
|
||||
qla2x00_wait_for_hba_online(vha);
|
||||
}
|
||||
EXPORT_SYMBOL(qla2x00_disable_tgt_mode);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
*/
|
||||
#include "qla_def.h"
|
||||
|
||||
#include "qla2x_tgt.h"
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
|
||||
@@ -2765,6 +2767,14 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha)
|
||||
vpmod->vp_count = 1;
|
||||
vpmod->vp_index1 = vha->vp_idx;
|
||||
vpmod->options_idx1 = BIT_3|BIT_4|BIT_5;
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
/* Enable target mode */
|
||||
if (qla_tgt_mode_enabled(vha))
|
||||
vpmod->options_idx1 &= ~BIT_5;
|
||||
/* Disable ini mode, if requested */
|
||||
if (!qla_ini_mode_enabled(vha))
|
||||
vpmod->options_idx1 &= ~BIT_4;
|
||||
#endif
|
||||
memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE);
|
||||
memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE);
|
||||
vpmod->entry_count = 1;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <scsi/scsicam.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "qla2x_tgt.h"
|
||||
|
||||
void
|
||||
qla2x00_vp_stop_timer(scsi_qla_host_t *vha)
|
||||
{
|
||||
@@ -25,7 +27,7 @@ qla2x00_vp_stop_timer(scsi_qla_host_t *vha)
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
static void
|
||||
qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
|
||||
{
|
||||
uint32_t vp_id;
|
||||
@@ -38,15 +40,16 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
|
||||
DEBUG15(printk ("vp_id %d is bigger than max-supported %d.\n",
|
||||
vp_id, ha->max_npiv_vports));
|
||||
mutex_unlock(&ha->vport_lock);
|
||||
return vp_id;
|
||||
} else {
|
||||
set_bit(vp_id, ha->vp_idx_map);
|
||||
ha->num_vhosts++;
|
||||
vha->vp_idx = vp_id;
|
||||
list_add_tail(&vha->vp_list, &ha->vp_list);
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
ha->tgt_vp_map[vp_id].vha = vha;
|
||||
#endif
|
||||
mutex_unlock(&ha->vport_lock);
|
||||
}
|
||||
|
||||
set_bit(vp_id, ha->vp_idx_map);
|
||||
ha->num_vhosts++;
|
||||
vha->vp_idx = vp_id;
|
||||
list_add_tail(&vha->vp_list, &ha->vp_list);
|
||||
mutex_unlock(&ha->vport_lock);
|
||||
return vp_id;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -60,6 +63,9 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
|
||||
ha->num_vhosts--;
|
||||
clear_bit(vp_id, ha->vp_idx_map);
|
||||
list_del(&vha->vp_list);
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
ha->tgt_vp_map[vp_id].vha = NULL;
|
||||
#endif
|
||||
mutex_unlock(&ha->vport_lock);
|
||||
}
|
||||
|
||||
@@ -116,6 +122,10 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
|
||||
ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
|
||||
atomic_set(&vha->loop_state, LOOP_DOWN);
|
||||
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
/* Remove port id from vp target map */
|
||||
vha->parent->tgt_vp_map[vha->d_id.b.al_pa].idx = 0;
|
||||
#endif
|
||||
|
||||
/* Delete all vp's fcports from parent's list */
|
||||
qla2x00_mark_vp_devices_dead(vha);
|
||||
@@ -249,6 +259,11 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
|
||||
DEBUG15(printk("scsi(%ld): Scheduling enable of Vport %d...\n",
|
||||
vha->host_no, vha->vp_idx));
|
||||
qla24xx_enable_vp(vha);
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
/* Enable target response to SCSI bus. */
|
||||
if (qla_tgt_mode_enabled(vha))
|
||||
qla2x00_send_enable_lun(vha, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -391,7 +406,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
|
||||
vha->fc_vport = fc_vport;
|
||||
vha->device_flags = 0;
|
||||
vha->instance = num_hosts;
|
||||
vha->vp_idx = qla24xx_allocate_vp_id(vha);
|
||||
qla24xx_allocate_vp_id(vha);
|
||||
if (vha->vp_idx > ha->max_npiv_vports) {
|
||||
DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n",
|
||||
vha->host_no));
|
||||
|
||||
@@ -1649,13 +1649,104 @@ qla2xxx_add_targets(void)
|
||||
|
||||
mutex_lock(&qla_ha_list_mutex);
|
||||
list_for_each_entry(ha, &qla_ha_list, ha_list_entry) {
|
||||
if (qla_target.tgt_host_action != NULL)
|
||||
if (qla_target.tgt_host_action != NULL) {
|
||||
int i, vp_idx_matched;
|
||||
|
||||
qla_target.tgt_host_action(ha, ADD_TARGET);
|
||||
for_each_mapped_vp_idx(ha, i) {
|
||||
scsi_qla_host_t *vha;
|
||||
vp_idx_matched = 0;
|
||||
|
||||
list_for_each_entry(vha, &ha->vp_list,
|
||||
vp_list) {
|
||||
if (i == vha->vp_idx) {
|
||||
vp_idx_matched = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vp_idx_matched)
|
||||
qla_target.tgt_host_action(vha, ADD_TARGET);
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex_unlock(&qla_ha_list_mutex);
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(qla2xxx_add_targets);
|
||||
|
||||
size_t qla2xxx_add_vtarget(u64 *port_name, u64 *node_name, u64 *parent_host)
|
||||
{
|
||||
struct Scsi_Host *shost = NULL;
|
||||
scsi_qla_host_t *ha;
|
||||
struct fc_vport_identifiers vid;
|
||||
uint8_t parent_wwn[WWN_SIZE];
|
||||
|
||||
memset(&vid, 0, sizeof(vid));
|
||||
|
||||
u64_to_wwn(*parent_host, parent_wwn);
|
||||
|
||||
mutex_lock(&qla_ha_list_mutex);
|
||||
list_for_each_entry(ha, &qla_ha_list, ha_list_entry) {
|
||||
if (!memcmp(parent_wwn, ha->port_name, WWN_SIZE)) {
|
||||
shost = ha->host;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&qla_ha_list_mutex);
|
||||
if (!ha || !shost)
|
||||
return -ENODEV;
|
||||
|
||||
vid.port_name = *port_name;
|
||||
vid.node_name = *node_name;
|
||||
vid.roles = FC_PORT_ROLE_FCP_INITIATOR;
|
||||
vid.vport_type = FC_PORTTYPE_NPIV;
|
||||
/* vid.symbolic_name is already zero/NULL's */
|
||||
vid.disable = false; /* always enabled */
|
||||
|
||||
/* We only allow support on Channel 0 !!! */
|
||||
if (!fc_vport_create(shost, 0, &vid))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qla2xxx_add_vtarget);
|
||||
|
||||
size_t qla2xxx_del_vtarget(u64 *port_name)
|
||||
{
|
||||
scsi_qla_host_t *ha;
|
||||
struct Scsi_Host *shost;
|
||||
struct fc_host_attrs *fc_host;
|
||||
struct fc_vport *vport;
|
||||
unsigned long flags;
|
||||
int match = 0;
|
||||
|
||||
mutex_lock(&qla_ha_list_mutex);
|
||||
list_for_each_entry(ha, &qla_ha_list, ha_list_entry) {
|
||||
shost = ha->host;
|
||||
fc_host = shost_to_fc_host(shost);
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
/* We only allow support on Channel 0 !!! */
|
||||
list_for_each_entry(vport, &fc_host->vports, peers) {
|
||||
if ((vport->channel == 0) &&
|
||||
(vport->port_name == *port_name)) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
if (match)
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&qla_ha_list_mutex);
|
||||
|
||||
if (!match)
|
||||
return -ENODEV;
|
||||
|
||||
return fc_vport_terminate(vport);
|
||||
}
|
||||
EXPORT_SYMBOL(qla2xxx_del_vtarget);
|
||||
|
||||
#endif /* CONFIG_SCSI_QLA2XXX_TARGET */
|
||||
|
||||
/*
|
||||
@@ -1729,6 +1820,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
mutex_init(&ha->tgt_mutex);
|
||||
mutex_init(&ha->tgt_host_action_mutex);
|
||||
qla_clear_tgt_mode(ha);
|
||||
ha->tgt_vp_map = NULL;
|
||||
#endif
|
||||
|
||||
/* Set ISP-type information. */
|
||||
@@ -2184,11 +2276,16 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha)
|
||||
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
if (IS_FWI2_CAPABLE(ha)) {
|
||||
ha->tgt_vp_map = kzalloc(sizeof(struct qla_tgt_vp_map) *
|
||||
MAX_MULTI_ID_FABRIC, GFP_KERNEL);
|
||||
if (!ha->tgt_vp_map)
|
||||
goto fail_free_response_ring;
|
||||
|
||||
ha->atio_ring = dma_alloc_coherent(&ha->pdev->dev,
|
||||
(ha->atio_q_length + 1) * sizeof(atio_t),
|
||||
&ha->atio_dma, GFP_KERNEL);
|
||||
if (ha->atio_ring == NULL)
|
||||
goto fail_free_response_ring;
|
||||
goto fail_free_vp_map;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2270,6 +2367,9 @@ fail_free_atio_ring:
|
||||
sizeof(response_t), ha->atio_ring, ha->atio_dma);
|
||||
ha->atio_ring = NULL;
|
||||
ha->atio_dma = 0;
|
||||
fail_free_vp_map:
|
||||
kfree(ha->tgt_vp_map);
|
||||
ha->tgt_vp_map = NULL;
|
||||
fail_free_response_ring:
|
||||
#endif
|
||||
dma_free_coherent(&ha->pdev->dev, (ha->response_q_length + 1) *
|
||||
@@ -2342,6 +2442,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
|
||||
dma_free_coherent(&ha->pdev->dev,
|
||||
(ha->atio_q_length + 1) * sizeof(atio_t),
|
||||
ha->atio_ring, ha->atio_dma);
|
||||
kfree(ha->tgt_vp_map);
|
||||
#endif
|
||||
|
||||
if (ha->response_ring)
|
||||
@@ -2378,6 +2479,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
|
||||
#ifdef CONFIG_SCSI_QLA2XXX_TARGET
|
||||
ha->atio_ring = NULL;
|
||||
ha->atio_dma = 0;
|
||||
ha->tgt_vp_map = NULL;
|
||||
#endif
|
||||
|
||||
list_for_each_safe(fcpl, fcptemp, &ha->fcports) {
|
||||
|
||||
Reference in New Issue
Block a user