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 /drivers/scsi/qla2xxx | |
| 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>
Diffstat (limited to 'drivers/scsi/qla2xxx')
| -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); |
