diff options
| -rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 89 | ||||
| -rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 60 |
2 files changed, 64 insertions, 85 deletions
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 8d503d9c8af7..ee7314d8c2da 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
| @@ -2243,29 +2243,26 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
| 2243 | return retval; | 2243 | return retval; |
| 2244 | } | 2244 | } |
| 2245 | 2245 | ||
| 2246 | /* | ||
| 2247 | * function: zfcp_fsf_init | ||
| 2248 | * | ||
| 2249 | * purpose: initializes FSF operation for the specified adapter | ||
| 2250 | * | ||
| 2251 | * returns: 0 - succesful initialization of FSF operation | ||
| 2252 | * !0 - failed to initialize FSF operation | ||
| 2253 | */ | ||
| 2254 | static int | 2246 | static int |
| 2255 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) | 2247 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) |
| 2256 | { | 2248 | { |
| 2257 | int xconfig, xport; | 2249 | int retval; |
| 2258 | 2250 | ||
| 2259 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 2251 | if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, |
| 2260 | &erp_action->adapter->status)) { | 2252 | &erp_action->adapter->status)) && |
| 2253 | (erp_action->adapter->adapter_features & | ||
| 2254 | FSF_FEATURE_HBAAPI_MANAGEMENT)) { | ||
| 2261 | zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | 2255 | zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); |
| 2262 | atomic_set(&erp_action->adapter->erp_counter, 0); | 2256 | atomic_set(&erp_action->adapter->erp_counter, 0); |
| 2263 | return ZFCP_ERP_FAILED; | 2257 | return ZFCP_ERP_FAILED; |
| 2264 | } | 2258 | } |
| 2265 | 2259 | ||
| 2266 | xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); | 2260 | retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); |
| 2267 | xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | 2261 | if (retval == ZFCP_ERP_FAILED) |
| 2268 | if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED)) | 2262 | return ZFCP_ERP_FAILED; |
| 2263 | |||
| 2264 | retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | ||
| 2265 | if (retval == ZFCP_ERP_FAILED) | ||
| 2269 | return ZFCP_ERP_FAILED; | 2266 | return ZFCP_ERP_FAILED; |
| 2270 | 2267 | ||
| 2271 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); | 2268 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); |
| @@ -2354,41 +2351,29 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | |||
| 2354 | static int | 2351 | static int |
| 2355 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | 2352 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) |
| 2356 | { | 2353 | { |
| 2357 | int retval = ZFCP_ERP_SUCCEEDED; | 2354 | int ret; |
| 2358 | int retries; | 2355 | int retries; |
| 2359 | int sleep; | 2356 | int sleep; |
| 2360 | struct zfcp_adapter *adapter = erp_action->adapter; | 2357 | struct zfcp_adapter *adapter = erp_action->adapter; |
| 2361 | 2358 | ||
| 2362 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | 2359 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); |
| 2363 | 2360 | ||
| 2364 | for (retries = 0; ; retries++) { | 2361 | retries = 0; |
| 2365 | ZFCP_LOG_DEBUG("Doing exchange port data\n"); | 2362 | do { |
| 2363 | write_lock(&adapter->erp_lock); | ||
| 2366 | zfcp_erp_action_to_running(erp_action); | 2364 | zfcp_erp_action_to_running(erp_action); |
| 2365 | write_unlock(&adapter->erp_lock); | ||
| 2367 | zfcp_erp_timeout_init(erp_action); | 2366 | zfcp_erp_timeout_init(erp_action); |
| 2368 | if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) { | 2367 | ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); |
| 2369 | retval = ZFCP_ERP_FAILED; | 2368 | if (ret == -EOPNOTSUPP) { |
| 2370 | debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); | 2369 | debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); |
| 2371 | ZFCP_LOG_INFO("error: initiation of exchange of " | 2370 | return ZFCP_ERP_SUCCEEDED; |
| 2372 | "port data failed for adapter %s\n", | 2371 | } else if (ret) { |
| 2373 | zfcp_get_busid_by_adapter(adapter)); | 2372 | debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); |
| 2374 | break; | 2373 | return ZFCP_ERP_FAILED; |
| 2375 | } | 2374 | } |
| 2376 | debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); | 2375 | debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); |
| 2377 | ZFCP_LOG_DEBUG("Xchange underway\n"); | ||
| 2378 | 2376 | ||
| 2379 | /* | ||
| 2380 | * Why this works: | ||
| 2381 | * Both the normal completion handler as well as the timeout | ||
| 2382 | * handler will do an 'up' when the 'exchange port data' | ||
| 2383 | * request completes or times out. Thus, the signal to go on | ||
| 2384 | * won't be lost utilizing this semaphore. | ||
| 2385 | * Furthermore, this 'adapter_reopen' action is | ||
| 2386 | * guaranteed to be the only action being there (highest action | ||
| 2387 | * which prevents other actions from being created). | ||
| 2388 | * Resulting from that, the wake signal recognized here | ||
| 2389 | * _must_ be the one belonging to the 'exchange port | ||
| 2390 | * data' request. | ||
| 2391 | */ | ||
| 2392 | down(&adapter->erp_ready_sem); | 2377 | down(&adapter->erp_ready_sem); |
| 2393 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { | 2378 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { |
| 2394 | ZFCP_LOG_INFO("error: exchange of port data " | 2379 | ZFCP_LOG_INFO("error: exchange of port data " |
| @@ -2396,29 +2381,19 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | |||
| 2396 | zfcp_get_busid_by_adapter(adapter)); | 2381 | zfcp_get_busid_by_adapter(adapter)); |
| 2397 | break; | 2382 | break; |
| 2398 | } | 2383 | } |
| 2399 | |||
| 2400 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 2384 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, |
| 2401 | &adapter->status)) | 2385 | &adapter->status)) |
| 2402 | break; | 2386 | break; |
| 2403 | 2387 | ||
| 2404 | ZFCP_LOG_DEBUG("host connection still initialising... " | 2388 | if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) { |
| 2405 | "waiting and retrying...\n"); | 2389 | sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP; |
| 2406 | /* sleep a little bit before retry */ | 2390 | retries++; |
| 2407 | sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ? | 2391 | } else |
| 2408 | ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP : | 2392 | sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; |
| 2409 | ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; | 2393 | schedule_timeout(sleep); |
| 2410 | msleep(jiffies_to_msecs(sleep)); | 2394 | } while (1); |
| 2411 | } | ||
| 2412 | |||
| 2413 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
| 2414 | &adapter->status)) { | ||
| 2415 | ZFCP_LOG_INFO("error: exchange of port data for " | ||
| 2416 | "adapter %s failed\n", | ||
| 2417 | zfcp_get_busid_by_adapter(adapter)); | ||
| 2418 | retval = ZFCP_ERP_FAILED; | ||
| 2419 | } | ||
| 2420 | 2395 | ||
| 2421 | return retval; | 2396 | return ZFCP_ERP_SUCCEEDED; |
| 2422 | } | 2397 | } |
| 2423 | 2398 | ||
| 2424 | /* | 2399 | /* |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 3b0fc1163f5f..fbc81b012919 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
| @@ -2191,13 +2191,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
| 2191 | return -EOPNOTSUPP; | 2191 | return -EOPNOTSUPP; |
| 2192 | } | 2192 | } |
| 2193 | 2193 | ||
| 2194 | timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); | ||
| 2195 | if (!timer) | ||
| 2196 | return -ENOMEM; | ||
| 2197 | |||
| 2198 | /* setup new FSF request */ | 2194 | /* setup new FSF request */ |
| 2199 | retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, | 2195 | retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, |
| 2200 | 0, 0, &lock_flags, &fsf_req); | 2196 | erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0, |
| 2197 | 0, &lock_flags, &fsf_req); | ||
| 2201 | if (retval < 0) { | 2198 | if (retval < 0) { |
| 2202 | ZFCP_LOG_INFO("error: Out of resources. Could not create an " | 2199 | ZFCP_LOG_INFO("error: Out of resources. Could not create an " |
| 2203 | "exchange port data request for" | 2200 | "exchange port data request for" |
| @@ -2205,25 +2202,33 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
| 2205 | zfcp_get_busid_by_adapter(adapter)); | 2202 | zfcp_get_busid_by_adapter(adapter)); |
| 2206 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | 2203 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, |
| 2207 | lock_flags); | 2204 | lock_flags); |
| 2208 | goto out; | 2205 | return retval; |
| 2209 | } | ||
| 2210 | |||
| 2211 | if (erp_action) { | ||
| 2212 | erp_action->fsf_req = fsf_req; | ||
| 2213 | fsf_req->erp_action = erp_action; | ||
| 2214 | } | 2206 | } |
| 2215 | 2207 | ||
| 2216 | if (data) | 2208 | if (data) |
| 2217 | fsf_req->data = (unsigned long) data; | 2209 | fsf_req->data = (unsigned long) data; |
| 2218 | 2210 | ||
| 2219 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 2211 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
| 2220 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 2212 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
| 2221 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2213 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
| 2222 | 2214 | ||
| 2223 | init_timer(timer); | 2215 | if (erp_action) { |
| 2224 | timer->function = zfcp_fsf_request_timeout_handler; | 2216 | erp_action->fsf_req = fsf_req; |
| 2225 | timer->data = (unsigned long) adapter; | 2217 | fsf_req->erp_action = erp_action; |
| 2226 | timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; | 2218 | timer = &erp_action->timer; |
| 2219 | } else { | ||
| 2220 | timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC); | ||
| 2221 | if (!timer) { | ||
| 2222 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | ||
| 2223 | lock_flags); | ||
| 2224 | zfcp_fsf_req_free(fsf_req); | ||
| 2225 | return -ENOMEM; | ||
| 2226 | } | ||
| 2227 | init_timer(timer); | ||
| 2228 | timer->function = zfcp_fsf_request_timeout_handler; | ||
| 2229 | timer->data = (unsigned long) adapter; | ||
| 2230 | timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; | ||
| 2231 | } | ||
| 2227 | 2232 | ||
| 2228 | retval = zfcp_fsf_req_send(fsf_req, timer); | 2233 | retval = zfcp_fsf_req_send(fsf_req, timer); |
| 2229 | if (retval) { | 2234 | if (retval) { |
| @@ -2233,23 +2238,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
| 2233 | zfcp_fsf_req_free(fsf_req); | 2238 | zfcp_fsf_req_free(fsf_req); |
| 2234 | if (erp_action) | 2239 | if (erp_action) |
| 2235 | erp_action->fsf_req = NULL; | 2240 | erp_action->fsf_req = NULL; |
| 2241 | else | ||
| 2242 | kfree(timer); | ||
| 2236 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | 2243 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, |
| 2237 | lock_flags); | 2244 | lock_flags); |
| 2238 | goto out; | 2245 | return retval; |
| 2239 | } | 2246 | } |
| 2240 | 2247 | ||
| 2241 | ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n", | 2248 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); |
| 2242 | zfcp_get_busid_by_adapter(adapter)); | ||
| 2243 | |||
| 2244 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | ||
| 2245 | lock_flags); | ||
| 2246 | 2249 | ||
| 2247 | wait_event(fsf_req->completion_wq, | 2250 | if (!erp_action) { |
| 2248 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 2251 | wait_event(fsf_req->completion_wq, |
| 2249 | del_timer_sync(timer); | 2252 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
| 2250 | zfcp_fsf_req_free(fsf_req); | 2253 | del_timer_sync(timer); |
| 2251 | out: | 2254 | zfcp_fsf_req_free(fsf_req); |
| 2252 | kfree(timer); | 2255 | kfree(timer); |
| 2256 | } | ||
| 2253 | return retval; | 2257 | return retval; |
| 2254 | } | 2258 | } |
| 2255 | 2259 | ||
