Skip to content

Commit

Permalink
[SCSI] qla2xxx: add support for NPIV
Browse files Browse the repository at this point in the history
Following patch adds support for NPIV (N-Port ID Virtualization) to the
qla2xxx.

- supported within switched-fabric topologies only.
- supports up to 63 virtual ports on each physical port.

Signed-off-by: Seokmann Ju <seokmann.ju@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
Seokmann Ju authored and James Bottomley committed Jul 15, 2007
1 parent 968a576 commit 2c3dfe3
Show file tree
Hide file tree
Showing 13 changed files with 1,593 additions and 154 deletions.
2 changes: 1 addition & 1 deletion drivers/scsi/qla2xxx/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
qla_dbg.o qla_sup.o qla_attr.o
qla_dbg.o qla_sup.o qla_attr.o qla_mid.o

obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
164 changes: 164 additions & 0 deletions drivers/scsi/qla2xxx/qla_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
*/
#include "qla_def.h"

#include <linux/kthread.h>
#include <linux/vmalloc.h>

int qla24xx_vport_disable(struct fc_vport *, bool);

/* SYSFS attributes --------------------------------------------------------- */

static ssize_t
Expand Down Expand Up @@ -959,6 +962,122 @@ qla2x00_get_host_port_state(struct Scsi_Host *shost)
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
}

static int
qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
{
int ret = 0;
scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
scsi_qla_host_t *vha;

ret = qla24xx_vport_create_req_sanity_check(fc_vport);
if (ret) {
DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, "
"status %x\n", ret));
return (ret);
}

vha = qla24xx_create_vhost(fc_vport);
if (vha == NULL) {
DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n",
vha));
return FC_VPORT_FAILED;
}
if (disable) {
atomic_set(&vha->vp_state, VP_OFFLINE);
fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
} else
atomic_set(&vha->vp_state, VP_FAILED);

/* ready to create vport */
qla_printk(KERN_INFO, vha, "VP entry id %d assigned.\n", vha->vp_idx);

/* initialized vport states */
atomic_set(&vha->loop_state, LOOP_DOWN);
vha->vp_err_state= VP_ERR_PORTDWN;
vha->vp_prev_err_state= VP_ERR_UNKWN;
/* Check if physical ha port is Up */
if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
atomic_read(&ha->loop_state) == LOOP_DEAD) {
/* Don't retry or attempt login of this virtual port */
DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n",
vha->host_no));
atomic_set(&vha->loop_state, LOOP_DEAD);
if (!disable)
fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
}

if (scsi_add_host(vha->host, &fc_vport->dev)) {
DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
vha->host_no, vha->vp_idx));
goto vport_create_failed_2;
}

/* initialize attributes */
fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name);
fc_host_supported_classes(vha->host) =
fc_host_supported_classes(ha->host);
fc_host_supported_speeds(vha->host) =
fc_host_supported_speeds(ha->host);

qla24xx_vport_disable(fc_vport, disable);

return 0;
vport_create_failed_2:
qla24xx_disable_vp(vha);
qla24xx_deallocate_vp_id(vha);
kfree(vha->port_name);
kfree(vha->node_name);
scsi_host_put(vha->host);
return FC_VPORT_FAILED;
}

int
qla24xx_vport_delete(struct fc_vport *fc_vport)
{
scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata;
scsi_qla_host_t *vha = fc_vport->dd_data;

qla24xx_disable_vp(vha);
qla24xx_deallocate_vp_id(vha);

down(&ha->vport_sem);
ha->cur_vport_count--;
clear_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map);
up(&ha->vport_sem);

kfree(vha->node_name);
kfree(vha->port_name);

if (vha->timer_active) {
qla2x00_vp_stop_timer(vha);
DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p "
"has stopped\n",
vha->host_no, vha->vp_idx, vha));
}

fc_remove_host(vha->host);

scsi_remove_host(vha->host);

scsi_host_put(vha->host);

return 0;
}

int
qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable)
{
scsi_qla_host_t *vha = fc_vport->dd_data;

if (disable)
qla24xx_disable_vp(vha);
else
qla24xx_enable_vp(vha);

return 0;
}

struct fc_function_template qla2xxx_transport_functions = {

.show_host_node_name = 1,
Expand Down Expand Up @@ -996,6 +1115,49 @@ struct fc_function_template qla2xxx_transport_functions = {

.issue_fc_host_lip = qla2x00_issue_lip,
.get_fc_host_stats = qla2x00_get_fc_host_stats,

.vport_create = qla24xx_vport_create,
.vport_disable = qla24xx_vport_disable,
.vport_delete = qla24xx_vport_delete,
};

struct fc_function_template qla2xxx_transport_vport_functions = {

.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,

.get_host_port_id = qla2x00_get_host_port_id,
.show_host_port_id = 1,
.get_host_speed = qla2x00_get_host_speed,
.show_host_speed = 1,
.get_host_port_type = qla2x00_get_host_port_type,
.show_host_port_type = 1,
.get_host_symbolic_name = qla2x00_get_host_symbolic_name,
.show_host_symbolic_name = 1,
.set_host_system_hostname = qla2x00_set_host_system_hostname,
.show_host_system_hostname = 1,
.get_host_fabric_name = qla2x00_get_host_fabric_name,
.show_host_fabric_name = 1,
.get_host_port_state = qla2x00_get_host_port_state,
.show_host_port_state = 1,

.dd_fcrport_size = sizeof(struct fc_port *),
.show_rport_supported_classes = 1,

.get_starget_node_name = qla2x00_get_starget_node_name,
.show_starget_node_name = 1,
.get_starget_port_name = qla2x00_get_starget_port_name,
.show_starget_port_name = 1,
.get_starget_port_id = qla2x00_get_starget_port_id,
.show_starget_port_id = 1,

.get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,

.issue_fc_host_lip = qla2x00_issue_lip,
.get_fc_host_stats = qla2x00_get_fc_host_stats,
};

void
Expand All @@ -1004,4 +1166,6 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha)
fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name);
fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
fc_host_supported_classes(ha->host) = FC_COS_CLASS3;
fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC;
fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count;
}
10 changes: 9 additions & 1 deletion drivers/scsi/qla2xxx/qla_dbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
/* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */
/* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */
/* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */
/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
/*
* Local Macro Definitions.
*/
Expand All @@ -30,7 +31,8 @@
defined(QL_DEBUG_LEVEL_7) || defined(QL_DEBUG_LEVEL_8) || \
defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_10) || \
defined(QL_DEBUG_LEVEL_11) || defined(QL_DEBUG_LEVEL_12) || \
defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14)
defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14) || \
defined(QL_DEBUG_LEVEL_15)
#define QL_DEBUG_ROUTINES
#endif

Expand Down Expand Up @@ -125,6 +127,12 @@
#define DEBUG14(x) do {} while (0)
#endif

#if defined(QL_DEBUG_LEVEL_15)
#define DEBUG15(x) do {x;} while (0)
#else
#define DEBUG15(x) do {} while (0)
#endif

/*
* Firmware Dump structure definition
*/
Expand Down
83 changes: 83 additions & 0 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,9 @@ typedef struct fc_port {

unsigned long last_queue_full;
unsigned long last_ramp_up;

struct list_head vp_fcport;
uint16_t vp_idx;
} fc_port_t;

/*
Expand Down Expand Up @@ -1999,6 +2002,36 @@ struct gid_list_info {
};
#define GID_LIST_SIZE (sizeof(struct gid_list_info) * MAX_FIBRE_DEVICES)

/* NPIV */
typedef struct vport_info {
uint8_t port_name[WWN_SIZE];
uint8_t node_name[WWN_SIZE];
int vp_id;
uint16_t loop_id;
unsigned long host_no;
uint8_t port_id[3];
int loop_state;
} vport_info_t;

typedef struct vport_params {
uint8_t port_name[WWN_SIZE];
uint8_t node_name[WWN_SIZE];
uint32_t options;
#define VP_OPTS_RETRY_ENABLE BIT_0
#define VP_OPTS_VP_DISABLE BIT_1
} vport_params_t;

/* NPIV - return codes of VP create and modify */
#define VP_RET_CODE_OK 0
#define VP_RET_CODE_FATAL 1
#define VP_RET_CODE_WRONG_ID 2
#define VP_RET_CODE_WWPN 3
#define VP_RET_CODE_RESOURCES 4
#define VP_RET_CODE_NO_MEM 5
#define VP_RET_CODE_NOT_FOUND 6

#define to_qla_parent(x) (((x)->parent) ? (x)->parent : (x))

/*
* ISP operations
*/
Expand Down Expand Up @@ -2073,6 +2106,16 @@ struct qla_msix_entry {
uint16_t msix_entry;
};

#define WATCH_INTERVAL 1 /* number of seconds */

/* NPIV */
#define MAX_MULTI_ID_LOOP 126
#define MAX_MULTI_ID_FABRIC 64
#define MAX_NUM_VPORT_LOOP (MAX_MULTI_ID_LOOP - 1)
#define MAX_NUM_VPORT_FABRIC (MAX_MULTI_ID_FABRIC - 1)
#define MAX_NUM_VHBA_LOOP (MAX_MULTI_ID_LOOP - 1)
#define MAX_NUM_VHBA_FABRIC (MAX_MULTI_ID_FABRIC - 1)

/*
* Linux Host Adapter structure
*/
Expand Down Expand Up @@ -2108,6 +2151,8 @@ typedef struct scsi_qla_host {
uint32_t msix_enabled :1;
uint32_t disable_serdes :1;
uint32_t gpsc_supported :1;
uint32_t vsan_enabled :1;
uint32_t npiv_supported :1;
} flags;

atomic_t loop_state;
Expand Down Expand Up @@ -2147,6 +2192,7 @@ typedef struct scsi_qla_host {
#define BEACON_BLINK_NEEDED 25
#define REGISTER_FDMI_NEEDED 26
#define FCPORT_UPDATE_NEEDED 27
#define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */

uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
Expand Down Expand Up @@ -2237,6 +2283,11 @@ typedef struct scsi_qla_host {

/* ISP configuration data. */
uint16_t loop_id; /* Host adapter loop id */
uint16_t switch_cap;
#define FLOGI_SEQ_DEL BIT_8
#define FLOGI_MID_SUPPORT BIT_10
#define FLOGI_VSAN_SUPPORT BIT_12
#define FLOGI_SP_SUPPORT BIT_13
uint16_t fb_rev;

port_id_t d_id; /* Host adapter port id */
Expand Down Expand Up @@ -2344,6 +2395,7 @@ typedef struct scsi_qla_host {
#define MBX_UPDATE_FLASH_ACTIVE 3

struct semaphore mbx_cmd_sem; /* Serialialize mbx access */
struct semaphore vport_sem; /* Virtual port synchronization */
struct semaphore mbx_intr_sem; /* Used for completion notification */

uint32_t mbx_flags;
Expand Down Expand Up @@ -2428,6 +2480,37 @@ typedef struct scsi_qla_host {
struct fc_host_statistics fc_host_stat;

struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES];

struct list_head vp_list; /* list of VP */
struct fc_vport *fc_vport; /* holds fc_vport * for each vport */
uint8_t vp_idx_map[16];
uint16_t num_vhosts; /* number of vports created */
uint16_t num_vsans; /* number of vsan created */
uint16_t vp_idx; /* vport ID */

struct scsi_qla_host *parent; /* holds pport */
unsigned long vp_flags;
struct list_head vp_fcports; /* list of fcports */
#define VP_IDX_ACQUIRED 0 /* bit no 0 */
#define VP_CREATE_NEEDED 1
#define VP_BIND_NEEDED 2
#define VP_DELETE_NEEDED 3
#define VP_SCR_NEEDED 4 /* State Change Request registration */
atomic_t vp_state;
#define VP_OFFLINE 0
#define VP_ACTIVE 1
#define VP_FAILED 2
// #define VP_DISABLE 3
uint16_t vp_err_state;
uint16_t vp_prev_err_state;
#define VP_ERR_UNKWN 0
#define VP_ERR_PORTDWN 1
#define VP_ERR_FAB_UNSUPPORTED 2
#define VP_ERR_FAB_NORESOURCES 3
#define VP_ERR_FAB_LOGOUT 4
#define VP_ERR_ADAP_NORESOURCES 5
int max_npiv_vports; /* 63 or 125 per topoloty */
int cur_vport_count;
} scsi_qla_host_t;


Expand Down
Loading

0 comments on commit 2c3dfe3

Please sign in to comment.