aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ibmvscsi/ibmvfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvfc.c')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c466
1 files changed, 324 insertions, 142 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index ea4abee7a2a9..166d96450a0e 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -110,7 +110,7 @@ static const struct {
110 { IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_DEAD, DID_ERROR, 0, 1, "transport dead" }, 110 { IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_DEAD, DID_ERROR, 0, 1, "transport dead" },
111 { IBMVFC_FABRIC_MAPPED, IBMVFC_CONFIG_ERROR, DID_ERROR, 1, 1, "configuration error" }, 111 { IBMVFC_FABRIC_MAPPED, IBMVFC_CONFIG_ERROR, DID_ERROR, 1, 1, "configuration error" },
112 { IBMVFC_FABRIC_MAPPED, IBMVFC_NAME_SERVER_FAIL, DID_ERROR, 1, 1, "name server failure" }, 112 { IBMVFC_FABRIC_MAPPED, IBMVFC_NAME_SERVER_FAIL, DID_ERROR, 1, 1, "name server failure" },
113 { IBMVFC_FABRIC_MAPPED, IBMVFC_LINK_HALTED, DID_REQUEUE, 0, 0, "link halted" }, 113 { IBMVFC_FABRIC_MAPPED, IBMVFC_LINK_HALTED, DID_REQUEUE, 1, 0, "link halted" },
114 { IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_GENERAL, DID_OK, 1, 0, "general transport error" }, 114 { IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_GENERAL, DID_OK, 1, 0, "general transport error" },
115 115
116 { IBMVFC_VIOS_FAILURE, IBMVFC_CRQ_FAILURE, DID_REQUEUE, 1, 1, "CRQ failure" }, 116 { IBMVFC_VIOS_FAILURE, IBMVFC_CRQ_FAILURE, DID_REQUEUE, 1, 1, "CRQ failure" },
@@ -143,6 +143,7 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *);
143static void ibmvfc_tgt_send_prli(struct ibmvfc_target *); 143static void ibmvfc_tgt_send_prli(struct ibmvfc_target *);
144static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *); 144static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *);
145static void ibmvfc_tgt_query_target(struct ibmvfc_target *); 145static void ibmvfc_tgt_query_target(struct ibmvfc_target *);
146static void ibmvfc_npiv_logout(struct ibmvfc_host *);
146 147
147static const char *unknown_error = "unknown error"; 148static const char *unknown_error = "unknown error";
148 149
@@ -275,7 +276,7 @@ static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd)
275 int fc_rsp_len = rsp->fcp_rsp_len; 276 int fc_rsp_len = rsp->fcp_rsp_len;
276 277
277 if ((rsp->flags & FCP_RSP_LEN_VALID) && 278 if ((rsp->flags & FCP_RSP_LEN_VALID) &&
278 ((!fc_rsp_len && fc_rsp_len != 4 && fc_rsp_len != 8) || 279 ((fc_rsp_len && fc_rsp_len != 4 && fc_rsp_len != 8) ||
279 rsp->data.info.rsp_code)) 280 rsp->data.info.rsp_code))
280 return DID_ERROR << 16; 281 return DID_ERROR << 16;
281 282
@@ -431,6 +432,8 @@ static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt,
431 case IBMVFC_TGT_ACTION_DEL_RPORT: 432 case IBMVFC_TGT_ACTION_DEL_RPORT:
432 break; 433 break;
433 default: 434 default:
435 if (action == IBMVFC_TGT_ACTION_DEL_RPORT)
436 tgt->add_rport = 0;
434 tgt->action = action; 437 tgt->action = action;
435 break; 438 break;
436 } 439 }
@@ -475,6 +478,10 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
475 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) 478 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT)
476 vhost->action = action; 479 vhost->action = action;
477 break; 480 break;
481 case IBMVFC_HOST_ACTION_LOGO_WAIT:
482 if (vhost->action == IBMVFC_HOST_ACTION_LOGO)
483 vhost->action = action;
484 break;
478 case IBMVFC_HOST_ACTION_INIT_WAIT: 485 case IBMVFC_HOST_ACTION_INIT_WAIT:
479 if (vhost->action == IBMVFC_HOST_ACTION_INIT) 486 if (vhost->action == IBMVFC_HOST_ACTION_INIT)
480 vhost->action = action; 487 vhost->action = action;
@@ -483,7 +490,7 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
483 switch (vhost->action) { 490 switch (vhost->action) {
484 case IBMVFC_HOST_ACTION_INIT_WAIT: 491 case IBMVFC_HOST_ACTION_INIT_WAIT:
485 case IBMVFC_HOST_ACTION_NONE: 492 case IBMVFC_HOST_ACTION_NONE:
486 case IBMVFC_HOST_ACTION_TGT_ADD: 493 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
487 vhost->action = action; 494 vhost->action = action;
488 break; 495 break;
489 default: 496 default:
@@ -494,11 +501,11 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost,
494 if (vhost->action == IBMVFC_HOST_ACTION_ALLOC_TGTS) 501 if (vhost->action == IBMVFC_HOST_ACTION_ALLOC_TGTS)
495 vhost->action = action; 502 vhost->action = action;
496 break; 503 break;
504 case IBMVFC_HOST_ACTION_LOGO:
497 case IBMVFC_HOST_ACTION_INIT: 505 case IBMVFC_HOST_ACTION_INIT:
498 case IBMVFC_HOST_ACTION_TGT_DEL: 506 case IBMVFC_HOST_ACTION_TGT_DEL:
499 case IBMVFC_HOST_ACTION_QUERY_TGTS: 507 case IBMVFC_HOST_ACTION_QUERY_TGTS:
500 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: 508 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
501 case IBMVFC_HOST_ACTION_TGT_ADD:
502 case IBMVFC_HOST_ACTION_NONE: 509 case IBMVFC_HOST_ACTION_NONE:
503 default: 510 default:
504 vhost->action = action; 511 vhost->action = action;
@@ -576,7 +583,7 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost, int relogin)
576 } 583 }
577 584
578 list_for_each_entry(tgt, &vhost->targets, queue) 585 list_for_each_entry(tgt, &vhost->targets, queue)
579 tgt->need_login = 1; 586 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
580 scsi_block_requests(vhost->host); 587 scsi_block_requests(vhost->host);
581 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); 588 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
582 vhost->job_step = ibmvfc_npiv_login; 589 vhost->job_step = ibmvfc_npiv_login;
@@ -646,6 +653,7 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost)
646 } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); 653 } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
647 654
648 vhost->state = IBMVFC_NO_CRQ; 655 vhost->state = IBMVFC_NO_CRQ;
656 vhost->logged_in = 0;
649 dma_unmap_single(vhost->dev, crq->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL); 657 dma_unmap_single(vhost->dev, crq->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL);
650 free_page((unsigned long)crq->msgs); 658 free_page((unsigned long)crq->msgs);
651} 659}
@@ -692,6 +700,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
692 } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); 700 } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
693 701
694 vhost->state = IBMVFC_NO_CRQ; 702 vhost->state = IBMVFC_NO_CRQ;
703 vhost->logged_in = 0;
695 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); 704 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
696 705
697 /* Clean out the queue */ 706 /* Clean out the queue */
@@ -807,10 +816,10 @@ static void ibmvfc_purge_requests(struct ibmvfc_host *vhost, int error_code)
807} 816}
808 817
809/** 818/**
810 * __ibmvfc_reset_host - Reset the connection to the server (no locking) 819 * ibmvfc_hard_reset_host - Reset the connection to the server by breaking the CRQ
811 * @vhost: struct ibmvfc host to reset 820 * @vhost: struct ibmvfc host to reset
812 **/ 821 **/
813static void __ibmvfc_reset_host(struct ibmvfc_host *vhost) 822static void ibmvfc_hard_reset_host(struct ibmvfc_host *vhost)
814{ 823{
815 int rc; 824 int rc;
816 825
@@ -826,9 +835,25 @@ static void __ibmvfc_reset_host(struct ibmvfc_host *vhost)
826} 835}
827 836
828/** 837/**
829 * ibmvfc_reset_host - Reset the connection to the server 838 * __ibmvfc_reset_host - Reset the connection to the server (no locking)
830 * @vhost: struct ibmvfc host to reset 839 * @vhost: struct ibmvfc host to reset
831 **/ 840 **/
841static void __ibmvfc_reset_host(struct ibmvfc_host *vhost)
842{
843 if (vhost->logged_in && vhost->action != IBMVFC_HOST_ACTION_LOGO_WAIT &&
844 !ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
845 scsi_block_requests(vhost->host);
846 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_LOGO);
847 vhost->job_step = ibmvfc_npiv_logout;
848 wake_up(&vhost->work_wait_q);
849 } else
850 ibmvfc_hard_reset_host(vhost);
851}
852
853/**
854 * ibmvfc_reset_host - Reset the connection to the server
855 * @vhost: ibmvfc host struct
856 **/
832static void ibmvfc_reset_host(struct ibmvfc_host *vhost) 857static void ibmvfc_reset_host(struct ibmvfc_host *vhost)
833{ 858{
834 unsigned long flags; 859 unsigned long flags;
@@ -842,9 +867,13 @@ static void ibmvfc_reset_host(struct ibmvfc_host *vhost)
842 * ibmvfc_retry_host_init - Retry host initialization if allowed 867 * ibmvfc_retry_host_init - Retry host initialization if allowed
843 * @vhost: ibmvfc host struct 868 * @vhost: ibmvfc host struct
844 * 869 *
870 * Returns: 1 if init will be retried / 0 if not
871 *
845 **/ 872 **/
846static void ibmvfc_retry_host_init(struct ibmvfc_host *vhost) 873static int ibmvfc_retry_host_init(struct ibmvfc_host *vhost)
847{ 874{
875 int retry = 0;
876
848 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) { 877 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) {
849 vhost->delay_init = 1; 878 vhost->delay_init = 1;
850 if (++vhost->init_retries > IBMVFC_MAX_HOST_INIT_RETRIES) { 879 if (++vhost->init_retries > IBMVFC_MAX_HOST_INIT_RETRIES) {
@@ -853,11 +882,14 @@ static void ibmvfc_retry_host_init(struct ibmvfc_host *vhost)
853 ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE); 882 ibmvfc_link_down(vhost, IBMVFC_HOST_OFFLINE);
854 } else if (vhost->init_retries == IBMVFC_MAX_HOST_INIT_RETRIES) 883 } else if (vhost->init_retries == IBMVFC_MAX_HOST_INIT_RETRIES)
855 __ibmvfc_reset_host(vhost); 884 __ibmvfc_reset_host(vhost);
856 else 885 else {
857 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); 886 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
887 retry = 1;
888 }
858 } 889 }
859 890
860 wake_up(&vhost->work_wait_q); 891 wake_up(&vhost->work_wait_q);
892 return retry;
861} 893}
862 894
863/** 895/**
@@ -1137,8 +1169,9 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
1137 login_info->partition_num = vhost->partition_number; 1169 login_info->partition_num = vhost->partition_number;
1138 login_info->vfc_frame_version = 1; 1170 login_info->vfc_frame_version = 1;
1139 login_info->fcp_version = 3; 1171 login_info->fcp_version = 3;
1172 login_info->flags = IBMVFC_FLUSH_ON_HALT;
1140 if (vhost->client_migrated) 1173 if (vhost->client_migrated)
1141 login_info->flags = IBMVFC_CLIENT_MIGRATED; 1174 login_info->flags |= IBMVFC_CLIENT_MIGRATED;
1142 1175
1143 login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ; 1176 login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ;
1144 login_info->capabilities = IBMVFC_CAN_MIGRATE; 1177 login_info->capabilities = IBMVFC_CAN_MIGRATE;
@@ -1452,6 +1485,27 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
1452} 1485}
1453 1486
1454/** 1487/**
1488 * ibmvfc_relogin - Log back into the specified device
1489 * @sdev: scsi device struct
1490 *
1491 **/
1492static void ibmvfc_relogin(struct scsi_device *sdev)
1493{
1494 struct ibmvfc_host *vhost = shost_priv(sdev->host);
1495 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
1496 struct ibmvfc_target *tgt;
1497
1498 list_for_each_entry(tgt, &vhost->targets, queue) {
1499 if (rport == tgt->rport) {
1500 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
1501 break;
1502 }
1503 }
1504
1505 ibmvfc_reinit_host(vhost);
1506}
1507
1508/**
1455 * ibmvfc_scsi_done - Handle responses from commands 1509 * ibmvfc_scsi_done - Handle responses from commands
1456 * @evt: ibmvfc event to be handled 1510 * @evt: ibmvfc event to be handled
1457 * 1511 *
@@ -1483,7 +1537,7 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
1483 if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8) 1537 if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8)
1484 memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len); 1538 memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len);
1485 if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED)) 1539 if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED))
1486 ibmvfc_reinit_host(evt->vhost); 1540 ibmvfc_relogin(cmnd->device);
1487 1541
1488 if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER))) 1542 if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER)))
1489 cmnd->result = (DID_ERROR << 16); 1543 cmnd->result = (DID_ERROR << 16);
@@ -2148,13 +2202,31 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
2148 struct ibmvfc_host *vhost) 2202 struct ibmvfc_host *vhost)
2149{ 2203{
2150 const char *desc = ibmvfc_get_ae_desc(crq->event); 2204 const char *desc = ibmvfc_get_ae_desc(crq->event);
2205 struct ibmvfc_target *tgt;
2151 2206
2152 ibmvfc_log(vhost, 3, "%s event received. scsi_id: %llx, wwpn: %llx," 2207 ibmvfc_log(vhost, 3, "%s event received. scsi_id: %llx, wwpn: %llx,"
2153 " node_name: %llx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name); 2208 " node_name: %llx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name);
2154 2209
2155 switch (crq->event) { 2210 switch (crq->event) {
2156 case IBMVFC_AE_LINK_UP:
2157 case IBMVFC_AE_RESUME: 2211 case IBMVFC_AE_RESUME:
2212 switch (crq->link_state) {
2213 case IBMVFC_AE_LS_LINK_DOWN:
2214 ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN);
2215 break;
2216 case IBMVFC_AE_LS_LINK_DEAD:
2217 ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
2218 break;
2219 case IBMVFC_AE_LS_LINK_UP:
2220 case IBMVFC_AE_LS_LINK_BOUNCED:
2221 default:
2222 vhost->events_to_log |= IBMVFC_AE_LINKUP;
2223 vhost->delay_init = 1;
2224 __ibmvfc_reset_host(vhost);
2225 break;
2226 };
2227
2228 break;
2229 case IBMVFC_AE_LINK_UP:
2158 vhost->events_to_log |= IBMVFC_AE_LINKUP; 2230 vhost->events_to_log |= IBMVFC_AE_LINKUP;
2159 vhost->delay_init = 1; 2231 vhost->delay_init = 1;
2160 __ibmvfc_reset_host(vhost); 2232 __ibmvfc_reset_host(vhost);
@@ -2168,10 +2240,27 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
2168 case IBMVFC_AE_SCN_NPORT: 2240 case IBMVFC_AE_SCN_NPORT:
2169 case IBMVFC_AE_SCN_GROUP: 2241 case IBMVFC_AE_SCN_GROUP:
2170 vhost->events_to_log |= IBMVFC_AE_RSCN; 2242 vhost->events_to_log |= IBMVFC_AE_RSCN;
2243 ibmvfc_reinit_host(vhost);
2244 break;
2171 case IBMVFC_AE_ELS_LOGO: 2245 case IBMVFC_AE_ELS_LOGO:
2172 case IBMVFC_AE_ELS_PRLO: 2246 case IBMVFC_AE_ELS_PRLO:
2173 case IBMVFC_AE_ELS_PLOGI: 2247 case IBMVFC_AE_ELS_PLOGI:
2174 ibmvfc_reinit_host(vhost); 2248 list_for_each_entry(tgt, &vhost->targets, queue) {
2249 if (!crq->scsi_id && !crq->wwpn && !crq->node_name)
2250 break;
2251 if (crq->scsi_id && tgt->scsi_id != crq->scsi_id)
2252 continue;
2253 if (crq->wwpn && tgt->ids.port_name != crq->wwpn)
2254 continue;
2255 if (crq->node_name && tgt->ids.node_name != crq->node_name)
2256 continue;
2257 if (tgt->need_login && crq->event == IBMVFC_AE_ELS_LOGO)
2258 tgt->logo_rcvd = 1;
2259 if (!tgt->need_login || crq->event == IBMVFC_AE_ELS_PLOGI) {
2260 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
2261 ibmvfc_reinit_host(vhost);
2262 }
2263 }
2175 break; 2264 break;
2176 case IBMVFC_AE_LINK_DOWN: 2265 case IBMVFC_AE_LINK_DOWN:
2177 case IBMVFC_AE_ADAPTER_FAILED: 2266 case IBMVFC_AE_ADAPTER_FAILED:
@@ -2222,6 +2311,7 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
2222 return; 2311 return;
2223 case IBMVFC_CRQ_XPORT_EVENT: 2312 case IBMVFC_CRQ_XPORT_EVENT:
2224 vhost->state = IBMVFC_NO_CRQ; 2313 vhost->state = IBMVFC_NO_CRQ;
2314 vhost->logged_in = 0;
2225 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); 2315 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
2226 if (crq->format == IBMVFC_PARTITION_MIGRATED) { 2316 if (crq->format == IBMVFC_PARTITION_MIGRATED) {
2227 /* We need to re-setup the interpartition connection */ 2317 /* We need to re-setup the interpartition connection */
@@ -2299,7 +2389,7 @@ static int ibmvfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
2299 done = 1; 2389 done = 1;
2300 } 2390 }
2301 2391
2302 if (vhost->state != IBMVFC_NO_CRQ && vhost->action == IBMVFC_HOST_ACTION_NONE) 2392 if (vhost->scan_complete)
2303 done = 1; 2393 done = 1;
2304 spin_unlock_irqrestore(shost->host_lock, flags); 2394 spin_unlock_irqrestore(shost->host_lock, flags);
2305 return done; 2395 return done;
@@ -2434,14 +2524,6 @@ static ssize_t ibmvfc_show_host_partition_name(struct device *dev,
2434 vhost->login_buf->resp.partition_name); 2524 vhost->login_buf->resp.partition_name);
2435} 2525}
2436 2526
2437static struct device_attribute ibmvfc_host_partition_name = {
2438 .attr = {
2439 .name = "partition_name",
2440 .mode = S_IRUGO,
2441 },
2442 .show = ibmvfc_show_host_partition_name,
2443};
2444
2445static ssize_t ibmvfc_show_host_device_name(struct device *dev, 2527static ssize_t ibmvfc_show_host_device_name(struct device *dev,
2446 struct device_attribute *attr, char *buf) 2528 struct device_attribute *attr, char *buf)
2447{ 2529{
@@ -2452,14 +2534,6 @@ static ssize_t ibmvfc_show_host_device_name(struct device *dev,
2452 vhost->login_buf->resp.device_name); 2534 vhost->login_buf->resp.device_name);
2453} 2535}
2454 2536
2455static struct device_attribute ibmvfc_host_device_name = {
2456 .attr = {
2457 .name = "device_name",
2458 .mode = S_IRUGO,
2459 },
2460 .show = ibmvfc_show_host_device_name,
2461};
2462
2463static ssize_t ibmvfc_show_host_loc_code(struct device *dev, 2537static ssize_t ibmvfc_show_host_loc_code(struct device *dev,
2464 struct device_attribute *attr, char *buf) 2538 struct device_attribute *attr, char *buf)
2465{ 2539{
@@ -2470,14 +2544,6 @@ static ssize_t ibmvfc_show_host_loc_code(struct device *dev,
2470 vhost->login_buf->resp.port_loc_code); 2544 vhost->login_buf->resp.port_loc_code);
2471} 2545}
2472 2546
2473static struct device_attribute ibmvfc_host_loc_code = {
2474 .attr = {
2475 .name = "port_loc_code",
2476 .mode = S_IRUGO,
2477 },
2478 .show = ibmvfc_show_host_loc_code,
2479};
2480
2481static ssize_t ibmvfc_show_host_drc_name(struct device *dev, 2547static ssize_t ibmvfc_show_host_drc_name(struct device *dev,
2482 struct device_attribute *attr, char *buf) 2548 struct device_attribute *attr, char *buf)
2483{ 2549{
@@ -2488,14 +2554,6 @@ static ssize_t ibmvfc_show_host_drc_name(struct device *dev,
2488 vhost->login_buf->resp.drc_name); 2554 vhost->login_buf->resp.drc_name);
2489} 2555}
2490 2556
2491static struct device_attribute ibmvfc_host_drc_name = {
2492 .attr = {
2493 .name = "drc_name",
2494 .mode = S_IRUGO,
2495 },
2496 .show = ibmvfc_show_host_drc_name,
2497};
2498
2499static ssize_t ibmvfc_show_host_npiv_version(struct device *dev, 2557static ssize_t ibmvfc_show_host_npiv_version(struct device *dev,
2500 struct device_attribute *attr, char *buf) 2558 struct device_attribute *attr, char *buf)
2501{ 2559{
@@ -2504,13 +2562,13 @@ static ssize_t ibmvfc_show_host_npiv_version(struct device *dev,
2504 return snprintf(buf, PAGE_SIZE, "%d\n", vhost->login_buf->resp.version); 2562 return snprintf(buf, PAGE_SIZE, "%d\n", vhost->login_buf->resp.version);
2505} 2563}
2506 2564
2507static struct device_attribute ibmvfc_host_npiv_version = { 2565static ssize_t ibmvfc_show_host_capabilities(struct device *dev,
2508 .attr = { 2566 struct device_attribute *attr, char *buf)
2509 .name = "npiv_version", 2567{
2510 .mode = S_IRUGO, 2568 struct Scsi_Host *shost = class_to_shost(dev);
2511 }, 2569 struct ibmvfc_host *vhost = shost_priv(shost);
2512 .show = ibmvfc_show_host_npiv_version, 2570 return snprintf(buf, PAGE_SIZE, "%llx\n", vhost->login_buf->resp.capabilities);
2513}; 2571}
2514 2572
2515/** 2573/**
2516 * ibmvfc_show_log_level - Show the adapter's error logging level 2574 * ibmvfc_show_log_level - Show the adapter's error logging level
@@ -2556,14 +2614,14 @@ static ssize_t ibmvfc_store_log_level(struct device *dev,
2556 return strlen(buf); 2614 return strlen(buf);
2557} 2615}
2558 2616
2559static struct device_attribute ibmvfc_log_level_attr = { 2617static DEVICE_ATTR(partition_name, S_IRUGO, ibmvfc_show_host_partition_name, NULL);
2560 .attr = { 2618static DEVICE_ATTR(device_name, S_IRUGO, ibmvfc_show_host_device_name, NULL);
2561 .name = "log_level", 2619static DEVICE_ATTR(port_loc_code, S_IRUGO, ibmvfc_show_host_loc_code, NULL);
2562 .mode = S_IRUGO | S_IWUSR, 2620static DEVICE_ATTR(drc_name, S_IRUGO, ibmvfc_show_host_drc_name, NULL);
2563 }, 2621static DEVICE_ATTR(npiv_version, S_IRUGO, ibmvfc_show_host_npiv_version, NULL);
2564 .show = ibmvfc_show_log_level, 2622static DEVICE_ATTR(capabilities, S_IRUGO, ibmvfc_show_host_capabilities, NULL);
2565 .store = ibmvfc_store_log_level 2623static DEVICE_ATTR(log_level, S_IRUGO | S_IWUSR,
2566}; 2624 ibmvfc_show_log_level, ibmvfc_store_log_level);
2567 2625
2568#ifdef CONFIG_SCSI_IBMVFC_TRACE 2626#ifdef CONFIG_SCSI_IBMVFC_TRACE
2569/** 2627/**
@@ -2612,12 +2670,13 @@ static struct bin_attribute ibmvfc_trace_attr = {
2612#endif 2670#endif
2613 2671
2614static struct device_attribute *ibmvfc_attrs[] = { 2672static struct device_attribute *ibmvfc_attrs[] = {
2615 &ibmvfc_host_partition_name, 2673 &dev_attr_partition_name,
2616 &ibmvfc_host_device_name, 2674 &dev_attr_device_name,
2617 &ibmvfc_host_loc_code, 2675 &dev_attr_port_loc_code,
2618 &ibmvfc_host_drc_name, 2676 &dev_attr_drc_name,
2619 &ibmvfc_host_npiv_version, 2677 &dev_attr_npiv_version,
2620 &ibmvfc_log_level_attr, 2678 &dev_attr_capabilities,
2679 &dev_attr_log_level,
2621 NULL 2680 NULL
2622}; 2681};
2623 2682
@@ -2727,27 +2786,27 @@ static void ibmvfc_tasklet(void *data)
2727 2786
2728 spin_lock_irqsave(vhost->host->host_lock, flags); 2787 spin_lock_irqsave(vhost->host->host_lock, flags);
2729 while (!done) { 2788 while (!done) {
2730 /* Pull all the valid messages off the CRQ */
2731 while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
2732 ibmvfc_handle_crq(crq, vhost);
2733 crq->valid = 0;
2734 }
2735
2736 /* Pull all the valid messages off the async CRQ */ 2789 /* Pull all the valid messages off the async CRQ */
2737 while ((async = ibmvfc_next_async_crq(vhost)) != NULL) { 2790 while ((async = ibmvfc_next_async_crq(vhost)) != NULL) {
2738 ibmvfc_handle_async(async, vhost); 2791 ibmvfc_handle_async(async, vhost);
2739 async->valid = 0; 2792 async->valid = 0;
2740 } 2793 }
2741 2794
2742 vio_enable_interrupts(vdev); 2795 /* Pull all the valid messages off the CRQ */
2743 if ((crq = ibmvfc_next_crq(vhost)) != NULL) { 2796 while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
2744 vio_disable_interrupts(vdev);
2745 ibmvfc_handle_crq(crq, vhost); 2797 ibmvfc_handle_crq(crq, vhost);
2746 crq->valid = 0; 2798 crq->valid = 0;
2747 } else if ((async = ibmvfc_next_async_crq(vhost)) != NULL) { 2799 }
2800
2801 vio_enable_interrupts(vdev);
2802 if ((async = ibmvfc_next_async_crq(vhost)) != NULL) {
2748 vio_disable_interrupts(vdev); 2803 vio_disable_interrupts(vdev);
2749 ibmvfc_handle_async(async, vhost); 2804 ibmvfc_handle_async(async, vhost);
2750 async->valid = 0; 2805 async->valid = 0;
2806 } else if ((crq = ibmvfc_next_crq(vhost)) != NULL) {
2807 vio_disable_interrupts(vdev);
2808 ibmvfc_handle_crq(crq, vhost);
2809 crq->valid = 0;
2751 } else 2810 } else
2752 done = 1; 2811 done = 1;
2753 } 2812 }
@@ -2774,15 +2833,19 @@ static void ibmvfc_init_tgt(struct ibmvfc_target *tgt,
2774 * @tgt: ibmvfc target struct 2833 * @tgt: ibmvfc target struct
2775 * @job_step: initialization job step 2834 * @job_step: initialization job step
2776 * 2835 *
2836 * Returns: 1 if step will be retried / 0 if not
2837 *
2777 **/ 2838 **/
2778static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt, 2839static int ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt,
2779 void (*job_step) (struct ibmvfc_target *)) 2840 void (*job_step) (struct ibmvfc_target *))
2780{ 2841{
2781 if (++tgt->init_retries > IBMVFC_MAX_TGT_INIT_RETRIES) { 2842 if (++tgt->init_retries > IBMVFC_MAX_TGT_INIT_RETRIES) {
2782 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 2843 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
2783 wake_up(&tgt->vhost->work_wait_q); 2844 wake_up(&tgt->vhost->work_wait_q);
2845 return 0;
2784 } else 2846 } else
2785 ibmvfc_init_tgt(tgt, job_step); 2847 ibmvfc_init_tgt(tgt, job_step);
2848 return 1;
2786} 2849}
2787 2850
2788/* Defined in FC-LS */ 2851/* Defined in FC-LS */
@@ -2831,7 +2894,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
2831 struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli; 2894 struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli;
2832 struct ibmvfc_prli_svc_parms *parms = &rsp->parms; 2895 struct ibmvfc_prli_svc_parms *parms = &rsp->parms;
2833 u32 status = rsp->common.status; 2896 u32 status = rsp->common.status;
2834 int index; 2897 int index, level = IBMVFC_DEFAULT_LOG_LEVEL;
2835 2898
2836 vhost->discovery_threads--; 2899 vhost->discovery_threads--;
2837 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); 2900 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
@@ -2850,7 +2913,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
2850 tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET; 2913 tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET;
2851 if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC) 2914 if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC)
2852 tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; 2915 tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
2853 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT); 2916 tgt->add_rport = 1;
2854 } else 2917 } else
2855 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 2918 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
2856 } else if (prli_rsp[index].retry) 2919 } else if (prli_rsp[index].retry)
@@ -2867,13 +2930,18 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
2867 break; 2930 break;
2868 case IBMVFC_MAD_FAILED: 2931 case IBMVFC_MAD_FAILED:
2869 default: 2932 default:
2870 tgt_err(tgt, "Process Login failed: %s (%x:%x) rc=0x%02X\n", 2933 if ((rsp->status & IBMVFC_VIOS_FAILURE) && rsp->error == IBMVFC_PLOGI_REQUIRED)
2871 ibmvfc_get_cmd_error(rsp->status, rsp->error), 2934 level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
2872 rsp->status, rsp->error, status); 2935 else if (tgt->logo_rcvd)
2873 if (ibmvfc_retry_cmd(rsp->status, rsp->error)) 2936 level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
2874 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); 2937 else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
2938 level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
2875 else 2939 else
2876 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 2940 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
2941
2942 tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n",
2943 ibmvfc_get_cmd_error(rsp->status, rsp->error),
2944 rsp->status, rsp->error, status);
2877 break; 2945 break;
2878 }; 2946 };
2879 2947
@@ -2932,6 +3000,7 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
2932 struct ibmvfc_host *vhost = evt->vhost; 3000 struct ibmvfc_host *vhost = evt->vhost;
2933 struct ibmvfc_port_login *rsp = &evt->xfer_iu->plogi; 3001 struct ibmvfc_port_login *rsp = &evt->xfer_iu->plogi;
2934 u32 status = rsp->common.status; 3002 u32 status = rsp->common.status;
3003 int level = IBMVFC_DEFAULT_LOG_LEVEL;
2935 3004
2936 vhost->discovery_threads--; 3005 vhost->discovery_threads--;
2937 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); 3006 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
@@ -2960,15 +3029,15 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
2960 break; 3029 break;
2961 case IBMVFC_MAD_FAILED: 3030 case IBMVFC_MAD_FAILED:
2962 default: 3031 default:
2963 tgt_err(tgt, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
2964 ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
2965 ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
2966 ibmvfc_get_ls_explain(rsp->fc_explain), rsp->fc_explain, status);
2967
2968 if (ibmvfc_retry_cmd(rsp->status, rsp->error)) 3032 if (ibmvfc_retry_cmd(rsp->status, rsp->error))
2969 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); 3033 level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
2970 else 3034 else
2971 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 3035 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
3036
3037 tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
3038 ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
3039 ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
3040 ibmvfc_get_ls_explain(rsp->fc_explain), rsp->fc_explain, status);
2972 break; 3041 break;
2973 }; 3042 };
2974 3043
@@ -2992,6 +3061,7 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt)
2992 return; 3061 return;
2993 3062
2994 kref_get(&tgt->kref); 3063 kref_get(&tgt->kref);
3064 tgt->logo_rcvd = 0;
2995 evt = ibmvfc_get_event(vhost); 3065 evt = ibmvfc_get_event(vhost);
2996 vhost->discovery_threads++; 3066 vhost->discovery_threads++;
2997 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); 3067 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
@@ -3129,13 +3199,13 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
3129 case IBMVFC_MAD_SUCCESS: 3199 case IBMVFC_MAD_SUCCESS:
3130 tgt_dbg(tgt, "ADISC succeeded\n"); 3200 tgt_dbg(tgt, "ADISC succeeded\n");
3131 if (ibmvfc_adisc_needs_plogi(mad, tgt)) 3201 if (ibmvfc_adisc_needs_plogi(mad, tgt))
3132 tgt->need_login = 1; 3202 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
3133 break; 3203 break;
3134 case IBMVFC_MAD_DRIVER_FAILED: 3204 case IBMVFC_MAD_DRIVER_FAILED:
3135 break; 3205 break;
3136 case IBMVFC_MAD_FAILED: 3206 case IBMVFC_MAD_FAILED:
3137 default: 3207 default:
3138 tgt->need_login = 1; 3208 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
3139 fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16; 3209 fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16;
3140 fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8; 3210 fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8;
3141 tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", 3211 tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
@@ -3322,6 +3392,7 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
3322 struct ibmvfc_host *vhost = evt->vhost; 3392 struct ibmvfc_host *vhost = evt->vhost;
3323 struct ibmvfc_query_tgt *rsp = &evt->xfer_iu->query_tgt; 3393 struct ibmvfc_query_tgt *rsp = &evt->xfer_iu->query_tgt;
3324 u32 status = rsp->common.status; 3394 u32 status = rsp->common.status;
3395 int level = IBMVFC_DEFAULT_LOG_LEVEL;
3325 3396
3326 vhost->discovery_threads--; 3397 vhost->discovery_threads--;
3327 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); 3398 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
@@ -3341,19 +3412,19 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
3341 break; 3412 break;
3342 case IBMVFC_MAD_FAILED: 3413 case IBMVFC_MAD_FAILED:
3343 default: 3414 default:
3344 tgt_err(tgt, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
3345 ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
3346 ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
3347 ibmvfc_get_gs_explain(rsp->fc_explain), rsp->fc_explain, status);
3348
3349 if ((rsp->status & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED && 3415 if ((rsp->status & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED &&
3350 rsp->error == IBMVFC_UNABLE_TO_PERFORM_REQ && 3416 rsp->error == IBMVFC_UNABLE_TO_PERFORM_REQ &&
3351 rsp->fc_explain == IBMVFC_PORT_NAME_NOT_REG) 3417 rsp->fc_explain == IBMVFC_PORT_NAME_NOT_REG)
3352 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 3418 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
3353 else if (ibmvfc_retry_cmd(rsp->status, rsp->error)) 3419 else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
3354 ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target); 3420 level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target);
3355 else 3421 else
3356 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); 3422 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
3423
3424 tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
3425 ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
3426 ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
3427 ibmvfc_get_gs_explain(rsp->fc_explain), rsp->fc_explain, status);
3357 break; 3428 break;
3358 }; 3429 };
3359 3430
@@ -3420,7 +3491,7 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id)
3420 } 3491 }
3421 spin_unlock_irqrestore(vhost->host->host_lock, flags); 3492 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3422 3493
3423 tgt = mempool_alloc(vhost->tgt_pool, GFP_KERNEL); 3494 tgt = mempool_alloc(vhost->tgt_pool, GFP_NOIO);
3424 if (!tgt) { 3495 if (!tgt) {
3425 dev_err(vhost->dev, "Target allocation failure for scsi id %08llx\n", 3496 dev_err(vhost->dev, "Target allocation failure for scsi id %08llx\n",
3426 scsi_id); 3497 scsi_id);
@@ -3472,6 +3543,7 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt)
3472 struct ibmvfc_host *vhost = evt->vhost; 3543 struct ibmvfc_host *vhost = evt->vhost;
3473 struct ibmvfc_discover_targets *rsp = &evt->xfer_iu->discover_targets; 3544 struct ibmvfc_discover_targets *rsp = &evt->xfer_iu->discover_targets;
3474 u32 mad_status = rsp->common.status; 3545 u32 mad_status = rsp->common.status;
3546 int level = IBMVFC_DEFAULT_LOG_LEVEL;
3475 3547
3476 switch (mad_status) { 3548 switch (mad_status) {
3477 case IBMVFC_MAD_SUCCESS: 3549 case IBMVFC_MAD_SUCCESS:
@@ -3480,9 +3552,9 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt)
3480 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS); 3552 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS);
3481 break; 3553 break;
3482 case IBMVFC_MAD_FAILED: 3554 case IBMVFC_MAD_FAILED:
3483 dev_err(vhost->dev, "Discover Targets failed: %s (%x:%x)\n", 3555 level += ibmvfc_retry_host_init(vhost);
3484 ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error); 3556 ibmvfc_log(vhost, level, "Discover Targets failed: %s (%x:%x)\n",
3485 ibmvfc_retry_host_init(vhost); 3557 ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
3486 break; 3558 break;
3487 case IBMVFC_MAD_DRIVER_FAILED: 3559 case IBMVFC_MAD_DRIVER_FAILED:
3488 break; 3560 break;
@@ -3534,18 +3606,19 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
3534 u32 mad_status = evt->xfer_iu->npiv_login.common.status; 3606 u32 mad_status = evt->xfer_iu->npiv_login.common.status;
3535 struct ibmvfc_npiv_login_resp *rsp = &vhost->login_buf->resp; 3607 struct ibmvfc_npiv_login_resp *rsp = &vhost->login_buf->resp;
3536 unsigned int npiv_max_sectors; 3608 unsigned int npiv_max_sectors;
3609 int level = IBMVFC_DEFAULT_LOG_LEVEL;
3537 3610
3538 switch (mad_status) { 3611 switch (mad_status) {
3539 case IBMVFC_MAD_SUCCESS: 3612 case IBMVFC_MAD_SUCCESS:
3540 ibmvfc_free_event(evt); 3613 ibmvfc_free_event(evt);
3541 break; 3614 break;
3542 case IBMVFC_MAD_FAILED: 3615 case IBMVFC_MAD_FAILED:
3543 dev_err(vhost->dev, "NPIV Login failed: %s (%x:%x)\n",
3544 ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
3545 if (ibmvfc_retry_cmd(rsp->status, rsp->error)) 3616 if (ibmvfc_retry_cmd(rsp->status, rsp->error))
3546 ibmvfc_retry_host_init(vhost); 3617 level += ibmvfc_retry_host_init(vhost);
3547 else 3618 else
3548 ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); 3619 ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
3620 ibmvfc_log(vhost, level, "NPIV Login failed: %s (%x:%x)\n",
3621 ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
3549 ibmvfc_free_event(evt); 3622 ibmvfc_free_event(evt);
3550 return; 3623 return;
3551 case IBMVFC_MAD_CRQ_ERROR: 3624 case IBMVFC_MAD_CRQ_ERROR:
@@ -3578,6 +3651,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
3578 return; 3651 return;
3579 } 3652 }
3580 3653
3654 vhost->logged_in = 1;
3581 npiv_max_sectors = min((uint)(rsp->max_dma_len >> 9), IBMVFC_MAX_SECTORS); 3655 npiv_max_sectors = min((uint)(rsp->max_dma_len >> 9), IBMVFC_MAX_SECTORS);
3582 dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n", 3656 dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n",
3583 rsp->partition_name, rsp->device_name, rsp->port_loc_code, 3657 rsp->partition_name, rsp->device_name, rsp->port_loc_code,
@@ -3636,6 +3710,65 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
3636}; 3710};
3637 3711
3638/** 3712/**
3713 * ibmvfc_npiv_logout_done - Completion handler for NPIV Logout
3714 * @vhost: ibmvfc host struct
3715 *
3716 **/
3717static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt)
3718{
3719 struct ibmvfc_host *vhost = evt->vhost;
3720 u32 mad_status = evt->xfer_iu->npiv_logout.common.status;
3721
3722 ibmvfc_free_event(evt);
3723
3724 switch (mad_status) {
3725 case IBMVFC_MAD_SUCCESS:
3726 if (list_empty(&vhost->sent) &&
3727 vhost->action == IBMVFC_HOST_ACTION_LOGO_WAIT) {
3728 ibmvfc_init_host(vhost, 0);
3729 return;
3730 }
3731 break;
3732 case IBMVFC_MAD_FAILED:
3733 case IBMVFC_MAD_NOT_SUPPORTED:
3734 case IBMVFC_MAD_CRQ_ERROR:
3735 case IBMVFC_MAD_DRIVER_FAILED:
3736 default:
3737 ibmvfc_dbg(vhost, "NPIV Logout failed. 0x%X\n", mad_status);
3738 break;
3739 }
3740
3741 ibmvfc_hard_reset_host(vhost);
3742}
3743
3744/**
3745 * ibmvfc_npiv_logout - Issue an NPIV Logout
3746 * @vhost: ibmvfc host struct
3747 *
3748 **/
3749static void ibmvfc_npiv_logout(struct ibmvfc_host *vhost)
3750{
3751 struct ibmvfc_npiv_logout_mad *mad;
3752 struct ibmvfc_event *evt;
3753
3754 evt = ibmvfc_get_event(vhost);
3755 ibmvfc_init_event(evt, ibmvfc_npiv_logout_done, IBMVFC_MAD_FORMAT);
3756
3757 mad = &evt->iu.npiv_logout;
3758 memset(mad, 0, sizeof(*mad));
3759 mad->common.version = 1;
3760 mad->common.opcode = IBMVFC_NPIV_LOGOUT;
3761 mad->common.length = sizeof(struct ibmvfc_npiv_logout_mad);
3762
3763 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_LOGO_WAIT);
3764
3765 if (!ibmvfc_send_event(evt, vhost, default_timeout))
3766 ibmvfc_dbg(vhost, "Sent NPIV logout\n");
3767 else
3768 ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
3769}
3770
3771/**
3639 * ibmvfc_dev_init_to_do - Is there target initialization work to do? 3772 * ibmvfc_dev_init_to_do - Is there target initialization work to do?
3640 * @vhost: ibmvfc host struct 3773 * @vhost: ibmvfc host struct
3641 * 3774 *
@@ -3671,6 +3804,7 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost)
3671 switch (vhost->action) { 3804 switch (vhost->action) {
3672 case IBMVFC_HOST_ACTION_NONE: 3805 case IBMVFC_HOST_ACTION_NONE:
3673 case IBMVFC_HOST_ACTION_INIT_WAIT: 3806 case IBMVFC_HOST_ACTION_INIT_WAIT:
3807 case IBMVFC_HOST_ACTION_LOGO_WAIT:
3674 return 0; 3808 return 0;
3675 case IBMVFC_HOST_ACTION_TGT_INIT: 3809 case IBMVFC_HOST_ACTION_TGT_INIT:
3676 case IBMVFC_HOST_ACTION_QUERY_TGTS: 3810 case IBMVFC_HOST_ACTION_QUERY_TGTS:
@@ -3683,9 +3817,9 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost)
3683 if (tgt->action == IBMVFC_TGT_ACTION_INIT_WAIT) 3817 if (tgt->action == IBMVFC_TGT_ACTION_INIT_WAIT)
3684 return 0; 3818 return 0;
3685 return 1; 3819 return 1;
3820 case IBMVFC_HOST_ACTION_LOGO:
3686 case IBMVFC_HOST_ACTION_INIT: 3821 case IBMVFC_HOST_ACTION_INIT:
3687 case IBMVFC_HOST_ACTION_ALLOC_TGTS: 3822 case IBMVFC_HOST_ACTION_ALLOC_TGTS:
3688 case IBMVFC_HOST_ACTION_TGT_ADD:
3689 case IBMVFC_HOST_ACTION_TGT_DEL: 3823 case IBMVFC_HOST_ACTION_TGT_DEL:
3690 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: 3824 case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
3691 case IBMVFC_HOST_ACTION_QUERY: 3825 case IBMVFC_HOST_ACTION_QUERY:
@@ -3740,25 +3874,26 @@ static void ibmvfc_log_ae(struct ibmvfc_host *vhost, int events)
3740static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) 3874static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
3741{ 3875{
3742 struct ibmvfc_host *vhost = tgt->vhost; 3876 struct ibmvfc_host *vhost = tgt->vhost;
3743 struct fc_rport *rport = tgt->rport; 3877 struct fc_rport *rport;
3744 unsigned long flags; 3878 unsigned long flags;
3745 3879
3746 if (rport) { 3880 tgt_dbg(tgt, "Adding rport\n");
3747 tgt_dbg(tgt, "Setting rport roles\n"); 3881 rport = fc_remote_port_add(vhost->host, 0, &tgt->ids);
3748 fc_remote_port_rolechg(rport, tgt->ids.roles); 3882 spin_lock_irqsave(vhost->host->host_lock, flags);
3749 spin_lock_irqsave(vhost->host->host_lock, flags); 3883
3750 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); 3884 if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) {
3885 tgt_dbg(tgt, "Deleting rport\n");
3886 list_del(&tgt->queue);
3751 spin_unlock_irqrestore(vhost->host->host_lock, flags); 3887 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3888 fc_remote_port_delete(rport);
3889 del_timer_sync(&tgt->timer);
3890 kref_put(&tgt->kref, ibmvfc_release_tgt);
3752 return; 3891 return;
3753 } 3892 }
3754 3893
3755 tgt_dbg(tgt, "Adding rport\n");
3756 rport = fc_remote_port_add(vhost->host, 0, &tgt->ids);
3757 spin_lock_irqsave(vhost->host->host_lock, flags);
3758 tgt->rport = rport;
3759 ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
3760 if (rport) { 3894 if (rport) {
3761 tgt_dbg(tgt, "rport add succeeded\n"); 3895 tgt_dbg(tgt, "rport add succeeded\n");
3896 tgt->rport = rport;
3762 rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff; 3897 rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff;
3763 rport->supported_classes = 0; 3898 rport->supported_classes = 0;
3764 tgt->target_id = rport->scsi_target_id; 3899 tgt->target_id = rport->scsi_target_id;
@@ -3789,8 +3924,12 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3789 vhost->events_to_log = 0; 3924 vhost->events_to_log = 0;
3790 switch (vhost->action) { 3925 switch (vhost->action) {
3791 case IBMVFC_HOST_ACTION_NONE: 3926 case IBMVFC_HOST_ACTION_NONE:
3927 case IBMVFC_HOST_ACTION_LOGO_WAIT:
3792 case IBMVFC_HOST_ACTION_INIT_WAIT: 3928 case IBMVFC_HOST_ACTION_INIT_WAIT:
3793 break; 3929 break;
3930 case IBMVFC_HOST_ACTION_LOGO:
3931 vhost->job_step(vhost);
3932 break;
3794 case IBMVFC_HOST_ACTION_INIT: 3933 case IBMVFC_HOST_ACTION_INIT:
3795 BUG_ON(vhost->state != IBMVFC_INITIALIZING); 3934 BUG_ON(vhost->state != IBMVFC_INITIALIZING);
3796 if (vhost->delay_init) { 3935 if (vhost->delay_init) {
@@ -3836,11 +3975,21 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3836 3975
3837 if (vhost->state == IBMVFC_INITIALIZING) { 3976 if (vhost->state == IBMVFC_INITIALIZING) {
3838 if (vhost->action == IBMVFC_HOST_ACTION_TGT_DEL_FAILED) { 3977 if (vhost->action == IBMVFC_HOST_ACTION_TGT_DEL_FAILED) {
3839 ibmvfc_set_host_state(vhost, IBMVFC_ACTIVE); 3978 if (vhost->reinit) {
3840 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_ADD); 3979 vhost->reinit = 0;
3841 vhost->init_retries = 0; 3980 scsi_block_requests(vhost->host);
3842 spin_unlock_irqrestore(vhost->host->host_lock, flags); 3981 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
3843 scsi_unblock_requests(vhost->host); 3982 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3983 } else {
3984 ibmvfc_set_host_state(vhost, IBMVFC_ACTIVE);
3985 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
3986 wake_up(&vhost->init_wait_q);
3987 schedule_work(&vhost->rport_add_work_q);
3988 vhost->init_retries = 0;
3989 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3990 scsi_unblock_requests(vhost->host);
3991 }
3992
3844 return; 3993 return;
3845 } else { 3994 } else {
3846 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT); 3995 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
@@ -3871,24 +4020,6 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
3871 if (!ibmvfc_dev_init_to_do(vhost)) 4020 if (!ibmvfc_dev_init_to_do(vhost))
3872 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL_FAILED); 4021 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL_FAILED);
3873 break; 4022 break;
3874 case IBMVFC_HOST_ACTION_TGT_ADD:
3875 list_for_each_entry(tgt, &vhost->targets, queue) {
3876 if (tgt->action == IBMVFC_TGT_ACTION_ADD_RPORT) {
3877 spin_unlock_irqrestore(vhost->host->host_lock, flags);
3878 ibmvfc_tgt_add_rport(tgt);
3879 return;
3880 }
3881 }
3882
3883 if (vhost->reinit && !ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
3884 vhost->reinit = 0;
3885 scsi_block_requests(vhost->host);
3886 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
3887 } else {
3888 ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
3889 wake_up(&vhost->init_wait_q);
3890 }
3891 break;
3892 default: 4023 default:
3893 break; 4024 break;
3894 }; 4025 };
@@ -4118,6 +4249,56 @@ nomem:
4118} 4249}
4119 4250
4120/** 4251/**
4252 * ibmvfc_rport_add_thread - Worker thread for rport adds
4253 * @work: work struct
4254 *
4255 **/
4256static void ibmvfc_rport_add_thread(struct work_struct *work)
4257{
4258 struct ibmvfc_host *vhost = container_of(work, struct ibmvfc_host,
4259 rport_add_work_q);
4260 struct ibmvfc_target *tgt;
4261 struct fc_rport *rport;
4262 unsigned long flags;
4263 int did_work;
4264
4265 ENTER;
4266 spin_lock_irqsave(vhost->host->host_lock, flags);
4267 do {
4268 did_work = 0;
4269 if (vhost->state != IBMVFC_ACTIVE)
4270 break;
4271
4272 list_for_each_entry(tgt, &vhost->targets, queue) {
4273 if (tgt->add_rport) {
4274 did_work = 1;
4275 tgt->add_rport = 0;
4276 kref_get(&tgt->kref);
4277 rport = tgt->rport;
4278 if (!rport) {
4279 spin_unlock_irqrestore(vhost->host->host_lock, flags);
4280 ibmvfc_tgt_add_rport(tgt);
4281 } else if (get_device(&rport->dev)) {
4282 spin_unlock_irqrestore(vhost->host->host_lock, flags);
4283 tgt_dbg(tgt, "Setting rport roles\n");
4284 fc_remote_port_rolechg(rport, tgt->ids.roles);
4285 put_device(&rport->dev);
4286 }
4287
4288 kref_put(&tgt->kref, ibmvfc_release_tgt);
4289 spin_lock_irqsave(vhost->host->host_lock, flags);
4290 break;
4291 }
4292 }
4293 } while(did_work);
4294
4295 if (vhost->state == IBMVFC_ACTIVE)
4296 vhost->scan_complete = 1;
4297 spin_unlock_irqrestore(vhost->host->host_lock, flags);
4298 LEAVE;
4299}
4300
4301/**
4121 * ibmvfc_probe - Adapter hot plug add entry point 4302 * ibmvfc_probe - Adapter hot plug add entry point
4122 * @vdev: vio device struct 4303 * @vdev: vio device struct
4123 * @id: vio device id struct 4304 * @id: vio device id struct
@@ -4160,6 +4341,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
4160 strcpy(vhost->partition_name, "UNKNOWN"); 4341 strcpy(vhost->partition_name, "UNKNOWN");
4161 init_waitqueue_head(&vhost->work_wait_q); 4342 init_waitqueue_head(&vhost->work_wait_q);
4162 init_waitqueue_head(&vhost->init_wait_q); 4343 init_waitqueue_head(&vhost->init_wait_q);
4344 INIT_WORK(&vhost->rport_add_work_q, ibmvfc_rport_add_thread);
4163 4345
4164 if ((rc = ibmvfc_alloc_mem(vhost))) 4346 if ((rc = ibmvfc_alloc_mem(vhost)))
4165 goto free_scsi_host; 4347 goto free_scsi_host;