Commit 2c3dfe3f authored by Seokmann Ju's avatar Seokmann Ju Committed by James Bottomley

[SCSI] qla2xxx: add support for NPIV

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: default avatarSeokmann Ju <seokmann.ju@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 968a5763
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ 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 obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
...@@ -6,8 +6,11 @@ ...@@ -6,8 +6,11 @@
*/ */
#include "qla_def.h" #include "qla_def.h"
#include <linux/kthread.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
int qla24xx_vport_disable(struct fc_vport *, bool);
/* SYSFS attributes --------------------------------------------------------- */ /* SYSFS attributes --------------------------------------------------------- */
static ssize_t static ssize_t
...@@ -959,6 +962,122 @@ qla2x00_get_host_port_state(struct Scsi_Host *shost) ...@@ -959,6 +962,122 @@ qla2x00_get_host_port_state(struct Scsi_Host *shost)
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; 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 = { struct fc_function_template qla2xxx_transport_functions = {
.show_host_node_name = 1, .show_host_node_name = 1,
...@@ -996,6 +1115,49 @@ struct fc_function_template qla2xxx_transport_functions = { ...@@ -996,6 +1115,49 @@ struct fc_function_template qla2xxx_transport_functions = {
.issue_fc_host_lip = qla2x00_issue_lip, .issue_fc_host_lip = qla2x00_issue_lip,
.get_fc_host_stats = qla2x00_get_fc_host_stats, .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 void
...@@ -1004,4 +1166,6 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha) ...@@ -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_node_name(ha->host) = wwn_to_u64(ha->node_name);
fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name);
fc_host_supported_classes(ha->host) = FC_COS_CLASS3; 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;
} }
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
/* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */ /* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */
/* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function 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_14 */ /* Output RSCN trace msgs */
/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
/* /*
* Local Macro Definitions. * Local Macro Definitions.
*/ */
...@@ -30,7 +31,8 @@ ...@@ -30,7 +31,8 @@
defined(QL_DEBUG_LEVEL_7) || defined(QL_DEBUG_LEVEL_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_9) || defined(QL_DEBUG_LEVEL_10) || \
defined(QL_DEBUG_LEVEL_11) || defined(QL_DEBUG_LEVEL_12) || \ 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 #define QL_DEBUG_ROUTINES
#endif #endif
...@@ -125,6 +127,12 @@ ...@@ -125,6 +127,12 @@
#define DEBUG14(x) do {} while (0) #define DEBUG14(x) do {} while (0)
#endif #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 * Firmware Dump structure definition
*/ */
......
...@@ -1551,6 +1551,9 @@ typedef struct fc_port { ...@@ -1551,6 +1551,9 @@ typedef struct fc_port {
unsigned long last_queue_full; unsigned long last_queue_full;
unsigned long last_ramp_up; unsigned long last_ramp_up;
struct list_head vp_fcport;
uint16_t vp_idx;
} fc_port_t; } fc_port_t;
/* /*
...@@ -1999,6 +2002,36 @@ struct gid_list_info { ...@@ -1999,6 +2002,36 @@ struct gid_list_info {
}; };
#define GID_LIST_SIZE (sizeof(struct gid_list_info) * MAX_FIBRE_DEVICES) #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 * ISP operations
*/ */
...@@ -2073,6 +2106,16 @@ struct qla_msix_entry { ...@@ -2073,6 +2106,16 @@ struct qla_msix_entry {
uint16_t 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 * Linux Host Adapter structure
*/ */
...@@ -2108,6 +2151,8 @@ typedef struct scsi_qla_host { ...@@ -2108,6 +2151,8 @@ typedef struct scsi_qla_host {
uint32_t msix_enabled :1; uint32_t msix_enabled :1;
uint32_t disable_serdes :1; uint32_t disable_serdes :1;
uint32_t gpsc_supported :1; uint32_t gpsc_supported :1;
uint32_t vsan_enabled :1;
uint32_t npiv_supported :1;
} flags; } flags;
atomic_t loop_state; atomic_t loop_state;
...@@ -2147,6 +2192,7 @@ typedef struct scsi_qla_host { ...@@ -2147,6 +2192,7 @@ typedef struct scsi_qla_host {
#define BEACON_BLINK_NEEDED 25 #define BEACON_BLINK_NEEDED 25
#define REGISTER_FDMI_NEEDED 26 #define REGISTER_FDMI_NEEDED 26
#define FCPORT_UPDATE_NEEDED 27 #define FCPORT_UPDATE_NEEDED 27
#define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */
uint32_t device_flags; uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0 #define DFLG_LOCAL_DEVICES BIT_0
...@@ -2237,6 +2283,11 @@ typedef struct scsi_qla_host { ...@@ -2237,6 +2283,11 @@ typedef struct scsi_qla_host {
/* ISP configuration data. */ /* ISP configuration data. */
uint16_t loop_id; /* Host adapter loop id */ 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; uint16_t fb_rev;
port_id_t d_id; /* Host adapter port id */ port_id_t d_id; /* Host adapter port id */
...@@ -2344,6 +2395,7 @@ typedef struct scsi_qla_host { ...@@ -2344,6 +2395,7 @@ typedef struct scsi_qla_host {
#define MBX_UPDATE_FLASH_ACTIVE 3 #define MBX_UPDATE_FLASH_ACTIVE 3
struct semaphore mbx_cmd_sem; /* Serialialize mbx access */ struct semaphore mbx_cmd_sem; /* Serialialize mbx access */
struct semaphore vport_sem; /* Virtual port synchronization */
struct semaphore mbx_intr_sem; /* Used for completion notification */ struct semaphore mbx_intr_sem; /* Used for completion notification */
uint32_t mbx_flags; uint32_t mbx_flags;
...@@ -2428,6 +2480,37 @@ typedef struct scsi_qla_host { ...@@ -2428,6 +2480,37 @@ typedef struct scsi_qla_host {
struct fc_host_statistics fc_host_stat; struct fc_host_statistics fc_host_stat;
struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES]; 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; } scsi_qla_host_t;
......
...@@ -69,6 +69,16 @@ struct port_database_24xx { ...@@ -69,6 +69,16 @@ struct port_database_24xx {
uint8_t reserved_3[24]; uint8_t reserved_3[24];
}; };
struct vp_database_24xx {
uint16_t vp_status;
uint8_t options;
uint8_t id;
uint8_t port_name[WWN_SIZE];
uint8_t node_name[WWN_SIZE];
uint16_t port_id_low;
uint16_t port_id_high;
};
struct nvram_24xx { struct nvram_24xx {
/* NVRAM header. */ /* NVRAM header. */
uint8_t id[4]; uint8_t id[4];
...@@ -962,6 +972,25 @@ struct mid_db_24xx { ...@@ -962,6 +972,25 @@ struct mid_db_24xx {
struct mid_db_entry_24xx entries[MAX_MID_VPS]; struct mid_db_entry_24xx entries[MAX_MID_VPS];
}; };
/*
* Virtual Fabric ID type definition.
*/
typedef struct vf_id {
uint16_t id : 12;
uint16_t priority : 4;
} vf_id_t;
/*
* Virtual Fabric HopCt type definition.
*/
typedef struct vf_hopct {
uint16_t reserved : 8;
uint16_t hopct : 8;
} vf_hopct_t;
/*
* Virtual Port Control IOCB
*/
#define VP_CTRL_IOCB_TYPE 0x30 /* Vitual Port Control entry. */ #define VP_CTRL_IOCB_TYPE 0x30 /* Vitual Port Control entry. */
struct vp_ctrl_entry_24xx { struct vp_ctrl_entry_24xx {
uint8_t entry_type; /* Entry type. */ uint8_t entry_type; /* Entry type. */
...@@ -974,6 +1003,7 @@ struct vp_ctrl_entry_24xx { ...@@ -974,6 +1003,7 @@ struct vp_ctrl_entry_24xx {
uint16_t vp_idx_failed; uint16_t vp_idx_failed;
uint16_t comp_status; /* Completion status. */ uint16_t comp_status; /* Completion status. */
#define CS_VCE_IOCB_ERROR 0x01 /* Error processing IOCB */
#define CS_VCE_ACQ_ID_ERROR 0x02 /* Error while acquireing ID. */ #define CS_VCE_ACQ_ID_ERROR 0x02 /* Error while acquireing ID. */
#define CS_VCE_BUSY 0x05 /* Firmware not ready to accept cmd. */ #define CS_VCE_BUSY 0x05 /* Firmware not ready to accept cmd. */
...@@ -982,24 +1012,34 @@ struct vp_ctrl_entry_24xx { ...@@ -982,24 +1012,34 @@ struct vp_ctrl_entry_24xx {
#define VCE_COMMAND_DISABLE_VPS 0x08 /* Disable VPs. */ #define VCE_COMMAND_DISABLE_VPS 0x08 /* Disable VPs. */
#define VCE_COMMAND_DISABLE_VPS_REINIT 0x09 /* Disable VPs and reinit link. */ #define VCE_COMMAND_DISABLE_VPS_REINIT 0x09 /* Disable VPs and reinit link. */
#define VCE_COMMAND_DISABLE_VPS_LOGO 0x0a /* Disable VPs and LOGO ports. */ #define VCE_COMMAND_DISABLE_VPS_LOGO 0x0a /* Disable VPs and LOGO ports. */
#define VCE_COMMAND_DISABLE_VPS_LOGO_ALL 0x0b /* Disable VPs and LOGO ports. */
uint16_t vp_count; uint16_t vp_count;
uint8_t vp_idx_map[16]; uint8_t vp_idx_map[16];
uint16_t flags;
uint8_t reserved_4[32]; struct vf_id id;
uint16_t reserved_4;
struct vf_hopct hopct;
uint8_t reserved_5[8];
}; };
/*
* Modify Virtual Port Configuration IOCB
*/
#define VP_CONFIG_IOCB_TYPE 0x31 /* Vitual Port Config entry. */ #define VP_CONFIG_IOCB_TYPE 0x31 /* Vitual Port Config entry. */
struct vp_config_entry_24xx { struct vp_config_entry_24xx {
uint8_t entry_type; /* Entry type. */ uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */ uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */ uint8_t handle_count;
uint8_t entry_status; /* Entry Status. */ uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */ uint32_t handle; /* System handle. */
uint16_t reserved_1; uint16_t flags;
#define CS_VF_BIND_VPORTS_TO_VF BIT_0
#define CS_VF_SET_QOS_OF_VPORTS BIT_1
#define CS_VF_SET_HOPS_OF_VPORTS BIT_2
uint16_t comp_status; /* Completion status. */ uint16_t comp_status; /* Completion status. */
#define CS_VCT_STS_ERROR 0x01 /* Specified VPs were not disabled. */ #define CS_VCT_STS_ERROR 0x01 /* Specified VPs were not disabled. */
...@@ -1009,27 +1049,29 @@ struct vp_config_entry_24xx { ...@@ -1009,27 +1049,29 @@ struct vp_config_entry_24xx {
#define CS_VCT_BUSY 0x05 /* Firmware not ready to accept cmd. */ #define CS_VCT_BUSY 0x05 /* Firmware not ready to accept cmd. */
uint8_t command; uint8_t command;
#define VCT_COMMAND_MOD_VPS 0x00 /* Enable VPs. */ #define VCT_COMMAND_MOD_VPS 0x00 /* Modify VP configurations. */
#define VCT_COMMAND_MOD_ENABLE_VPS 0x08 /* Disable VPs. */ #define VCT_COMMAND_MOD_ENABLE_VPS 0x01 /* Modify configuration & enable VPs. */
uint8_t vp_count; uint8_t vp_count;
uint8_t vp_idx1; uint8_t vp_index1;
uint8_t vp_idx2; uint8_t vp_index2;
uint8_t options_idx1; uint8_t options_idx1;
uint8_t hard_address_idx1; uint8_t hard_address_idx1;
uint16_t reserved_2; uint16_t reserved_vp1;
uint8_t port_name_idx1[WWN_SIZE]; uint8_t port_name_idx1[WWN_SIZE];
uint8_t node_name_idx1[WWN_SIZE]; uint8_t node_name_idx1[WWN_SIZE];
uint8_t options_idx2; uint8_t options_idx2;
uint8_t hard_address_idx2; uint8_t hard_address_idx2;
uint16_t reserved_3; uint16_t reserved_vp2;
uint8_t port_name_idx2[WWN_SIZE]; uint8_t port_name_idx2[WWN_SIZE];
uint8_t node_name_idx2[WWN_SIZE]; uint8_t node_name_idx2[WWN_SIZE];
struct vf_id id;
uint8_t reserved_4[8]; uint16_t reserved_4;
struct vf_hopct hopct;
uint8_t reserved_5;
}; };
#define VP_RPT_ID_IOCB_TYPE 0x32 /* Report ID Acquisition entry. */ #define VP_RPT_ID_IOCB_TYPE 0x32 /* Report ID Acquisition entry. */
...@@ -1054,5 +1096,30 @@ struct vp_rpt_id_entry_24xx { ...@@ -1054,5 +1096,30 @@ struct vp_rpt_id_entry_24xx {
uint8_t reserved_4[32]; uint8_t reserved_4[32];
}; };
#define VF_EVFP_IOCB_TYPE 0x26 /* Exchange Virtual Fabric Parameters entry. */
struct vf_evfp_entry_24xx {
uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
uint16_t comp_status; /* Completion status. */
uint16_t timeout; /* timeout */
uint16_t adim_tagging_mode;
uint16_t vfport_id;
uint32_t exch_addr;
uint16_t nport_handle; /* N_PORT handle. */
uint16_t control_flags;
uint32_t io_parameter_0;
uint32_t io_parameter_1;
uint32_t tx_address[2]; /* Data segment 0 address. */
uint32_t tx_len; /* Data segment 0 length. */
uint32_t rx_address[2]; /* Data segment 1 address. */
uint32_t rx_len; /* Data segment 1 length. */
};
/* END MID Support ***********************************************************/ /* END MID Support ***********************************************************/
#endif #endif
...@@ -62,6 +62,38 @@ extern int ql2xfdmienable; ...@@ -62,6 +62,38 @@ extern int ql2xfdmienable;
extern int ql2xallocfwdump; extern int ql2xallocfwdump;
extern int ql2xextended_error_logging; extern int ql2xextended_error_logging;
extern int ql2xqfullrampup; extern int ql2xqfullrampup;
extern int num_hosts;
/*
* Global Functions in qla_mid.c source file.
*/
extern struct scsi_host_template qla2x00_driver_template;
extern struct scsi_host_template qla24xx_driver_template;
extern struct scsi_transport_template *qla2xxx_transport_vport_template;
extern uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
extern void qla2x00_timer(scsi_qla_host_t *);
extern void qla2x00_start_timer(scsi_qla_host_t *, void *, unsigned long);
extern void qla2x00_stop_timer(scsi_qla_host_t *);
extern uint32_t qla24xx_allocate_vp_id(scsi_qla_host_t *);
extern void qla24xx_deallocate_vp_id(scsi_qla_host_t *);
extern int qla24xx_disable_vp (scsi_qla_host_t *);
extern int qla24xx_enable_vp (scsi_qla_host_t *);
extern void qla2x00_mem_free(scsi_qla_host_t *);
extern int qla24xx_control_vp(scsi_qla_host_t *, int );
extern int qla24xx_modify_vp_config(scsi_qla_host_t *);
extern int qla2x00_send_change_request(scsi_qla_host_t *, uint16_t, uint16_t);
extern void qla2x00_vp_stop_timer(scsi_qla_host_t *);
extern int qla24xx_configure_vhba (scsi_qla_host_t *);
extern int qla24xx_get_vp_entry(scsi_qla_host_t *, uint16_t, int);
extern int qla24xx_get_vp_database(scsi_qla_host_t *, uint16_t);
extern int qla2x00_do_dpc_vp(scsi_qla_host_t *);
extern void qla24xx_report_id_acquisition(scsi_qla_host_t *,
struct vp_rpt_id_entry_24xx *);
extern scsi_qla_host_t * qla24xx_find_vhost_by_name(scsi_qla_host_t *,
uint8_t *);
extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *);
extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *);
extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *);
extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
...@@ -77,6 +109,10 @@ extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); ...@@ -77,6 +109,10 @@ extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
extern void qla2xxx_wake_dpc(scsi_qla_host_t *); extern void qla2xxx_wake_dpc(scsi_qla_host_t *);
extern void qla2x00_alert_all_vps(scsi_qla_host_t *, uint16_t *);
extern void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);
extern void qla2x00_vp_abort_isp(scsi_qla_host_t *);
extern int qla24xx_vport_delete(struct fc_vport *);
/* /*
* Global Function Prototypes in qla_iocb.c source file. * Global Function Prototypes in qla_iocb.c source file.
...@@ -128,7 +164,7 @@ qla2x00_abort_target(fc_port_t *); ...@@ -128,7 +164,7 @@ qla2x00_abort_target(fc_port_t *);
extern int extern int
qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
uint8_t *, uint16_t *); uint8_t *, uint16_t *, uint16_t *);
extern int extern int
qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *); qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *);
...@@ -303,6 +339,7 @@ struct class_device_attribute; ...@@ -303,6 +339,7 @@ struct class_device_attribute;
extern struct class_device_attribute *qla2x00_host_attrs[]; extern struct class_device_attribute *qla2x00_host_attrs[];
struct fc_function_template; struct fc_function_template;
extern struct fc_function_template qla2xxx_transport_functions; extern struct fc_function_template qla2xxx_transport_functions;
extern struct fc_function_template qla2xxx_transport_vport_functions;
extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
extern void qla2x00_init_host_attr(scsi_qla_host_t *); extern void qla2x00_init_host_attr(scsi_qla_host_t *);
......
...@@ -88,6 +88,7 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size) ...@@ -88,6 +88,7 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
ct_pkt->vp_index = ha->vp_idx;
return (ct_pkt); return (ct_pkt);
} }
...@@ -1186,6 +1187,7 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size, ...@@ -1186,6 +1187,7 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
ct_pkt->vp_index = ha->vp_idx;
return ct_pkt; return ct_pkt;
} }
...@@ -1746,6 +1748,7 @@ qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *ha, uint32_t req_size, ...@@ -1746,6 +1748,7 @@ qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *ha, uint32_t req_size,
ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
ct_pkt->vp_index = ha->vp_idx;
return ct_pkt; return ct_pkt;
} }
......
This diff is collapsed.
...@@ -179,7 +179,6 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, ...@@ -179,7 +179,6 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
/* Load data segments */ /* Load data segments */
scsi_for_each_sg(cmd, sg, tot_dsds, i) { scsi_for_each_sg(cmd, sg, tot_dsds, i) {
cont_entry_t *cont_pkt; cont_entry_t *cont_pkt;
...@@ -316,9 +315,14 @@ qla2x00_start_scsi(srb_t *sp) ...@@ -316,9 +315,14 @@ qla2x00_start_scsi(srb_t *sp)
goto queuing_error; goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */ /* Map the sg table so we have an accurate count of sg entries needed */
nseg = scsi_dma_map(cmd); if (scsi_sg_count(cmd)) {
if (nseg < 0) nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
goto queuing_error; scsi_sg_count(cmd), cmd->sc_data_direction);
if (unlikely(!nseg))
goto queuing_error;
} else
nseg = 0;
tot_dsds = nseg; tot_dsds = nseg;
/* Calculate the number of request entries needed. */ /* Calculate the number of request entries needed. */
...@@ -414,9 +418,10 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, ...@@ -414,9 +418,10 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
{ {
mrk_entry_t *mrk; mrk_entry_t *mrk;
struct mrk_entry_24xx *mrk24; struct mrk_entry_24xx *mrk24;
scsi_qla_host_t *pha = to_qla_parent(ha);
mrk24 = NULL; mrk24 = NULL;
mrk = (mrk_entry_t *)qla2x00_req_pkt(ha); mrk = (mrk_entry_t *)qla2x00_req_pkt(pha);
if (mrk == NULL) { if (mrk == NULL) {
DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n", DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n",
__func__, ha->host_no)); __func__, ha->host_no));
...@@ -433,6 +438,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, ...@@ -433,6 +438,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
mrk24->lun[1] = LSB(lun); mrk24->lun[1] = LSB(lun);
mrk24->lun[2] = MSB(lun); mrk24->lun[2] = MSB(lun);
host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
mrk24->vp_index = ha->vp_idx;
} else { } else {
SET_TARGET_ID(ha, mrk->target, loop_id); SET_TARGET_ID(ha, mrk->target, loop_id);
mrk->lun = cpu_to_le16(lun); mrk->lun = cpu_to_le16(lun);
...@@ -440,7 +446,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, ...@@ -440,7 +446,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
} }
wmb(); wmb();
qla2x00_isp_cmd(ha); qla2x00_isp_cmd(pha);
return (QLA_SUCCESS); return (QLA_SUCCESS);
} }
...@@ -712,9 +718,14 @@ qla24xx_start_scsi(srb_t *sp) ...@@ -712,9 +718,14 @@ qla24xx_start_scsi(srb_t *sp)
goto queuing_error; goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */ /* Map the sg table so we have an accurate count of sg entries needed */
nseg = scsi_dma_map(cmd); if (scsi_sg_count(cmd)) {
if (nseg < 0) nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd),
scsi_sg_count(cmd), cmd->sc_data_direction);
if (unlikely(!nseg))
goto queuing_error; goto queuing_error;
} else
nseg = 0;
tot_dsds = nseg; tot_dsds = nseg;
req_cnt = qla24xx_calc_iocbs(tot_dsds); req_cnt = qla24xx_calc_iocbs(tot_dsds);
...@@ -750,6 +761,7 @@ qla24xx_start_scsi(srb_t *sp) ...@@ -750,6 +761,7 @@ qla24xx_start_scsi(srb_t *sp)
cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa;
cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; cmd_pkt->port_id[1] = sp->fcport->d_id.b.area;
cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain;
cmd_pkt->vp_index = sp->fcport->vp_idx;
int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);
static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
static void qla2x00_status_entry(scsi_qla_host_t *, void *); static void qla2x00_status_entry(scsi_qla_host_t *, void *);
static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *); static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
...@@ -244,7 +243,7 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0) ...@@ -244,7 +243,7 @@ qla2x00_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0)
* @ha: SCSI driver HA context * @ha: SCSI driver HA context
* @mb: Mailbox registers (0 - 3) * @mb: Mailbox registers (0 - 3)
*/ */
static void void
qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
{ {
#define LS_UNKNOWN 2 #define LS_UNKNOWN 2
...@@ -386,6 +385,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -386,6 +385,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
qla2x00_mark_all_devices_lost(ha, 1); qla2x00_mark_all_devices_lost(ha, 1);
} }
if (ha->parent) {
atomic_set(&ha->vp_state, VP_FAILED);
fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
}
set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
ha->flags.management_server_logged_in = 0; ha->flags.management_server_logged_in = 0;
...@@ -422,6 +426,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -422,6 +426,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
qla2x00_mark_all_devices_lost(ha, 1); qla2x00_mark_all_devices_lost(ha, 1);
} }
if (ha->parent) {
atomic_set(&ha->vp_state, VP_FAILED);
fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
}
ha->flags.management_server_logged_in = 0; ha->flags.management_server_logged_in = 0;
ha->link_data_rate = PORT_SPEED_UNKNOWN; ha->link_data_rate = PORT_SPEED_UNKNOWN;
if (ql2xfdmienable) if (ql2xfdmienable)
...@@ -440,6 +449,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -440,6 +449,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
qla2x00_mark_all_devices_lost(ha, 1); qla2x00_mark_all_devices_lost(ha, 1);
} }
if (ha->parent) {
atomic_set(&ha->vp_state, VP_FAILED);
fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
}
set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
ha->operating_mode = LOOP; ha->operating_mode = LOOP;
...@@ -465,6 +479,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -465,6 +479,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
qla2x00_mark_all_devices_lost(ha, 1); qla2x00_mark_all_devices_lost(ha, 1);
} }
if (ha->parent) {
atomic_set(&ha->vp_state, VP_FAILED);
fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
}
if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) {
set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
} }
...@@ -491,6 +510,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -491,6 +510,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
qla2x00_mark_all_devices_lost(ha, 1); qla2x00_mark_all_devices_lost(ha, 1);
} }
if (ha->parent) {
atomic_set(&ha->vp_state, VP_FAILED);
fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED);
}
set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
break; break;
...@@ -530,6 +554,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -530,6 +554,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break; break;
case MBA_RSCN_UPDATE: /* State Change Registration */ case MBA_RSCN_UPDATE: /* State Change Registration */
/* Check if the Vport has issued a SCR */
if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags))
break;
DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
ha->host_no)); ha->host_no));
DEBUG(printk(KERN_INFO DEBUG(printk(KERN_INFO
...@@ -589,6 +617,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) ...@@ -589,6 +617,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
ha->host_no, mb[1], mb[2])); ha->host_no, mb[1], mb[2]));
break; break;
} }
if (!ha->parent && ha->num_vhosts)
qla2x00_alert_all_vps(ha, mb);
} }
static void static void
...@@ -1393,6 +1424,10 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha) ...@@ -1393,6 +1424,10 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
case MS_IOCB_TYPE: case MS_IOCB_TYPE:
qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt); qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
break; break;
case VP_RPT_ID_IOCB_TYPE:
qla24xx_report_id_acquisition(ha,
(struct vp_rpt_id_entry_24xx *)pkt);
break;
default: default:
/* Type Not Supported. */ /* Type Not Supported. */
DEBUG4(printk(KERN_WARNING DEBUG4(printk(KERN_WARNING
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment