diff options
author | Seokmann Ju <seokmann.ju@qlogic.com> | 2007-07-05 16:16:51 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-07-14 20:08:05 -0400 |
commit | 2c3dfe3f6ad8daff5acdb01713e4f2b116e78136 (patch) | |
tree | 8d95e2356c0f5121ceab48ab564d2796b6530d29 | |
parent | 968a5763fb7247feb0e69573a2975a7a0c094267 (diff) |
[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: Seokmann Ju <seokmann.ju@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/scsi/qla2xxx/Makefile | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 164 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.h | 10 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 83 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_fw.h | 91 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 39 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gs.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 166 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 28 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 39 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 396 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 497 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 229 |
13 files changed, 1593 insertions, 154 deletions
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile index 411663af7bb7..71ddb5db4944 100644 --- a/drivers/scsi/qla2xxx/Makefile +++ b/drivers/scsi/qla2xxx/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ | 1 | qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ |
2 | qla_dbg.o qla_sup.o qla_attr.o | 2 | qla_dbg.o qla_sup.o qla_attr.o qla_mid.o |
3 | 3 | ||
4 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o | 4 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 8081b637d97e..b79c4dfc2a9c 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -6,8 +6,11 @@ | |||
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | 8 | ||
9 | #include <linux/kthread.h> | ||
9 | #include <linux/vmalloc.h> | 10 | #include <linux/vmalloc.h> |
10 | 11 | ||
12 | int qla24xx_vport_disable(struct fc_vport *, bool); | ||
13 | |||
11 | /* SYSFS attributes --------------------------------------------------------- */ | 14 | /* SYSFS attributes --------------------------------------------------------- */ |
12 | 15 | ||
13 | static ssize_t | 16 | static ssize_t |
@@ -959,6 +962,122 @@ qla2x00_get_host_port_state(struct Scsi_Host *shost) | |||
959 | fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; | 962 | fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; |
960 | } | 963 | } |
961 | 964 | ||
965 | static int | ||
966 | qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) | ||
967 | { | ||
968 | int ret = 0; | ||
969 | scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; | ||
970 | scsi_qla_host_t *vha; | ||
971 | |||
972 | ret = qla24xx_vport_create_req_sanity_check(fc_vport); | ||
973 | if (ret) { | ||
974 | DEBUG15(printk("qla24xx_vport_create_req_sanity_check failed, " | ||
975 | "status %x\n", ret)); | ||
976 | return (ret); | ||
977 | } | ||
978 | |||
979 | vha = qla24xx_create_vhost(fc_vport); | ||
980 | if (vha == NULL) { | ||
981 | DEBUG15(printk ("qla24xx_create_vhost failed, vha = %p\n", | ||
982 | vha)); | ||
983 | return FC_VPORT_FAILED; | ||
984 | } | ||
985 | if (disable) { | ||
986 | atomic_set(&vha->vp_state, VP_OFFLINE); | ||
987 | fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); | ||
988 | } else | ||
989 | atomic_set(&vha->vp_state, VP_FAILED); | ||
990 | |||
991 | /* ready to create vport */ | ||
992 | qla_printk(KERN_INFO, vha, "VP entry id %d assigned.\n", vha->vp_idx); | ||
993 | |||
994 | /* initialized vport states */ | ||
995 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
996 | vha->vp_err_state= VP_ERR_PORTDWN; | ||
997 | vha->vp_prev_err_state= VP_ERR_UNKWN; | ||
998 | /* Check if physical ha port is Up */ | ||
999 | if (atomic_read(&ha->loop_state) == LOOP_DOWN || | ||
1000 | atomic_read(&ha->loop_state) == LOOP_DEAD) { | ||
1001 | /* Don't retry or attempt login of this virtual port */ | ||
1002 | DEBUG15(printk ("scsi(%ld): pport loop_state is not UP.\n", | ||
1003 | vha->host_no)); | ||
1004 | atomic_set(&vha->loop_state, LOOP_DEAD); | ||
1005 | if (!disable) | ||
1006 | fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN); | ||
1007 | } | ||
1008 | |||
1009 | if (scsi_add_host(vha->host, &fc_vport->dev)) { | ||
1010 | DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n", | ||
1011 | vha->host_no, vha->vp_idx)); | ||
1012 | goto vport_create_failed_2; | ||
1013 | } | ||
1014 | |||
1015 | /* initialize attributes */ | ||
1016 | fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); | ||
1017 | fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); | ||
1018 | fc_host_supported_classes(vha->host) = | ||
1019 | fc_host_supported_classes(ha->host); | ||
1020 | fc_host_supported_speeds(vha->host) = | ||
1021 | fc_host_supported_speeds(ha->host); | ||
1022 | |||
1023 | qla24xx_vport_disable(fc_vport, disable); | ||
1024 | |||
1025 | return 0; | ||
1026 | vport_create_failed_2: | ||
1027 | qla24xx_disable_vp(vha); | ||
1028 | qla24xx_deallocate_vp_id(vha); | ||
1029 | kfree(vha->port_name); | ||
1030 | kfree(vha->node_name); | ||
1031 | scsi_host_put(vha->host); | ||
1032 | return FC_VPORT_FAILED; | ||
1033 | } | ||
1034 | |||
1035 | int | ||
1036 | qla24xx_vport_delete(struct fc_vport *fc_vport) | ||
1037 | { | ||
1038 | scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; | ||
1039 | scsi_qla_host_t *vha = fc_vport->dd_data; | ||
1040 | |||
1041 | qla24xx_disable_vp(vha); | ||
1042 | qla24xx_deallocate_vp_id(vha); | ||
1043 | |||
1044 | down(&ha->vport_sem); | ||
1045 | ha->cur_vport_count--; | ||
1046 | clear_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map); | ||
1047 | up(&ha->vport_sem); | ||
1048 | |||
1049 | kfree(vha->node_name); | ||
1050 | kfree(vha->port_name); | ||
1051 | |||
1052 | if (vha->timer_active) { | ||
1053 | qla2x00_vp_stop_timer(vha); | ||
1054 | DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p " | ||
1055 | "has stopped\n", | ||
1056 | vha->host_no, vha->vp_idx, vha)); | ||
1057 | } | ||
1058 | |||
1059 | fc_remove_host(vha->host); | ||
1060 | |||
1061 | scsi_remove_host(vha->host); | ||
1062 | |||
1063 | scsi_host_put(vha->host); | ||
1064 | |||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | int | ||
1069 | qla24xx_vport_disable(struct fc_vport *fc_vport, bool disable) | ||
1070 | { | ||
1071 | scsi_qla_host_t *vha = fc_vport->dd_data; | ||
1072 | |||
1073 | if (disable) | ||
1074 | qla24xx_disable_vp(vha); | ||
1075 | else | ||
1076 | qla24xx_enable_vp(vha); | ||
1077 | |||
1078 | return 0; | ||
1079 | } | ||
1080 | |||
962 | struct fc_function_template qla2xxx_transport_functions = { | 1081 | struct fc_function_template qla2xxx_transport_functions = { |
963 | 1082 | ||
964 | .show_host_node_name = 1, | 1083 | .show_host_node_name = 1, |
@@ -996,6 +1115,49 @@ struct fc_function_template qla2xxx_transport_functions = { | |||
996 | 1115 | ||
997 | .issue_fc_host_lip = qla2x00_issue_lip, | 1116 | .issue_fc_host_lip = qla2x00_issue_lip, |
998 | .get_fc_host_stats = qla2x00_get_fc_host_stats, | 1117 | .get_fc_host_stats = qla2x00_get_fc_host_stats, |
1118 | |||
1119 | .vport_create = qla24xx_vport_create, | ||
1120 | .vport_disable = qla24xx_vport_disable, | ||
1121 | .vport_delete = qla24xx_vport_delete, | ||
1122 | }; | ||
1123 | |||
1124 | struct fc_function_template qla2xxx_transport_vport_functions = { | ||
1125 | |||
1126 | .show_host_node_name = 1, | ||
1127 | .show_host_port_name = 1, | ||
1128 | .show_host_supported_classes = 1, | ||
1129 | |||
1130 | .get_host_port_id = qla2x00_get_host_port_id, | ||
1131 | .show_host_port_id = 1, | ||
1132 | .get_host_speed = qla2x00_get_host_speed, | ||
1133 | .show_host_speed = 1, | ||
1134 | .get_host_port_type = qla2x00_get_host_port_type, | ||
1135 | .show_host_port_type = 1, | ||
1136 | .get_host_symbolic_name = qla2x00_get_host_symbolic_name, | ||
1137 | .show_host_symbolic_name = 1, | ||
1138 | .set_host_system_hostname = qla2x00_set_host_system_hostname, | ||
1139 | .show_host_system_hostname = 1, | ||
1140 | .get_host_fabric_name = qla2x00_get_host_fabric_name, | ||
1141 | .show_host_fabric_name = 1, | ||
1142 | .get_host_port_state = qla2x00_get_host_port_state, | ||
1143 | .show_host_port_state = 1, | ||
1144 | |||
1145 | .dd_fcrport_size = sizeof(struct fc_port *), | ||
1146 | .show_rport_supported_classes = 1, | ||
1147 | |||
1148 | .get_starget_node_name = qla2x00_get_starget_node_name, | ||
1149 | .show_starget_node_name = 1, | ||
1150 | .get_starget_port_name = qla2x00_get_starget_port_name, | ||
1151 | .show_starget_port_name = 1, | ||
1152 | .get_starget_port_id = qla2x00_get_starget_port_id, | ||
1153 | .show_starget_port_id = 1, | ||
1154 | |||
1155 | .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo, | ||
1156 | .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, | ||
1157 | .show_rport_dev_loss_tmo = 1, | ||
1158 | |||
1159 | .issue_fc_host_lip = qla2x00_issue_lip, | ||
1160 | .get_fc_host_stats = qla2x00_get_fc_host_stats, | ||
999 | }; | 1161 | }; |
1000 | 1162 | ||
1001 | void | 1163 | void |
@@ -1004,4 +1166,6 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha) | |||
1004 | fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name); | 1166 | fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name); |
1005 | fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); | 1167 | fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); |
1006 | fc_host_supported_classes(ha->host) = FC_COS_CLASS3; | 1168 | fc_host_supported_classes(ha->host) = FC_COS_CLASS3; |
1169 | fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC; | ||
1170 | fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count; | ||
1007 | } | 1171 | } |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 5b12278968e0..49dffeb78512 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
@@ -21,6 +21,7 @@ | |||
21 | /* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */ | 21 | /* #define QL_DEBUG_LEVEL_12 */ /* Output IP trace msgs */ |
22 | /* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */ | 22 | /* #define QL_DEBUG_LEVEL_13 */ /* Output fdmi function trace msgs */ |
23 | /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */ | 23 | /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */ |
24 | /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */ | ||
24 | /* | 25 | /* |
25 | * Local Macro Definitions. | 26 | * Local Macro Definitions. |
26 | */ | 27 | */ |
@@ -30,7 +31,8 @@ | |||
30 | defined(QL_DEBUG_LEVEL_7) || defined(QL_DEBUG_LEVEL_8) || \ | 31 | defined(QL_DEBUG_LEVEL_7) || defined(QL_DEBUG_LEVEL_8) || \ |
31 | defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_10) || \ | 32 | defined(QL_DEBUG_LEVEL_9) || defined(QL_DEBUG_LEVEL_10) || \ |
32 | defined(QL_DEBUG_LEVEL_11) || defined(QL_DEBUG_LEVEL_12) || \ | 33 | defined(QL_DEBUG_LEVEL_11) || defined(QL_DEBUG_LEVEL_12) || \ |
33 | defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14) | 34 | defined(QL_DEBUG_LEVEL_13) || defined(QL_DEBUG_LEVEL_14) || \ |
35 | defined(QL_DEBUG_LEVEL_15) | ||
34 | #define QL_DEBUG_ROUTINES | 36 | #define QL_DEBUG_ROUTINES |
35 | #endif | 37 | #endif |
36 | 38 | ||
@@ -125,6 +127,12 @@ | |||
125 | #define DEBUG14(x) do {} while (0) | 127 | #define DEBUG14(x) do {} while (0) |
126 | #endif | 128 | #endif |
127 | 129 | ||
130 | #if defined(QL_DEBUG_LEVEL_15) | ||
131 | #define DEBUG15(x) do {x;} while (0) | ||
132 | #else | ||
133 | #define DEBUG15(x) do {} while (0) | ||
134 | #endif | ||
135 | |||
128 | /* | 136 | /* |
129 | * Firmware Dump structure definition | 137 | * Firmware Dump structure definition |
130 | */ | 138 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index e8948b679f5b..a1ca590ba447 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -1551,6 +1551,9 @@ typedef struct fc_port { | |||
1551 | 1551 | ||
1552 | unsigned long last_queue_full; | 1552 | unsigned long last_queue_full; |
1553 | unsigned long last_ramp_up; | 1553 | unsigned long last_ramp_up; |
1554 | |||
1555 | struct list_head vp_fcport; | ||
1556 | uint16_t vp_idx; | ||
1554 | } fc_port_t; | 1557 | } fc_port_t; |
1555 | 1558 | ||
1556 | /* | 1559 | /* |
@@ -1999,6 +2002,36 @@ struct gid_list_info { | |||
1999 | }; | 2002 | }; |
2000 | #define GID_LIST_SIZE (sizeof(struct gid_list_info) * MAX_FIBRE_DEVICES) | 2003 | #define GID_LIST_SIZE (sizeof(struct gid_list_info) * MAX_FIBRE_DEVICES) |
2001 | 2004 | ||
2005 | /* NPIV */ | ||
2006 | typedef struct vport_info { | ||
2007 | uint8_t port_name[WWN_SIZE]; | ||
2008 | uint8_t node_name[WWN_SIZE]; | ||
2009 | int vp_id; | ||
2010 | uint16_t loop_id; | ||
2011 | unsigned long host_no; | ||
2012 | uint8_t port_id[3]; | ||
2013 | int loop_state; | ||
2014 | } vport_info_t; | ||
2015 | |||
2016 | typedef struct vport_params { | ||
2017 | uint8_t port_name[WWN_SIZE]; | ||
2018 | uint8_t node_name[WWN_SIZE]; | ||
2019 | uint32_t options; | ||
2020 | #define VP_OPTS_RETRY_ENABLE BIT_0 | ||
2021 | #define VP_OPTS_VP_DISABLE BIT_1 | ||
2022 | } vport_params_t; | ||
2023 | |||
2024 | /* NPIV - return codes of VP create and modify */ | ||
2025 | #define VP_RET_CODE_OK 0 | ||
2026 | #define VP_RET_CODE_FATAL 1 | ||
2027 | #define VP_RET_CODE_WRONG_ID 2 | ||
2028 | #define VP_RET_CODE_WWPN 3 | ||
2029 | #define VP_RET_CODE_RESOURCES 4 | ||
2030 | #define VP_RET_CODE_NO_MEM 5 | ||
2031 | #define VP_RET_CODE_NOT_FOUND 6 | ||
2032 | |||
2033 | #define to_qla_parent(x) (((x)->parent) ? (x)->parent : (x)) | ||
2034 | |||
2002 | /* | 2035 | /* |
2003 | * ISP operations | 2036 | * ISP operations |
2004 | */ | 2037 | */ |
@@ -2073,6 +2106,16 @@ struct qla_msix_entry { | |||
2073 | uint16_t msix_entry; | 2106 | uint16_t msix_entry; |
2074 | }; | 2107 | }; |
2075 | 2108 | ||
2109 | #define WATCH_INTERVAL 1 /* number of seconds */ | ||
2110 | |||
2111 | /* NPIV */ | ||
2112 | #define MAX_MULTI_ID_LOOP 126 | ||
2113 | #define MAX_MULTI_ID_FABRIC 64 | ||
2114 | #define MAX_NUM_VPORT_LOOP (MAX_MULTI_ID_LOOP - 1) | ||
2115 | #define MAX_NUM_VPORT_FABRIC (MAX_MULTI_ID_FABRIC - 1) | ||
2116 | #define MAX_NUM_VHBA_LOOP (MAX_MULTI_ID_LOOP - 1) | ||
2117 | #define MAX_NUM_VHBA_FABRIC (MAX_MULTI_ID_FABRIC - 1) | ||
2118 | |||
2076 | /* | 2119 | /* |
2077 | * Linux Host Adapter structure | 2120 | * Linux Host Adapter structure |
2078 | */ | 2121 | */ |
@@ -2108,6 +2151,8 @@ typedef struct scsi_qla_host { | |||
2108 | uint32_t msix_enabled :1; | 2151 | uint32_t msix_enabled :1; |
2109 | uint32_t disable_serdes :1; | 2152 | uint32_t disable_serdes :1; |
2110 | uint32_t gpsc_supported :1; | 2153 | uint32_t gpsc_supported :1; |
2154 | uint32_t vsan_enabled :1; | ||
2155 | uint32_t npiv_supported :1; | ||
2111 | } flags; | 2156 | } flags; |
2112 | 2157 | ||
2113 | atomic_t loop_state; | 2158 | atomic_t loop_state; |
@@ -2147,6 +2192,7 @@ typedef struct scsi_qla_host { | |||
2147 | #define BEACON_BLINK_NEEDED 25 | 2192 | #define BEACON_BLINK_NEEDED 25 |
2148 | #define REGISTER_FDMI_NEEDED 26 | 2193 | #define REGISTER_FDMI_NEEDED 26 |
2149 | #define FCPORT_UPDATE_NEEDED 27 | 2194 | #define FCPORT_UPDATE_NEEDED 27 |
2195 | #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ | ||
2150 | 2196 | ||
2151 | uint32_t device_flags; | 2197 | uint32_t device_flags; |
2152 | #define DFLG_LOCAL_DEVICES BIT_0 | 2198 | #define DFLG_LOCAL_DEVICES BIT_0 |
@@ -2237,6 +2283,11 @@ typedef struct scsi_qla_host { | |||
2237 | 2283 | ||
2238 | /* ISP configuration data. */ | 2284 | /* ISP configuration data. */ |
2239 | uint16_t loop_id; /* Host adapter loop id */ | 2285 | uint16_t loop_id; /* Host adapter loop id */ |
2286 | uint16_t switch_cap; | ||
2287 | #define FLOGI_SEQ_DEL BIT_8 | ||
2288 | #define FLOGI_MID_SUPPORT BIT_10 | ||
2289 | #define FLOGI_VSAN_SUPPORT BIT_12 | ||
2290 | #define FLOGI_SP_SUPPORT BIT_13 | ||
2240 | uint16_t fb_rev; | 2291 | uint16_t fb_rev; |
2241 | 2292 | ||
2242 | port_id_t d_id; /* Host adapter port id */ | 2293 | port_id_t d_id; /* Host adapter port id */ |
@@ -2344,6 +2395,7 @@ typedef struct scsi_qla_host { | |||
2344 | #define MBX_UPDATE_FLASH_ACTIVE 3 | 2395 | #define MBX_UPDATE_FLASH_ACTIVE 3 |
2345 | 2396 | ||
2346 | struct semaphore mbx_cmd_sem; /* Serialialize mbx access */ | 2397 | struct semaphore mbx_cmd_sem; /* Serialialize mbx access */ |
2398 | struct semaphore vport_sem; /* Virtual port synchronization */ | ||
2347 | struct semaphore mbx_intr_sem; /* Used for completion notification */ | 2399 | struct semaphore mbx_intr_sem; /* Used for completion notification */ |
2348 | 2400 | ||
2349 | uint32_t mbx_flags; | 2401 | uint32_t mbx_flags; |
@@ -2428,6 +2480,37 @@ typedef struct scsi_qla_host { | |||
2428 | struct fc_host_statistics fc_host_stat; | 2480 | struct fc_host_statistics fc_host_stat; |
2429 | 2481 | ||
2430 | struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES]; | 2482 | struct qla_msix_entry msix_entries[QLA_MSIX_ENTRIES]; |
2483 | |||
2484 | struct list_head vp_list; /* list of VP */ | ||
2485 | struct fc_vport *fc_vport; /* holds fc_vport * for each vport */ | ||
2486 | uint8_t vp_idx_map[16]; | ||
2487 | uint16_t num_vhosts; /* number of vports created */ | ||
2488 | uint16_t num_vsans; /* number of vsan created */ | ||
2489 | uint16_t vp_idx; /* vport ID */ | ||
2490 | |||
2491 | struct scsi_qla_host *parent; /* holds pport */ | ||
2492 | unsigned long vp_flags; | ||
2493 | struct list_head vp_fcports; /* list of fcports */ | ||
2494 | #define VP_IDX_ACQUIRED 0 /* bit no 0 */ | ||
2495 | #define VP_CREATE_NEEDED 1 | ||
2496 | #define VP_BIND_NEEDED 2 | ||
2497 | #define VP_DELETE_NEEDED 3 | ||
2498 | #define VP_SCR_NEEDED 4 /* State Change Request registration */ | ||
2499 | atomic_t vp_state; | ||
2500 | #define VP_OFFLINE 0 | ||
2501 | #define VP_ACTIVE 1 | ||
2502 | #define VP_FAILED 2 | ||
2503 | // #define VP_DISABLE 3 | ||
2504 | uint16_t vp_err_state; | ||
2505 | uint16_t vp_prev_err_state; | ||
2506 | #define VP_ERR_UNKWN 0 | ||
2507 | #define VP_ERR_PORTDWN 1 | ||
2508 | #define VP_ERR_FAB_UNSUPPORTED 2 | ||
2509 | #define VP_ERR_FAB_NORESOURCES 3 | ||
2510 | #define VP_ERR_FAB_LOGOUT 4 | ||
2511 | #define VP_ERR_ADAP_NORESOURCES 5 | ||
2512 | int max_npiv_vports; /* 63 or 125 per topoloty */ | ||
2513 | int cur_vport_count; | ||
2431 | } scsi_qla_host_t; | 2514 | } scsi_qla_host_t; |
2432 | 2515 | ||
2433 | 2516 | ||
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index a0a722cf4237..63a11fef5d1b 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -69,6 +69,16 @@ struct port_database_24xx { | |||
69 | uint8_t reserved_3[24]; | 69 | uint8_t reserved_3[24]; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | struct vp_database_24xx { | ||
73 | uint16_t vp_status; | ||
74 | uint8_t options; | ||
75 | uint8_t id; | ||
76 | uint8_t port_name[WWN_SIZE]; | ||
77 | uint8_t node_name[WWN_SIZE]; | ||
78 | uint16_t port_id_low; | ||
79 | uint16_t port_id_high; | ||
80 | }; | ||
81 | |||
72 | struct nvram_24xx { | 82 | struct nvram_24xx { |
73 | /* NVRAM header. */ | 83 | /* NVRAM header. */ |
74 | uint8_t id[4]; | 84 | uint8_t id[4]; |
@@ -962,6 +972,25 @@ struct mid_db_24xx { | |||
962 | struct mid_db_entry_24xx entries[MAX_MID_VPS]; | 972 | struct mid_db_entry_24xx entries[MAX_MID_VPS]; |
963 | }; | 973 | }; |
964 | 974 | ||
975 | /* | ||
976 | * Virtual Fabric ID type definition. | ||
977 | */ | ||
978 | typedef struct vf_id { | ||
979 | uint16_t id : 12; | ||
980 | uint16_t priority : 4; | ||
981 | } vf_id_t; | ||
982 | |||
983 | /* | ||
984 | * Virtual Fabric HopCt type definition. | ||
985 | */ | ||
986 | typedef struct vf_hopct { | ||
987 | uint16_t reserved : 8; | ||
988 | uint16_t hopct : 8; | ||
989 | } vf_hopct_t; | ||
990 | |||
991 | /* | ||
992 | * Virtual Port Control IOCB | ||
993 | */ | ||
965 | #define VP_CTRL_IOCB_TYPE 0x30 /* Vitual Port Control entry. */ | 994 | #define VP_CTRL_IOCB_TYPE 0x30 /* Vitual Port Control entry. */ |
966 | struct vp_ctrl_entry_24xx { | 995 | struct vp_ctrl_entry_24xx { |
967 | uint8_t entry_type; /* Entry type. */ | 996 | uint8_t entry_type; /* Entry type. */ |
@@ -974,6 +1003,7 @@ struct vp_ctrl_entry_24xx { | |||
974 | uint16_t vp_idx_failed; | 1003 | uint16_t vp_idx_failed; |
975 | 1004 | ||
976 | uint16_t comp_status; /* Completion status. */ | 1005 | uint16_t comp_status; /* Completion status. */ |
1006 | #define CS_VCE_IOCB_ERROR 0x01 /* Error processing IOCB */ | ||
977 | #define CS_VCE_ACQ_ID_ERROR 0x02 /* Error while acquireing ID. */ | 1007 | #define CS_VCE_ACQ_ID_ERROR 0x02 /* Error while acquireing ID. */ |
978 | #define CS_VCE_BUSY 0x05 /* Firmware not ready to accept cmd. */ | 1008 | #define CS_VCE_BUSY 0x05 /* Firmware not ready to accept cmd. */ |
979 | 1009 | ||
@@ -982,24 +1012,34 @@ struct vp_ctrl_entry_24xx { | |||
982 | #define VCE_COMMAND_DISABLE_VPS 0x08 /* Disable VPs. */ | 1012 | #define VCE_COMMAND_DISABLE_VPS 0x08 /* Disable VPs. */ |
983 | #define VCE_COMMAND_DISABLE_VPS_REINIT 0x09 /* Disable VPs and reinit link. */ | 1013 | #define VCE_COMMAND_DISABLE_VPS_REINIT 0x09 /* Disable VPs and reinit link. */ |
984 | #define VCE_COMMAND_DISABLE_VPS_LOGO 0x0a /* Disable VPs and LOGO ports. */ | 1014 | #define VCE_COMMAND_DISABLE_VPS_LOGO 0x0a /* Disable VPs and LOGO ports. */ |
1015 | #define VCE_COMMAND_DISABLE_VPS_LOGO_ALL 0x0b /* Disable VPs and LOGO ports. */ | ||
985 | 1016 | ||
986 | uint16_t vp_count; | 1017 | uint16_t vp_count; |
987 | 1018 | ||
988 | uint8_t vp_idx_map[16]; | 1019 | uint8_t vp_idx_map[16]; |
989 | 1020 | uint16_t flags; | |
990 | uint8_t reserved_4[32]; | 1021 | struct vf_id id; |
1022 | uint16_t reserved_4; | ||
1023 | struct vf_hopct hopct; | ||
1024 | uint8_t reserved_5[8]; | ||
991 | }; | 1025 | }; |
992 | 1026 | ||
1027 | /* | ||
1028 | * Modify Virtual Port Configuration IOCB | ||
1029 | */ | ||
993 | #define VP_CONFIG_IOCB_TYPE 0x31 /* Vitual Port Config entry. */ | 1030 | #define VP_CONFIG_IOCB_TYPE 0x31 /* Vitual Port Config entry. */ |
994 | struct vp_config_entry_24xx { | 1031 | struct vp_config_entry_24xx { |
995 | uint8_t entry_type; /* Entry type. */ | 1032 | uint8_t entry_type; /* Entry type. */ |
996 | uint8_t entry_count; /* Entry count. */ | 1033 | uint8_t entry_count; /* Entry count. */ |
997 | uint8_t sys_define; /* System defined. */ | 1034 | uint8_t handle_count; |
998 | uint8_t entry_status; /* Entry Status. */ | 1035 | uint8_t entry_status; /* Entry Status. */ |
999 | 1036 | ||
1000 | uint32_t handle; /* System handle. */ | 1037 | uint32_t handle; /* System handle. */ |
1001 | 1038 | ||
1002 | uint16_t reserved_1; | 1039 | uint16_t flags; |
1040 | #define CS_VF_BIND_VPORTS_TO_VF BIT_0 | ||
1041 | #define CS_VF_SET_QOS_OF_VPORTS BIT_1 | ||
1042 | #define CS_VF_SET_HOPS_OF_VPORTS BIT_2 | ||
1003 | 1043 | ||
1004 | uint16_t comp_status; /* Completion status. */ | 1044 | uint16_t comp_status; /* Completion status. */ |
1005 | #define CS_VCT_STS_ERROR 0x01 /* Specified VPs were not disabled. */ | 1045 | #define CS_VCT_STS_ERROR 0x01 /* Specified VPs were not disabled. */ |
@@ -1009,27 +1049,29 @@ struct vp_config_entry_24xx { | |||
1009 | #define CS_VCT_BUSY 0x05 /* Firmware not ready to accept cmd. */ | 1049 | #define CS_VCT_BUSY 0x05 /* Firmware not ready to accept cmd. */ |
1010 | 1050 | ||
1011 | uint8_t command; | 1051 | uint8_t command; |
1012 | #define VCT_COMMAND_MOD_VPS 0x00 /* Enable VPs. */ | 1052 | #define VCT_COMMAND_MOD_VPS 0x00 /* Modify VP configurations. */ |
1013 | #define VCT_COMMAND_MOD_ENABLE_VPS 0x08 /* Disable VPs. */ | 1053 | #define VCT_COMMAND_MOD_ENABLE_VPS 0x01 /* Modify configuration & enable VPs. */ |
1014 | 1054 | ||
1015 | uint8_t vp_count; | 1055 | uint8_t vp_count; |
1016 | 1056 | ||
1017 | uint8_t vp_idx1; | 1057 | uint8_t vp_index1; |
1018 | uint8_t vp_idx2; | 1058 | uint8_t vp_index2; |
1019 | 1059 | ||
1020 | uint8_t options_idx1; | 1060 | uint8_t options_idx1; |
1021 | uint8_t hard_address_idx1; | 1061 | uint8_t hard_address_idx1; |
1022 | uint16_t reserved_2; | 1062 | uint16_t reserved_vp1; |
1023 | uint8_t port_name_idx1[WWN_SIZE]; | 1063 | uint8_t port_name_idx1[WWN_SIZE]; |
1024 | uint8_t node_name_idx1[WWN_SIZE]; | 1064 | uint8_t node_name_idx1[WWN_SIZE]; |
1025 | 1065 | ||
1026 | uint8_t options_idx2; | 1066 | uint8_t options_idx2; |
1027 | uint8_t hard_address_idx2; | 1067 | uint8_t hard_address_idx2; |
1028 | uint16_t reserved_3; | 1068 | uint16_t reserved_vp2; |
1029 | uint8_t port_name_idx2[WWN_SIZE]; | 1069 | uint8_t port_name_idx2[WWN_SIZE]; |
1030 | uint8_t node_name_idx2[WWN_SIZE]; | 1070 | uint8_t node_name_idx2[WWN_SIZE]; |
1031 | 1071 | struct vf_id id; | |
1032 | uint8_t reserved_4[8]; | 1072 | uint16_t reserved_4; |
1073 | struct vf_hopct hopct; | ||
1074 | uint8_t reserved_5; | ||
1033 | }; | 1075 | }; |
1034 | 1076 | ||
1035 | #define VP_RPT_ID_IOCB_TYPE 0x32 /* Report ID Acquisition entry. */ | 1077 | #define VP_RPT_ID_IOCB_TYPE 0x32 /* Report ID Acquisition entry. */ |
@@ -1054,5 +1096,30 @@ struct vp_rpt_id_entry_24xx { | |||
1054 | uint8_t reserved_4[32]; | 1096 | uint8_t reserved_4[32]; |
1055 | }; | 1097 | }; |
1056 | 1098 | ||
1099 | #define VF_EVFP_IOCB_TYPE 0x26 /* Exchange Virtual Fabric Parameters entry. */ | ||
1100 | struct vf_evfp_entry_24xx { | ||
1101 | uint8_t entry_type; /* Entry type. */ | ||
1102 | uint8_t entry_count; /* Entry count. */ | ||
1103 | uint8_t sys_define; /* System defined. */ | ||
1104 | uint8_t entry_status; /* Entry Status. */ | ||
1105 | |||
1106 | uint32_t handle; /* System handle. */ | ||
1107 | uint16_t comp_status; /* Completion status. */ | ||
1108 | uint16_t timeout; /* timeout */ | ||
1109 | uint16_t adim_tagging_mode; | ||
1110 | |||
1111 | uint16_t vfport_id; | ||
1112 | uint32_t exch_addr; | ||
1113 | |||
1114 | uint16_t nport_handle; /* N_PORT handle. */ | ||
1115 | uint16_t control_flags; | ||
1116 | uint32_t io_parameter_0; | ||
1117 | uint32_t io_parameter_1; | ||
1118 | uint32_t tx_address[2]; /* Data segment 0 address. */ | ||
1119 | uint32_t tx_len; /* Data segment 0 length. */ | ||
1120 | uint32_t rx_address[2]; /* Data segment 1 address. */ | ||
1121 | uint32_t rx_len; /* Data segment 1 length. */ | ||
1122 | }; | ||
1123 | |||
1057 | /* END MID Support ***********************************************************/ | 1124 | /* END MID Support ***********************************************************/ |
1058 | #endif | 1125 | #endif |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 74544ae4b0e2..b44eff2803ce 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -62,6 +62,38 @@ extern int ql2xfdmienable; | |||
62 | extern int ql2xallocfwdump; | 62 | extern int ql2xallocfwdump; |
63 | extern int ql2xextended_error_logging; | 63 | extern int ql2xextended_error_logging; |
64 | extern int ql2xqfullrampup; | 64 | extern int ql2xqfullrampup; |
65 | extern int num_hosts; | ||
66 | |||
67 | /* | ||
68 | * Global Functions in qla_mid.c source file. | ||
69 | */ | ||
70 | extern struct scsi_host_template qla2x00_driver_template; | ||
71 | extern struct scsi_host_template qla24xx_driver_template; | ||
72 | extern struct scsi_transport_template *qla2xxx_transport_vport_template; | ||
73 | extern uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); | ||
74 | extern void qla2x00_timer(scsi_qla_host_t *); | ||
75 | extern void qla2x00_start_timer(scsi_qla_host_t *, void *, unsigned long); | ||
76 | extern void qla2x00_stop_timer(scsi_qla_host_t *); | ||
77 | extern uint32_t qla24xx_allocate_vp_id(scsi_qla_host_t *); | ||
78 | extern void qla24xx_deallocate_vp_id(scsi_qla_host_t *); | ||
79 | extern int qla24xx_disable_vp (scsi_qla_host_t *); | ||
80 | extern int qla24xx_enable_vp (scsi_qla_host_t *); | ||
81 | extern void qla2x00_mem_free(scsi_qla_host_t *); | ||
82 | extern int qla24xx_control_vp(scsi_qla_host_t *, int ); | ||
83 | extern int qla24xx_modify_vp_config(scsi_qla_host_t *); | ||
84 | extern int qla2x00_send_change_request(scsi_qla_host_t *, uint16_t, uint16_t); | ||
85 | extern void qla2x00_vp_stop_timer(scsi_qla_host_t *); | ||
86 | extern int qla24xx_configure_vhba (scsi_qla_host_t *); | ||
87 | extern int qla24xx_get_vp_entry(scsi_qla_host_t *, uint16_t, int); | ||
88 | extern int qla24xx_get_vp_database(scsi_qla_host_t *, uint16_t); | ||
89 | extern int qla2x00_do_dpc_vp(scsi_qla_host_t *); | ||
90 | extern void qla24xx_report_id_acquisition(scsi_qla_host_t *, | ||
91 | struct vp_rpt_id_entry_24xx *); | ||
92 | extern scsi_qla_host_t * qla24xx_find_vhost_by_name(scsi_qla_host_t *, | ||
93 | uint8_t *); | ||
94 | extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *); | ||
95 | extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *); | ||
96 | extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *); | ||
65 | 97 | ||
66 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); | 98 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); |
67 | 99 | ||
@@ -77,6 +109,10 @@ extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *); | |||
77 | extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); | 109 | extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *); |
78 | 110 | ||
79 | extern void qla2xxx_wake_dpc(scsi_qla_host_t *); | 111 | extern void qla2xxx_wake_dpc(scsi_qla_host_t *); |
112 | extern void qla2x00_alert_all_vps(scsi_qla_host_t *, uint16_t *); | ||
113 | extern void qla2x00_async_event(scsi_qla_host_t *, uint16_t *); | ||
114 | extern void qla2x00_vp_abort_isp(scsi_qla_host_t *); | ||
115 | extern int qla24xx_vport_delete(struct fc_vport *); | ||
80 | 116 | ||
81 | /* | 117 | /* |
82 | * Global Function Prototypes in qla_iocb.c source file. | 118 | * Global Function Prototypes in qla_iocb.c source file. |
@@ -128,7 +164,7 @@ qla2x00_abort_target(fc_port_t *); | |||
128 | 164 | ||
129 | extern int | 165 | extern int |
130 | qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, | 166 | qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, |
131 | uint8_t *, uint16_t *); | 167 | uint8_t *, uint16_t *, uint16_t *); |
132 | 168 | ||
133 | extern int | 169 | extern int |
134 | qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *); | 170 | qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *); |
@@ -303,6 +339,7 @@ struct class_device_attribute; | |||
303 | extern struct class_device_attribute *qla2x00_host_attrs[]; | 339 | extern struct class_device_attribute *qla2x00_host_attrs[]; |
304 | struct fc_function_template; | 340 | struct fc_function_template; |
305 | extern struct fc_function_template qla2xxx_transport_functions; | 341 | extern struct fc_function_template qla2xxx_transport_functions; |
342 | extern struct fc_function_template qla2xxx_transport_vport_functions; | ||
306 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); | 343 | extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *); |
307 | extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); | 344 | extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *); |
308 | extern void qla2x00_init_host_attr(scsi_qla_host_t *); | 345 | extern void qla2x00_init_host_attr(scsi_qla_host_t *); |
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index ec5b2dd90d6a..a086b3f0df65 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
@@ -88,6 +88,7 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size) | |||
88 | ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | 88 | ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); |
89 | ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | 89 | ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); |
90 | ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; | 90 | ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; |
91 | ct_pkt->vp_index = ha->vp_idx; | ||
91 | 92 | ||
92 | return (ct_pkt); | 93 | return (ct_pkt); |
93 | } | 94 | } |
@@ -1186,6 +1187,7 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size, | |||
1186 | ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | 1187 | ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); |
1187 | ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | 1188 | ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); |
1188 | ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; | 1189 | ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; |
1190 | ct_pkt->vp_index = ha->vp_idx; | ||
1189 | 1191 | ||
1190 | return ct_pkt; | 1192 | return ct_pkt; |
1191 | } | 1193 | } |
@@ -1746,6 +1748,7 @@ qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *ha, uint32_t req_size, | |||
1746 | ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); | 1748 | ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma)); |
1747 | ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); | 1749 | ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma)); |
1748 | ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; | 1750 | ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count; |
1751 | ct_pkt->vp_index = ha->vp_idx; | ||
1749 | 1752 | ||
1750 | return ct_pkt; | 1753 | return ct_pkt; |
1751 | } | 1754 | } |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 2a45aec4ff29..bd95f7dc5cfc 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -899,6 +899,10 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) | |||
899 | &ha->fw_subminor_version, | 899 | &ha->fw_subminor_version, |
900 | &ha->fw_attributes, &ha->fw_memory_size); | 900 | &ha->fw_attributes, &ha->fw_memory_size); |
901 | qla2x00_resize_request_q(ha); | 901 | qla2x00_resize_request_q(ha); |
902 | ha->flags.npiv_supported = 0; | ||
903 | if (IS_QLA24XX(ha) && | ||
904 | (ha->fw_attributes & BIT_2)) | ||
905 | ha->flags.npiv_supported = 1; | ||
902 | 906 | ||
903 | if (ql2xallocfwdump) | 907 | if (ql2xallocfwdump) |
904 | qla2x00_alloc_fw_dump(ha); | 908 | qla2x00_alloc_fw_dump(ha); |
@@ -1101,6 +1105,8 @@ qla2x00_init_rings(scsi_qla_host_t *ha) | |||
1101 | int rval; | 1105 | int rval; |
1102 | unsigned long flags = 0; | 1106 | unsigned long flags = 0; |
1103 | int cnt; | 1107 | int cnt; |
1108 | struct mid_init_cb_24xx *mid_init_cb = | ||
1109 | (struct mid_init_cb_24xx *) ha->init_cb; | ||
1104 | 1110 | ||
1105 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1111 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1106 | 1112 | ||
@@ -1132,6 +1138,10 @@ qla2x00_init_rings(scsi_qla_host_t *ha) | |||
1132 | ha->isp_ops.update_fw_options(ha); | 1138 | ha->isp_ops.update_fw_options(ha); |
1133 | 1139 | ||
1134 | DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); | 1140 | DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); |
1141 | |||
1142 | mid_init_cb->count = MAX_NUM_VPORT_FABRIC; | ||
1143 | ha->max_npiv_vports = MAX_NUM_VPORT_FABRIC; | ||
1144 | |||
1135 | rval = qla2x00_init_firmware(ha, ha->init_cb_size); | 1145 | rval = qla2x00_init_firmware(ha, ha->init_cb_size); |
1136 | if (rval) { | 1146 | if (rval) { |
1137 | DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n", | 1147 | DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n", |
@@ -1263,6 +1273,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) | |||
1263 | int rval; | 1273 | int rval; |
1264 | uint16_t loop_id; | 1274 | uint16_t loop_id; |
1265 | uint16_t topo; | 1275 | uint16_t topo; |
1276 | uint16_t sw_cap; | ||
1266 | uint8_t al_pa; | 1277 | uint8_t al_pa; |
1267 | uint8_t area; | 1278 | uint8_t area; |
1268 | uint8_t domain; | 1279 | uint8_t domain; |
@@ -1270,7 +1281,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) | |||
1270 | 1281 | ||
1271 | /* Get host addresses. */ | 1282 | /* Get host addresses. */ |
1272 | rval = qla2x00_get_adapter_id(ha, | 1283 | rval = qla2x00_get_adapter_id(ha, |
1273 | &loop_id, &al_pa, &area, &domain, &topo); | 1284 | &loop_id, &al_pa, &area, &domain, &topo, &sw_cap); |
1274 | if (rval != QLA_SUCCESS) { | 1285 | if (rval != QLA_SUCCESS) { |
1275 | if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) || | 1286 | if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) || |
1276 | (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) { | 1287 | (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) { |
@@ -1295,6 +1306,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) | |||
1295 | /* initialize */ | 1306 | /* initialize */ |
1296 | ha->min_external_loopid = SNS_FIRST_LOOP_ID; | 1307 | ha->min_external_loopid = SNS_FIRST_LOOP_ID; |
1297 | ha->operating_mode = LOOP; | 1308 | ha->operating_mode = LOOP; |
1309 | ha->switch_cap = 0; | ||
1298 | 1310 | ||
1299 | switch (topo) { | 1311 | switch (topo) { |
1300 | case 0: | 1312 | case 0: |
@@ -1307,6 +1319,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) | |||
1307 | case 1: | 1319 | case 1: |
1308 | DEBUG3(printk("scsi(%ld): HBA in FL topology.\n", | 1320 | DEBUG3(printk("scsi(%ld): HBA in FL topology.\n", |
1309 | ha->host_no)); | 1321 | ha->host_no)); |
1322 | ha->switch_cap = sw_cap; | ||
1310 | ha->current_topology = ISP_CFG_FL; | 1323 | ha->current_topology = ISP_CFG_FL; |
1311 | strcpy(connect_type, "(FL_Port)"); | 1324 | strcpy(connect_type, "(FL_Port)"); |
1312 | break; | 1325 | break; |
@@ -1322,6 +1335,7 @@ qla2x00_configure_hba(scsi_qla_host_t *ha) | |||
1322 | case 3: | 1335 | case 3: |
1323 | DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n", | 1336 | DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n", |
1324 | ha->host_no)); | 1337 | ha->host_no)); |
1338 | ha->switch_cap = sw_cap; | ||
1325 | ha->operating_mode = P2P; | 1339 | ha->operating_mode = P2P; |
1326 | ha->current_topology = ISP_CFG_F; | 1340 | ha->current_topology = ISP_CFG_F; |
1327 | strcpy(connect_type, "(F_Port)"); | 1341 | strcpy(connect_type, "(F_Port)"); |
@@ -1743,7 +1757,6 @@ qla2x00_rport_del(void *data) | |||
1743 | spin_unlock_irqrestore(&fcport->rport_lock, flags); | 1757 | spin_unlock_irqrestore(&fcport->rport_lock, flags); |
1744 | if (rport) | 1758 | if (rport) |
1745 | fc_remote_port_delete(rport); | 1759 | fc_remote_port_delete(rport); |
1746 | |||
1747 | } | 1760 | } |
1748 | 1761 | ||
1749 | /** | 1762 | /** |
@@ -1765,6 +1778,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) | |||
1765 | /* Setup fcport template structure. */ | 1778 | /* Setup fcport template structure. */ |
1766 | memset(fcport, 0, sizeof (fc_port_t)); | 1779 | memset(fcport, 0, sizeof (fc_port_t)); |
1767 | fcport->ha = ha; | 1780 | fcport->ha = ha; |
1781 | fcport->vp_idx = ha->vp_idx; | ||
1768 | fcport->port_type = FCT_UNKNOWN; | 1782 | fcport->port_type = FCT_UNKNOWN; |
1769 | fcport->loop_id = FC_NO_LOOP_ID; | 1783 | fcport->loop_id = FC_NO_LOOP_ID; |
1770 | atomic_set(&fcport->state, FCS_UNCONFIGURED); | 1784 | atomic_set(&fcport->state, FCS_UNCONFIGURED); |
@@ -1911,6 +1925,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
1911 | char *id_iter; | 1925 | char *id_iter; |
1912 | uint16_t loop_id; | 1926 | uint16_t loop_id; |
1913 | uint8_t domain, area, al_pa; | 1927 | uint8_t domain, area, al_pa; |
1928 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
1914 | 1929 | ||
1915 | found_devs = 0; | 1930 | found_devs = 0; |
1916 | new_fcport = NULL; | 1931 | new_fcport = NULL; |
@@ -1942,7 +1957,10 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
1942 | /* | 1957 | /* |
1943 | * Mark local devices that were present with FCF_DEVICE_LOST for now. | 1958 | * Mark local devices that were present with FCF_DEVICE_LOST for now. |
1944 | */ | 1959 | */ |
1945 | list_for_each_entry(fcport, &ha->fcports, list) { | 1960 | list_for_each_entry(fcport, &pha->fcports, list) { |
1961 | if (fcport->vp_idx != ha->vp_idx) | ||
1962 | continue; | ||
1963 | |||
1946 | if (atomic_read(&fcport->state) == FCS_ONLINE && | 1964 | if (atomic_read(&fcport->state) == FCS_ONLINE && |
1947 | fcport->port_type != FCT_BROADCAST && | 1965 | fcport->port_type != FCT_BROADCAST && |
1948 | (fcport->flags & FCF_FABRIC_DEVICE) == 0) { | 1966 | (fcport->flags & FCF_FABRIC_DEVICE) == 0) { |
@@ -1988,6 +2006,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
1988 | new_fcport->d_id.b.area = area; | 2006 | new_fcport->d_id.b.area = area; |
1989 | new_fcport->d_id.b.al_pa = al_pa; | 2007 | new_fcport->d_id.b.al_pa = al_pa; |
1990 | new_fcport->loop_id = loop_id; | 2008 | new_fcport->loop_id = loop_id; |
2009 | new_fcport->vp_idx = ha->vp_idx; | ||
1991 | rval2 = qla2x00_get_port_database(ha, new_fcport, 0); | 2010 | rval2 = qla2x00_get_port_database(ha, new_fcport, 0); |
1992 | if (rval2 != QLA_SUCCESS) { | 2011 | if (rval2 != QLA_SUCCESS) { |
1993 | DEBUG2(printk("scsi(%ld): Failed to retrieve fcport " | 2012 | DEBUG2(printk("scsi(%ld): Failed to retrieve fcport " |
@@ -2003,7 +2022,10 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
2003 | /* Check for matching device in port list. */ | 2022 | /* Check for matching device in port list. */ |
2004 | found = 0; | 2023 | found = 0; |
2005 | fcport = NULL; | 2024 | fcport = NULL; |
2006 | list_for_each_entry(fcport, &ha->fcports, list) { | 2025 | list_for_each_entry(fcport, &pha->fcports, list) { |
2026 | if (fcport->vp_idx != ha->vp_idx) | ||
2027 | continue; | ||
2028 | |||
2007 | if (memcmp(new_fcport->port_name, fcport->port_name, | 2029 | if (memcmp(new_fcport->port_name, fcport->port_name, |
2008 | WWN_SIZE)) | 2030 | WWN_SIZE)) |
2009 | continue; | 2031 | continue; |
@@ -2023,7 +2045,13 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) | |||
2023 | if (!found) { | 2045 | if (!found) { |
2024 | /* New device, add to fcports list. */ | 2046 | /* New device, add to fcports list. */ |
2025 | new_fcport->flags &= ~FCF_PERSISTENT_BOUND; | 2047 | new_fcport->flags &= ~FCF_PERSISTENT_BOUND; |
2026 | list_add_tail(&new_fcport->list, &ha->fcports); | 2048 | if (ha->parent) { |
2049 | new_fcport->ha = ha; | ||
2050 | new_fcport->vp_idx = ha->vp_idx; | ||
2051 | list_add_tail(&new_fcport->vp_fcport, | ||
2052 | &ha->vp_fcports); | ||
2053 | } | ||
2054 | list_add_tail(&new_fcport->list, &pha->fcports); | ||
2027 | 2055 | ||
2028 | /* Allocate a new replacement fcport. */ | 2056 | /* Allocate a new replacement fcport. */ |
2029 | fcport = new_fcport; | 2057 | fcport = new_fcport; |
@@ -2199,11 +2227,13 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
2199 | void | 2227 | void |
2200 | qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) | 2228 | qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) |
2201 | { | 2229 | { |
2230 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
2231 | |||
2202 | fcport->ha = ha; | 2232 | fcport->ha = ha; |
2203 | fcport->login_retry = 0; | 2233 | fcport->login_retry = 0; |
2204 | fcport->port_login_retry_count = ha->port_down_retry_count * | 2234 | fcport->port_login_retry_count = pha->port_down_retry_count * |
2205 | PORT_RETRY_TIME; | 2235 | PORT_RETRY_TIME; |
2206 | atomic_set(&fcport->port_down_timer, ha->port_down_retry_count * | 2236 | atomic_set(&fcport->port_down_timer, pha->port_down_retry_count * |
2207 | PORT_RETRY_TIME); | 2237 | PORT_RETRY_TIME); |
2208 | fcport->flags &= ~FCF_LOGIN_NEEDED; | 2238 | fcport->flags &= ~FCF_LOGIN_NEEDED; |
2209 | 2239 | ||
@@ -2234,6 +2264,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
2234 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | 2264 | uint16_t mb[MAILBOX_REGISTER_COUNT]; |
2235 | uint16_t loop_id; | 2265 | uint16_t loop_id; |
2236 | LIST_HEAD(new_fcports); | 2266 | LIST_HEAD(new_fcports); |
2267 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
2237 | 2268 | ||
2238 | /* If FL port exists, then SNS is present */ | 2269 | /* If FL port exists, then SNS is present */ |
2239 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) | 2270 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) |
@@ -2307,7 +2338,10 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
2307 | * Logout all previous fabric devices marked lost, except | 2338 | * Logout all previous fabric devices marked lost, except |
2308 | * tape devices. | 2339 | * tape devices. |
2309 | */ | 2340 | */ |
2310 | list_for_each_entry(fcport, &ha->fcports, list) { | 2341 | list_for_each_entry(fcport, &pha->fcports, list) { |
2342 | if (fcport->vp_idx !=ha->vp_idx) | ||
2343 | continue; | ||
2344 | |||
2311 | if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) | 2345 | if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) |
2312 | break; | 2346 | break; |
2313 | 2347 | ||
@@ -2332,13 +2366,16 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
2332 | } | 2366 | } |
2333 | 2367 | ||
2334 | /* Starting free loop ID. */ | 2368 | /* Starting free loop ID. */ |
2335 | next_loopid = ha->min_external_loopid; | 2369 | next_loopid = pha->min_external_loopid; |
2336 | 2370 | ||
2337 | /* | 2371 | /* |
2338 | * Scan through our port list and login entries that need to be | 2372 | * Scan through our port list and login entries that need to be |
2339 | * logged in. | 2373 | * logged in. |
2340 | */ | 2374 | */ |
2341 | list_for_each_entry(fcport, &ha->fcports, list) { | 2375 | list_for_each_entry(fcport, &pha->fcports, list) { |
2376 | if (fcport->vp_idx != ha->vp_idx) | ||
2377 | continue; | ||
2378 | |||
2342 | if (atomic_read(&ha->loop_down_timer) || | 2379 | if (atomic_read(&ha->loop_down_timer) || |
2343 | test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) | 2380 | test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) |
2344 | break; | 2381 | break; |
@@ -2380,11 +2417,18 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) | |||
2380 | break; | 2417 | break; |
2381 | } | 2418 | } |
2382 | 2419 | ||
2383 | /* Remove device from the new list and add it to DB */ | ||
2384 | list_move_tail(&fcport->list, &ha->fcports); | ||
2385 | |||
2386 | /* Login and update database */ | 2420 | /* Login and update database */ |
2387 | qla2x00_fabric_dev_login(ha, fcport, &next_loopid); | 2421 | qla2x00_fabric_dev_login(ha, fcport, &next_loopid); |
2422 | |||
2423 | if (ha->parent) { | ||
2424 | fcport->ha = ha; | ||
2425 | fcport->vp_idx = ha->vp_idx; | ||
2426 | list_add_tail(&fcport->vp_fcport, | ||
2427 | &ha->vp_fcports); | ||
2428 | list_move_tail(&fcport->list, | ||
2429 | &ha->parent->fcports); | ||
2430 | } else | ||
2431 | list_move_tail(&fcport->list, &ha->fcports); | ||
2388 | } | 2432 | } |
2389 | } while (0); | 2433 | } while (0); |
2390 | 2434 | ||
@@ -2428,6 +2472,11 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2428 | int swl_idx; | 2472 | int swl_idx; |
2429 | int first_dev, last_dev; | 2473 | int first_dev, last_dev; |
2430 | port_id_t wrap, nxt_d_id; | 2474 | port_id_t wrap, nxt_d_id; |
2475 | int vp_index; | ||
2476 | int empty_vp_index; | ||
2477 | int found_vp; | ||
2478 | scsi_qla_host_t *vha; | ||
2479 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
2431 | 2480 | ||
2432 | rval = QLA_SUCCESS; | 2481 | rval = QLA_SUCCESS; |
2433 | 2482 | ||
@@ -2461,13 +2510,13 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2461 | return (QLA_MEMORY_ALLOC_FAILED); | 2510 | return (QLA_MEMORY_ALLOC_FAILED); |
2462 | } | 2511 | } |
2463 | new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED); | 2512 | new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED); |
2464 | 2513 | new_fcport->vp_idx = ha->vp_idx; | |
2465 | /* Set start port ID scan at adapter ID. */ | 2514 | /* Set start port ID scan at adapter ID. */ |
2466 | first_dev = 1; | 2515 | first_dev = 1; |
2467 | last_dev = 0; | 2516 | last_dev = 0; |
2468 | 2517 | ||
2469 | /* Starting free loop ID. */ | 2518 | /* Starting free loop ID. */ |
2470 | loop_id = ha->min_external_loopid; | 2519 | loop_id = pha->min_external_loopid; |
2471 | for (; loop_id <= ha->last_loop_id; loop_id++) { | 2520 | for (; loop_id <= ha->last_loop_id; loop_id++) { |
2472 | if (qla2x00_is_reserved_id(ha, loop_id)) | 2521 | if (qla2x00_is_reserved_id(ha, loop_id)) |
2473 | continue; | 2522 | continue; |
@@ -2521,10 +2570,42 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2521 | break; | 2570 | break; |
2522 | } | 2571 | } |
2523 | 2572 | ||
2524 | /* Bypass if host adapter. */ | 2573 | /* Bypass if same physical adapter. */ |
2525 | if (new_fcport->d_id.b24 == ha->d_id.b24) | 2574 | if (new_fcport->d_id.b24 == pha->d_id.b24) |
2526 | continue; | 2575 | continue; |
2527 | 2576 | ||
2577 | /* Bypass virtual ports of the same host. */ | ||
2578 | if (pha->num_vhosts) { | ||
2579 | vp_index = find_next_bit( | ||
2580 | (unsigned long *)pha->vp_idx_map, | ||
2581 | MAX_MULTI_ID_FABRIC + 1, 1); | ||
2582 | |||
2583 | for (;vp_index <= MAX_MULTI_ID_FABRIC; | ||
2584 | vp_index = find_next_bit( | ||
2585 | (unsigned long *)pha->vp_idx_map, | ||
2586 | MAX_MULTI_ID_FABRIC + 1, vp_index + 1)) { | ||
2587 | empty_vp_index = 1; | ||
2588 | found_vp = 0; | ||
2589 | list_for_each_entry(vha, &pha->vp_list, | ||
2590 | vp_list) { | ||
2591 | if (vp_index == vha->vp_idx) { | ||
2592 | empty_vp_index = 0; | ||
2593 | found_vp = 1; | ||
2594 | break; | ||
2595 | } | ||
2596 | } | ||
2597 | |||
2598 | if (empty_vp_index) | ||
2599 | continue; | ||
2600 | |||
2601 | if (found_vp && | ||
2602 | new_fcport->d_id.b24 == vha->d_id.b24) | ||
2603 | break; | ||
2604 | } | ||
2605 | if (vp_index <= MAX_MULTI_ID_FABRIC) | ||
2606 | continue; | ||
2607 | } | ||
2608 | |||
2528 | /* Bypass if same domain and area of adapter. */ | 2609 | /* Bypass if same domain and area of adapter. */ |
2529 | if (((new_fcport->d_id.b24 & 0xffff00) == | 2610 | if (((new_fcport->d_id.b24 & 0xffff00) == |
2530 | (ha->d_id.b24 & 0xffff00)) && ha->current_topology == | 2611 | (ha->d_id.b24 & 0xffff00)) && ha->current_topology == |
@@ -2537,7 +2618,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2537 | 2618 | ||
2538 | /* Locate matching device in database. */ | 2619 | /* Locate matching device in database. */ |
2539 | found = 0; | 2620 | found = 0; |
2540 | list_for_each_entry(fcport, &ha->fcports, list) { | 2621 | list_for_each_entry(fcport, &pha->fcports, list) { |
2622 | if (new_fcport->vp_idx != fcport->vp_idx) | ||
2623 | continue; | ||
2541 | if (memcmp(new_fcport->port_name, fcport->port_name, | 2624 | if (memcmp(new_fcport->port_name, fcport->port_name, |
2542 | WWN_SIZE)) | 2625 | WWN_SIZE)) |
2543 | continue; | 2626 | continue; |
@@ -2605,6 +2688,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2605 | } | 2688 | } |
2606 | new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED); | 2689 | new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED); |
2607 | new_fcport->d_id.b24 = nxt_d_id.b24; | 2690 | new_fcport->d_id.b24 = nxt_d_id.b24; |
2691 | new_fcport->vp_idx = ha->vp_idx; | ||
2608 | } | 2692 | } |
2609 | 2693 | ||
2610 | kfree(swl); | 2694 | kfree(swl); |
@@ -2637,6 +2721,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) | |||
2637 | int found; | 2721 | int found; |
2638 | fc_port_t *fcport; | 2722 | fc_port_t *fcport; |
2639 | uint16_t first_loop_id; | 2723 | uint16_t first_loop_id; |
2724 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
2640 | 2725 | ||
2641 | rval = QLA_SUCCESS; | 2726 | rval = QLA_SUCCESS; |
2642 | 2727 | ||
@@ -2663,7 +2748,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev) | |||
2663 | /* Check for loop ID being already in use. */ | 2748 | /* Check for loop ID being already in use. */ |
2664 | found = 0; | 2749 | found = 0; |
2665 | fcport = NULL; | 2750 | fcport = NULL; |
2666 | list_for_each_entry(fcport, &ha->fcports, list) { | 2751 | list_for_each_entry(fcport, &pha->fcports, list) { |
2667 | if (fcport->loop_id == dev->loop_id && fcport != dev) { | 2752 | if (fcport->loop_id == dev->loop_id && fcport != dev) { |
2668 | /* ID possibly in use */ | 2753 | /* ID possibly in use */ |
2669 | found++; | 2754 | found++; |
@@ -2710,6 +2795,7 @@ qla2x00_device_resync(scsi_qla_host_t *ha) | |||
2710 | uint8_t rscn_out_iter; | 2795 | uint8_t rscn_out_iter; |
2711 | uint8_t format; | 2796 | uint8_t format; |
2712 | port_id_t d_id; | 2797 | port_id_t d_id; |
2798 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
2713 | 2799 | ||
2714 | rval = QLA_RSCNS_HANDLED; | 2800 | rval = QLA_RSCNS_HANDLED; |
2715 | 2801 | ||
@@ -2776,7 +2862,10 @@ qla2x00_device_resync(scsi_qla_host_t *ha) | |||
2776 | 2862 | ||
2777 | rval = QLA_SUCCESS; | 2863 | rval = QLA_SUCCESS; |
2778 | 2864 | ||
2779 | list_for_each_entry(fcport, &ha->fcports, list) { | 2865 | list_for_each_entry(fcport, &pha->fcports, list) { |
2866 | if (fcport->vp_idx != ha->vp_idx) | ||
2867 | continue; | ||
2868 | |||
2780 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || | 2869 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || |
2781 | (fcport->d_id.b24 & mask) != d_id.b24 || | 2870 | (fcport->d_id.b24 & mask) != d_id.b24 || |
2782 | fcport->port_type == FCT_BROADCAST) | 2871 | fcport->port_type == FCT_BROADCAST) |
@@ -3940,3 +4029,40 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) | |||
3940 | ret = qla2x00_stop_firmware(ha); | 4029 | ret = qla2x00_stop_firmware(ha); |
3941 | } | 4030 | } |
3942 | } | 4031 | } |
4032 | |||
4033 | int | ||
4034 | qla24xx_configure_vhba(scsi_qla_host_t *ha) | ||
4035 | { | ||
4036 | int rval = QLA_SUCCESS; | ||
4037 | uint16_t mb[MAILBOX_REGISTER_COUNT]; | ||
4038 | |||
4039 | if (!ha->parent) | ||
4040 | return -EINVAL; | ||
4041 | |||
4042 | rval = qla2x00_fw_ready(ha); | ||
4043 | if (rval == QLA_SUCCESS) { | ||
4044 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | ||
4045 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); | ||
4046 | } | ||
4047 | |||
4048 | ha->flags.management_server_logged_in = 0; | ||
4049 | |||
4050 | /* Login to SNS first */ | ||
4051 | qla24xx_login_fabric(ha, NPH_SNS, 0xff, 0xff, 0xfc, | ||
4052 | mb, BIT_1); | ||
4053 | if (mb[0] != MBS_COMMAND_COMPLETE) { | ||
4054 | DEBUG15(qla_printk(KERN_INFO, ha, | ||
4055 | "Failed SNS login: loop_id=%x mb[0]=%x mb[1]=%x " | ||
4056 | "mb[2]=%x mb[6]=%x mb[7]=%x\n", NPH_SNS, | ||
4057 | mb[0], mb[1], mb[2], mb[6], mb[7])); | ||
4058 | return (QLA_FUNCTION_FAILED); | ||
4059 | } | ||
4060 | |||
4061 | atomic_set(&ha->loop_down_timer, 0); | ||
4062 | atomic_set(&ha->loop_state, LOOP_UP); | ||
4063 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); | ||
4064 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); | ||
4065 | rval = qla2x00_loop_resync(ha); | ||
4066 | |||
4067 | return rval; | ||
4068 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index c517a1478e44..c71863ff5489 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -179,7 +179,6 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, | |||
179 | cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; | 179 | cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address; |
180 | 180 | ||
181 | /* Load data segments */ | 181 | /* Load data segments */ |
182 | |||
183 | scsi_for_each_sg(cmd, sg, tot_dsds, i) { | 182 | scsi_for_each_sg(cmd, sg, tot_dsds, i) { |
184 | cont_entry_t *cont_pkt; | 183 | cont_entry_t *cont_pkt; |
185 | 184 | ||
@@ -316,9 +315,14 @@ qla2x00_start_scsi(srb_t *sp) | |||
316 | goto queuing_error; | 315 | goto queuing_error; |
317 | 316 | ||
318 | /* Map the sg table so we have an accurate count of sg entries needed */ | 317 | /* Map the sg table so we have an accurate count of sg entries needed */ |
319 | nseg = scsi_dma_map(cmd); | 318 | if (scsi_sg_count(cmd)) { |
320 | if (nseg < 0) | 319 | nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), |
321 | goto queuing_error; | 320 | scsi_sg_count(cmd), cmd->sc_data_direction); |
321 | if (unlikely(!nseg)) | ||
322 | goto queuing_error; | ||
323 | } else | ||
324 | nseg = 0; | ||
325 | |||
322 | tot_dsds = nseg; | 326 | tot_dsds = nseg; |
323 | 327 | ||
324 | /* Calculate the number of request entries needed. */ | 328 | /* 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 | { | 418 | { |
415 | mrk_entry_t *mrk; | 419 | mrk_entry_t *mrk; |
416 | struct mrk_entry_24xx *mrk24; | 420 | struct mrk_entry_24xx *mrk24; |
421 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
417 | 422 | ||
418 | mrk24 = NULL; | 423 | mrk24 = NULL; |
419 | mrk = (mrk_entry_t *)qla2x00_req_pkt(ha); | 424 | mrk = (mrk_entry_t *)qla2x00_req_pkt(pha); |
420 | if (mrk == NULL) { | 425 | if (mrk == NULL) { |
421 | DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n", | 426 | DEBUG2_3(printk("%s(%ld): failed to allocate Marker IOCB.\n", |
422 | __func__, ha->host_no)); | 427 | __func__, ha->host_no)); |
@@ -433,6 +438,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, | |||
433 | mrk24->lun[1] = LSB(lun); | 438 | mrk24->lun[1] = LSB(lun); |
434 | mrk24->lun[2] = MSB(lun); | 439 | mrk24->lun[2] = MSB(lun); |
435 | host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); | 440 | host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); |
441 | mrk24->vp_index = ha->vp_idx; | ||
436 | } else { | 442 | } else { |
437 | SET_TARGET_ID(ha, mrk->target, loop_id); | 443 | SET_TARGET_ID(ha, mrk->target, loop_id); |
438 | mrk->lun = cpu_to_le16(lun); | 444 | 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 | } | 446 | } |
441 | wmb(); | 447 | wmb(); |
442 | 448 | ||
443 | qla2x00_isp_cmd(ha); | 449 | qla2x00_isp_cmd(pha); |
444 | 450 | ||
445 | return (QLA_SUCCESS); | 451 | return (QLA_SUCCESS); |
446 | } | 452 | } |
@@ -712,9 +718,14 @@ qla24xx_start_scsi(srb_t *sp) | |||
712 | goto queuing_error; | 718 | goto queuing_error; |
713 | 719 | ||
714 | /* Map the sg table so we have an accurate count of sg entries needed */ | 720 | /* Map the sg table so we have an accurate count of sg entries needed */ |
715 | nseg = scsi_dma_map(cmd); | 721 | if (scsi_sg_count(cmd)) { |
716 | if (nseg < 0) | 722 | nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), |
723 | scsi_sg_count(cmd), cmd->sc_data_direction); | ||
724 | if (unlikely(!nseg)) | ||
717 | goto queuing_error; | 725 | goto queuing_error; |
726 | } else | ||
727 | nseg = 0; | ||
728 | |||
718 | tot_dsds = nseg; | 729 | tot_dsds = nseg; |
719 | 730 | ||
720 | req_cnt = qla24xx_calc_iocbs(tot_dsds); | 731 | req_cnt = qla24xx_calc_iocbs(tot_dsds); |
@@ -750,6 +761,7 @@ qla24xx_start_scsi(srb_t *sp) | |||
750 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; | 761 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; |
751 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; | 762 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; |
752 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; | 763 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; |
764 | cmd_pkt->vp_index = sp->fcport->vp_idx; | ||
753 | 765 | ||
754 | int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); | 766 | int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); |
755 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); | 767 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6ce532cdc4c1..0ba4c8d37879 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <scsi/scsi_tcq.h> | 9 | #include <scsi/scsi_tcq.h> |
10 | 10 | ||
11 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); | 11 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); |
12 | static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *); | ||
13 | static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); | 12 | static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); |
14 | static void qla2x00_status_entry(scsi_qla_host_t *, void *); | 13 | static void qla2x00_status_entry(scsi_qla_host_t *, void *); |
15 | static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *); | 14 | 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 | * @ha: SCSI driver HA context | 243 | * @ha: SCSI driver HA context |
245 | * @mb: Mailbox registers (0 - 3) | 244 | * @mb: Mailbox registers (0 - 3) |
246 | */ | 245 | */ |
247 | static void | 246 | void |
248 | qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | 247 | qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) |
249 | { | 248 | { |
250 | #define LS_UNKNOWN 2 | 249 | #define LS_UNKNOWN 2 |
@@ -386,6 +385,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
386 | qla2x00_mark_all_devices_lost(ha, 1); | 385 | qla2x00_mark_all_devices_lost(ha, 1); |
387 | } | 386 | } |
388 | 387 | ||
388 | if (ha->parent) { | ||
389 | atomic_set(&ha->vp_state, VP_FAILED); | ||
390 | fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED); | ||
391 | } | ||
392 | |||
389 | set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); | 393 | set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); |
390 | 394 | ||
391 | ha->flags.management_server_logged_in = 0; | 395 | ha->flags.management_server_logged_in = 0; |
@@ -422,6 +426,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
422 | qla2x00_mark_all_devices_lost(ha, 1); | 426 | qla2x00_mark_all_devices_lost(ha, 1); |
423 | } | 427 | } |
424 | 428 | ||
429 | if (ha->parent) { | ||
430 | atomic_set(&ha->vp_state, VP_FAILED); | ||
431 | fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED); | ||
432 | } | ||
433 | |||
425 | ha->flags.management_server_logged_in = 0; | 434 | ha->flags.management_server_logged_in = 0; |
426 | ha->link_data_rate = PORT_SPEED_UNKNOWN; | 435 | ha->link_data_rate = PORT_SPEED_UNKNOWN; |
427 | if (ql2xfdmienable) | 436 | if (ql2xfdmienable) |
@@ -440,6 +449,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
440 | qla2x00_mark_all_devices_lost(ha, 1); | 449 | qla2x00_mark_all_devices_lost(ha, 1); |
441 | } | 450 | } |
442 | 451 | ||
452 | if (ha->parent) { | ||
453 | atomic_set(&ha->vp_state, VP_FAILED); | ||
454 | fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED); | ||
455 | } | ||
456 | |||
443 | set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 457 | set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
444 | 458 | ||
445 | ha->operating_mode = LOOP; | 459 | ha->operating_mode = LOOP; |
@@ -465,6 +479,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
465 | qla2x00_mark_all_devices_lost(ha, 1); | 479 | qla2x00_mark_all_devices_lost(ha, 1); |
466 | } | 480 | } |
467 | 481 | ||
482 | if (ha->parent) { | ||
483 | atomic_set(&ha->vp_state, VP_FAILED); | ||
484 | fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED); | ||
485 | } | ||
486 | |||
468 | if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { | 487 | if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { |
469 | set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | 488 | set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); |
470 | } | 489 | } |
@@ -491,6 +510,11 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
491 | qla2x00_mark_all_devices_lost(ha, 1); | 510 | qla2x00_mark_all_devices_lost(ha, 1); |
492 | } | 511 | } |
493 | 512 | ||
513 | if (ha->parent) { | ||
514 | atomic_set(&ha->vp_state, VP_FAILED); | ||
515 | fc_vport_set_state(ha->fc_vport, FC_VPORT_FAILED); | ||
516 | } | ||
517 | |||
494 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); | 518 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); |
495 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); | 519 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); |
496 | break; | 520 | break; |
@@ -530,6 +554,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
530 | break; | 554 | break; |
531 | 555 | ||
532 | case MBA_RSCN_UPDATE: /* State Change Registration */ | 556 | case MBA_RSCN_UPDATE: /* State Change Registration */ |
557 | /* Check if the Vport has issued a SCR */ | ||
558 | if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags)) | ||
559 | break; | ||
560 | |||
533 | DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", | 561 | DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n", |
534 | ha->host_no)); | 562 | ha->host_no)); |
535 | DEBUG(printk(KERN_INFO | 563 | DEBUG(printk(KERN_INFO |
@@ -589,6 +617,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
589 | ha->host_no, mb[1], mb[2])); | 617 | ha->host_no, mb[1], mb[2])); |
590 | break; | 618 | break; |
591 | } | 619 | } |
620 | |||
621 | if (!ha->parent && ha->num_vhosts) | ||
622 | qla2x00_alert_all_vps(ha, mb); | ||
592 | } | 623 | } |
593 | 624 | ||
594 | static void | 625 | static void |
@@ -1393,6 +1424,10 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha) | |||
1393 | case MS_IOCB_TYPE: | 1424 | case MS_IOCB_TYPE: |
1394 | qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt); | 1425 | qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt); |
1395 | break; | 1426 | break; |
1427 | case VP_RPT_ID_IOCB_TYPE: | ||
1428 | qla24xx_report_id_acquisition(ha, | ||
1429 | (struct vp_rpt_id_entry_24xx *)pkt); | ||
1430 | break; | ||
1396 | default: | 1431 | default: |
1397 | /* Type Not Supported. */ | 1432 | /* Type Not Supported. */ |
1398 | DEBUG4(printk(KERN_WARNING | 1433 | DEBUG4(printk(KERN_WARNING |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 71e32a248528..2cd0cff25928 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -42,25 +42,29 @@ qla2x00_mbx_sem_timeout(unsigned long data) | |||
42 | * Kernel context. | 42 | * Kernel context. |
43 | */ | 43 | */ |
44 | static int | 44 | static int |
45 | qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp) | 45 | qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) |
46 | { | 46 | { |
47 | int rval; | 47 | int rval; |
48 | unsigned long flags = 0; | 48 | unsigned long flags = 0; |
49 | device_reg_t __iomem *reg = ha->iobase; | 49 | device_reg_t __iomem *reg; |
50 | struct timer_list tmp_intr_timer; | 50 | struct timer_list tmp_intr_timer; |
51 | uint8_t abort_active; | 51 | uint8_t abort_active; |
52 | uint8_t io_lock_on = ha->flags.init_done; | 52 | uint8_t io_lock_on; |
53 | uint16_t command; | 53 | uint16_t command; |
54 | uint16_t *iptr; | 54 | uint16_t *iptr; |
55 | uint16_t __iomem *optr; | 55 | uint16_t __iomem *optr; |
56 | uint32_t cnt; | 56 | uint32_t cnt; |
57 | uint32_t mboxes; | 57 | uint32_t mboxes; |
58 | unsigned long wait_time; | 58 | unsigned long wait_time; |
59 | scsi_qla_host_t *ha = to_qla_parent(pvha); | ||
60 | |||
61 | reg = ha->iobase; | ||
62 | io_lock_on = ha->flags.init_done; | ||
59 | 63 | ||
60 | rval = QLA_SUCCESS; | 64 | rval = QLA_SUCCESS; |
61 | abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 65 | abort_active = test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); |
62 | 66 | ||
63 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | 67 | DEBUG11(printk("%s(%ld): entered.\n", __func__, pvha->host_no)); |
64 | 68 | ||
65 | /* | 69 | /* |
66 | * Wait for active mailbox commands to finish by waiting at most tov | 70 | * Wait for active mailbox commands to finish by waiting at most tov |
@@ -889,7 +893,7 @@ qla2x00_abort_target(fc_port_t *fcport) | |||
889 | */ | 893 | */ |
890 | int | 894 | int |
891 | qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, | 895 | qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, |
892 | uint8_t *area, uint8_t *domain, uint16_t *top) | 896 | uint8_t *area, uint8_t *domain, uint16_t *top, uint16_t *sw_cap) |
893 | { | 897 | { |
894 | int rval; | 898 | int rval; |
895 | mbx_cmd_t mc; | 899 | mbx_cmd_t mc; |
@@ -899,8 +903,9 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, | |||
899 | ha->host_no)); | 903 | ha->host_no)); |
900 | 904 | ||
901 | mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; | 905 | mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; |
906 | mcp->mb[9] = ha->vp_idx; | ||
902 | mcp->out_mb = MBX_0; | 907 | mcp->out_mb = MBX_0; |
903 | mcp->in_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; | 908 | mcp->in_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; |
904 | mcp->tov = 30; | 909 | mcp->tov = 30; |
905 | mcp->flags = 0; | 910 | mcp->flags = 0; |
906 | rval = qla2x00_mailbox_command(ha, mcp); | 911 | rval = qla2x00_mailbox_command(ha, mcp); |
@@ -913,6 +918,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, | |||
913 | *area = MSB(mcp->mb[2]); | 918 | *area = MSB(mcp->mb[2]); |
914 | *domain = LSB(mcp->mb[3]); | 919 | *domain = LSB(mcp->mb[3]); |
915 | *top = mcp->mb[6]; | 920 | *top = mcp->mb[6]; |
921 | *sw_cap = mcp->mb[7]; | ||
916 | 922 | ||
917 | if (rval != QLA_SUCCESS) { | 923 | if (rval != QLA_SUCCESS) { |
918 | /*EMPTY*/ | 924 | /*EMPTY*/ |
@@ -1009,7 +1015,11 @@ qla2x00_init_firmware(scsi_qla_host_t *ha, uint16_t size) | |||
1009 | DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", | 1015 | DEBUG11(printk("qla2x00_init_firmware(%ld): entered.\n", |
1010 | ha->host_no)); | 1016 | ha->host_no)); |
1011 | 1017 | ||
1012 | mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; | 1018 | if (ha->flags.npiv_supported) |
1019 | mcp->mb[0] = MBC_MID_INITIALIZE_FIRMWARE; | ||
1020 | else | ||
1021 | mcp->mb[0] = MBC_INITIALIZE_FIRMWARE; | ||
1022 | |||
1013 | mcp->mb[2] = MSW(ha->init_cb_dma); | 1023 | mcp->mb[2] = MSW(ha->init_cb_dma); |
1014 | mcp->mb[3] = LSW(ha->init_cb_dma); | 1024 | mcp->mb[3] = LSW(ha->init_cb_dma); |
1015 | mcp->mb[4] = 0; | 1025 | mcp->mb[4] = 0; |
@@ -1081,7 +1091,8 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) | |||
1081 | mcp->mb[3] = LSW(pd_dma); | 1091 | mcp->mb[3] = LSW(pd_dma); |
1082 | mcp->mb[6] = MSW(MSD(pd_dma)); | 1092 | mcp->mb[6] = MSW(MSD(pd_dma)); |
1083 | mcp->mb[7] = LSW(MSD(pd_dma)); | 1093 | mcp->mb[7] = LSW(MSD(pd_dma)); |
1084 | mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | 1094 | mcp->mb[9] = ha->vp_idx; |
1095 | mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | ||
1085 | mcp->in_mb = MBX_0; | 1096 | mcp->in_mb = MBX_0; |
1086 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 1097 | if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { |
1087 | mcp->mb[1] = fcport->loop_id; | 1098 | mcp->mb[1] = fcport->loop_id; |
@@ -1259,7 +1270,8 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name, | |||
1259 | ha->host_no)); | 1270 | ha->host_no)); |
1260 | 1271 | ||
1261 | mcp->mb[0] = MBC_GET_PORT_NAME; | 1272 | mcp->mb[0] = MBC_GET_PORT_NAME; |
1262 | mcp->out_mb = MBX_1|MBX_0; | 1273 | mcp->mb[9] = ha->vp_idx; |
1274 | mcp->out_mb = MBX_9|MBX_1|MBX_0; | ||
1263 | if (HAS_EXTENDED_IDS(ha)) { | 1275 | if (HAS_EXTENDED_IDS(ha)) { |
1264 | mcp->mb[1] = loop_id; | 1276 | mcp->mb[1] = loop_id; |
1265 | mcp->mb[10] = opt; | 1277 | mcp->mb[10] = opt; |
@@ -1447,6 +1459,7 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1447 | lg->port_id[0] = al_pa; | 1459 | lg->port_id[0] = al_pa; |
1448 | lg->port_id[1] = area; | 1460 | lg->port_id[1] = area; |
1449 | lg->port_id[2] = domain; | 1461 | lg->port_id[2] = domain; |
1462 | lg->vp_index = cpu_to_le16(ha->vp_idx); | ||
1450 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); | 1463 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); |
1451 | if (rval != QLA_SUCCESS) { | 1464 | if (rval != QLA_SUCCESS) { |
1452 | DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB " | 1465 | DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB " |
@@ -1701,6 +1714,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain, | |||
1701 | lg->port_id[0] = al_pa; | 1714 | lg->port_id[0] = al_pa; |
1702 | lg->port_id[1] = area; | 1715 | lg->port_id[1] = area; |
1703 | lg->port_id[2] = domain; | 1716 | lg->port_id[2] = domain; |
1717 | lg->vp_index = cpu_to_le16(ha->vp_idx); | ||
1704 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); | 1718 | rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0); |
1705 | if (rval != QLA_SUCCESS) { | 1719 | if (rval != QLA_SUCCESS) { |
1706 | DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB " | 1720 | DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB " |
@@ -1863,7 +1877,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, | |||
1863 | mcp->mb[6] = MSW(MSD(id_list_dma)); | 1877 | mcp->mb[6] = MSW(MSD(id_list_dma)); |
1864 | mcp->mb[7] = LSW(MSD(id_list_dma)); | 1878 | mcp->mb[7] = LSW(MSD(id_list_dma)); |
1865 | mcp->mb[8] = 0; | 1879 | mcp->mb[8] = 0; |
1866 | mcp->out_mb |= MBX_8|MBX_7|MBX_6|MBX_3|MBX_2; | 1880 | mcp->mb[9] = ha->vp_idx; |
1881 | mcp->out_mb |= MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2; | ||
1867 | } else { | 1882 | } else { |
1868 | mcp->mb[1] = MSW(id_list_dma); | 1883 | mcp->mb[1] = MSW(id_list_dma); |
1869 | mcp->mb[2] = LSW(id_list_dma); | 1884 | mcp->mb[2] = LSW(id_list_dma); |
@@ -2212,6 +2227,7 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp) | |||
2212 | abt->port_id[0] = fcport->d_id.b.al_pa; | 2227 | abt->port_id[0] = fcport->d_id.b.al_pa; |
2213 | abt->port_id[1] = fcport->d_id.b.area; | 2228 | abt->port_id[1] = fcport->d_id.b.area; |
2214 | abt->port_id[2] = fcport->d_id.b.domain; | 2229 | abt->port_id[2] = fcport->d_id.b.domain; |
2230 | abt->vp_index = fcport->vp_idx; | ||
2215 | rval = qla2x00_issue_iocb(ha, abt, abt_dma, 0); | 2231 | rval = qla2x00_issue_iocb(ha, abt, abt_dma, 0); |
2216 | if (rval != QLA_SUCCESS) { | 2232 | if (rval != QLA_SUCCESS) { |
2217 | DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n", | 2233 | DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n", |
@@ -2249,7 +2265,7 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2249 | int rval; | 2265 | int rval; |
2250 | struct tsk_mgmt_cmd *tsk; | 2266 | struct tsk_mgmt_cmd *tsk; |
2251 | dma_addr_t tsk_dma; | 2267 | dma_addr_t tsk_dma; |
2252 | scsi_qla_host_t *ha; | 2268 | scsi_qla_host_t *ha, *pha; |
2253 | 2269 | ||
2254 | if (fcport == NULL) | 2270 | if (fcport == NULL) |
2255 | return 0; | 2271 | return 0; |
@@ -2257,7 +2273,8 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2257 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no)); | 2273 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no)); |
2258 | 2274 | ||
2259 | ha = fcport->ha; | 2275 | ha = fcport->ha; |
2260 | tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); | 2276 | pha = to_qla_parent(ha); |
2277 | tsk = dma_pool_alloc(pha->s_dma_pool, GFP_KERNEL, &tsk_dma); | ||
2261 | if (tsk == NULL) { | 2278 | if (tsk == NULL) { |
2262 | DEBUG2_3(printk("%s(%ld): failed to allocate Task Management " | 2279 | DEBUG2_3(printk("%s(%ld): failed to allocate Task Management " |
2263 | "IOCB.\n", __func__, ha->host_no)); | 2280 | "IOCB.\n", __func__, ha->host_no)); |
@@ -2273,6 +2290,8 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2273 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; | 2290 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; |
2274 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; | 2291 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; |
2275 | tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; | 2292 | tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; |
2293 | tsk->p.tsk.vp_index = fcport->vp_idx; | ||
2294 | |||
2276 | rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0); | 2295 | rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0); |
2277 | if (rval != QLA_SUCCESS) { | 2296 | if (rval != QLA_SUCCESS) { |
2278 | DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB " | 2297 | DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB " |
@@ -2303,7 +2322,7 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2303 | } | 2322 | } |
2304 | 2323 | ||
2305 | atarget_done: | 2324 | atarget_done: |
2306 | dma_pool_free(ha->s_dma_pool, tsk, tsk_dma); | 2325 | dma_pool_free(pha->s_dma_pool, tsk, tsk_dma); |
2307 | 2326 | ||
2308 | return rval; | 2327 | return rval; |
2309 | } | 2328 | } |
@@ -2610,3 +2629,354 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, | |||
2610 | 2629 | ||
2611 | return rval; | 2630 | return rval; |
2612 | } | 2631 | } |
2632 | |||
2633 | /* | ||
2634 | * qla24xx_get_vp_database | ||
2635 | * Get the VP's database for all configured ports. | ||
2636 | * | ||
2637 | * Input: | ||
2638 | * ha = adapter block pointer. | ||
2639 | * size = size of initialization control block. | ||
2640 | * | ||
2641 | * Returns: | ||
2642 | * qla2x00 local function return status code. | ||
2643 | * | ||
2644 | * Context: | ||
2645 | * Kernel context. | ||
2646 | */ | ||
2647 | int | ||
2648 | qla24xx_get_vp_database(scsi_qla_host_t *ha, uint16_t size) | ||
2649 | { | ||
2650 | int rval; | ||
2651 | mbx_cmd_t mc; | ||
2652 | mbx_cmd_t *mcp = &mc; | ||
2653 | |||
2654 | DEBUG11(printk("scsi(%ld):%s - entered.\n", | ||
2655 | ha->host_no, __func__)); | ||
2656 | |||
2657 | mcp->mb[0] = MBC_MID_GET_VP_DATABASE; | ||
2658 | mcp->mb[2] = MSW(ha->init_cb_dma); | ||
2659 | mcp->mb[3] = LSW(ha->init_cb_dma); | ||
2660 | mcp->mb[4] = 0; | ||
2661 | mcp->mb[5] = 0; | ||
2662 | mcp->mb[6] = MSW(MSD(ha->init_cb_dma)); | ||
2663 | mcp->mb[7] = LSW(MSD(ha->init_cb_dma)); | ||
2664 | mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | ||
2665 | mcp->in_mb = MBX_1|MBX_0; | ||
2666 | mcp->buf_size = size; | ||
2667 | mcp->flags = MBX_DMA_OUT; | ||
2668 | mcp->tov = MBX_TOV_SECONDS; | ||
2669 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2670 | |||
2671 | if (rval != QLA_SUCCESS) { | ||
2672 | /*EMPTY*/ | ||
2673 | DEBUG2_3_11(printk("%s(%ld): failed=%x " | ||
2674 | "mb0=%x.\n", | ||
2675 | __func__, ha->host_no, rval, mcp->mb[0])); | ||
2676 | } else { | ||
2677 | /*EMPTY*/ | ||
2678 | DEBUG11(printk("%s(%ld): done.\n", | ||
2679 | __func__, ha->host_no)); | ||
2680 | } | ||
2681 | |||
2682 | return rval; | ||
2683 | } | ||
2684 | |||
2685 | int | ||
2686 | qla24xx_get_vp_entry(scsi_qla_host_t *ha, uint16_t size, int vp_id) | ||
2687 | { | ||
2688 | int rval; | ||
2689 | mbx_cmd_t mc; | ||
2690 | mbx_cmd_t *mcp = &mc; | ||
2691 | |||
2692 | DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); | ||
2693 | |||
2694 | mcp->mb[0] = MBC_MID_GET_VP_ENTRY; | ||
2695 | mcp->mb[2] = MSW(ha->init_cb_dma); | ||
2696 | mcp->mb[3] = LSW(ha->init_cb_dma); | ||
2697 | mcp->mb[4] = 0; | ||
2698 | mcp->mb[5] = 0; | ||
2699 | mcp->mb[6] = MSW(MSD(ha->init_cb_dma)); | ||
2700 | mcp->mb[7] = LSW(MSD(ha->init_cb_dma)); | ||
2701 | mcp->mb[9] = vp_id; | ||
2702 | mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; | ||
2703 | mcp->in_mb = MBX_0; | ||
2704 | mcp->buf_size = size; | ||
2705 | mcp->flags = MBX_DMA_OUT; | ||
2706 | mcp->tov = 30; | ||
2707 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2708 | |||
2709 | if (rval != QLA_SUCCESS) { | ||
2710 | /*EMPTY*/ | ||
2711 | DEBUG2_3_11(printk("qla24xx_get_vp_entry(%ld): failed=%x " | ||
2712 | "mb0=%x.\n", | ||
2713 | ha->host_no, rval, mcp->mb[0])); | ||
2714 | } else { | ||
2715 | /*EMPTY*/ | ||
2716 | DEBUG11(printk("qla24xx_get_vp_entry(%ld): done.\n", | ||
2717 | ha->host_no)); | ||
2718 | } | ||
2719 | |||
2720 | return rval; | ||
2721 | } | ||
2722 | |||
2723 | void | ||
2724 | qla24xx_report_id_acquisition(scsi_qla_host_t *ha, | ||
2725 | struct vp_rpt_id_entry_24xx *rptid_entry) | ||
2726 | { | ||
2727 | uint8_t vp_idx; | ||
2728 | scsi_qla_host_t *vha; | ||
2729 | |||
2730 | if (rptid_entry->entry_status != 0) | ||
2731 | return; | ||
2732 | if (rptid_entry->entry_status != __constant_cpu_to_le16(CS_COMPLETE)) | ||
2733 | return; | ||
2734 | |||
2735 | if (rptid_entry->format == 0) { | ||
2736 | DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d," | ||
2737 | " number of VPs acquired %d\n", __func__, ha->host_no, | ||
2738 | MSB(rptid_entry->vp_count), LSB(rptid_entry->vp_count))); | ||
2739 | DEBUG15(printk("%s primary port id %02x%02x%02x\n", __func__, | ||
2740 | rptid_entry->port_id[2], rptid_entry->port_id[1], | ||
2741 | rptid_entry->port_id[0])); | ||
2742 | } else if (rptid_entry->format == 1) { | ||
2743 | vp_idx = LSB(rptid_entry->vp_idx); | ||
2744 | DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled " | ||
2745 | "- status %d - " | ||
2746 | "with port id %02x%02x%02x\n",__func__,ha->host_no, | ||
2747 | vp_idx, MSB(rptid_entry->vp_idx), | ||
2748 | rptid_entry->port_id[2], rptid_entry->port_id[1], | ||
2749 | rptid_entry->port_id[0])); | ||
2750 | if (vp_idx == 0) | ||
2751 | return; | ||
2752 | |||
2753 | if (MSB(rptid_entry->vp_idx) == 1) | ||
2754 | return; | ||
2755 | |||
2756 | list_for_each_entry(vha, &ha->vp_list, vp_list) | ||
2757 | if (vp_idx == vha->vp_idx) | ||
2758 | break; | ||
2759 | |||
2760 | if (!vha) | ||
2761 | return; | ||
2762 | |||
2763 | vha->d_id.b.domain = rptid_entry->port_id[2]; | ||
2764 | vha->d_id.b.area = rptid_entry->port_id[1]; | ||
2765 | vha->d_id.b.al_pa = rptid_entry->port_id[0]; | ||
2766 | |||
2767 | /* | ||
2768 | * Cannot configure here as we are still sitting on the | ||
2769 | * response queue. Handle it in dpc context. | ||
2770 | */ | ||
2771 | set_bit(VP_IDX_ACQUIRED, &vha->vp_flags); | ||
2772 | set_bit(VP_DPC_NEEDED, &ha->dpc_flags); | ||
2773 | |||
2774 | wake_up_process(ha->dpc_thread); | ||
2775 | } | ||
2776 | } | ||
2777 | |||
2778 | /* | ||
2779 | * qla24xx_modify_vp_config | ||
2780 | * Change VP configuration for vha | ||
2781 | * | ||
2782 | * Input: | ||
2783 | * vha = adapter block pointer. | ||
2784 | * | ||
2785 | * Returns: | ||
2786 | * qla2xxx local function return status code. | ||
2787 | * | ||
2788 | * Context: | ||
2789 | * Kernel context. | ||
2790 | */ | ||
2791 | int | ||
2792 | qla24xx_modify_vp_config(scsi_qla_host_t *vha) | ||
2793 | { | ||
2794 | int rval; | ||
2795 | struct vp_config_entry_24xx *vpmod; | ||
2796 | dma_addr_t vpmod_dma; | ||
2797 | scsi_qla_host_t *pha; | ||
2798 | |||
2799 | /* This can be called by the parent */ | ||
2800 | pha = to_qla_parent(vha); | ||
2801 | |||
2802 | vpmod = dma_pool_alloc(pha->s_dma_pool, GFP_KERNEL, &vpmod_dma); | ||
2803 | if (!vpmod) { | ||
2804 | DEBUG2_3(printk("%s(%ld): failed to allocate Modify VP " | ||
2805 | "IOCB.\n", __func__, pha->host_no)); | ||
2806 | return QLA_MEMORY_ALLOC_FAILED; | ||
2807 | } | ||
2808 | |||
2809 | memset(vpmod, 0, sizeof(struct vp_config_entry_24xx)); | ||
2810 | vpmod->entry_type = VP_CONFIG_IOCB_TYPE; | ||
2811 | vpmod->entry_count = 1; | ||
2812 | vpmod->command = VCT_COMMAND_MOD_ENABLE_VPS; | ||
2813 | vpmod->vp_count = 1; | ||
2814 | vpmod->vp_index1 = vha->vp_idx; | ||
2815 | vpmod->options_idx1 = BIT_3|BIT_4|BIT_5; | ||
2816 | memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE); | ||
2817 | memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE); | ||
2818 | vpmod->entry_count = 1; | ||
2819 | |||
2820 | rval = qla2x00_issue_iocb(pha, vpmod, vpmod_dma, 0); | ||
2821 | if (rval != QLA_SUCCESS) { | ||
2822 | DEBUG2_3_11(printk("%s(%ld): failed to issue VP config IOCB" | ||
2823 | "(%x).\n", __func__, pha->host_no, rval)); | ||
2824 | } else if (vpmod->comp_status != 0) { | ||
2825 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2826 | "-- error status (%x).\n", __func__, pha->host_no, | ||
2827 | vpmod->comp_status)); | ||
2828 | rval = QLA_FUNCTION_FAILED; | ||
2829 | } else if (vpmod->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | ||
2830 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2831 | "-- completion status (%x).\n", __func__, pha->host_no, | ||
2832 | le16_to_cpu(vpmod->comp_status))); | ||
2833 | rval = QLA_FUNCTION_FAILED; | ||
2834 | } else { | ||
2835 | /* EMPTY */ | ||
2836 | DEBUG11(printk("%s(%ld): done.\n", __func__, pha->host_no)); | ||
2837 | fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING); | ||
2838 | } | ||
2839 | dma_pool_free(pha->s_dma_pool, vpmod, vpmod_dma); | ||
2840 | |||
2841 | return rval; | ||
2842 | } | ||
2843 | |||
2844 | /* | ||
2845 | * qla24xx_control_vp | ||
2846 | * Enable a virtual port for given host | ||
2847 | * | ||
2848 | * Input: | ||
2849 | * ha = adapter block pointer. | ||
2850 | * vhba = virtual adapter (unused) | ||
2851 | * index = index number for enabled VP | ||
2852 | * | ||
2853 | * Returns: | ||
2854 | * qla2xxx local function return status code. | ||
2855 | * | ||
2856 | * Context: | ||
2857 | * Kernel context. | ||
2858 | */ | ||
2859 | int | ||
2860 | qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) | ||
2861 | { | ||
2862 | int rval; | ||
2863 | int map, pos; | ||
2864 | struct vp_ctrl_entry_24xx *vce; | ||
2865 | dma_addr_t vce_dma; | ||
2866 | scsi_qla_host_t *ha = vha->parent; | ||
2867 | int vp_index = vha->vp_idx; | ||
2868 | |||
2869 | DEBUG11(printk("%s(%ld): entered. Enabling index %d\n", __func__, | ||
2870 | ha->host_no, vp_index)); | ||
2871 | |||
2872 | if (vp_index == 0 || vp_index >= MAX_MULTI_ID_LOOP) | ||
2873 | return QLA_PARAMETER_ERROR; | ||
2874 | |||
2875 | vce = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vce_dma); | ||
2876 | if (!vce) { | ||
2877 | DEBUG2_3(printk("%s(%ld): " | ||
2878 | "failed to allocate VP Control IOCB.\n", __func__, | ||
2879 | ha->host_no)); | ||
2880 | return QLA_MEMORY_ALLOC_FAILED; | ||
2881 | } | ||
2882 | memset(vce, 0, sizeof(struct vp_ctrl_entry_24xx)); | ||
2883 | |||
2884 | vce->entry_type = VP_CTRL_IOCB_TYPE; | ||
2885 | vce->entry_count = 1; | ||
2886 | vce->command = cpu_to_le16(cmd); | ||
2887 | vce->vp_count = __constant_cpu_to_le16(1); | ||
2888 | |||
2889 | /* index map in firmware starts with 1; decrement index | ||
2890 | * this is ok as we never use index 0 | ||
2891 | */ | ||
2892 | map = (vp_index - 1) / 8; | ||
2893 | pos = (vp_index - 1) & 7; | ||
2894 | down(&ha->vport_sem); | ||
2895 | vce->vp_idx_map[map] |= 1 << pos; | ||
2896 | up(&ha->vport_sem); | ||
2897 | |||
2898 | rval = qla2x00_issue_iocb(ha, vce, vce_dma, 0); | ||
2899 | if (rval != QLA_SUCCESS) { | ||
2900 | DEBUG2_3_11(printk("%s(%ld): failed to issue VP control IOCB" | ||
2901 | "(%x).\n", __func__, ha->host_no, rval)); | ||
2902 | printk("%s(%ld): failed to issue VP control IOCB" | ||
2903 | "(%x).\n", __func__, ha->host_no, rval); | ||
2904 | } else if (vce->entry_status != 0) { | ||
2905 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2906 | "-- error status (%x).\n", __func__, ha->host_no, | ||
2907 | vce->entry_status)); | ||
2908 | printk("%s(%ld): failed to complete IOCB " | ||
2909 | "-- error status (%x).\n", __func__, ha->host_no, | ||
2910 | vce->entry_status); | ||
2911 | rval = QLA_FUNCTION_FAILED; | ||
2912 | } else if (vce->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | ||
2913 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | ||
2914 | "-- completion status (%x).\n", __func__, ha->host_no, | ||
2915 | le16_to_cpu(vce->comp_status))); | ||
2916 | printk("%s(%ld): failed to complete IOCB " | ||
2917 | "-- completion status (%x).\n", __func__, ha->host_no, | ||
2918 | le16_to_cpu(vce->comp_status)); | ||
2919 | rval = QLA_FUNCTION_FAILED; | ||
2920 | } else { | ||
2921 | DEBUG2(printk("%s(%ld): done.\n", __func__, ha->host_no)); | ||
2922 | } | ||
2923 | |||
2924 | dma_pool_free(ha->s_dma_pool, vce, vce_dma); | ||
2925 | |||
2926 | return rval; | ||
2927 | } | ||
2928 | |||
2929 | /* | ||
2930 | * qla2x00_send_change_request | ||
2931 | * Receive or disable RSCN request from fabric controller | ||
2932 | * | ||
2933 | * Input: | ||
2934 | * ha = adapter block pointer | ||
2935 | * format = registration format: | ||
2936 | * 0 - Reserved | ||
2937 | * 1 - Fabric detected registration | ||
2938 | * 2 - N_port detected registration | ||
2939 | * 3 - Full registration | ||
2940 | * FF - clear registration | ||
2941 | * vp_idx = Virtual port index | ||
2942 | * | ||
2943 | * Returns: | ||
2944 | * qla2x00 local function return status code. | ||
2945 | * | ||
2946 | * Context: | ||
2947 | * Kernel Context | ||
2948 | */ | ||
2949 | |||
2950 | int | ||
2951 | qla2x00_send_change_request(scsi_qla_host_t *ha, uint16_t format, | ||
2952 | uint16_t vp_idx) | ||
2953 | { | ||
2954 | int rval; | ||
2955 | mbx_cmd_t mc; | ||
2956 | mbx_cmd_t *mcp = &mc; | ||
2957 | |||
2958 | /* | ||
2959 | * This command is implicitly executed by firmware during login for the | ||
2960 | * physical hosts | ||
2961 | */ | ||
2962 | if (vp_idx == 0) | ||
2963 | return QLA_FUNCTION_FAILED; | ||
2964 | |||
2965 | mcp->mb[0] = MBC_SEND_CHANGE_REQUEST; | ||
2966 | mcp->mb[1] = format; | ||
2967 | mcp->mb[9] = vp_idx; | ||
2968 | mcp->out_mb = MBX_9|MBX_1|MBX_0; | ||
2969 | mcp->in_mb = MBX_0|MBX_1; | ||
2970 | mcp->tov = MBX_TOV_SECONDS; | ||
2971 | mcp->flags = 0; | ||
2972 | rval = qla2x00_mailbox_command(ha, mcp); | ||
2973 | |||
2974 | if (rval == QLA_SUCCESS) { | ||
2975 | if (mcp->mb[0] != MBS_COMMAND_COMPLETE) { | ||
2976 | rval = BIT_1; | ||
2977 | } | ||
2978 | } else | ||
2979 | rval = BIT_1; | ||
2980 | |||
2981 | return rval; | ||
2982 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c new file mode 100644 index 000000000000..54dc415d8b53 --- /dev/null +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -0,0 +1,497 @@ | |||
1 | /* | ||
2 | * QLOGIC LINUX SOFTWARE | ||
3 | * | ||
4 | * QLogic ISP2x00 device driver for Linux 2.6.x | ||
5 | * Copyright (C) 2003-2005 QLogic Corporation | ||
6 | * (www.qlogic.com) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2, or (at your option) any | ||
11 | * later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | #include "qla_def.h" | ||
20 | |||
21 | #include <linux/version.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/vmalloc.h> | ||
24 | #include <linux/smp_lock.h> | ||
25 | #include <linux/list.h> | ||
26 | |||
27 | #include <scsi/scsi_tcq.h> | ||
28 | #include <scsi/scsicam.h> | ||
29 | #include <linux/delay.h> | ||
30 | |||
31 | void qla2x00_vp_stop_timer(scsi_qla_host_t *); | ||
32 | |||
33 | void | ||
34 | qla2x00_vp_stop_timer(scsi_qla_host_t *vha) | ||
35 | { | ||
36 | if (vha->parent && vha->timer_active) { | ||
37 | del_timer_sync(&vha->timer); | ||
38 | vha->timer_active = 0; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | uint32_t | ||
43 | qla24xx_allocate_vp_id(scsi_qla_host_t *vha) | ||
44 | { | ||
45 | uint32_t vp_id; | ||
46 | scsi_qla_host_t *ha = vha->parent; | ||
47 | |||
48 | /* Find an empty slot and assign an vp_id */ | ||
49 | down(&ha->vport_sem); | ||
50 | vp_id = find_first_zero_bit((unsigned long *)ha->vp_idx_map, | ||
51 | MAX_MULTI_ID_FABRIC); | ||
52 | if (vp_id > MAX_MULTI_ID_FABRIC) { | ||
53 | DEBUG15(printk ("vp_id %d is bigger than MAX_MULTI_ID_FABRID\n", | ||
54 | vp_id)); | ||
55 | up(&ha->vport_sem); | ||
56 | return vp_id; | ||
57 | } | ||
58 | |||
59 | set_bit(vp_id, (unsigned long *)ha->vp_idx_map); | ||
60 | ha->num_vhosts++; | ||
61 | vha->vp_idx = vp_id; | ||
62 | list_add_tail(&vha->vp_list, &ha->vp_list); | ||
63 | up(&ha->vport_sem); | ||
64 | return vp_id; | ||
65 | } | ||
66 | |||
67 | void | ||
68 | qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) | ||
69 | { | ||
70 | uint16_t vp_id; | ||
71 | scsi_qla_host_t *ha = vha->parent; | ||
72 | |||
73 | down(&ha->vport_sem); | ||
74 | vp_id = vha->vp_idx; | ||
75 | ha->num_vhosts--; | ||
76 | clear_bit(vp_id, (unsigned long *)ha->vp_idx_map); | ||
77 | list_del(&vha->vp_list); | ||
78 | up(&ha->vport_sem); | ||
79 | } | ||
80 | |||
81 | scsi_qla_host_t * | ||
82 | qla24xx_find_vhost_by_name(scsi_qla_host_t *ha, uint8_t *port_name) | ||
83 | { | ||
84 | scsi_qla_host_t *vha; | ||
85 | |||
86 | /* Locate matching device in database. */ | ||
87 | list_for_each_entry(vha, &ha->vp_list, vp_list) { | ||
88 | if (!memcmp(port_name, vha->port_name, WWN_SIZE)) | ||
89 | return vha; | ||
90 | } | ||
91 | return NULL; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * qla2x00_mark_vp_devices_dead | ||
96 | * Updates fcport state when device goes offline. | ||
97 | * | ||
98 | * Input: | ||
99 | * ha = adapter block pointer. | ||
100 | * fcport = port structure pointer. | ||
101 | * | ||
102 | * Return: | ||
103 | * None. | ||
104 | * | ||
105 | * Context: | ||
106 | */ | ||
107 | void | ||
108 | qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) | ||
109 | { | ||
110 | fc_port_t *fcport; | ||
111 | scsi_qla_host_t *pha = to_qla_parent(vha); | ||
112 | |||
113 | list_for_each_entry(fcport, &pha->fcports, list) { | ||
114 | if (fcport->vp_idx != vha->vp_idx) | ||
115 | continue; | ||
116 | |||
117 | DEBUG15(printk("scsi(%ld): Marking port dead, " | ||
118 | "loop_id=0x%04x :%x\n", | ||
119 | vha->host_no, fcport->loop_id, fcport->vp_idx)); | ||
120 | |||
121 | atomic_set(&fcport->state, FCS_DEVICE_DEAD); | ||
122 | qla2x00_mark_device_lost(vha, fcport, 0, 0); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | int | ||
127 | qla24xx_disable_vp(scsi_qla_host_t *vha) | ||
128 | { | ||
129 | int ret; | ||
130 | |||
131 | ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); | ||
132 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
133 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | ||
134 | |||
135 | /* Delete all vp's fcports from parent's list */ | ||
136 | qla2x00_mark_vp_devices_dead(vha); | ||
137 | atomic_set(&vha->vp_state, VP_FAILED); | ||
138 | vha->flags.management_server_logged_in = 0; | ||
139 | if (ret == QLA_SUCCESS) { | ||
140 | fc_vport_set_state(vha->fc_vport, FC_VPORT_DISABLED); | ||
141 | } else { | ||
142 | fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED); | ||
143 | return -1; | ||
144 | } | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | int | ||
149 | qla24xx_enable_vp(scsi_qla_host_t *vha) | ||
150 | { | ||
151 | int ret; | ||
152 | scsi_qla_host_t *ha = vha->parent; | ||
153 | |||
154 | /* Check if physical ha port is Up */ | ||
155 | if (atomic_read(&ha->loop_state) == LOOP_DOWN || | ||
156 | atomic_read(&ha->loop_state) == LOOP_DEAD ) { | ||
157 | vha->vp_err_state = VP_ERR_PORTDWN; | ||
158 | fc_vport_set_state(vha->fc_vport, FC_VPORT_LINKDOWN); | ||
159 | goto enable_failed; | ||
160 | } | ||
161 | |||
162 | /* Initialize the new vport unless it is a persistent port */ | ||
163 | down(&ha->vport_sem); | ||
164 | ret = qla24xx_modify_vp_config(vha); | ||
165 | up(&ha->vport_sem); | ||
166 | |||
167 | if (ret != QLA_SUCCESS) { | ||
168 | fc_vport_set_state(vha->fc_vport, FC_VPORT_FAILED); | ||
169 | goto enable_failed; | ||
170 | } | ||
171 | |||
172 | DEBUG15(qla_printk(KERN_INFO, ha, | ||
173 | "Virtual port with id: %d - Enabled\n", vha->vp_idx)); | ||
174 | return 0; | ||
175 | |||
176 | enable_failed: | ||
177 | DEBUG15(qla_printk(KERN_INFO, ha, | ||
178 | "Virtual port with id: %d - Disabled\n", vha->vp_idx)); | ||
179 | return 1; | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * qla24xx_modify_vport() - Modifies the virtual fabric port's configuration | ||
184 | * @ha: HA context | ||
185 | * @vp: pointer to buffer of virtual port parameters. | ||
186 | * @ret_code: return error code: | ||
187 | * | ||
188 | * Returns the virtual port id, or MAX_VSAN_ID, if couldn't create. | ||
189 | */ | ||
190 | uint32_t | ||
191 | qla24xx_modify_vhba(scsi_qla_host_t *ha, vport_params_t *vp, uint32_t *vp_id) | ||
192 | { | ||
193 | scsi_qla_host_t *vha; | ||
194 | |||
195 | vha = qla24xx_find_vhost_by_name(ha, vp->port_name); | ||
196 | if (!vha) { | ||
197 | *vp_id = MAX_NUM_VPORT_LOOP; | ||
198 | return VP_RET_CODE_WWPN; | ||
199 | } | ||
200 | |||
201 | if (qla24xx_enable_vp(vha)) { | ||
202 | scsi_host_put(vha->host); | ||
203 | qla2x00_mem_free(vha); | ||
204 | *vp_id = MAX_NUM_VPORT_LOOP; | ||
205 | return VP_RET_CODE_RESOURCES; | ||
206 | } | ||
207 | |||
208 | *vp_id = vha->vp_idx; | ||
209 | return VP_RET_CODE_OK; | ||
210 | } | ||
211 | |||
212 | void | ||
213 | qla24xx_configure_vp(scsi_qla_host_t *vha) | ||
214 | { | ||
215 | struct fc_vport *fc_vport; | ||
216 | int ret; | ||
217 | |||
218 | fc_vport = vha->fc_vport; | ||
219 | |||
220 | DEBUG15(printk("scsi(%ld): %s: change request #3 for this host.\n", | ||
221 | vha->host_no, __func__)); | ||
222 | ret = qla2x00_send_change_request(vha, 0x3, vha->vp_idx); | ||
223 | if (ret != QLA_SUCCESS) { | ||
224 | DEBUG15(qla_printk(KERN_ERR, vha, "Failed to enable receiving" | ||
225 | " of RSCN requests: 0x%x\n", ret)); | ||
226 | return; | ||
227 | } else { | ||
228 | /* Corresponds to SCR enabled */ | ||
229 | clear_bit(VP_SCR_NEEDED, &vha->vp_flags); | ||
230 | } | ||
231 | |||
232 | vha->flags.online = 1; | ||
233 | if (qla24xx_configure_vhba(vha)) | ||
234 | return; | ||
235 | |||
236 | atomic_set(&vha->vp_state, VP_ACTIVE); | ||
237 | fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); | ||
238 | } | ||
239 | |||
240 | void | ||
241 | qla2x00_alert_all_vps(scsi_qla_host_t *ha, uint16_t *mb) | ||
242 | { | ||
243 | int i, vp_idx_matched; | ||
244 | scsi_qla_host_t *vha; | ||
245 | |||
246 | if (ha->parent) | ||
247 | return; | ||
248 | |||
249 | i = find_next_bit((unsigned long *)ha->vp_idx_map, | ||
250 | MAX_MULTI_ID_FABRIC + 1, 1); | ||
251 | for (;i <= MAX_MULTI_ID_FABRIC; | ||
252 | i = find_next_bit((unsigned long *)ha->vp_idx_map, | ||
253 | MAX_MULTI_ID_FABRIC + 1, i + 1)) { | ||
254 | vp_idx_matched = 0; | ||
255 | |||
256 | list_for_each_entry(vha, &ha->vp_list, vp_list) { | ||
257 | if (i == vha->vp_idx) { | ||
258 | vp_idx_matched = 1; | ||
259 | break; | ||
260 | } | ||
261 | } | ||
262 | |||
263 | if (vp_idx_matched) { | ||
264 | switch (mb[0]) { | ||
265 | case MBA_LIP_OCCURRED: | ||
266 | case MBA_LOOP_UP: | ||
267 | case MBA_LOOP_DOWN: | ||
268 | case MBA_LIP_RESET: | ||
269 | case MBA_POINT_TO_POINT: | ||
270 | case MBA_CHG_IN_CONNECTION: | ||
271 | case MBA_PORT_UPDATE: | ||
272 | case MBA_RSCN_UPDATE: | ||
273 | DEBUG15(printk("scsi(%ld)%s: Async_event for" | ||
274 | " VP[%d], mb = 0x%x, vha=%p\n", | ||
275 | vha->host_no, __func__,i, *mb, vha)); | ||
276 | qla2x00_async_event(vha, mb); | ||
277 | break; | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | void | ||
284 | qla2x00_vp_abort_isp(scsi_qla_host_t *vha) | ||
285 | { | ||
286 | /* | ||
287 | * Physical port will do most of the abort and recovery work. We can | ||
288 | * just treat it as a loop down | ||
289 | */ | ||
290 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | ||
291 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
292 | qla2x00_mark_all_devices_lost(vha, 0); | ||
293 | } else { | ||
294 | if (!atomic_read(&vha->loop_down_timer)) | ||
295 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | ||
296 | } | ||
297 | |||
298 | DEBUG15(printk("scsi(%ld): Scheduling enable of Vport %d...\n", | ||
299 | vha->host_no, vha->vp_idx)); | ||
300 | qla24xx_enable_vp(vha); | ||
301 | } | ||
302 | |||
303 | int | ||
304 | qla2x00_do_dpc_vp(scsi_qla_host_t *vha) | ||
305 | { | ||
306 | if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { | ||
307 | /* VP acquired. complete port configuration */ | ||
308 | qla24xx_configure_vp(vha); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | if (test_and_clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) | ||
313 | qla2x00_vp_abort_isp(vha); | ||
314 | |||
315 | if (test_and_clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) && | ||
316 | (!(test_and_set_bit(RESET_ACTIVE, &vha->dpc_flags)))) { | ||
317 | clear_bit(RESET_ACTIVE, &vha->dpc_flags); | ||
318 | } | ||
319 | |||
320 | if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) { | ||
321 | if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))) { | ||
322 | qla2x00_loop_resync(vha); | ||
323 | clear_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags); | ||
324 | } | ||
325 | } | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | void | ||
331 | qla2x00_do_dpc_all_vps(scsi_qla_host_t *ha) | ||
332 | { | ||
333 | int ret; | ||
334 | int i, vp_idx_matched; | ||
335 | scsi_qla_host_t *vha; | ||
336 | |||
337 | if (ha->parent) | ||
338 | return; | ||
339 | if (list_empty(&ha->vp_list)) | ||
340 | return; | ||
341 | |||
342 | clear_bit(VP_DPC_NEEDED, &ha->dpc_flags); | ||
343 | |||
344 | i = find_next_bit((unsigned long *)ha->vp_idx_map, | ||
345 | MAX_MULTI_ID_FABRIC + 1, 1); | ||
346 | for (;i <= MAX_MULTI_ID_FABRIC; | ||
347 | i = find_next_bit((unsigned long *)ha->vp_idx_map, | ||
348 | MAX_MULTI_ID_FABRIC + 1, i + 1)) { | ||
349 | vp_idx_matched = 0; | ||
350 | |||
351 | list_for_each_entry(vha, &ha->vp_list, vp_list) { | ||
352 | if (i == vha->vp_idx) { | ||
353 | vp_idx_matched = 1; | ||
354 | break; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | if (vp_idx_matched) | ||
359 | ret = qla2x00_do_dpc_vp(vha); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | int | ||
364 | qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport) | ||
365 | { | ||
366 | scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; | ||
367 | scsi_qla_host_t *vha; | ||
368 | uint8_t port_name[WWN_SIZE]; | ||
369 | |||
370 | if (fc_vport->roles != FC_PORT_ROLE_FCP_INITIATOR) | ||
371 | return VPCERR_UNSUPPORTED; | ||
372 | |||
373 | /* Check up the F/W and H/W support NPIV */ | ||
374 | if (!ha->flags.npiv_supported) | ||
375 | return VPCERR_UNSUPPORTED; | ||
376 | |||
377 | /* Check up whether npiv supported switch presented */ | ||
378 | if (!(ha->switch_cap & FLOGI_MID_SUPPORT)) | ||
379 | return VPCERR_NO_FABRIC_SUPP; | ||
380 | |||
381 | /* Check up unique WWPN */ | ||
382 | u64_to_wwn(fc_vport->port_name, port_name); | ||
383 | vha = qla24xx_find_vhost_by_name(ha, port_name); | ||
384 | if (vha) | ||
385 | return VPCERR_BAD_WWN; | ||
386 | |||
387 | /* Check up max-npiv-supports */ | ||
388 | if (ha->num_vhosts > ha->max_npiv_vports) { | ||
389 | DEBUG15(printk("scsi(%ld): num_vhosts %d is bigger than " | ||
390 | "max_npv_vports %d.\n", ha->host_no, | ||
391 | (uint16_t) ha->num_vhosts, (int) ha->max_npiv_vports)); | ||
392 | return VPCERR_UNSUPPORTED; | ||
393 | } | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | scsi_qla_host_t * | ||
398 | qla24xx_create_vhost(struct fc_vport *fc_vport) | ||
399 | { | ||
400 | scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; | ||
401 | scsi_qla_host_t *vha; | ||
402 | struct Scsi_Host *host; | ||
403 | |||
404 | host = scsi_host_alloc(&qla24xx_driver_template, | ||
405 | sizeof(scsi_qla_host_t)); | ||
406 | if (!host) { | ||
407 | printk(KERN_WARNING | ||
408 | "qla2xxx: scsi_host_alloc() failed for vport\n"); | ||
409 | return(NULL); | ||
410 | } | ||
411 | |||
412 | vha = (scsi_qla_host_t *)host->hostdata; | ||
413 | |||
414 | /* clone the parent hba */ | ||
415 | memcpy(vha, ha, sizeof (scsi_qla_host_t)); | ||
416 | |||
417 | fc_vport->dd_data = vha; | ||
418 | |||
419 | vha->node_name = kmalloc(WWN_SIZE * sizeof(char), GFP_KERNEL); | ||
420 | if (!vha->node_name) | ||
421 | goto create_vhost_failed_1; | ||
422 | |||
423 | vha->port_name = kmalloc(WWN_SIZE * sizeof(char), GFP_KERNEL); | ||
424 | if (!vha->port_name) | ||
425 | goto create_vhost_failed_2; | ||
426 | |||
427 | /* New host info */ | ||
428 | u64_to_wwn(fc_vport->node_name, vha->node_name); | ||
429 | u64_to_wwn(fc_vport->port_name, vha->port_name); | ||
430 | |||
431 | vha->host = host; | ||
432 | vha->host_no = host->host_no; | ||
433 | vha->parent = ha; | ||
434 | vha->fc_vport = fc_vport; | ||
435 | vha->device_flags = 0; | ||
436 | vha->instance = num_hosts; | ||
437 | vha->vp_idx = qla24xx_allocate_vp_id(vha); | ||
438 | if (vha->vp_idx > ha->max_npiv_vports) { | ||
439 | DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n", | ||
440 | vha->host_no)); | ||
441 | goto create_vhost_failed_3; | ||
442 | } | ||
443 | vha->mgmt_svr_loop_id = 10 + vha->vp_idx; | ||
444 | |||
445 | init_MUTEX(&vha->mbx_cmd_sem); | ||
446 | init_MUTEX_LOCKED(&vha->mbx_intr_sem); | ||
447 | |||
448 | INIT_LIST_HEAD(&vha->list); | ||
449 | INIT_LIST_HEAD(&vha->fcports); | ||
450 | INIT_LIST_HEAD(&vha->vp_fcports); | ||
451 | |||
452 | vha->dpc_flags = 0L; | ||
453 | set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); | ||
454 | set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); | ||
455 | |||
456 | /* | ||
457 | * To fix the issue of processing a parent's RSCN for the vport before | ||
458 | * its SCR is complete. | ||
459 | */ | ||
460 | set_bit(VP_SCR_NEEDED, &vha->vp_flags); | ||
461 | atomic_set(&vha->loop_state, LOOP_DOWN); | ||
462 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | ||
463 | |||
464 | qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL); | ||
465 | |||
466 | host->can_queue = vha->request_q_length + 128; | ||
467 | host->this_id = 255; | ||
468 | host->cmd_per_lun = 3; | ||
469 | host->max_cmd_len = MAX_CMDSZ; | ||
470 | host->max_channel = MAX_BUSES - 1; | ||
471 | host->max_lun = MAX_LUNS; | ||
472 | host->unique_id = vha->instance; | ||
473 | host->max_id = MAX_TARGETS_2200; | ||
474 | host->transportt = qla2xxx_transport_vport_template; | ||
475 | |||
476 | DEBUG15(printk("DEBUG: detect vport hba %ld at address = %p\n", | ||
477 | vha->host_no, vha)); | ||
478 | |||
479 | vha->flags.init_done = 1; | ||
480 | num_hosts++; | ||
481 | |||
482 | down(&ha->vport_sem); | ||
483 | set_bit(vha->vp_idx, (unsigned long *)ha->vp_idx_map); | ||
484 | ha->cur_vport_count++; | ||
485 | up(&ha->vport_sem); | ||
486 | |||
487 | return vha; | ||
488 | |||
489 | create_vhost_failed_3: | ||
490 | kfree(vha->port_name); | ||
491 | |||
492 | create_vhost_failed_2: | ||
493 | kfree(vha->node_name); | ||
494 | |||
495 | create_vhost_failed_1: | ||
496 | return NULL; | ||
497 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 18baa5bf69c4..a8658b1d284f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -29,8 +29,7 @@ static struct kmem_cache *srb_cachep; | |||
29 | /* | 29 | /* |
30 | * Ioctl related information. | 30 | * Ioctl related information. |
31 | */ | 31 | */ |
32 | static int num_hosts; | 32 | int num_hosts; |
33 | |||
34 | int ql2xlogintimeout = 20; | 33 | int ql2xlogintimeout = 20; |
35 | module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); | 34 | module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); |
36 | MODULE_PARM_DESC(ql2xlogintimeout, | 35 | MODULE_PARM_DESC(ql2xlogintimeout, |
@@ -112,7 +111,7 @@ static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); | |||
112 | static int qla2x00_change_queue_depth(struct scsi_device *, int); | 111 | static int qla2x00_change_queue_depth(struct scsi_device *, int); |
113 | static int qla2x00_change_queue_type(struct scsi_device *, int); | 112 | static int qla2x00_change_queue_type(struct scsi_device *, int); |
114 | 113 | ||
115 | static struct scsi_host_template qla2x00_driver_template = { | 114 | struct scsi_host_template qla2x00_driver_template = { |
116 | .module = THIS_MODULE, | 115 | .module = THIS_MODULE, |
117 | .name = QLA2XXX_DRIVER_NAME, | 116 | .name = QLA2XXX_DRIVER_NAME, |
118 | .queuecommand = qla2x00_queuecommand, | 117 | .queuecommand = qla2x00_queuecommand, |
@@ -143,7 +142,7 @@ static struct scsi_host_template qla2x00_driver_template = { | |||
143 | .shost_attrs = qla2x00_host_attrs, | 142 | .shost_attrs = qla2x00_host_attrs, |
144 | }; | 143 | }; |
145 | 144 | ||
146 | static struct scsi_host_template qla24xx_driver_template = { | 145 | struct scsi_host_template qla24xx_driver_template = { |
147 | .module = THIS_MODULE, | 146 | .module = THIS_MODULE, |
148 | .name = QLA2XXX_DRIVER_NAME, | 147 | .name = QLA2XXX_DRIVER_NAME, |
149 | .queuecommand = qla24xx_queuecommand, | 148 | .queuecommand = qla24xx_queuecommand, |
@@ -171,21 +170,21 @@ static struct scsi_host_template qla24xx_driver_template = { | |||
171 | }; | 170 | }; |
172 | 171 | ||
173 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; | 172 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; |
173 | struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; | ||
174 | 174 | ||
175 | /* TODO Convert to inlines | 175 | /* TODO Convert to inlines |
176 | * | 176 | * |
177 | * Timer routines | 177 | * Timer routines |
178 | */ | 178 | */ |
179 | #define WATCH_INTERVAL 1 /* number of seconds */ | ||
180 | 179 | ||
181 | static void qla2x00_timer(scsi_qla_host_t *); | 180 | void qla2x00_timer(scsi_qla_host_t *); |
182 | 181 | ||
183 | static __inline__ void qla2x00_start_timer(scsi_qla_host_t *, | 182 | __inline__ void qla2x00_start_timer(scsi_qla_host_t *, |
184 | void *, unsigned long); | 183 | void *, unsigned long); |
185 | static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long); | 184 | static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long); |
186 | static __inline__ void qla2x00_stop_timer(scsi_qla_host_t *); | 185 | __inline__ void qla2x00_stop_timer(scsi_qla_host_t *); |
187 | 186 | ||
188 | static inline void | 187 | __inline__ void |
189 | qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval) | 188 | qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval) |
190 | { | 189 | { |
191 | init_timer(&ha->timer); | 190 | init_timer(&ha->timer); |
@@ -202,7 +201,7 @@ qla2x00_restart_timer(scsi_qla_host_t *ha, unsigned long interval) | |||
202 | mod_timer(&ha->timer, jiffies + interval * HZ); | 201 | mod_timer(&ha->timer, jiffies + interval * HZ); |
203 | } | 202 | } |
204 | 203 | ||
205 | static __inline__ void | 204 | __inline__ void |
206 | qla2x00_stop_timer(scsi_qla_host_t *ha) | 205 | qla2x00_stop_timer(scsi_qla_host_t *ha) |
207 | { | 206 | { |
208 | del_timer_sync(&ha->timer); | 207 | del_timer_sync(&ha->timer); |
@@ -213,8 +212,8 @@ static int qla2x00_do_dpc(void *data); | |||
213 | 212 | ||
214 | static void qla2x00_rst_aen(scsi_qla_host_t *); | 213 | static void qla2x00_rst_aen(scsi_qla_host_t *); |
215 | 214 | ||
216 | static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); | 215 | uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); |
217 | static void qla2x00_mem_free(scsi_qla_host_t *ha); | 216 | void qla2x00_mem_free(scsi_qla_host_t *ha); |
218 | static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); | 217 | static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); |
219 | static void qla2x00_free_sp_pool(scsi_qla_host_t *ha); | 218 | static void qla2x00_free_sp_pool(scsi_qla_host_t *ha); |
220 | static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); | 219 | static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); |
@@ -438,6 +437,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
438 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); | 437 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); |
439 | srb_t *sp; | 438 | srb_t *sp; |
440 | int rval; | 439 | int rval; |
440 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
441 | 441 | ||
442 | rval = fc_remote_port_chkready(rport); | 442 | rval = fc_remote_port_chkready(rport); |
443 | if (rval) { | 443 | if (rval) { |
@@ -453,7 +453,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
453 | 453 | ||
454 | if (atomic_read(&fcport->state) != FCS_ONLINE) { | 454 | if (atomic_read(&fcport->state) != FCS_ONLINE) { |
455 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || | 455 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || |
456 | atomic_read(&ha->loop_state) == LOOP_DEAD) { | 456 | atomic_read(&pha->loop_state) == LOOP_DEAD) { |
457 | cmd->result = DID_NO_CONNECT << 16; | 457 | cmd->result = DID_NO_CONNECT << 16; |
458 | goto qc24_fail_command; | 458 | goto qc24_fail_command; |
459 | } | 459 | } |
@@ -462,7 +462,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
462 | 462 | ||
463 | spin_unlock_irq(ha->host->host_lock); | 463 | spin_unlock_irq(ha->host->host_lock); |
464 | 464 | ||
465 | sp = qla2x00_get_new_sp(ha, fcport, cmd, done); | 465 | sp = qla2x00_get_new_sp(pha, fcport, cmd, done); |
466 | if (!sp) | 466 | if (!sp) |
467 | goto qc24_host_busy_lock; | 467 | goto qc24_host_busy_lock; |
468 | 468 | ||
@@ -475,8 +475,8 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
475 | return 0; | 475 | return 0; |
476 | 476 | ||
477 | qc24_host_busy_free_sp: | 477 | qc24_host_busy_free_sp: |
478 | qla2x00_sp_free_dma(ha, sp); | 478 | qla2x00_sp_free_dma(pha, sp); |
479 | mempool_free(sp, ha->srb_mempool); | 479 | mempool_free(sp, pha->srb_mempool); |
480 | 480 | ||
481 | qc24_host_busy_lock: | 481 | qc24_host_busy_lock: |
482 | spin_lock_irq(ha->host->host_lock); | 482 | spin_lock_irq(ha->host->host_lock); |
@@ -548,16 +548,17 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha) | |||
548 | { | 548 | { |
549 | int return_status; | 549 | int return_status; |
550 | unsigned long wait_online; | 550 | unsigned long wait_online; |
551 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
551 | 552 | ||
552 | wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ); | 553 | wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ); |
553 | while (((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || | 554 | while (((test_bit(ISP_ABORT_NEEDED, &pha->dpc_flags)) || |
554 | test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || | 555 | test_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags) || |
555 | test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) || | 556 | test_bit(ISP_ABORT_RETRY, &pha->dpc_flags) || |
556 | ha->dpc_active) && time_before(jiffies, wait_online)) { | 557 | pha->dpc_active) && time_before(jiffies, wait_online)) { |
557 | 558 | ||
558 | msleep(1000); | 559 | msleep(1000); |
559 | } | 560 | } |
560 | if (ha->flags.online) | 561 | if (pha->flags.online) |
561 | return_status = QLA_SUCCESS; | 562 | return_status = QLA_SUCCESS; |
562 | else | 563 | else |
563 | return_status = QLA_FUNCTION_FAILED; | 564 | return_status = QLA_FUNCTION_FAILED; |
@@ -588,14 +589,15 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) | |||
588 | { | 589 | { |
589 | int return_status = QLA_SUCCESS; | 590 | int return_status = QLA_SUCCESS; |
590 | unsigned long loop_timeout ; | 591 | unsigned long loop_timeout ; |
592 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
591 | 593 | ||
592 | /* wait for 5 min at the max for loop to be ready */ | 594 | /* wait for 5 min at the max for loop to be ready */ |
593 | loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ); | 595 | loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ); |
594 | 596 | ||
595 | while ((!atomic_read(&ha->loop_down_timer) && | 597 | while ((!atomic_read(&pha->loop_down_timer) && |
596 | atomic_read(&ha->loop_state) == LOOP_DOWN) || | 598 | atomic_read(&pha->loop_state) == LOOP_DOWN) || |
597 | atomic_read(&ha->loop_state) != LOOP_READY) { | 599 | atomic_read(&pha->loop_state) != LOOP_READY) { |
598 | if (atomic_read(&ha->loop_state) == LOOP_DEAD) { | 600 | if (atomic_read(&pha->loop_state) == LOOP_DEAD) { |
599 | return_status = QLA_FUNCTION_FAILED; | 601 | return_status = QLA_FUNCTION_FAILED; |
600 | break; | 602 | break; |
601 | } | 603 | } |
@@ -650,6 +652,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
650 | unsigned long serial; | 652 | unsigned long serial; |
651 | unsigned long flags; | 653 | unsigned long flags; |
652 | int wait = 0; | 654 | int wait = 0; |
655 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
653 | 656 | ||
654 | qla2x00_block_error_handler(cmd); | 657 | qla2x00_block_error_handler(cmd); |
655 | 658 | ||
@@ -663,9 +666,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
663 | serial = cmd->serial_number; | 666 | serial = cmd->serial_number; |
664 | 667 | ||
665 | /* Check active list for command command. */ | 668 | /* Check active list for command command. */ |
666 | spin_lock_irqsave(&ha->hardware_lock, flags); | 669 | spin_lock_irqsave(&pha->hardware_lock, flags); |
667 | for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { | 670 | for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { |
668 | sp = ha->outstanding_cmds[i]; | 671 | sp = pha->outstanding_cmds[i]; |
669 | 672 | ||
670 | if (sp == NULL) | 673 | if (sp == NULL) |
671 | continue; | 674 | continue; |
@@ -677,7 +680,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
677 | __func__, ha->host_no, sp, serial)); | 680 | __func__, ha->host_no, sp, serial)); |
678 | DEBUG3(qla2x00_print_scsi_cmd(cmd)); | 681 | DEBUG3(qla2x00_print_scsi_cmd(cmd)); |
679 | 682 | ||
680 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 683 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
681 | if (ha->isp_ops.abort_command(ha, sp)) { | 684 | if (ha->isp_ops.abort_command(ha, sp)) { |
682 | DEBUG2(printk("%s(%ld): abort_command " | 685 | DEBUG2(printk("%s(%ld): abort_command " |
683 | "mbx failed.\n", __func__, ha->host_no)); | 686 | "mbx failed.\n", __func__, ha->host_no)); |
@@ -686,11 +689,11 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
686 | "mbx success.\n", __func__, ha->host_no)); | 689 | "mbx success.\n", __func__, ha->host_no)); |
687 | wait = 1; | 690 | wait = 1; |
688 | } | 691 | } |
689 | spin_lock_irqsave(&ha->hardware_lock, flags); | 692 | spin_lock_irqsave(&pha->hardware_lock, flags); |
690 | 693 | ||
691 | break; | 694 | break; |
692 | } | 695 | } |
693 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 696 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
694 | 697 | ||
695 | /* Wait for the command to be returned. */ | 698 | /* Wait for the command to be returned. */ |
696 | if (wait) { | 699 | if (wait) { |
@@ -731,6 +734,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) | |||
731 | srb_t *sp; | 734 | srb_t *sp; |
732 | struct scsi_cmnd *cmd; | 735 | struct scsi_cmnd *cmd; |
733 | unsigned long flags; | 736 | unsigned long flags; |
737 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
734 | 738 | ||
735 | status = 0; | 739 | status = 0; |
736 | 740 | ||
@@ -739,19 +743,20 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) | |||
739 | * array | 743 | * array |
740 | */ | 744 | */ |
741 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { | 745 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { |
742 | spin_lock_irqsave(&ha->hardware_lock, flags); | 746 | spin_lock_irqsave(&pha->hardware_lock, flags); |
743 | sp = ha->outstanding_cmds[cnt]; | 747 | sp = pha->outstanding_cmds[cnt]; |
744 | if (sp) { | 748 | if (sp) { |
745 | cmd = sp->cmd; | 749 | cmd = sp->cmd; |
746 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 750 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
747 | if (cmd->device->id == t) { | 751 | if (cmd->device->id == t && |
752 | ha->vp_idx == sp->ha->vp_idx) { | ||
748 | if (!qla2x00_eh_wait_on_command(ha, cmd)) { | 753 | if (!qla2x00_eh_wait_on_command(ha, cmd)) { |
749 | status = 1; | 754 | status = 1; |
750 | break; | 755 | break; |
751 | } | 756 | } |
752 | } | 757 | } |
753 | } else { | 758 | } else { |
754 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 759 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
755 | } | 760 | } |
756 | } | 761 | } |
757 | return (status); | 762 | return (status); |
@@ -782,14 +787,12 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
782 | { | 787 | { |
783 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 788 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
784 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 789 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
785 | int ret; | 790 | int ret = FAILED; |
786 | unsigned int id, lun; | 791 | unsigned int id, lun; |
787 | unsigned long serial; | 792 | unsigned long serial; |
788 | 793 | ||
789 | qla2x00_block_error_handler(cmd); | 794 | qla2x00_block_error_handler(cmd); |
790 | 795 | ||
791 | ret = FAILED; | ||
792 | |||
793 | id = cmd->device->id; | 796 | id = cmd->device->id; |
794 | lun = cmd->device->lun; | 797 | lun = cmd->device->lun; |
795 | serial = cmd->serial_number; | 798 | serial = cmd->serial_number; |
@@ -912,15 +915,14 @@ static int | |||
912 | qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | 915 | qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) |
913 | { | 916 | { |
914 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 917 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
918 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
915 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 919 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
916 | int ret; | 920 | int ret = FAILED; |
917 | unsigned int id, lun; | 921 | unsigned int id, lun; |
918 | unsigned long serial; | 922 | unsigned long serial; |
919 | 923 | ||
920 | qla2x00_block_error_handler(cmd); | 924 | qla2x00_block_error_handler(cmd); |
921 | 925 | ||
922 | ret = FAILED; | ||
923 | |||
924 | id = cmd->device->id; | 926 | id = cmd->device->id; |
925 | lun = cmd->device->lun; | 927 | lun = cmd->device->lun; |
926 | serial = cmd->serial_number; | 928 | serial = cmd->serial_number; |
@@ -944,7 +946,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
944 | goto eh_bus_reset_done; | 946 | goto eh_bus_reset_done; |
945 | 947 | ||
946 | /* Flush outstanding commands. */ | 948 | /* Flush outstanding commands. */ |
947 | if (!qla2x00_eh_wait_for_pending_commands(ha)) | 949 | if (!qla2x00_eh_wait_for_pending_commands(pha)) |
948 | ret = FAILED; | 950 | ret = FAILED; |
949 | 951 | ||
950 | eh_bus_reset_done: | 952 | eh_bus_reset_done: |
@@ -974,14 +976,13 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
974 | { | 976 | { |
975 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 977 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
976 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 978 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
977 | int ret; | 979 | int ret = FAILED; |
978 | unsigned int id, lun; | 980 | unsigned int id, lun; |
979 | unsigned long serial; | 981 | unsigned long serial; |
982 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
980 | 983 | ||
981 | qla2x00_block_error_handler(cmd); | 984 | qla2x00_block_error_handler(cmd); |
982 | 985 | ||
983 | ret = FAILED; | ||
984 | |||
985 | id = cmd->device->id; | 986 | id = cmd->device->id; |
986 | lun = cmd->device->lun; | 987 | lun = cmd->device->lun; |
987 | serial = cmd->serial_number; | 988 | serial = cmd->serial_number; |
@@ -1004,21 +1005,24 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1004 | * while dpc is stuck for the mailbox to complete. | 1005 | * while dpc is stuck for the mailbox to complete. |
1005 | */ | 1006 | */ |
1006 | qla2x00_wait_for_loop_ready(ha); | 1007 | qla2x00_wait_for_loop_ready(ha); |
1007 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 1008 | set_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); |
1008 | if (qla2x00_abort_isp(ha)) { | 1009 | if (qla2x00_abort_isp(pha)) { |
1009 | clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 1010 | clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); |
1010 | /* failed. schedule dpc to try */ | 1011 | /* failed. schedule dpc to try */ |
1011 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 1012 | set_bit(ISP_ABORT_NEEDED, &pha->dpc_flags); |
1012 | 1013 | ||
1013 | if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) | 1014 | if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) |
1014 | goto eh_host_reset_lock; | 1015 | goto eh_host_reset_lock; |
1015 | } | 1016 | } |
1016 | clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 1017 | clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); |
1017 | 1018 | ||
1018 | /* Waiting for our command in done_queue to be returned to OS.*/ | 1019 | /* Waiting for our command in done_queue to be returned to OS.*/ |
1019 | if (qla2x00_eh_wait_for_pending_commands(ha)) | 1020 | if (qla2x00_eh_wait_for_pending_commands(pha)) |
1020 | ret = SUCCESS; | 1021 | ret = SUCCESS; |
1021 | 1022 | ||
1023 | if (ha->parent) | ||
1024 | qla2x00_vp_abort_isp(ha); | ||
1025 | |||
1022 | eh_host_reset_lock: | 1026 | eh_host_reset_lock: |
1023 | qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, | 1027 | qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, |
1024 | (ret == FAILED) ? "failed" : "succeded"); | 1028 | (ret == FAILED) ? "failed" : "succeded"); |
@@ -1435,6 +1439,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1435 | ha->host = host; | 1439 | ha->host = host; |
1436 | ha->host_no = host->host_no; | 1440 | ha->host_no = host->host_no; |
1437 | sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); | 1441 | sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); |
1442 | ha->parent = NULL; | ||
1438 | 1443 | ||
1439 | /* Set ISP-type information. */ | 1444 | /* Set ISP-type information. */ |
1440 | qla2x00_set_isp_flags(ha); | 1445 | qla2x00_set_isp_flags(ha); |
@@ -1452,7 +1457,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1452 | 1457 | ||
1453 | ha->prev_topology = 0; | 1458 | ha->prev_topology = 0; |
1454 | ha->init_cb_size = sizeof(init_cb_t); | 1459 | ha->init_cb_size = sizeof(init_cb_t); |
1455 | ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; | 1460 | ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx; |
1456 | ha->link_data_rate = PORT_SPEED_UNKNOWN; | 1461 | ha->link_data_rate = PORT_SPEED_UNKNOWN; |
1457 | ha->optrom_size = OPTROM_SIZE_2300; | 1462 | ha->optrom_size = OPTROM_SIZE_2300; |
1458 | 1463 | ||
@@ -1524,8 +1529,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1524 | ha->request_q_length = REQUEST_ENTRY_CNT_24XX; | 1529 | ha->request_q_length = REQUEST_ENTRY_CNT_24XX; |
1525 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; | 1530 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; |
1526 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; | 1531 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; |
1527 | ha->init_cb_size = sizeof(struct init_cb_24xx); | 1532 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); |
1528 | ha->mgmt_svr_loop_id = 10; | 1533 | ha->mgmt_svr_loop_id = 10 + ha->vp_idx; |
1529 | ha->isp_ops.pci_config = qla24xx_pci_config; | 1534 | ha->isp_ops.pci_config = qla24xx_pci_config; |
1530 | ha->isp_ops.reset_chip = qla24xx_reset_chip; | 1535 | ha->isp_ops.reset_chip = qla24xx_reset_chip; |
1531 | ha->isp_ops.chip_diag = qla24xx_chip_diag; | 1536 | ha->isp_ops.chip_diag = qla24xx_chip_diag; |
@@ -1563,10 +1568,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1563 | ha->instance = num_hosts; | 1568 | ha->instance = num_hosts; |
1564 | 1569 | ||
1565 | init_MUTEX(&ha->mbx_cmd_sem); | 1570 | init_MUTEX(&ha->mbx_cmd_sem); |
1571 | init_MUTEX(&ha->vport_sem); | ||
1566 | init_MUTEX_LOCKED(&ha->mbx_intr_sem); | 1572 | init_MUTEX_LOCKED(&ha->mbx_intr_sem); |
1567 | 1573 | ||
1568 | INIT_LIST_HEAD(&ha->list); | 1574 | INIT_LIST_HEAD(&ha->list); |
1569 | INIT_LIST_HEAD(&ha->fcports); | 1575 | INIT_LIST_HEAD(&ha->fcports); |
1576 | INIT_LIST_HEAD(&ha->vp_list); | ||
1577 | |||
1578 | set_bit(0, (unsigned long *) ha->vp_idx_map); | ||
1570 | 1579 | ||
1571 | qla2x00_config_dma_addressing(ha); | 1580 | qla2x00_config_dma_addressing(ha); |
1572 | if (qla2x00_mem_alloc(ha)) { | 1581 | if (qla2x00_mem_alloc(ha)) { |
@@ -1789,7 +1798,8 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, | |||
1789 | void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, | 1798 | void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, |
1790 | int do_login, int defer) | 1799 | int do_login, int defer) |
1791 | { | 1800 | { |
1792 | if (atomic_read(&fcport->state) == FCS_ONLINE) | 1801 | if (atomic_read(&fcport->state) == FCS_ONLINE && |
1802 | ha->vp_idx == fcport->vp_idx) | ||
1793 | qla2x00_schedule_rport_del(ha, fcport, defer); | 1803 | qla2x00_schedule_rport_del(ha, fcport, defer); |
1794 | 1804 | ||
1795 | /* | 1805 | /* |
@@ -1840,19 +1850,23 @@ void | |||
1840 | qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) | 1850 | qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) |
1841 | { | 1851 | { |
1842 | fc_port_t *fcport; | 1852 | fc_port_t *fcport; |
1853 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
1843 | 1854 | ||
1844 | list_for_each_entry(fcport, &ha->fcports, list) { | 1855 | list_for_each_entry(fcport, &pha->fcports, list) { |
1845 | if (fcport->port_type != FCT_TARGET) | 1856 | if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx) |
1846 | continue; | 1857 | continue; |
1847 | |||
1848 | /* | 1858 | /* |
1849 | * No point in marking the device as lost, if the device is | 1859 | * No point in marking the device as lost, if the device is |
1850 | * already DEAD. | 1860 | * already DEAD. |
1851 | */ | 1861 | */ |
1852 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) | 1862 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) |
1853 | continue; | 1863 | continue; |
1854 | if (atomic_read(&fcport->state) == FCS_ONLINE) | 1864 | if (atomic_read(&fcport->state) == FCS_ONLINE) { |
1855 | qla2x00_schedule_rport_del(ha, fcport, defer); | 1865 | if (defer) |
1866 | qla2x00_schedule_rport_del(ha, fcport, defer); | ||
1867 | else if (ha->vp_idx == fcport->vp_idx) | ||
1868 | qla2x00_schedule_rport_del(ha, fcport, defer); | ||
1869 | } | ||
1856 | atomic_set(&fcport->state, FCS_DEVICE_LOST); | 1870 | atomic_set(&fcport->state, FCS_DEVICE_LOST); |
1857 | } | 1871 | } |
1858 | 1872 | ||
@@ -1868,7 +1882,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) | |||
1868 | * 0 = success. | 1882 | * 0 = success. |
1869 | * 1 = failure. | 1883 | * 1 = failure. |
1870 | */ | 1884 | */ |
1871 | static uint8_t | 1885 | uint8_t |
1872 | qla2x00_mem_alloc(scsi_qla_host_t *ha) | 1886 | qla2x00_mem_alloc(scsi_qla_host_t *ha) |
1873 | { | 1887 | { |
1874 | char name[16]; | 1888 | char name[16]; |
@@ -1920,33 +1934,33 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) | |||
1920 | continue; | 1934 | continue; |
1921 | } | 1935 | } |
1922 | 1936 | ||
1923 | snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, | 1937 | /* get consistent memory allocated for init control block */ |
1924 | ha->host_no); | 1938 | ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, |
1925 | ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, | 1939 | ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); |
1926 | DMA_POOL_SIZE, 8, 0); | 1940 | if (ha->init_cb == NULL) { |
1927 | if (ha->s_dma_pool == NULL) { | ||
1928 | qla_printk(KERN_WARNING, ha, | 1941 | qla_printk(KERN_WARNING, ha, |
1929 | "Memory Allocation failed - s_dma_pool\n"); | 1942 | "Memory Allocation failed - init_cb\n"); |
1930 | 1943 | ||
1931 | qla2x00_mem_free(ha); | 1944 | qla2x00_mem_free(ha); |
1932 | msleep(100); | 1945 | msleep(100); |
1933 | 1946 | ||
1934 | continue; | 1947 | continue; |
1935 | } | 1948 | } |
1949 | memset(ha->init_cb, 0, ha->init_cb_size); | ||
1936 | 1950 | ||
1937 | /* get consistent memory allocated for init control block */ | 1951 | snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, |
1938 | ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | 1952 | ha->host_no); |
1939 | &ha->init_cb_dma); | 1953 | ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, |
1940 | if (ha->init_cb == NULL) { | 1954 | DMA_POOL_SIZE, 8, 0); |
1955 | if (ha->s_dma_pool == NULL) { | ||
1941 | qla_printk(KERN_WARNING, ha, | 1956 | qla_printk(KERN_WARNING, ha, |
1942 | "Memory Allocation failed - init_cb\n"); | 1957 | "Memory Allocation failed - s_dma_pool\n"); |
1943 | 1958 | ||
1944 | qla2x00_mem_free(ha); | 1959 | qla2x00_mem_free(ha); |
1945 | msleep(100); | 1960 | msleep(100); |
1946 | 1961 | ||
1947 | continue; | 1962 | continue; |
1948 | } | 1963 | } |
1949 | memset(ha->init_cb, 0, ha->init_cb_size); | ||
1950 | 1964 | ||
1951 | if (qla2x00_allocate_sp_pool(ha)) { | 1965 | if (qla2x00_allocate_sp_pool(ha)) { |
1952 | qla_printk(KERN_WARNING, ha, | 1966 | qla_printk(KERN_WARNING, ha, |
@@ -2052,7 +2066,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) | |||
2052 | * Input: | 2066 | * Input: |
2053 | * ha = adapter block pointer. | 2067 | * ha = adapter block pointer. |
2054 | */ | 2068 | */ |
2055 | static void | 2069 | void |
2056 | qla2x00_mem_free(scsi_qla_host_t *ha) | 2070 | qla2x00_mem_free(scsi_qla_host_t *ha) |
2057 | { | 2071 | { |
2058 | struct list_head *fcpl, *fcptemp; | 2072 | struct list_head *fcpl, *fcptemp; |
@@ -2088,12 +2102,13 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
2088 | if (ha->ms_iocb) | 2102 | if (ha->ms_iocb) |
2089 | dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); | 2103 | dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); |
2090 | 2104 | ||
2091 | if (ha->init_cb) | ||
2092 | dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); | ||
2093 | |||
2094 | if (ha->s_dma_pool) | 2105 | if (ha->s_dma_pool) |
2095 | dma_pool_destroy(ha->s_dma_pool); | 2106 | dma_pool_destroy(ha->s_dma_pool); |
2096 | 2107 | ||
2108 | if (ha->init_cb) | ||
2109 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, | ||
2110 | ha->init_cb, ha->init_cb_dma); | ||
2111 | |||
2097 | if (ha->gid_list) | 2112 | if (ha->gid_list) |
2098 | dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, | 2113 | dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, |
2099 | ha->gid_list_dma); | 2114 | ha->gid_list_dma); |
@@ -2199,6 +2214,7 @@ qla2x00_free_sp_pool( scsi_qla_host_t *ha) | |||
2199 | static int | 2214 | static int |
2200 | qla2x00_do_dpc(void *data) | 2215 | qla2x00_do_dpc(void *data) |
2201 | { | 2216 | { |
2217 | int rval; | ||
2202 | scsi_qla_host_t *ha; | 2218 | scsi_qla_host_t *ha; |
2203 | fc_port_t *fcport; | 2219 | fc_port_t *fcport; |
2204 | uint8_t status; | 2220 | uint8_t status; |
@@ -2347,7 +2363,7 @@ qla2x00_do_dpc(void *data) | |||
2347 | if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, | 2363 | if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, |
2348 | &ha->dpc_flags))) { | 2364 | &ha->dpc_flags))) { |
2349 | 2365 | ||
2350 | qla2x00_loop_resync(ha); | 2366 | rval = qla2x00_loop_resync(ha); |
2351 | 2367 | ||
2352 | clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags); | 2368 | clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags); |
2353 | } | 2369 | } |
@@ -2374,6 +2390,8 @@ qla2x00_do_dpc(void *data) | |||
2374 | if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) | 2390 | if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) |
2375 | ha->isp_ops.beacon_blink(ha); | 2391 | ha->isp_ops.beacon_blink(ha); |
2376 | 2392 | ||
2393 | qla2x00_do_dpc_all_vps(ha); | ||
2394 | |||
2377 | ha->dpc_active = 0; | 2395 | ha->dpc_active = 0; |
2378 | } /* End of while(1) */ | 2396 | } /* End of while(1) */ |
2379 | 2397 | ||
@@ -2452,7 +2470,7 @@ qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *sp) | |||
2452 | * | 2470 | * |
2453 | * Context: Interrupt | 2471 | * Context: Interrupt |
2454 | ***************************************************************************/ | 2472 | ***************************************************************************/ |
2455 | static void | 2473 | void |
2456 | qla2x00_timer(scsi_qla_host_t *ha) | 2474 | qla2x00_timer(scsi_qla_host_t *ha) |
2457 | { | 2475 | { |
2458 | unsigned long cpu_flags = 0; | 2476 | unsigned long cpu_flags = 0; |
@@ -2461,6 +2479,7 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2461 | int index; | 2479 | int index; |
2462 | srb_t *sp; | 2480 | srb_t *sp; |
2463 | int t; | 2481 | int t; |
2482 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
2464 | 2483 | ||
2465 | /* | 2484 | /* |
2466 | * Ports - Port down timer. | 2485 | * Ports - Port down timer. |
@@ -2506,23 +2525,29 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2506 | atomic_set(&ha->loop_state, LOOP_DEAD); | 2525 | atomic_set(&ha->loop_state, LOOP_DEAD); |
2507 | 2526 | ||
2508 | /* Schedule an ISP abort to return any tape commands. */ | 2527 | /* Schedule an ISP abort to return any tape commands. */ |
2509 | spin_lock_irqsave(&ha->hardware_lock, cpu_flags); | 2528 | /* NPIV - scan physical port only */ |
2510 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; | 2529 | if (!ha->parent) { |
2511 | index++) { | 2530 | spin_lock_irqsave(&ha->hardware_lock, |
2512 | fc_port_t *sfcp; | 2531 | cpu_flags); |
2532 | for (index = 1; | ||
2533 | index < MAX_OUTSTANDING_COMMANDS; | ||
2534 | index++) { | ||
2535 | fc_port_t *sfcp; | ||
2536 | |||
2537 | sp = ha->outstanding_cmds[index]; | ||
2538 | if (!sp) | ||
2539 | continue; | ||
2540 | sfcp = sp->fcport; | ||
2541 | if (!(sfcp->flags & FCF_TAPE_PRESENT)) | ||
2542 | continue; | ||
2513 | 2543 | ||
2514 | sp = ha->outstanding_cmds[index]; | 2544 | set_bit(ISP_ABORT_NEEDED, |
2515 | if (!sp) | 2545 | &ha->dpc_flags); |
2516 | continue; | 2546 | break; |
2517 | sfcp = sp->fcport; | 2547 | } |
2518 | if (!(sfcp->flags & FCF_TAPE_PRESENT)) | 2548 | spin_unlock_irqrestore(&ha->hardware_lock, |
2519 | continue; | 2549 | cpu_flags); |
2520 | |||
2521 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
2522 | break; | ||
2523 | } | 2550 | } |
2524 | spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); | ||
2525 | |||
2526 | set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); | 2551 | set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); |
2527 | start_dpc++; | 2552 | start_dpc++; |
2528 | } | 2553 | } |
@@ -2566,8 +2591,9 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2566 | test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || | 2591 | test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || |
2567 | test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || | 2592 | test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || |
2568 | test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || | 2593 | test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || |
2594 | test_bit(VP_DPC_NEEDED, &ha->dpc_flags) || | ||
2569 | test_bit(RELOGIN_NEEDED, &ha->dpc_flags))) | 2595 | test_bit(RELOGIN_NEEDED, &ha->dpc_flags))) |
2570 | qla2xxx_wake_dpc(ha); | 2596 | qla2xxx_wake_dpc(pha); |
2571 | 2597 | ||
2572 | qla2x00_restart_timer(ha, WATCH_INTERVAL); | 2598 | qla2x00_restart_timer(ha, WATCH_INTERVAL); |
2573 | } | 2599 | } |
@@ -2711,14 +2737,24 @@ qla2x00_module_init(void) | |||
2711 | 2737 | ||
2712 | qla2xxx_transport_template = | 2738 | qla2xxx_transport_template = |
2713 | fc_attach_transport(&qla2xxx_transport_functions); | 2739 | fc_attach_transport(&qla2xxx_transport_functions); |
2714 | if (!qla2xxx_transport_template) | 2740 | if (!qla2xxx_transport_template) { |
2741 | kmem_cache_destroy(srb_cachep); | ||
2742 | return -ENODEV; | ||
2743 | } | ||
2744 | qla2xxx_transport_vport_template = | ||
2745 | fc_attach_transport(&qla2xxx_transport_vport_functions); | ||
2746 | if (!qla2xxx_transport_vport_template) { | ||
2747 | kmem_cache_destroy(srb_cachep); | ||
2748 | fc_release_transport(qla2xxx_transport_template); | ||
2715 | return -ENODEV; | 2749 | return -ENODEV; |
2750 | } | ||
2716 | 2751 | ||
2717 | printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); | 2752 | printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); |
2718 | ret = pci_register_driver(&qla2xxx_pci_driver); | 2753 | ret = pci_register_driver(&qla2xxx_pci_driver); |
2719 | if (ret) { | 2754 | if (ret) { |
2720 | kmem_cache_destroy(srb_cachep); | 2755 | kmem_cache_destroy(srb_cachep); |
2721 | fc_release_transport(qla2xxx_transport_template); | 2756 | fc_release_transport(qla2xxx_transport_template); |
2757 | fc_release_transport(qla2xxx_transport_vport_template); | ||
2722 | } | 2758 | } |
2723 | return ret; | 2759 | return ret; |
2724 | } | 2760 | } |
@@ -2733,6 +2769,7 @@ qla2x00_module_exit(void) | |||
2733 | qla2x00_release_firmware(); | 2769 | qla2x00_release_firmware(); |
2734 | kmem_cache_destroy(srb_cachep); | 2770 | kmem_cache_destroy(srb_cachep); |
2735 | fc_release_transport(qla2xxx_transport_template); | 2771 | fc_release_transport(qla2xxx_transport_template); |
2772 | fc_release_transport(qla2xxx_transport_vport_template); | ||
2736 | } | 2773 | } |
2737 | 2774 | ||
2738 | module_init(qla2x00_module_init); | 2775 | module_init(qla2x00_module_init); |