diff options
Diffstat (limited to 'drivers/s390/scsi')
-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 | ||