diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 8 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 14 | ||||
-rw-r--r-- | drivers/s390/net/qeth_main.c | 8 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 120 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ccw.c | 5 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 15 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 212 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 9 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 122 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 79 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 73 |
11 files changed, 354 insertions, 311 deletions
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 9d0c6e1a0e66..9af02c79ce8a 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -54,11 +54,11 @@ struct dasd_devmap { | |||
54 | */ | 54 | */ |
55 | struct dasd_server_ssid_map { | 55 | struct dasd_server_ssid_map { |
56 | struct list_head list; | 56 | struct list_head list; |
57 | struct server_id { | 57 | struct system_id { |
58 | char vendor[4]; | 58 | char vendor[4]; |
59 | char serial[15]; | 59 | char serial[15]; |
60 | __u16 ssid; | ||
60 | } sid; | 61 | } sid; |
61 | __u16 ssid; | ||
62 | }; | 62 | }; |
63 | 63 | ||
64 | static struct list_head dasd_server_ssid_list; | 64 | static struct list_head dasd_server_ssid_list; |
@@ -904,14 +904,14 @@ dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | |||
904 | return -ENOMEM; | 904 | return -ENOMEM; |
905 | strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1); | 905 | strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1); |
906 | strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1); | 906 | strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1); |
907 | srv->ssid = uid->ssid; | 907 | srv->sid.ssid = uid->ssid; |
908 | 908 | ||
909 | /* server is already contained ? */ | 909 | /* server is already contained ? */ |
910 | spin_lock(&dasd_devmap_lock); | 910 | spin_lock(&dasd_devmap_lock); |
911 | devmap->uid = *uid; | 911 | devmap->uid = *uid; |
912 | list_for_each_entry(tmp, &dasd_server_ssid_list, list) { | 912 | list_for_each_entry(tmp, &dasd_server_ssid_list, list) { |
913 | if (!memcmp(&srv->sid, &tmp->sid, | 913 | if (!memcmp(&srv->sid, &tmp->sid, |
914 | sizeof(struct dasd_server_ssid_map))) { | 914 | sizeof(struct system_id))) { |
915 | kfree(srv); | 915 | kfree(srv); |
916 | srv = NULL; | 916 | srv = NULL; |
917 | break; | 917 | break; |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 957ed5db98e4..b7a7fac3f7c3 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -607,7 +607,7 @@ dasd_eckd_psf_ssc(struct dasd_device *device) | |||
607 | * Valide storage server of current device. | 607 | * Valide storage server of current device. |
608 | */ | 608 | */ |
609 | static int | 609 | static int |
610 | dasd_eckd_validate_server(struct dasd_device *device) | 610 | dasd_eckd_validate_server(struct dasd_device *device, struct dasd_uid *uid) |
611 | { | 611 | { |
612 | int rc; | 612 | int rc; |
613 | 613 | ||
@@ -616,11 +616,11 @@ dasd_eckd_validate_server(struct dasd_device *device) | |||
616 | return 0; | 616 | return 0; |
617 | 617 | ||
618 | rc = dasd_eckd_psf_ssc(device); | 618 | rc = dasd_eckd_psf_ssc(device); |
619 | if (rc) | 619 | /* may be requested feature is not available on server, |
620 | /* may be requested feature is not available on server, | 620 | * therefore just report error and go ahead */ |
621 | * therefore just report error and go ahead */ | 621 | DEV_MESSAGE(KERN_INFO, device, |
622 | DEV_MESSAGE(KERN_INFO, device, | 622 | "PSF-SSC on storage subsystem %s.%s.%04x returned rc=%d", |
623 | "Perform Subsystem Function returned rc=%d", rc); | 623 | uid->vendor, uid->serial, uid->ssid, rc); |
624 | /* RE-Read Configuration Data */ | 624 | /* RE-Read Configuration Data */ |
625 | return dasd_eckd_read_conf(device); | 625 | return dasd_eckd_read_conf(device); |
626 | } | 626 | } |
@@ -666,7 +666,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
666 | return rc; | 666 | return rc; |
667 | rc = dasd_set_uid(device->cdev, &uid); | 667 | rc = dasd_set_uid(device->cdev, &uid); |
668 | if (rc == 1) /* new server found */ | 668 | if (rc == 1) /* new server found */ |
669 | rc = dasd_eckd_validate_server(device); | 669 | rc = dasd_eckd_validate_server(device, &uid); |
670 | if (rc) | 670 | if (rc) |
671 | return rc; | 671 | return rc; |
672 | 672 | ||
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 5fff1f93973a..e1327b8fce00 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -8510,9 +8510,9 @@ static int | |||
8510 | qeth_ipv6_init(void) | 8510 | qeth_ipv6_init(void) |
8511 | { | 8511 | { |
8512 | qeth_old_arp_constructor = arp_tbl.constructor; | 8512 | qeth_old_arp_constructor = arp_tbl.constructor; |
8513 | write_lock(&arp_tbl.lock); | 8513 | write_lock_bh(&arp_tbl.lock); |
8514 | arp_tbl.constructor = qeth_arp_constructor; | 8514 | arp_tbl.constructor = qeth_arp_constructor; |
8515 | write_unlock(&arp_tbl.lock); | 8515 | write_unlock_bh(&arp_tbl.lock); |
8516 | 8516 | ||
8517 | arp_direct_ops = (struct neigh_ops*) | 8517 | arp_direct_ops = (struct neigh_ops*) |
8518 | kmalloc(sizeof(struct neigh_ops), GFP_KERNEL); | 8518 | kmalloc(sizeof(struct neigh_ops), GFP_KERNEL); |
@@ -8528,9 +8528,9 @@ qeth_ipv6_init(void) | |||
8528 | static void | 8528 | static void |
8529 | qeth_ipv6_uninit(void) | 8529 | qeth_ipv6_uninit(void) |
8530 | { | 8530 | { |
8531 | write_lock(&arp_tbl.lock); | 8531 | write_lock_bh(&arp_tbl.lock); |
8532 | arp_tbl.constructor = qeth_old_arp_constructor; | 8532 | arp_tbl.constructor = qeth_old_arp_constructor; |
8533 | write_unlock(&arp_tbl.lock); | 8533 | write_unlock_bh(&arp_tbl.lock); |
8534 | kfree(arp_direct_ops); | 8534 | kfree(arp_direct_ops); |
8535 | } | 8535 | } |
8536 | #endif /* CONFIG_QETH_IPV6 */ | 8536 | #endif /* CONFIG_QETH_IPV6 */ |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 9cd789b8acd4..adc9d8f2c28f 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -112,6 +112,105 @@ _zfcp_hex_dump(char *addr, int count) | |||
112 | printk("\n"); | 112 | printk("\n"); |
113 | } | 113 | } |
114 | 114 | ||
115 | |||
116 | /****************************************************************/ | ||
117 | /****** Functions to handle the request ID hash table ********/ | ||
118 | /****************************************************************/ | ||
119 | |||
120 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF | ||
121 | |||
122 | static int zfcp_reqlist_init(struct zfcp_adapter *adapter) | ||
123 | { | ||
124 | int i; | ||
125 | |||
126 | adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head), | ||
127 | GFP_KERNEL); | ||
128 | |||
129 | if (!adapter->req_list) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | for (i=0; i<REQUEST_LIST_SIZE; i++) | ||
133 | INIT_LIST_HEAD(&adapter->req_list[i]); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static void zfcp_reqlist_free(struct zfcp_adapter *adapter) | ||
139 | { | ||
140 | struct zfcp_fsf_req *request, *tmp; | ||
141 | unsigned int i; | ||
142 | |||
143 | for (i=0; i<REQUEST_LIST_SIZE; i++) { | ||
144 | if (list_empty(&adapter->req_list[i])) | ||
145 | continue; | ||
146 | |||
147 | list_for_each_entry_safe(request, tmp, | ||
148 | &adapter->req_list[i], list) | ||
149 | list_del(&request->list); | ||
150 | } | ||
151 | |||
152 | kfree(adapter->req_list); | ||
153 | } | ||
154 | |||
155 | void zfcp_reqlist_add(struct zfcp_adapter *adapter, | ||
156 | struct zfcp_fsf_req *fsf_req) | ||
157 | { | ||
158 | unsigned int i; | ||
159 | |||
160 | i = fsf_req->req_id % REQUEST_LIST_SIZE; | ||
161 | list_add_tail(&fsf_req->list, &adapter->req_list[i]); | ||
162 | } | ||
163 | |||
164 | void zfcp_reqlist_remove(struct zfcp_adapter *adapter, unsigned long req_id) | ||
165 | { | ||
166 | struct zfcp_fsf_req *request, *tmp; | ||
167 | unsigned int i, counter; | ||
168 | u64 dbg_tmp[2]; | ||
169 | |||
170 | i = req_id % REQUEST_LIST_SIZE; | ||
171 | BUG_ON(list_empty(&adapter->req_list[i])); | ||
172 | |||
173 | counter = 0; | ||
174 | list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) { | ||
175 | if (request->req_id == req_id) { | ||
176 | dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active); | ||
177 | dbg_tmp[1] = (u64) counter; | ||
178 | debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); | ||
179 | list_del(&request->list); | ||
180 | break; | ||
181 | } | ||
182 | counter++; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter, | ||
187 | unsigned long req_id) | ||
188 | { | ||
189 | struct zfcp_fsf_req *request, *tmp; | ||
190 | unsigned int i; | ||
191 | |||
192 | i = req_id % REQUEST_LIST_SIZE; | ||
193 | |||
194 | list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) | ||
195 | if (request->req_id == req_id) | ||
196 | return request; | ||
197 | |||
198 | return NULL; | ||
199 | } | ||
200 | |||
201 | int zfcp_reqlist_isempty(struct zfcp_adapter *adapter) | ||
202 | { | ||
203 | unsigned int i; | ||
204 | |||
205 | for (i=0; i<REQUEST_LIST_SIZE; i++) | ||
206 | if (!list_empty(&adapter->req_list[i])) | ||
207 | return 0; | ||
208 | |||
209 | return 1; | ||
210 | } | ||
211 | |||
212 | #undef ZFCP_LOG_AREA | ||
213 | |||
115 | /****************************************************************/ | 214 | /****************************************************************/ |
116 | /************** Uncategorised Functions *************************/ | 215 | /************** Uncategorised Functions *************************/ |
117 | /****************************************************************/ | 216 | /****************************************************************/ |
@@ -961,8 +1060,12 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
961 | INIT_LIST_HEAD(&adapter->port_remove_lh); | 1060 | INIT_LIST_HEAD(&adapter->port_remove_lh); |
962 | 1061 | ||
963 | /* initialize list of fsf requests */ | 1062 | /* initialize list of fsf requests */ |
964 | spin_lock_init(&adapter->fsf_req_list_lock); | 1063 | spin_lock_init(&adapter->req_list_lock); |
965 | INIT_LIST_HEAD(&adapter->fsf_req_list_head); | 1064 | retval = zfcp_reqlist_init(adapter); |
1065 | if (retval) { | ||
1066 | ZFCP_LOG_INFO("request list initialization failed\n"); | ||
1067 | goto failed_low_mem_buffers; | ||
1068 | } | ||
966 | 1069 | ||
967 | /* initialize debug locks */ | 1070 | /* initialize debug locks */ |
968 | 1071 | ||
@@ -1041,8 +1144,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
1041 | * !0 - struct zfcp_adapter data structure could not be removed | 1144 | * !0 - struct zfcp_adapter data structure could not be removed |
1042 | * (e.g. still used) | 1145 | * (e.g. still used) |
1043 | * locks: adapter list write lock is assumed to be held by caller | 1146 | * locks: adapter list write lock is assumed to be held by caller |
1044 | * adapter->fsf_req_list_lock is taken and released within this | ||
1045 | * function and must not be held on entry | ||
1046 | */ | 1147 | */ |
1047 | void | 1148 | void |
1048 | zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | 1149 | zfcp_adapter_dequeue(struct zfcp_adapter *adapter) |
@@ -1054,14 +1155,14 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
1054 | zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); | 1155 | zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); |
1055 | dev_set_drvdata(&adapter->ccw_device->dev, NULL); | 1156 | dev_set_drvdata(&adapter->ccw_device->dev, NULL); |
1056 | /* sanity check: no pending FSF requests */ | 1157 | /* sanity check: no pending FSF requests */ |
1057 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); | 1158 | spin_lock_irqsave(&adapter->req_list_lock, flags); |
1058 | retval = !list_empty(&adapter->fsf_req_list_head); | 1159 | retval = zfcp_reqlist_isempty(adapter); |
1059 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | 1160 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); |
1060 | if (retval) { | 1161 | if (!retval) { |
1061 | ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, " | 1162 | ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, " |
1062 | "%i requests outstanding\n", | 1163 | "%i requests outstanding\n", |
1063 | zfcp_get_busid_by_adapter(adapter), adapter, | 1164 | zfcp_get_busid_by_adapter(adapter), adapter, |
1064 | atomic_read(&adapter->fsf_reqs_active)); | 1165 | atomic_read(&adapter->reqs_active)); |
1065 | retval = -EBUSY; | 1166 | retval = -EBUSY; |
1066 | goto out; | 1167 | goto out; |
1067 | } | 1168 | } |
@@ -1087,6 +1188,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) | |||
1087 | zfcp_free_low_mem_buffers(adapter); | 1188 | zfcp_free_low_mem_buffers(adapter); |
1088 | /* free memory of adapter data structure and queues */ | 1189 | /* free memory of adapter data structure and queues */ |
1089 | zfcp_qdio_free_queues(adapter); | 1190 | zfcp_qdio_free_queues(adapter); |
1191 | zfcp_reqlist_free(adapter); | ||
1090 | kfree(adapter->fc_stats); | 1192 | kfree(adapter->fc_stats); |
1091 | kfree(adapter->stats_reset_data); | 1193 | kfree(adapter->stats_reset_data); |
1092 | ZFCP_LOG_TRACE("freeing adapter structure\n"); | 1194 | ZFCP_LOG_TRACE("freeing adapter structure\n"); |
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 57d8e4bfb8d9..fdabadeaa9ee 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -164,6 +164,11 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device) | |||
164 | retval = zfcp_adapter_scsi_register(adapter); | 164 | retval = zfcp_adapter_scsi_register(adapter); |
165 | if (retval) | 165 | if (retval) |
166 | goto out_scsi_register; | 166 | goto out_scsi_register; |
167 | |||
168 | /* initialize request counter */ | ||
169 | BUG_ON(!zfcp_reqlist_isempty(adapter)); | ||
170 | adapter->req_no = 0; | ||
171 | |||
167 | zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, | 172 | zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, |
168 | ZFCP_SET); | 173 | ZFCP_SET); |
169 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); | 174 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 2df512a18e2c..94d1b74db356 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -52,7 +52,7 @@ | |||
52 | /********************* GENERAL DEFINES *********************************/ | 52 | /********************* GENERAL DEFINES *********************************/ |
53 | 53 | ||
54 | /* zfcp version number, it consists of major, minor, and patch-level number */ | 54 | /* zfcp version number, it consists of major, minor, and patch-level number */ |
55 | #define ZFCP_VERSION "4.7.0" | 55 | #define ZFCP_VERSION "4.8.0" |
56 | 56 | ||
57 | /** | 57 | /** |
58 | * zfcp_sg_to_address - determine kernel address from struct scatterlist | 58 | * zfcp_sg_to_address - determine kernel address from struct scatterlist |
@@ -80,7 +80,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list) | |||
80 | #define REQUEST_LIST_SIZE 128 | 80 | #define REQUEST_LIST_SIZE 128 |
81 | 81 | ||
82 | /********************* SCSI SPECIFIC DEFINES *********************************/ | 82 | /********************* SCSI SPECIFIC DEFINES *********************************/ |
83 | #define ZFCP_SCSI_ER_TIMEOUT (100*HZ) | 83 | #define ZFCP_SCSI_ER_TIMEOUT (10*HZ) |
84 | 84 | ||
85 | /********************* CIO/QDIO SPECIFIC DEFINES *****************************/ | 85 | /********************* CIO/QDIO SPECIFIC DEFINES *****************************/ |
86 | 86 | ||
@@ -886,11 +886,11 @@ struct zfcp_adapter { | |||
886 | struct list_head port_remove_lh; /* head of ports to be | 886 | struct list_head port_remove_lh; /* head of ports to be |
887 | removed */ | 887 | removed */ |
888 | u32 ports; /* number of remote ports */ | 888 | u32 ports; /* number of remote ports */ |
889 | struct timer_list scsi_er_timer; /* SCSI err recovery watch */ | 889 | struct timer_list scsi_er_timer; /* SCSI err recovery watch */ |
890 | struct list_head fsf_req_list_head; /* head of FSF req list */ | 890 | atomic_t reqs_active; /* # active FSF reqs */ |
891 | spinlock_t fsf_req_list_lock; /* lock for ops on list of | 891 | unsigned long req_no; /* unique FSF req number */ |
892 | FSF requests */ | 892 | struct list_head *req_list; /* list of pending reqs */ |
893 | atomic_t fsf_reqs_active; /* # active FSF reqs */ | 893 | spinlock_t req_list_lock; /* request list lock */ |
894 | struct zfcp_qdio_queue request_queue; /* request queue */ | 894 | struct zfcp_qdio_queue request_queue; /* request queue */ |
895 | u32 fsf_req_seq_no; /* FSF cmnd seq number */ | 895 | u32 fsf_req_seq_no; /* FSF cmnd seq number */ |
896 | wait_queue_head_t request_wq; /* can be used to wait for | 896 | wait_queue_head_t request_wq; /* can be used to wait for |
@@ -986,6 +986,7 @@ struct zfcp_unit { | |||
986 | /* FSF request */ | 986 | /* FSF request */ |
987 | struct zfcp_fsf_req { | 987 | struct zfcp_fsf_req { |
988 | struct list_head list; /* list of FSF requests */ | 988 | struct list_head list; /* list of FSF requests */ |
989 | unsigned long req_id; /* unique request ID */ | ||
989 | struct zfcp_adapter *adapter; /* adapter request belongs to */ | 990 | struct zfcp_adapter *adapter; /* adapter request belongs to */ |
990 | u8 sbal_number; /* nr of SBALs free for use */ | 991 | u8 sbal_number; /* nr of SBALs free for use */ |
991 | u8 sbal_first; /* first SBAL for this request */ | 992 | u8 sbal_first; /* first SBAL for this request */ |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 8ec8da0beaa8..7f60b6fdf724 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -64,8 +64,8 @@ static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int); | |||
64 | static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *); | 64 | static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *); |
65 | static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int); | 65 | static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int); |
66 | static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *); | 66 | static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *); |
67 | static int zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *); | 67 | static void zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *); |
68 | static int zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *); | 68 | static void zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *); |
69 | static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); | 69 | static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); |
70 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); | 70 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); |
71 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); | 71 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); |
@@ -93,10 +93,9 @@ static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *); | |||
93 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *); | 93 | static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *); |
94 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *); | 94 | static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *); |
95 | 95 | ||
96 | static int zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); | 96 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *); |
97 | static int zfcp_erp_action_dismiss_port(struct zfcp_port *); | 97 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *); |
98 | static int zfcp_erp_action_dismiss_unit(struct zfcp_unit *); | 98 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *); |
99 | static int zfcp_erp_action_dismiss(struct zfcp_erp_action *); | ||
100 | 99 | ||
101 | static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *, | 100 | static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *, |
102 | struct zfcp_port *, struct zfcp_unit *); | 101 | struct zfcp_port *, struct zfcp_unit *); |
@@ -135,29 +134,39 @@ zfcp_fsf_request_timeout_handler(unsigned long data) | |||
135 | zfcp_erp_adapter_reopen(adapter, 0); | 134 | zfcp_erp_adapter_reopen(adapter, 0); |
136 | } | 135 | } |
137 | 136 | ||
138 | /* | 137 | /** |
139 | * function: zfcp_fsf_scsi_er_timeout_handler | 138 | * zfcp_fsf_scsi_er_timeout_handler - timeout handler for scsi eh tasks |
140 | * | 139 | * |
141 | * purpose: This function needs to be called whenever a SCSI error recovery | 140 | * This function needs to be called whenever a SCSI error recovery |
142 | * action (abort/reset) does not return. | 141 | * action (abort/reset) does not return. Re-opening the adapter means |
143 | * Re-opening the adapter means that the command can be returned | 142 | * that the abort/reset command can be returned by zfcp. It won't complete |
144 | * by zfcp (it is guarranteed that it does not return via the | 143 | * via the adapter anymore (because qdio queues are closed). If ERP is |
145 | * adapter anymore). The buffer can then be used again. | 144 | * already running on this adapter it will be stopped. |
146 | * | ||
147 | * returns: sod all | ||
148 | */ | 145 | */ |
149 | void | 146 | void zfcp_fsf_scsi_er_timeout_handler(unsigned long data) |
150 | zfcp_fsf_scsi_er_timeout_handler(unsigned long data) | ||
151 | { | 147 | { |
152 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; | 148 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; |
149 | unsigned long flags; | ||
153 | 150 | ||
154 | ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. " | 151 | ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. " |
155 | "Restarting all operations on the adapter %s\n", | 152 | "Restarting all operations on the adapter %s\n", |
156 | zfcp_get_busid_by_adapter(adapter)); | 153 | zfcp_get_busid_by_adapter(adapter)); |
157 | debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout"); | 154 | debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout"); |
158 | zfcp_erp_adapter_reopen(adapter, 0); | ||
159 | 155 | ||
160 | return; | 156 | write_lock_irqsave(&adapter->erp_lock, flags); |
157 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | ||
158 | &adapter->status)) { | ||
159 | zfcp_erp_modify_adapter_status(adapter, | ||
160 | ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN, | ||
161 | ZFCP_CLEAR); | ||
162 | zfcp_erp_action_dismiss_adapter(adapter); | ||
163 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
164 | /* dismiss all pending requests including requests for ERP */ | ||
165 | zfcp_fsf_req_dismiss_all(adapter); | ||
166 | adapter->fsf_req_seq_no = 0; | ||
167 | } else | ||
168 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
169 | zfcp_erp_adapter_reopen(adapter, 0); | ||
161 | } | 170 | } |
162 | 171 | ||
163 | /* | 172 | /* |
@@ -670,17 +679,10 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask) | |||
670 | return retval; | 679 | return retval; |
671 | } | 680 | } |
672 | 681 | ||
673 | /* | 682 | /** |
674 | * function: | 683 | * zfcp_erp_adapter_block - mark adapter as blocked, block scsi requests |
675 | * | ||
676 | * purpose: disable I/O, | ||
677 | * return any open requests and clean them up, | ||
678 | * aim: no pending and incoming I/O | ||
679 | * | ||
680 | * returns: | ||
681 | */ | 684 | */ |
682 | static void | 685 | static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) |
683 | zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) | ||
684 | { | 686 | { |
685 | debug_text_event(adapter->erp_dbf, 6, "a_bl"); | 687 | debug_text_event(adapter->erp_dbf, 6, "a_bl"); |
686 | zfcp_erp_modify_adapter_status(adapter, | 688 | zfcp_erp_modify_adapter_status(adapter, |
@@ -688,15 +690,10 @@ zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) | |||
688 | clear_mask, ZFCP_CLEAR); | 690 | clear_mask, ZFCP_CLEAR); |
689 | } | 691 | } |
690 | 692 | ||
691 | /* | 693 | /** |
692 | * function: | 694 | * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests |
693 | * | ||
694 | * purpose: enable I/O | ||
695 | * | ||
696 | * returns: | ||
697 | */ | 695 | */ |
698 | static void | 696 | static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) |
699 | zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) | ||
700 | { | 697 | { |
701 | debug_text_event(adapter->erp_dbf, 6, "a_ubl"); | 698 | debug_text_event(adapter->erp_dbf, 6, "a_ubl"); |
702 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); | 699 | atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); |
@@ -848,18 +845,16 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | |||
848 | struct zfcp_adapter *adapter = erp_action->adapter; | 845 | struct zfcp_adapter *adapter = erp_action->adapter; |
849 | 846 | ||
850 | if (erp_action->fsf_req) { | 847 | if (erp_action->fsf_req) { |
851 | /* take lock to ensure that request is not being deleted meanwhile */ | 848 | /* take lock to ensure that request is not deleted meanwhile */ |
852 | spin_lock(&adapter->fsf_req_list_lock); | 849 | spin_lock(&adapter->req_list_lock); |
853 | /* check whether fsf req does still exist */ | 850 | if ((!zfcp_reqlist_ismember(adapter, |
854 | list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) | 851 | erp_action->fsf_req->req_id)) && |
855 | if (fsf_req == erp_action->fsf_req) | 852 | (fsf_req->erp_action == erp_action)) { |
856 | break; | ||
857 | if (fsf_req && (fsf_req->erp_action == erp_action)) { | ||
858 | /* fsf_req still exists */ | 853 | /* fsf_req still exists */ |
859 | debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); | 854 | debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); |
860 | debug_event(adapter->erp_dbf, 3, &fsf_req, | 855 | debug_event(adapter->erp_dbf, 3, &fsf_req, |
861 | sizeof (unsigned long)); | 856 | sizeof (unsigned long)); |
862 | /* dismiss fsf_req of timed out or dismissed erp_action */ | 857 | /* dismiss fsf_req of timed out/dismissed erp_action */ |
863 | if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | | 858 | if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | |
864 | ZFCP_STATUS_ERP_TIMEDOUT)) { | 859 | ZFCP_STATUS_ERP_TIMEDOUT)) { |
865 | debug_text_event(adapter->erp_dbf, 3, | 860 | debug_text_event(adapter->erp_dbf, 3, |
@@ -892,30 +887,22 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | |||
892 | */ | 887 | */ |
893 | erp_action->fsf_req = NULL; | 888 | erp_action->fsf_req = NULL; |
894 | } | 889 | } |
895 | spin_unlock(&adapter->fsf_req_list_lock); | 890 | spin_unlock(&adapter->req_list_lock); |
896 | } else | 891 | } else |
897 | debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); | 892 | debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); |
898 | 893 | ||
899 | return retval; | 894 | return retval; |
900 | } | 895 | } |
901 | 896 | ||
902 | /* | 897 | /** |
903 | * purpose: generic handler for asynchronous events related to erp_action events | 898 | * zfcp_erp_async_handler_nolock - complete erp_action |
904 | * (normal completion, time-out, dismissing, retry after | ||
905 | * low memory condition) | ||
906 | * | ||
907 | * note: deletion of timer is not required (e.g. in case of a time-out), | ||
908 | * but a second try does no harm, | ||
909 | * we leave it in here to allow for greater simplification | ||
910 | * | 899 | * |
911 | * returns: 0 - there was an action to handle | 900 | * Used for normal completion, time-out, dismissal and failure after |
912 | * !0 - otherwise | 901 | * low memory condition. |
913 | */ | 902 | */ |
914 | static int | 903 | static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, |
915 | zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, | 904 | unsigned long set_mask) |
916 | unsigned long set_mask) | ||
917 | { | 905 | { |
918 | int retval; | ||
919 | struct zfcp_adapter *adapter = erp_action->adapter; | 906 | struct zfcp_adapter *adapter = erp_action->adapter; |
920 | 907 | ||
921 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { | 908 | if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { |
@@ -926,43 +913,26 @@ zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, | |||
926 | del_timer(&erp_action->timer); | 913 | del_timer(&erp_action->timer); |
927 | erp_action->status |= set_mask; | 914 | erp_action->status |= set_mask; |
928 | zfcp_erp_action_ready(erp_action); | 915 | zfcp_erp_action_ready(erp_action); |
929 | retval = 0; | ||
930 | } else { | 916 | } else { |
931 | /* action is ready or gone - nothing to do */ | 917 | /* action is ready or gone - nothing to do */ |
932 | debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone"); | 918 | debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone"); |
933 | debug_event(adapter->erp_dbf, 3, &erp_action->action, | 919 | debug_event(adapter->erp_dbf, 3, &erp_action->action, |
934 | sizeof (int)); | 920 | sizeof (int)); |
935 | retval = 1; | ||
936 | } | 921 | } |
937 | |||
938 | return retval; | ||
939 | } | 922 | } |
940 | 923 | ||
941 | /* | 924 | /** |
942 | * purpose: generic handler for asynchronous events related to erp_action | 925 | * zfcp_erp_async_handler - wrapper for erp_async_handler_nolock w/ locking |
943 | * events (normal completion, time-out, dismissing, retry after | ||
944 | * low memory condition) | ||
945 | * | ||
946 | * note: deletion of timer is not required (e.g. in case of a time-out), | ||
947 | * but a second try does no harm, | ||
948 | * we leave it in here to allow for greater simplification | ||
949 | * | ||
950 | * returns: 0 - there was an action to handle | ||
951 | * !0 - otherwise | ||
952 | */ | 926 | */ |
953 | int | 927 | void zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, |
954 | zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, | 928 | unsigned long set_mask) |
955 | unsigned long set_mask) | ||
956 | { | 929 | { |
957 | struct zfcp_adapter *adapter = erp_action->adapter; | 930 | struct zfcp_adapter *adapter = erp_action->adapter; |
958 | unsigned long flags; | 931 | unsigned long flags; |
959 | int retval; | ||
960 | 932 | ||
961 | write_lock_irqsave(&adapter->erp_lock, flags); | 933 | write_lock_irqsave(&adapter->erp_lock, flags); |
962 | retval = zfcp_erp_async_handler_nolock(erp_action, set_mask); | 934 | zfcp_erp_async_handler_nolock(erp_action, set_mask); |
963 | write_unlock_irqrestore(&adapter->erp_lock, flags); | 935 | write_unlock_irqrestore(&adapter->erp_lock, flags); |
964 | |||
965 | return retval; | ||
966 | } | 936 | } |
967 | 937 | ||
968 | /* | 938 | /* |
@@ -999,17 +969,15 @@ zfcp_erp_timeout_handler(unsigned long data) | |||
999 | zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT); | 969 | zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT); |
1000 | } | 970 | } |
1001 | 971 | ||
1002 | /* | 972 | /** |
1003 | * purpose: is called for an erp_action which needs to be ended | 973 | * zfcp_erp_action_dismiss - dismiss an erp_action |
1004 | * though not being done, | ||
1005 | * this is usually required if an higher is generated, | ||
1006 | * action gets an appropriate flag and will be processed | ||
1007 | * accordingly | ||
1008 | * | 974 | * |
1009 | * locks: erp_lock held (thus we need to call another handler variant) | 975 | * adapter->erp_lock must be held |
976 | * | ||
977 | * Dismissal of an erp_action is usually required if an erp_action of | ||
978 | * higher priority is generated. | ||
1010 | */ | 979 | */ |
1011 | static int | 980 | static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) |
1012 | zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) | ||
1013 | { | 981 | { |
1014 | struct zfcp_adapter *adapter = erp_action->adapter; | 982 | struct zfcp_adapter *adapter = erp_action->adapter; |
1015 | 983 | ||
@@ -1017,8 +985,6 @@ zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) | |||
1017 | debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); | 985 | debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); |
1018 | 986 | ||
1019 | zfcp_erp_async_handler_nolock(erp_action, ZFCP_STATUS_ERP_DISMISSED); | 987 | zfcp_erp_async_handler_nolock(erp_action, ZFCP_STATUS_ERP_DISMISSED); |
1020 | |||
1021 | return 0; | ||
1022 | } | 988 | } |
1023 | 989 | ||
1024 | int | 990 | int |
@@ -2074,18 +2040,12 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) | |||
2074 | return retval; | 2040 | return retval; |
2075 | } | 2041 | } |
2076 | 2042 | ||
2077 | /* | 2043 | /** |
2078 | * function: zfcp_qdio_cleanup | 2044 | * zfcp_erp_adapter_strategy_close_qdio - close qdio queues for an adapter |
2079 | * | ||
2080 | * purpose: cleans up QDIO operation for the specified adapter | ||
2081 | * | ||
2082 | * returns: 0 - successful cleanup | ||
2083 | * !0 - failed cleanup | ||
2084 | */ | 2045 | */ |
2085 | int | 2046 | static void |
2086 | zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | 2047 | zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) |
2087 | { | 2048 | { |
2088 | int retval = ZFCP_ERP_SUCCEEDED; | ||
2089 | int first_used; | 2049 | int first_used; |
2090 | int used_count; | 2050 | int used_count; |
2091 | struct zfcp_adapter *adapter = erp_action->adapter; | 2051 | struct zfcp_adapter *adapter = erp_action->adapter; |
@@ -2094,15 +2054,13 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
2094 | ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO " | 2054 | ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO " |
2095 | "queues on adapter %s\n", | 2055 | "queues on adapter %s\n", |
2096 | zfcp_get_busid_by_adapter(adapter)); | 2056 | zfcp_get_busid_by_adapter(adapter)); |
2097 | retval = ZFCP_ERP_FAILED; | 2057 | return; |
2098 | goto out; | ||
2099 | } | 2058 | } |
2100 | 2059 | ||
2101 | /* | 2060 | /* |
2102 | * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that | 2061 | * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that |
2103 | * do_QDIO won't be called while qdio_shutdown is in progress. | 2062 | * do_QDIO won't be called while qdio_shutdown is in progress. |
2104 | */ | 2063 | */ |
2105 | |||
2106 | write_lock_irq(&adapter->request_queue.queue_lock); | 2064 | write_lock_irq(&adapter->request_queue.queue_lock); |
2107 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); | 2065 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); |
2108 | write_unlock_irq(&adapter->request_queue.queue_lock); | 2066 | write_unlock_irq(&adapter->request_queue.queue_lock); |
@@ -2134,8 +2092,6 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
2134 | adapter->request_queue.free_index = 0; | 2092 | adapter->request_queue.free_index = 0; |
2135 | atomic_set(&adapter->request_queue.free_count, 0); | 2093 | atomic_set(&adapter->request_queue.free_count, 0); |
2136 | adapter->request_queue.distance_from_int = 0; | 2094 | adapter->request_queue.distance_from_int = 0; |
2137 | out: | ||
2138 | return retval; | ||
2139 | } | 2095 | } |
2140 | 2096 | ||
2141 | static int | 2097 | static int |
@@ -2258,11 +2214,11 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | |||
2258 | "%s)\n", zfcp_get_busid_by_adapter(adapter)); | 2214 | "%s)\n", zfcp_get_busid_by_adapter(adapter)); |
2259 | ret = ZFCP_ERP_FAILED; | 2215 | ret = ZFCP_ERP_FAILED; |
2260 | } | 2216 | } |
2261 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) { | 2217 | |
2262 | ZFCP_LOG_INFO("error: exchange port data failed (adapter " | 2218 | /* don't treat as error for the sake of compatibility */ |
2219 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) | ||
2220 | ZFCP_LOG_INFO("warning: exchange port data failed (adapter " | ||
2263 | "%s\n", zfcp_get_busid_by_adapter(adapter)); | 2221 | "%s\n", zfcp_get_busid_by_adapter(adapter)); |
2264 | ret = ZFCP_ERP_FAILED; | ||
2265 | } | ||
2266 | 2222 | ||
2267 | return ret; | 2223 | return ret; |
2268 | } | 2224 | } |
@@ -2292,18 +2248,12 @@ zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action | |||
2292 | return retval; | 2248 | return retval; |
2293 | } | 2249 | } |
2294 | 2250 | ||
2295 | /* | 2251 | /** |
2296 | * function: zfcp_fsf_cleanup | 2252 | * zfcp_erp_adapter_strategy_close_fsf - stop FSF operations for an adapter |
2297 | * | ||
2298 | * purpose: cleanup FSF operation for specified adapter | ||
2299 | * | ||
2300 | * returns: 0 - FSF operation successfully cleaned up | ||
2301 | * !0 - failed to cleanup FSF operation for this adapter | ||
2302 | */ | 2253 | */ |
2303 | static int | 2254 | static void |
2304 | zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action) | 2255 | zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action) |
2305 | { | 2256 | { |
2306 | int retval = ZFCP_ERP_SUCCEEDED; | ||
2307 | struct zfcp_adapter *adapter = erp_action->adapter; | 2257 | struct zfcp_adapter *adapter = erp_action->adapter; |
2308 | 2258 | ||
2309 | /* | 2259 | /* |
@@ -2317,8 +2267,6 @@ zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action) | |||
2317 | /* all ports and units are closed */ | 2267 | /* all ports and units are closed */ |
2318 | zfcp_erp_modify_adapter_status(adapter, | 2268 | zfcp_erp_modify_adapter_status(adapter, |
2319 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); | 2269 | ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); |
2320 | |||
2321 | return retval; | ||
2322 | } | 2270 | } |
2323 | 2271 | ||
2324 | /* | 2272 | /* |
@@ -3293,10 +3241,8 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, | |||
3293 | } | 3241 | } |
3294 | 3242 | ||
3295 | 3243 | ||
3296 | static int | 3244 | void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) |
3297 | zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | ||
3298 | { | 3245 | { |
3299 | int retval = 0; | ||
3300 | struct zfcp_port *port; | 3246 | struct zfcp_port *port; |
3301 | 3247 | ||
3302 | debug_text_event(adapter->erp_dbf, 5, "a_actab"); | 3248 | debug_text_event(adapter->erp_dbf, 5, "a_actab"); |
@@ -3305,14 +3251,10 @@ zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) | |||
3305 | else | 3251 | else |
3306 | list_for_each_entry(port, &adapter->port_list_head, list) | 3252 | list_for_each_entry(port, &adapter->port_list_head, list) |
3307 | zfcp_erp_action_dismiss_port(port); | 3253 | zfcp_erp_action_dismiss_port(port); |
3308 | |||
3309 | return retval; | ||
3310 | } | 3254 | } |
3311 | 3255 | ||
3312 | static int | 3256 | static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) |
3313 | zfcp_erp_action_dismiss_port(struct zfcp_port *port) | ||
3314 | { | 3257 | { |
3315 | int retval = 0; | ||
3316 | struct zfcp_unit *unit; | 3258 | struct zfcp_unit *unit; |
3317 | struct zfcp_adapter *adapter = port->adapter; | 3259 | struct zfcp_adapter *adapter = port->adapter; |
3318 | 3260 | ||
@@ -3323,22 +3265,16 @@ zfcp_erp_action_dismiss_port(struct zfcp_port *port) | |||
3323 | else | 3265 | else |
3324 | list_for_each_entry(unit, &port->unit_list_head, list) | 3266 | list_for_each_entry(unit, &port->unit_list_head, list) |
3325 | zfcp_erp_action_dismiss_unit(unit); | 3267 | zfcp_erp_action_dismiss_unit(unit); |
3326 | |||
3327 | return retval; | ||
3328 | } | 3268 | } |
3329 | 3269 | ||
3330 | static int | 3270 | static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) |
3331 | zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) | ||
3332 | { | 3271 | { |
3333 | int retval = 0; | ||
3334 | struct zfcp_adapter *adapter = unit->port->adapter; | 3272 | struct zfcp_adapter *adapter = unit->port->adapter; |
3335 | 3273 | ||
3336 | debug_text_event(adapter->erp_dbf, 5, "u_actab"); | 3274 | debug_text_event(adapter->erp_dbf, 5, "u_actab"); |
3337 | debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); | 3275 | debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); |
3338 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) | 3276 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) |
3339 | zfcp_erp_action_dismiss(&unit->erp_action); | 3277 | zfcp_erp_action_dismiss(&unit->erp_action); |
3340 | |||
3341 | return retval; | ||
3342 | } | 3278 | } |
3343 | 3279 | ||
3344 | static inline void | 3280 | static inline void |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index d02366004cdd..146d7a2b4c4a 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -63,7 +63,6 @@ extern int zfcp_qdio_allocate_queues(struct zfcp_adapter *); | |||
63 | extern void zfcp_qdio_free_queues(struct zfcp_adapter *); | 63 | extern void zfcp_qdio_free_queues(struct zfcp_adapter *); |
64 | extern int zfcp_qdio_determine_pci(struct zfcp_qdio_queue *, | 64 | extern int zfcp_qdio_determine_pci(struct zfcp_qdio_queue *, |
65 | struct zfcp_fsf_req *); | 65 | struct zfcp_fsf_req *); |
66 | extern int zfcp_qdio_reqid_check(struct zfcp_adapter *, void *); | ||
67 | 66 | ||
68 | extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req | 67 | extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req |
69 | (struct zfcp_fsf_req *, int, int); | 68 | (struct zfcp_fsf_req *, int, int); |
@@ -140,6 +139,7 @@ extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int); | |||
140 | extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int); | 139 | extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int); |
141 | extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int); | 140 | extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int); |
142 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *); | 141 | extern void zfcp_erp_adapter_failed(struct zfcp_adapter *); |
142 | extern void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); | ||
143 | 143 | ||
144 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int); | 144 | extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int); |
145 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int); | 145 | extern int zfcp_erp_port_reopen(struct zfcp_port *, int); |
@@ -156,7 +156,7 @@ extern void zfcp_erp_unit_failed(struct zfcp_unit *); | |||
156 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); | 156 | extern int zfcp_erp_thread_setup(struct zfcp_adapter *); |
157 | extern int zfcp_erp_thread_kill(struct zfcp_adapter *); | 157 | extern int zfcp_erp_thread_kill(struct zfcp_adapter *); |
158 | extern int zfcp_erp_wait(struct zfcp_adapter *); | 158 | extern int zfcp_erp_wait(struct zfcp_adapter *); |
159 | extern int zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); | 159 | extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); |
160 | 160 | ||
161 | extern int zfcp_test_link(struct zfcp_port *); | 161 | extern int zfcp_test_link(struct zfcp_port *); |
162 | 162 | ||
@@ -190,5 +190,10 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, | |||
190 | struct zfcp_fsf_req *); | 190 | struct zfcp_fsf_req *); |
191 | extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, | 191 | extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, |
192 | struct scsi_cmnd *); | 192 | struct scsi_cmnd *); |
193 | extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *); | ||
194 | extern void zfcp_reqlist_remove(struct zfcp_adapter *, unsigned long); | ||
195 | extern struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *, | ||
196 | unsigned long); | ||
197 | extern int zfcp_reqlist_isempty(struct zfcp_adapter *); | ||
193 | 198 | ||
194 | #endif /* ZFCP_EXT_H */ | 199 | #endif /* ZFCP_EXT_H */ |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 31db2b06faba..ff2eacf5ec8c 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -49,7 +49,6 @@ static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); | |||
49 | static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *, | 49 | static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *, |
50 | struct fsf_link_down_info *); | 50 | struct fsf_link_down_info *); |
51 | static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); | 51 | static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); |
52 | static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); | ||
53 | 52 | ||
54 | /* association between FSF command and FSF QTCB type */ | 53 | /* association between FSF command and FSF QTCB type */ |
55 | static u32 fsf_qtcb_type[] = { | 54 | static u32 fsf_qtcb_type[] = { |
@@ -146,47 +145,48 @@ zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) | |||
146 | kfree(fsf_req); | 145 | kfree(fsf_req); |
147 | } | 146 | } |
148 | 147 | ||
149 | /* | 148 | /** |
150 | * function: | 149 | * zfcp_fsf_req_dismiss - dismiss a single fsf request |
151 | * | ||
152 | * purpose: | ||
153 | * | ||
154 | * returns: | ||
155 | * | ||
156 | * note: qdio queues shall be down (no ongoing inbound processing) | ||
157 | */ | 150 | */ |
158 | int | 151 | static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter, |
159 | zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) | 152 | struct zfcp_fsf_req *fsf_req, |
153 | unsigned int counter) | ||
160 | { | 154 | { |
161 | struct zfcp_fsf_req *fsf_req, *tmp; | 155 | u64 dbg_tmp[2]; |
162 | unsigned long flags; | ||
163 | LIST_HEAD(remove_queue); | ||
164 | 156 | ||
165 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); | 157 | dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active); |
166 | list_splice_init(&adapter->fsf_req_list_head, &remove_queue); | 158 | dbg_tmp[1] = (u64) counter; |
167 | atomic_set(&adapter->fsf_reqs_active, 0); | 159 | debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); |
168 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | 160 | list_del(&fsf_req->list); |
169 | 161 | fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; | |
170 | list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) { | 162 | zfcp_fsf_req_complete(fsf_req); |
171 | list_del(&fsf_req->list); | ||
172 | zfcp_fsf_req_dismiss(fsf_req); | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | } | 163 | } |
177 | 164 | ||
178 | /* | 165 | /** |
179 | * function: | 166 | * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests |
180 | * | ||
181 | * purpose: | ||
182 | * | ||
183 | * returns: | ||
184 | */ | 167 | */ |
185 | static void | 168 | int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) |
186 | zfcp_fsf_req_dismiss(struct zfcp_fsf_req *fsf_req) | ||
187 | { | 169 | { |
188 | fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; | 170 | struct zfcp_fsf_req *request, *tmp; |
189 | zfcp_fsf_req_complete(fsf_req); | 171 | unsigned long flags; |
172 | unsigned int i, counter; | ||
173 | |||
174 | spin_lock_irqsave(&adapter->req_list_lock, flags); | ||
175 | atomic_set(&adapter->reqs_active, 0); | ||
176 | for (i=0; i<REQUEST_LIST_SIZE; i++) { | ||
177 | if (list_empty(&adapter->req_list[i])) | ||
178 | continue; | ||
179 | |||
180 | counter = 0; | ||
181 | list_for_each_entry_safe(request, tmp, | ||
182 | &adapter->req_list[i], list) { | ||
183 | zfcp_fsf_req_dismiss(adapter, request, counter); | ||
184 | counter++; | ||
185 | } | ||
186 | } | ||
187 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
188 | |||
189 | return 0; | ||
190 | } | 190 | } |
191 | 191 | ||
192 | /* | 192 | /* |
@@ -4592,12 +4592,14 @@ static inline void | |||
4592 | zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) | 4592 | zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) |
4593 | { | 4593 | { |
4594 | if (likely(fsf_req->qtcb != NULL)) { | 4594 | if (likely(fsf_req->qtcb != NULL)) { |
4595 | fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no; | 4595 | fsf_req->qtcb->prefix.req_seq_no = |
4596 | fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req; | 4596 | fsf_req->adapter->fsf_req_seq_no; |
4597 | fsf_req->qtcb->prefix.req_id = fsf_req->req_id; | ||
4597 | fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; | 4598 | fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; |
4598 | fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command]; | 4599 | fsf_req->qtcb->prefix.qtcb_type = |
4600 | fsf_qtcb_type[fsf_req->fsf_command]; | ||
4599 | fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; | 4601 | fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; |
4600 | fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req; | 4602 | fsf_req->qtcb->header.req_handle = fsf_req->req_id; |
4601 | fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; | 4603 | fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; |
4602 | } | 4604 | } |
4603 | } | 4605 | } |
@@ -4654,6 +4656,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, | |||
4654 | { | 4656 | { |
4655 | volatile struct qdio_buffer_element *sbale; | 4657 | volatile struct qdio_buffer_element *sbale; |
4656 | struct zfcp_fsf_req *fsf_req = NULL; | 4658 | struct zfcp_fsf_req *fsf_req = NULL; |
4659 | unsigned long flags; | ||
4657 | int ret = 0; | 4660 | int ret = 0; |
4658 | struct zfcp_qdio_queue *req_queue = &adapter->request_queue; | 4661 | struct zfcp_qdio_queue *req_queue = &adapter->request_queue; |
4659 | 4662 | ||
@@ -4668,6 +4671,12 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, | |||
4668 | 4671 | ||
4669 | fsf_req->adapter = adapter; | 4672 | fsf_req->adapter = adapter; |
4670 | fsf_req->fsf_command = fsf_cmd; | 4673 | fsf_req->fsf_command = fsf_cmd; |
4674 | INIT_LIST_HEAD(&fsf_req->list); | ||
4675 | |||
4676 | /* unique request id */ | ||
4677 | spin_lock_irqsave(&adapter->req_list_lock, flags); | ||
4678 | fsf_req->req_id = adapter->req_no++; | ||
4679 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
4671 | 4680 | ||
4672 | zfcp_fsf_req_qtcb_init(fsf_req); | 4681 | zfcp_fsf_req_qtcb_init(fsf_req); |
4673 | 4682 | ||
@@ -4707,7 +4716,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, | |||
4707 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 4716 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
4708 | 4717 | ||
4709 | /* setup common SBALE fields */ | 4718 | /* setup common SBALE fields */ |
4710 | sbale[0].addr = fsf_req; | 4719 | sbale[0].addr = (void *) fsf_req->req_id; |
4711 | sbale[0].flags |= SBAL_FLAGS0_COMMAND; | 4720 | sbale[0].flags |= SBAL_FLAGS0_COMMAND; |
4712 | if (likely(fsf_req->qtcb != NULL)) { | 4721 | if (likely(fsf_req->qtcb != NULL)) { |
4713 | sbale[1].addr = (void *) fsf_req->qtcb; | 4722 | sbale[1].addr = (void *) fsf_req->qtcb; |
@@ -4747,7 +4756,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4747 | volatile struct qdio_buffer_element *sbale; | 4756 | volatile struct qdio_buffer_element *sbale; |
4748 | int inc_seq_no; | 4757 | int inc_seq_no; |
4749 | int new_distance_from_int; | 4758 | int new_distance_from_int; |
4750 | unsigned long flags; | 4759 | u64 dbg_tmp[2]; |
4751 | int retval = 0; | 4760 | int retval = 0; |
4752 | 4761 | ||
4753 | adapter = fsf_req->adapter; | 4762 | adapter = fsf_req->adapter; |
@@ -4761,10 +4770,10 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4761 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, | 4770 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, |
4762 | sbale[1].length); | 4771 | sbale[1].length); |
4763 | 4772 | ||
4764 | /* put allocated FSF request at list tail */ | 4773 | /* put allocated FSF request into hash table */ |
4765 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); | 4774 | spin_lock(&adapter->req_list_lock); |
4766 | list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); | 4775 | zfcp_reqlist_add(adapter, fsf_req); |
4767 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | 4776 | spin_unlock(&adapter->req_list_lock); |
4768 | 4777 | ||
4769 | inc_seq_no = (fsf_req->qtcb != NULL); | 4778 | inc_seq_no = (fsf_req->qtcb != NULL); |
4770 | 4779 | ||
@@ -4803,6 +4812,10 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4803 | QDIO_FLAG_SYNC_OUTPUT, | 4812 | QDIO_FLAG_SYNC_OUTPUT, |
4804 | 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); | 4813 | 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); |
4805 | 4814 | ||
4815 | dbg_tmp[0] = (unsigned long) sbale[0].addr; | ||
4816 | dbg_tmp[1] = (u64) retval; | ||
4817 | debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); | ||
4818 | |||
4806 | if (unlikely(retval)) { | 4819 | if (unlikely(retval)) { |
4807 | /* Queues are down..... */ | 4820 | /* Queues are down..... */ |
4808 | retval = -EIO; | 4821 | retval = -EIO; |
@@ -4812,22 +4825,17 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4812 | */ | 4825 | */ |
4813 | if (timer) | 4826 | if (timer) |
4814 | del_timer(timer); | 4827 | del_timer(timer); |
4815 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); | 4828 | spin_lock(&adapter->req_list_lock); |
4816 | list_del(&fsf_req->list); | 4829 | zfcp_reqlist_remove(adapter, fsf_req->req_id); |
4817 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | 4830 | spin_unlock(&adapter->req_list_lock); |
4818 | /* | 4831 | /* undo changes in request queue made for this request */ |
4819 | * adjust the number of free SBALs in request queue as well as | ||
4820 | * position of first one | ||
4821 | */ | ||
4822 | zfcp_qdio_zero_sbals(req_queue->buffer, | 4832 | zfcp_qdio_zero_sbals(req_queue->buffer, |
4823 | fsf_req->sbal_first, fsf_req->sbal_number); | 4833 | fsf_req->sbal_first, fsf_req->sbal_number); |
4824 | atomic_add(fsf_req->sbal_number, &req_queue->free_count); | 4834 | atomic_add(fsf_req->sbal_number, &req_queue->free_count); |
4825 | req_queue->free_index -= fsf_req->sbal_number; /* increase */ | 4835 | req_queue->free_index -= fsf_req->sbal_number; |
4826 | req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q; | 4836 | req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q; |
4827 | req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ | 4837 | req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ |
4828 | ZFCP_LOG_DEBUG | 4838 | zfcp_erp_adapter_reopen(adapter, 0); |
4829 | ("error: do_QDIO failed. Buffers could not be enqueued " | ||
4830 | "to request queue.\n"); | ||
4831 | } else { | 4839 | } else { |
4832 | req_queue->distance_from_int = new_distance_from_int; | 4840 | req_queue->distance_from_int = new_distance_from_int; |
4833 | /* | 4841 | /* |
@@ -4843,7 +4851,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4843 | adapter->fsf_req_seq_no++; | 4851 | adapter->fsf_req_seq_no++; |
4844 | 4852 | ||
4845 | /* count FSF requests pending */ | 4853 | /* count FSF requests pending */ |
4846 | atomic_inc(&adapter->fsf_reqs_active); | 4854 | atomic_inc(&adapter->reqs_active); |
4847 | } | 4855 | } |
4848 | return retval; | 4856 | return retval; |
4849 | } | 4857 | } |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 49ea5add4abc..dbd9f48e863e 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -282,6 +282,37 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device, | |||
282 | return; | 282 | return; |
283 | } | 283 | } |
284 | 284 | ||
285 | /** | ||
286 | * zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status | ||
287 | */ | ||
288 | static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, | ||
289 | unsigned long req_id) | ||
290 | { | ||
291 | struct zfcp_fsf_req *fsf_req; | ||
292 | unsigned long flags; | ||
293 | |||
294 | debug_long_event(adapter->erp_dbf, 4, req_id); | ||
295 | |||
296 | spin_lock_irqsave(&adapter->req_list_lock, flags); | ||
297 | fsf_req = zfcp_reqlist_ismember(adapter, req_id); | ||
298 | |||
299 | if (!fsf_req) { | ||
300 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
301 | ZFCP_LOG_NORMAL("error: unknown request id (%ld).\n", req_id); | ||
302 | zfcp_erp_adapter_reopen(adapter, 0); | ||
303 | return -EINVAL; | ||
304 | } | ||
305 | |||
306 | zfcp_reqlist_remove(adapter, req_id); | ||
307 | atomic_dec(&adapter->reqs_active); | ||
308 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | ||
309 | |||
310 | /* finish the FSF request */ | ||
311 | zfcp_fsf_req_complete(fsf_req); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
285 | /* | 316 | /* |
286 | * function: zfcp_qdio_response_handler | 317 | * function: zfcp_qdio_response_handler |
287 | * | 318 | * |
@@ -344,7 +375,7 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, | |||
344 | /* look for QDIO request identifiers in SB */ | 375 | /* look for QDIO request identifiers in SB */ |
345 | buffere = &buffer->element[buffere_index]; | 376 | buffere = &buffer->element[buffere_index]; |
346 | retval = zfcp_qdio_reqid_check(adapter, | 377 | retval = zfcp_qdio_reqid_check(adapter, |
347 | (void *) buffere->addr); | 378 | (unsigned long) buffere->addr); |
348 | 379 | ||
349 | if (retval) { | 380 | if (retval) { |
350 | ZFCP_LOG_NORMAL("bug: unexpected inbound " | 381 | ZFCP_LOG_NORMAL("bug: unexpected inbound " |
@@ -415,52 +446,6 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, | |||
415 | return; | 446 | return; |
416 | } | 447 | } |
417 | 448 | ||
418 | /* | ||
419 | * function: zfcp_qdio_reqid_check | ||
420 | * | ||
421 | * purpose: checks for valid reqids or unsolicited status | ||
422 | * | ||
423 | * returns: 0 - valid request id or unsolicited status | ||
424 | * !0 - otherwise | ||
425 | */ | ||
426 | int | ||
427 | zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) | ||
428 | { | ||
429 | struct zfcp_fsf_req *fsf_req; | ||
430 | unsigned long flags; | ||
431 | |||
432 | /* invalid (per convention used in this driver) */ | ||
433 | if (unlikely(!sbale_addr)) { | ||
434 | ZFCP_LOG_NORMAL("bug: invalid reqid\n"); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | |||
438 | /* valid request id and thus (hopefully :) valid fsf_req address */ | ||
439 | fsf_req = (struct zfcp_fsf_req *) sbale_addr; | ||
440 | |||
441 | /* serialize with zfcp_fsf_req_dismiss_all */ | ||
442 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); | ||
443 | if (list_empty(&adapter->fsf_req_list_head)) { | ||
444 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | ||
445 | return 0; | ||
446 | } | ||
447 | list_del(&fsf_req->list); | ||
448 | atomic_dec(&adapter->fsf_reqs_active); | ||
449 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | ||
450 | |||
451 | if (unlikely(adapter != fsf_req->adapter)) { | ||
452 | ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, " | ||
453 | "fsf_req->adapter=%p, adapter=%p)\n", | ||
454 | fsf_req, fsf_req->adapter, adapter); | ||
455 | return -EINVAL; | ||
456 | } | ||
457 | |||
458 | /* finish the FSF request */ | ||
459 | zfcp_fsf_req_complete(fsf_req); | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | /** | 449 | /** |
465 | * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue | 450 | * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue |
466 | * @queue: queue from which SBALE should be returned | 451 | * @queue: queue from which SBALE should be returned |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 671f4a6a5d18..1bb55086db9f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -30,7 +30,6 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *, | |||
30 | void (*done) (struct scsi_cmnd *)); | 30 | void (*done) (struct scsi_cmnd *)); |
31 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); | 31 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); |
32 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); | 32 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); |
33 | static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); | ||
34 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); | 33 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); |
35 | static int zfcp_task_management_function(struct zfcp_unit *, u8, | 34 | static int zfcp_task_management_function(struct zfcp_unit *, u8, |
36 | struct scsi_cmnd *); | 35 | struct scsi_cmnd *); |
@@ -46,30 +45,22 @@ struct zfcp_data zfcp_data = { | |||
46 | .scsi_host_template = { | 45 | .scsi_host_template = { |
47 | .name = ZFCP_NAME, | 46 | .name = ZFCP_NAME, |
48 | .proc_name = "zfcp", | 47 | .proc_name = "zfcp", |
49 | .proc_info = NULL, | ||
50 | .detect = NULL, | ||
51 | .slave_alloc = zfcp_scsi_slave_alloc, | 48 | .slave_alloc = zfcp_scsi_slave_alloc, |
52 | .slave_configure = zfcp_scsi_slave_configure, | 49 | .slave_configure = zfcp_scsi_slave_configure, |
53 | .slave_destroy = zfcp_scsi_slave_destroy, | 50 | .slave_destroy = zfcp_scsi_slave_destroy, |
54 | .queuecommand = zfcp_scsi_queuecommand, | 51 | .queuecommand = zfcp_scsi_queuecommand, |
55 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, | 52 | .eh_abort_handler = zfcp_scsi_eh_abort_handler, |
56 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, | 53 | .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, |
57 | .eh_bus_reset_handler = zfcp_scsi_eh_bus_reset_handler, | 54 | .eh_bus_reset_handler = zfcp_scsi_eh_host_reset_handler, |
58 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, | 55 | .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, |
59 | .can_queue = 4096, | 56 | .can_queue = 4096, |
60 | .this_id = -1, | 57 | .this_id = -1, |
61 | /* | ||
62 | * FIXME: | ||
63 | * one less? can zfcp_create_sbale cope with it? | ||
64 | */ | ||
65 | .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ, | 58 | .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ, |
66 | .cmd_per_lun = 1, | 59 | .cmd_per_lun = 1, |
67 | .unchecked_isa_dma = 0, | ||
68 | .use_clustering = 1, | 60 | .use_clustering = 1, |
69 | .sdev_attrs = zfcp_sysfs_sdev_attrs, | 61 | .sdev_attrs = zfcp_sysfs_sdev_attrs, |
70 | }, | 62 | }, |
71 | .driver_version = ZFCP_VERSION, | 63 | .driver_version = ZFCP_VERSION, |
72 | /* rest initialised with zeros */ | ||
73 | }; | 64 | }; |
74 | 65 | ||
75 | /* Find start of Response Information in FCP response unit*/ | 66 | /* Find start of Response Information in FCP response unit*/ |
@@ -176,8 +167,14 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) | |||
176 | return retval; | 167 | return retval; |
177 | } | 168 | } |
178 | 169 | ||
179 | static void | 170 | /** |
180 | zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | 171 | * zfcp_scsi_slave_destroy - called when scsi device is removed |
172 | * | ||
173 | * Remove reference to associated scsi device for an zfcp_unit. | ||
174 | * Mark zfcp_unit as failed. The scsi device might be deleted via sysfs | ||
175 | * or a scan for this device might have failed. | ||
176 | */ | ||
177 | static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | ||
181 | { | 178 | { |
182 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; | 179 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; |
183 | 180 | ||
@@ -185,6 +182,7 @@ zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | |||
185 | atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); | 182 | atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); |
186 | sdpnt->hostdata = NULL; | 183 | sdpnt->hostdata = NULL; |
187 | unit->device = NULL; | 184 | unit->device = NULL; |
185 | zfcp_erp_unit_failed(unit); | ||
188 | zfcp_unit_put(unit); | 186 | zfcp_unit_put(unit); |
189 | } else { | 187 | } else { |
190 | ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " | 188 | ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " |
@@ -549,35 +547,38 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, | |||
549 | } | 547 | } |
550 | 548 | ||
551 | /** | 549 | /** |
552 | * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter) | 550 | * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset |
551 | * | ||
552 | * If ERP is already running it will be stopped. | ||
553 | */ | 553 | */ |
554 | int | 554 | int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
555 | zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) | ||
556 | { | 555 | { |
557 | struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; | 556 | struct zfcp_unit *unit; |
558 | struct zfcp_adapter *adapter = unit->port->adapter; | 557 | struct zfcp_adapter *adapter; |
559 | 558 | unsigned long flags; | |
560 | ZFCP_LOG_NORMAL("bus reset because of problems with " | ||
561 | "unit 0x%016Lx\n", unit->fcp_lun); | ||
562 | zfcp_erp_adapter_reopen(adapter, 0); | ||
563 | zfcp_erp_wait(adapter); | ||
564 | |||
565 | return SUCCESS; | ||
566 | } | ||
567 | 559 | ||
568 | /** | 560 | unit = (struct zfcp_unit*) scpnt->device->hostdata; |
569 | * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter) | 561 | adapter = unit->port->adapter; |
570 | */ | ||
571 | int | ||
572 | zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | ||
573 | { | ||
574 | struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; | ||
575 | struct zfcp_adapter *adapter = unit->port->adapter; | ||
576 | 562 | ||
577 | ZFCP_LOG_NORMAL("host reset because of problems with " | 563 | ZFCP_LOG_NORMAL("host/bus reset because of problems with " |
578 | "unit 0x%016Lx\n", unit->fcp_lun); | 564 | "unit 0x%016Lx\n", unit->fcp_lun); |
579 | zfcp_erp_adapter_reopen(adapter, 0); | 565 | |
580 | zfcp_erp_wait(adapter); | 566 | write_lock_irqsave(&adapter->erp_lock, flags); |
567 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, | ||
568 | &adapter->status)) { | ||
569 | zfcp_erp_modify_adapter_status(adapter, | ||
570 | ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN, | ||
571 | ZFCP_CLEAR); | ||
572 | zfcp_erp_action_dismiss_adapter(adapter); | ||
573 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
574 | zfcp_fsf_req_dismiss_all(adapter); | ||
575 | adapter->fsf_req_seq_no = 0; | ||
576 | zfcp_erp_adapter_reopen(adapter, 0); | ||
577 | } else { | ||
578 | write_unlock_irqrestore(&adapter->erp_lock, flags); | ||
579 | zfcp_erp_adapter_reopen(adapter, 0); | ||
580 | zfcp_erp_wait(adapter); | ||
581 | } | ||
581 | 582 | ||
582 | return SUCCESS; | 583 | return SUCCESS; |
583 | } | 584 | } |