Lines Matching +full:rx +full:- +full:num +full:- +full:evt
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * ibmvfc.c -- driver for IBM Power Virtual Fibre Channel Adapter
12 #include <linux/dma-mapping.h>
22 #include <linux/bsg-lib.h>
70 MODULE_PARM_DESC(mig_channels_only, "Prevent migration to non-channelized system. "
99 MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. "
184 u64 host_caps = be64_to_cpu(vhost->login_buf->resp.capabilities); in ibmvfc_check_caps()
193 return &vfc_cmd->v2.iu; in ibmvfc_get_fcp_iu()
195 return &vfc_cmd->v1.iu; in ibmvfc_get_fcp_iu()
202 return &vfc_cmd->v2.rsp; in ibmvfc_get_fcp_rsp()
204 return &vfc_cmd->v1.rsp; in ibmvfc_get_fcp_rsp()
209 * ibmvfc_trc_start - Log a start trace entry
210 * @evt: ibmvfc event struct
213 static void ibmvfc_trc_start(struct ibmvfc_event *evt) in ibmvfc_trc_start() argument
215 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_trc_start()
216 struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; in ibmvfc_trc_start()
217 struct ibmvfc_mad_common *mad = &evt->iu.mad_common; in ibmvfc_trc_start()
220 int index = atomic_inc_return(&vhost->trace_index) & IBMVFC_TRACE_INDEX_MASK; in ibmvfc_trc_start()
222 entry = &vhost->trace[index]; in ibmvfc_trc_start()
223 entry->evt = evt; in ibmvfc_trc_start()
224 entry->time = jiffies; in ibmvfc_trc_start()
225 entry->fmt = evt->crq.format; in ibmvfc_trc_start()
226 entry->type = IBMVFC_TRC_START; in ibmvfc_trc_start()
228 switch (entry->fmt) { in ibmvfc_trc_start()
230 entry->op_code = iu->cdb[0]; in ibmvfc_trc_start()
231 entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); in ibmvfc_trc_start()
232 entry->lun = scsilun_to_int(&iu->lun); in ibmvfc_trc_start()
233 entry->tmf_flags = iu->tmf_flags; in ibmvfc_trc_start()
234 entry->u.start.xfer_len = be32_to_cpu(iu->xfer_len); in ibmvfc_trc_start()
237 entry->op_code = be32_to_cpu(mad->opcode); in ibmvfc_trc_start()
245 * ibmvfc_trc_end - Log an end trace entry
246 * @evt: ibmvfc event struct
249 static void ibmvfc_trc_end(struct ibmvfc_event *evt) in ibmvfc_trc_end() argument
251 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_trc_end()
252 struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; in ibmvfc_trc_end()
253 struct ibmvfc_mad_common *mad = &evt->xfer_iu->mad_common; in ibmvfc_trc_end()
257 int index = atomic_inc_return(&vhost->trace_index) & IBMVFC_TRACE_INDEX_MASK; in ibmvfc_trc_end()
259 entry = &vhost->trace[index]; in ibmvfc_trc_end()
260 entry->evt = evt; in ibmvfc_trc_end()
261 entry->time = jiffies; in ibmvfc_trc_end()
262 entry->fmt = evt->crq.format; in ibmvfc_trc_end()
263 entry->type = IBMVFC_TRC_END; in ibmvfc_trc_end()
265 switch (entry->fmt) { in ibmvfc_trc_end()
267 entry->op_code = iu->cdb[0]; in ibmvfc_trc_end()
268 entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); in ibmvfc_trc_end()
269 entry->lun = scsilun_to_int(&iu->lun); in ibmvfc_trc_end()
270 entry->tmf_flags = iu->tmf_flags; in ibmvfc_trc_end()
271 entry->u.end.status = be16_to_cpu(vfc_cmd->status); in ibmvfc_trc_end()
272 entry->u.end.error = be16_to_cpu(vfc_cmd->error); in ibmvfc_trc_end()
273 entry->u.end.fcp_rsp_flags = rsp->flags; in ibmvfc_trc_end()
274 entry->u.end.rsp_code = rsp->data.info.rsp_code; in ibmvfc_trc_end()
275 entry->u.end.scsi_status = rsp->scsi_status; in ibmvfc_trc_end()
278 entry->op_code = be32_to_cpu(mad->opcode); in ibmvfc_trc_end()
279 entry->u.end.status = be16_to_cpu(mad->status); in ibmvfc_trc_end()
288 #define ibmvfc_trc_start(evt) do { } while (0) argument
289 #define ibmvfc_trc_end(evt) do { } while (0) argument
293 * ibmvfc_get_err_index - Find the index into cmd_status for the fcp response
298 * index into cmd_status / -EINVAL on failure
309 return -EINVAL; in ibmvfc_get_err_index()
313 * ibmvfc_get_cmd_error - Find the error description for the fcp response
329 * ibmvfc_get_err_result - Find the scsi status to return for the fcp response
340 int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len); in ibmvfc_get_err_result()
342 if ((rsp->flags & FCP_RSP_LEN_VALID) && in ibmvfc_get_err_result()
344 rsp->data.info.rsp_code)) in ibmvfc_get_err_result()
347 err = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error)); in ibmvfc_get_err_result()
349 return rsp->scsi_status | (cmd_status[err].result << 16); in ibmvfc_get_err_result()
350 return rsp->scsi_status | (DID_ERROR << 16); in ibmvfc_get_err_result()
354 * ibmvfc_retry_cmd - Determine if error status is retryable
377 { 0x01, "service parameter error - options" },
378 { 0x03, "service parameter error - initiator control" },
379 { 0x05, "service parameter error - recipient control" },
380 { 0x07, "service parameter error - received data field size" },
381 { 0x09, "service parameter error - concurrent seq" },
382 { 0x0B, "service parameter error - credit" },
389 { 0x17, "invalid OX_ID-RX-ID combination" },
405 { 0x07, "FC-4 TYPEs not registered" },
419 * ibmvfc_get_ls_explain - Return the FC Explain description text
437 * ibmvfc_get_gs_explain - Return the FC Explain description text
469 * ibmvfc_get_fc_type - Return the FC Type description text
487 * ibmvfc_set_tgt_action - Set the next init action for the target
492 * 0 if action changed / non-zero if not changed
497 int rc = -EINVAL; in ibmvfc_set_tgt_action()
499 switch (tgt->action) { in ibmvfc_set_tgt_action()
503 tgt->action = action; in ibmvfc_set_tgt_action()
510 tgt->action = action; in ibmvfc_set_tgt_action()
516 tgt->action = action; in ibmvfc_set_tgt_action()
522 tgt->action = action; in ibmvfc_set_tgt_action()
528 tgt->action = action; in ibmvfc_set_tgt_action()
535 tgt->action = action; in ibmvfc_set_tgt_action()
541 tgt->add_rport = 0; in ibmvfc_set_tgt_action()
547 * ibmvfc_set_host_state - Set the state for the host
552 * 0 if state changed / non-zero if not changed
559 switch (vhost->state) { in ibmvfc_set_host_state()
561 rc = -EINVAL; in ibmvfc_set_host_state()
564 vhost->state = state; in ibmvfc_set_host_state()
572 * ibmvfc_set_host_action - Set the next init action for the host
582 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) in ibmvfc_set_host_action()
583 vhost->action = action; in ibmvfc_set_host_action()
586 if (vhost->action == IBMVFC_HOST_ACTION_LOGO) in ibmvfc_set_host_action()
587 vhost->action = action; in ibmvfc_set_host_action()
590 if (vhost->action == IBMVFC_HOST_ACTION_INIT) in ibmvfc_set_host_action()
591 vhost->action = action; in ibmvfc_set_host_action()
594 switch (vhost->action) { in ibmvfc_set_host_action()
598 vhost->action = action; in ibmvfc_set_host_action()
605 if (vhost->action == IBMVFC_HOST_ACTION_ALLOC_TGTS) in ibmvfc_set_host_action()
606 vhost->action = action; in ibmvfc_set_host_action()
610 vhost->action = action; in ibmvfc_set_host_action()
619 switch (vhost->action) { in ibmvfc_set_host_action()
624 vhost->action = action; in ibmvfc_set_host_action()
632 * ibmvfc_reinit_host - Re-start host initialization (no NPIV Login)
640 if (vhost->action == IBMVFC_HOST_ACTION_NONE && in ibmvfc_reinit_host()
641 vhost->state == IBMVFC_ACTIVE) { in ibmvfc_reinit_host()
643 scsi_block_requests(vhost->host); in ibmvfc_reinit_host()
647 vhost->reinit = 1; in ibmvfc_reinit_host()
649 wake_up(&vhost->work_wait_q); in ibmvfc_reinit_host()
653 * ibmvfc_del_tgt - Schedule cleanup and removal of the target
659 tgt->job_step = ibmvfc_tgt_implicit_logout_and_del; in ibmvfc_del_tgt()
660 tgt->init_retries = 0; in ibmvfc_del_tgt()
662 wake_up(&tgt->vhost->work_wait_q); in ibmvfc_del_tgt()
666 * ibmvfc_link_down - Handle a link down event from the adapter
677 scsi_block_requests(vhost->host); in ibmvfc_link_down()
678 list_for_each_entry(tgt, &vhost->targets, queue) in ibmvfc_link_down()
682 vhost->events_to_log |= IBMVFC_AE_LINKDOWN; in ibmvfc_link_down()
683 wake_up(&vhost->work_wait_q); in ibmvfc_link_down()
688 * ibmvfc_init_host - Start host initialization
698 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) { in ibmvfc_init_host()
699 if (++vhost->init_retries > IBMVFC_MAX_HOST_INIT_RETRIES) { in ibmvfc_init_host()
700 dev_err(vhost->dev, in ibmvfc_init_host()
708 memset(vhost->async_crq.msgs.async, 0, PAGE_SIZE); in ibmvfc_init_host()
709 vhost->async_crq.cur = 0; in ibmvfc_init_host()
711 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_init_host()
712 if (vhost->client_migrated) in ibmvfc_init_host()
713 tgt->need_login = 1; in ibmvfc_init_host()
718 scsi_block_requests(vhost->host); in ibmvfc_init_host()
720 vhost->job_step = ibmvfc_npiv_login; in ibmvfc_init_host()
721 wake_up(&vhost->work_wait_q); in ibmvfc_init_host()
726 * ibmvfc_send_crq - Send a CRQ
736 struct vio_dev *vdev = to_vio_dev(vhost->dev); in ibmvfc_send_crq()
737 return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2); in ibmvfc_send_crq()
743 struct vio_dev *vdev = to_vio_dev(vhost->dev); in ibmvfc_send_sub_crq()
745 return plpar_hcall_norets(H_SEND_SUB_CRQ, vdev->unit_address, cookie, in ibmvfc_send_sub_crq()
750 * ibmvfc_send_crq_init - Send a CRQ init message
763 * ibmvfc_send_crq_init_complete - Send a CRQ init complete message
776 * ibmvfc_init_event_pool - Allocates and initializes the event pool for a host
788 struct ibmvfc_event_pool *pool = &queue->evt_pool; in ibmvfc_init_event_pool()
794 pool->size = size; in ibmvfc_init_event_pool()
795 pool->events = kcalloc(size, sizeof(*pool->events), GFP_KERNEL); in ibmvfc_init_event_pool()
796 if (!pool->events) in ibmvfc_init_event_pool()
797 return -ENOMEM; in ibmvfc_init_event_pool()
799 pool->iu_storage = dma_alloc_coherent(vhost->dev, in ibmvfc_init_event_pool()
800 size * sizeof(*pool->iu_storage), in ibmvfc_init_event_pool()
801 &pool->iu_token, 0); in ibmvfc_init_event_pool()
803 if (!pool->iu_storage) { in ibmvfc_init_event_pool()
804 kfree(pool->events); in ibmvfc_init_event_pool()
805 return -ENOMEM; in ibmvfc_init_event_pool()
808 INIT_LIST_HEAD(&queue->sent); in ibmvfc_init_event_pool()
809 INIT_LIST_HEAD(&queue->free); in ibmvfc_init_event_pool()
810 spin_lock_init(&queue->l_lock); in ibmvfc_init_event_pool()
813 struct ibmvfc_event *evt = &pool->events[i]; in ibmvfc_init_event_pool() local
816 * evt->active states in ibmvfc_init_event_pool()
819 * -1 = free/freed in ibmvfc_init_event_pool()
821 atomic_set(&evt->active, -1); in ibmvfc_init_event_pool()
822 atomic_set(&evt->free, 1); in ibmvfc_init_event_pool()
823 evt->crq.valid = 0x80; in ibmvfc_init_event_pool()
824 evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i)); in ibmvfc_init_event_pool()
825 evt->xfer_iu = pool->iu_storage + i; in ibmvfc_init_event_pool()
826 evt->vhost = vhost; in ibmvfc_init_event_pool()
827 evt->queue = queue; in ibmvfc_init_event_pool()
828 evt->ext_list = NULL; in ibmvfc_init_event_pool()
829 list_add_tail(&evt->queue_list, &queue->free); in ibmvfc_init_event_pool()
837 * ibmvfc_free_event_pool - Frees memory of the event pool of a host
846 struct ibmvfc_event_pool *pool = &queue->evt_pool; in ibmvfc_free_event_pool()
849 for (i = 0; i < pool->size; ++i) { in ibmvfc_free_event_pool()
850 list_del(&pool->events[i].queue_list); in ibmvfc_free_event_pool()
851 BUG_ON(atomic_read(&pool->events[i].free) != 1); in ibmvfc_free_event_pool()
852 if (pool->events[i].ext_list) in ibmvfc_free_event_pool()
853 dma_pool_free(vhost->sg_pool, in ibmvfc_free_event_pool()
854 pool->events[i].ext_list, in ibmvfc_free_event_pool()
855 pool->events[i].ext_list_token); in ibmvfc_free_event_pool()
858 kfree(pool->events); in ibmvfc_free_event_pool()
859 dma_free_coherent(vhost->dev, in ibmvfc_free_event_pool()
860 pool->size * sizeof(*pool->iu_storage), in ibmvfc_free_event_pool()
861 pool->iu_storage, pool->iu_token); in ibmvfc_free_event_pool()
866 * ibmvfc_free_queue - Deallocate queue
875 struct device *dev = vhost->dev; in ibmvfc_free_queue()
877 dma_unmap_single(dev, queue->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL); in ibmvfc_free_queue()
878 free_page((unsigned long)queue->msgs.handle); in ibmvfc_free_queue()
879 queue->msgs.handle = NULL; in ibmvfc_free_queue()
885 * ibmvfc_release_crq_queue - Deallocates data and unregisters CRQ
894 struct vio_dev *vdev = to_vio_dev(vhost->dev); in ibmvfc_release_crq_queue()
895 struct ibmvfc_queue *crq = &vhost->crq; in ibmvfc_release_crq_queue()
898 free_irq(vdev->irq, vhost); in ibmvfc_release_crq_queue()
899 tasklet_kill(&vhost->tasklet); in ibmvfc_release_crq_queue()
903 rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); in ibmvfc_release_crq_queue()
906 vhost->state = IBMVFC_NO_CRQ; in ibmvfc_release_crq_queue()
907 vhost->logged_in = 0; in ibmvfc_release_crq_queue()
913 * ibmvfc_reenable_crq_queue - reenables the CRQ
922 struct vio_dev *vdev = to_vio_dev(vhost->dev); in ibmvfc_reenable_crq_queue()
927 /* Re-enable the CRQ */ in ibmvfc_reenable_crq_queue()
931 rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address); in ibmvfc_reenable_crq_queue()
935 dev_err(vhost->dev, "Error enabling adapter (rc=%d)\n", rc); in ibmvfc_reenable_crq_queue()
937 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_reenable_crq_queue()
938 spin_lock(vhost->crq.q_lock); in ibmvfc_reenable_crq_queue()
939 vhost->do_enquiry = 1; in ibmvfc_reenable_crq_queue()
940 vhost->using_channels = 0; in ibmvfc_reenable_crq_queue()
941 spin_unlock(vhost->crq.q_lock); in ibmvfc_reenable_crq_queue()
942 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_reenable_crq_queue()
950 * ibmvfc_reset_crq - resets a crq after a failure
960 struct vio_dev *vdev = to_vio_dev(vhost->dev); in ibmvfc_reset_crq()
961 struct ibmvfc_queue *crq = &vhost->crq; in ibmvfc_reset_crq()
969 rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); in ibmvfc_reset_crq()
972 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_reset_crq()
973 spin_lock(vhost->crq.q_lock); in ibmvfc_reset_crq()
974 vhost->state = IBMVFC_NO_CRQ; in ibmvfc_reset_crq()
975 vhost->logged_in = 0; in ibmvfc_reset_crq()
976 vhost->do_enquiry = 1; in ibmvfc_reset_crq()
977 vhost->using_channels = 0; in ibmvfc_reset_crq()
980 memset(crq->msgs.crq, 0, PAGE_SIZE); in ibmvfc_reset_crq()
981 crq->cur = 0; in ibmvfc_reset_crq()
983 /* And re-open it again */ in ibmvfc_reset_crq()
984 rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address, in ibmvfc_reset_crq()
985 crq->msg_token, PAGE_SIZE); in ibmvfc_reset_crq()
989 dev_warn(vhost->dev, "Partner adapter not ready\n"); in ibmvfc_reset_crq()
991 dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc); in ibmvfc_reset_crq()
993 spin_unlock(vhost->crq.q_lock); in ibmvfc_reset_crq()
994 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_reset_crq()
1002 * ibmvfc_valid_event - Determines if event is valid.
1004 * @evt: ibmvfc event to be checked for validity
1010 struct ibmvfc_event *evt) in ibmvfc_valid_event() argument
1012 int index = evt - pool->events; in ibmvfc_valid_event()
1013 if (index < 0 || index >= pool->size) /* outside of bounds */ in ibmvfc_valid_event()
1015 if (evt != pool->events + index) /* unaligned */ in ibmvfc_valid_event()
1021 * ibmvfc_free_event - Free the specified event
1022 * @evt: ibmvfc_event to be freed
1025 static void ibmvfc_free_event(struct ibmvfc_event *evt) in ibmvfc_free_event() argument
1027 struct ibmvfc_event_pool *pool = &evt->queue->evt_pool; in ibmvfc_free_event()
1030 BUG_ON(!ibmvfc_valid_event(pool, evt)); in ibmvfc_free_event()
1031 BUG_ON(atomic_inc_return(&evt->free) != 1); in ibmvfc_free_event()
1032 BUG_ON(atomic_dec_and_test(&evt->active)); in ibmvfc_free_event()
1034 spin_lock_irqsave(&evt->queue->l_lock, flags); in ibmvfc_free_event()
1035 list_add_tail(&evt->queue_list, &evt->queue->free); in ibmvfc_free_event()
1036 if (evt->eh_comp) in ibmvfc_free_event()
1037 complete(evt->eh_comp); in ibmvfc_free_event()
1038 spin_unlock_irqrestore(&evt->queue->l_lock, flags); in ibmvfc_free_event()
1042 * ibmvfc_scsi_eh_done - EH done function for queuecommand commands
1043 * @evt: ibmvfc event struct
1048 static void ibmvfc_scsi_eh_done(struct ibmvfc_event *evt) in ibmvfc_scsi_eh_done() argument
1050 struct scsi_cmnd *cmnd = evt->cmnd; in ibmvfc_scsi_eh_done()
1057 ibmvfc_free_event(evt); in ibmvfc_scsi_eh_done()
1061 * ibmvfc_complete_purge - Complete failed command list
1069 struct ibmvfc_event *evt, *pos; in ibmvfc_complete_purge() local
1071 list_for_each_entry_safe(evt, pos, purge_list, queue_list) { in ibmvfc_complete_purge()
1072 list_del(&evt->queue_list); in ibmvfc_complete_purge()
1073 ibmvfc_trc_end(evt); in ibmvfc_complete_purge()
1074 evt->done(evt); in ibmvfc_complete_purge()
1079 * ibmvfc_fail_request - Fail request with specified error code
1080 * @evt: ibmvfc event struct
1086 static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code) in ibmvfc_fail_request() argument
1093 BUG_ON(!atomic_dec_and_test(&evt->active)); in ibmvfc_fail_request()
1094 if (evt->cmnd) { in ibmvfc_fail_request()
1095 evt->cmnd->result = (error_code << 16); in ibmvfc_fail_request()
1096 evt->done = ibmvfc_scsi_eh_done; in ibmvfc_fail_request()
1098 evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED); in ibmvfc_fail_request()
1100 del_timer(&evt->timer); in ibmvfc_fail_request()
1104 * ibmvfc_purge_requests - Our virtual adapter just shut down. Purge any sent requests
1113 struct ibmvfc_event *evt, *pos; in ibmvfc_purge_requests() local
1114 struct ibmvfc_queue *queues = vhost->scsi_scrqs.scrqs; in ibmvfc_purge_requests()
1119 if (vhost->using_channels) in ibmvfc_purge_requests()
1120 hwqs = vhost->scsi_scrqs.active_queues; in ibmvfc_purge_requests()
1123 spin_lock_irqsave(&vhost->crq.l_lock, flags); in ibmvfc_purge_requests()
1124 list_for_each_entry_safe(evt, pos, &vhost->crq.sent, queue_list) in ibmvfc_purge_requests()
1125 ibmvfc_fail_request(evt, error_code); in ibmvfc_purge_requests()
1126 list_splice_init(&vhost->crq.sent, &vhost->purge); in ibmvfc_purge_requests()
1127 spin_unlock_irqrestore(&vhost->crq.l_lock, flags); in ibmvfc_purge_requests()
1132 list_for_each_entry_safe(evt, pos, &queues[i].sent, queue_list) in ibmvfc_purge_requests()
1133 ibmvfc_fail_request(evt, error_code); in ibmvfc_purge_requests()
1134 list_splice_init(&queues[i].sent, &vhost->purge); in ibmvfc_purge_requests()
1141 * ibmvfc_hard_reset_host - Reset the connection to the server by breaking the CRQ
1152 * __ibmvfc_reset_host - Reset the connection to the server (no locking)
1157 if (vhost->logged_in && vhost->action != IBMVFC_HOST_ACTION_LOGO_WAIT && in __ibmvfc_reset_host()
1159 scsi_block_requests(vhost->host); in __ibmvfc_reset_host()
1161 vhost->job_step = ibmvfc_npiv_logout; in __ibmvfc_reset_host()
1162 wake_up(&vhost->work_wait_q); in __ibmvfc_reset_host()
1168 * ibmvfc_reset_host - Reset the connection to the server
1175 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_reset_host()
1177 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_reset_host()
1181 * ibmvfc_retry_host_init - Retry host initialization if allowed
1191 if (vhost->action == IBMVFC_HOST_ACTION_INIT_WAIT) { in ibmvfc_retry_host_init()
1192 vhost->delay_init = 1; in ibmvfc_retry_host_init()
1193 if (++vhost->init_retries > IBMVFC_MAX_HOST_INIT_RETRIES) { in ibmvfc_retry_host_init()
1194 dev_err(vhost->dev, in ibmvfc_retry_host_init()
1197 } else if (vhost->init_retries == IBMVFC_MAX_HOST_INIT_RETRIES) in ibmvfc_retry_host_init()
1205 wake_up(&vhost->work_wait_q); in ibmvfc_retry_host_init()
1210 * __ibmvfc_get_target - Find the specified scsi_target (no locking)
1218 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); in __ibmvfc_get_target()
1222 list_for_each_entry(tgt, &vhost->targets, queue) in __ibmvfc_get_target()
1223 if (tgt->target_id == starget->id) { in __ibmvfc_get_target()
1224 kref_get(&tgt->kref); in __ibmvfc_get_target()
1231 * ibmvfc_get_target - Find the specified scsi_target
1239 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); in ibmvfc_get_target()
1243 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_get_target()
1245 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_get_target()
1250 * ibmvfc_get_host_speed - Get host port speed
1261 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_get_host_speed()
1262 if (vhost->state == IBMVFC_ACTIVE) { in ibmvfc_get_host_speed()
1263 switch (be64_to_cpu(vhost->login_buf->resp.link_speed) / 100) { in ibmvfc_get_host_speed()
1284 be64_to_cpu(vhost->login_buf->resp.link_speed) / 100); in ibmvfc_get_host_speed()
1290 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_get_host_speed()
1294 * ibmvfc_get_host_port_state - Get host port state
1305 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_get_host_port_state()
1306 switch (vhost->state) { in ibmvfc_get_host_port_state()
1325 ibmvfc_log(vhost, 3, "Unknown port state: %d\n", vhost->state); in ibmvfc_get_host_port_state()
1329 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_get_host_port_state()
1333 * ibmvfc_set_rport_dev_loss_tmo - Set rport's device loss timeout
1343 rport->dev_loss_tmo = timeout; in ibmvfc_set_rport_dev_loss_tmo()
1345 rport->dev_loss_tmo = 1; in ibmvfc_set_rport_dev_loss_tmo()
1349 * ibmvfc_release_tgt - Free memory allocated for a target
1360 * ibmvfc_get_starget_node_name - Get SCSI target's node name
1369 fc_starget_port_name(starget) = tgt ? tgt->ids.node_name : 0; in ibmvfc_get_starget_node_name()
1371 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_get_starget_node_name()
1375 * ibmvfc_get_starget_port_name - Get SCSI target's port name
1384 fc_starget_port_name(starget) = tgt ? tgt->ids.port_name : 0; in ibmvfc_get_starget_port_name()
1386 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_get_starget_port_name()
1390 * ibmvfc_get_starget_port_id - Get SCSI target's port ID
1399 fc_starget_port_id(starget) = tgt ? tgt->scsi_id : -1; in ibmvfc_get_starget_port_id()
1401 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_get_starget_port_id()
1405 * ibmvfc_wait_while_resetting - Wait while the host resets
1413 long timeout = wait_event_timeout(vhost->init_wait_q, in ibmvfc_wait_while_resetting()
1414 ((vhost->state == IBMVFC_ACTIVE || in ibmvfc_wait_while_resetting()
1415 vhost->state == IBMVFC_HOST_OFFLINE || in ibmvfc_wait_while_resetting()
1416 vhost->state == IBMVFC_LINK_DEAD) && in ibmvfc_wait_while_resetting()
1417 vhost->action == IBMVFC_HOST_ACTION_NONE), in ibmvfc_wait_while_resetting()
1420 return timeout ? 0 : -EIO; in ibmvfc_wait_while_resetting()
1424 * ibmvfc_issue_fc_host_lip - Re-initiate link initialization
1434 dev_err(vhost->dev, "Initiating host LIP. Resetting connection\n"); in ibmvfc_issue_fc_host_lip()
1440 * ibmvfc_gather_partition_info - Gather info about the LPAR
1450 const unsigned int *num; in ibmvfc_gather_partition_info() local
1456 name = of_get_property(rootdn, "ibm,partition-name", NULL); in ibmvfc_gather_partition_info()
1458 strncpy(vhost->partition_name, name, sizeof(vhost->partition_name)); in ibmvfc_gather_partition_info()
1459 num = of_get_property(rootdn, "ibm,partition-no", NULL); in ibmvfc_gather_partition_info()
1460 if (num) in ibmvfc_gather_partition_info()
1461 vhost->partition_number = *num; in ibmvfc_gather_partition_info()
1466 * ibmvfc_set_login_info - Setup info for NPIV login
1474 struct ibmvfc_npiv_login *login_info = &vhost->login_info; in ibmvfc_set_login_info()
1475 struct ibmvfc_queue *async_crq = &vhost->async_crq; in ibmvfc_set_login_info()
1476 struct device_node *of_node = vhost->dev->of_node; in ibmvfc_set_login_info()
1481 login_info->ostype = cpu_to_be32(IBMVFC_OS_LINUX); in ibmvfc_set_login_info()
1482 login_info->max_dma_len = cpu_to_be64(IBMVFC_MAX_SECTORS << 9); in ibmvfc_set_login_info()
1483 login_info->max_payload = cpu_to_be32(sizeof(struct ibmvfc_fcp_cmd_iu)); in ibmvfc_set_login_info()
1484 login_info->max_response = cpu_to_be32(sizeof(struct ibmvfc_fcp_rsp)); in ibmvfc_set_login_info()
1485 login_info->partition_num = cpu_to_be32(vhost->partition_number); in ibmvfc_set_login_info()
1486 login_info->vfc_frame_version = cpu_to_be32(1); in ibmvfc_set_login_info()
1487 login_info->fcp_version = cpu_to_be16(3); in ibmvfc_set_login_info()
1488 login_info->flags = cpu_to_be16(IBMVFC_FLUSH_ON_HALT); in ibmvfc_set_login_info()
1489 if (vhost->client_migrated) in ibmvfc_set_login_info()
1490 login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED); in ibmvfc_set_login_info()
1492 login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ); in ibmvfc_set_login_info()
1493 login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE | IBMVFC_CAN_SEND_VF_WWPN); in ibmvfc_set_login_info()
1495 if (vhost->mq_enabled || vhost->using_channels) in ibmvfc_set_login_info()
1496 login_info->capabilities |= cpu_to_be64(IBMVFC_CAN_USE_CHANNELS); in ibmvfc_set_login_info()
1498 login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token); in ibmvfc_set_login_info()
1499 login_info->async.len = cpu_to_be32(async_crq->size * in ibmvfc_set_login_info()
1500 sizeof(*async_crq->msgs.async)); in ibmvfc_set_login_info()
1501 strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME); in ibmvfc_set_login_info()
1502 strncpy(login_info->device_name, in ibmvfc_set_login_info()
1503 dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME); in ibmvfc_set_login_info()
1505 location = of_get_property(of_node, "ibm,loc-code", NULL); in ibmvfc_set_login_info()
1506 location = location ? location : dev_name(vhost->dev); in ibmvfc_set_login_info()
1507 strncpy(login_info->drc_name, location, IBMVFC_MAX_NAME); in ibmvfc_set_login_info()
1511 * ibmvfc_get_event - Gets the next free event in pool
1518 struct ibmvfc_event *evt; in ibmvfc_get_event() local
1521 spin_lock_irqsave(&queue->l_lock, flags); in ibmvfc_get_event()
1522 BUG_ON(list_empty(&queue->free)); in ibmvfc_get_event()
1523 evt = list_entry(queue->free.next, struct ibmvfc_event, queue_list); in ibmvfc_get_event()
1524 atomic_set(&evt->free, 0); in ibmvfc_get_event()
1525 list_del(&evt->queue_list); in ibmvfc_get_event()
1526 spin_unlock_irqrestore(&queue->l_lock, flags); in ibmvfc_get_event()
1527 return evt; in ibmvfc_get_event()
1531 * ibmvfc_locked_done - Calls evt completion with host_lock held
1532 * @evt: ibmvfc evt to complete
1534 * All non-scsi command completion callbacks have the expectation that the
1536 * MAD evt with the host_lock.
1538 static void ibmvfc_locked_done(struct ibmvfc_event *evt) in ibmvfc_locked_done() argument
1542 spin_lock_irqsave(evt->vhost->host->host_lock, flags); in ibmvfc_locked_done()
1543 evt->_done(evt); in ibmvfc_locked_done()
1544 spin_unlock_irqrestore(evt->vhost->host->host_lock, flags); in ibmvfc_locked_done()
1548 * ibmvfc_init_event - Initialize fields in an event struct that are always
1550 * @evt: The event
1554 static void ibmvfc_init_event(struct ibmvfc_event *evt, in ibmvfc_init_event() argument
1557 evt->cmnd = NULL; in ibmvfc_init_event()
1558 evt->sync_iu = NULL; in ibmvfc_init_event()
1559 evt->eh_comp = NULL; in ibmvfc_init_event()
1560 evt->crq.format = format; in ibmvfc_init_event()
1562 evt->done = done; in ibmvfc_init_event()
1564 evt->_done = done; in ibmvfc_init_event()
1565 evt->done = ibmvfc_locked_done; in ibmvfc_init_event()
1567 evt->hwq = 0; in ibmvfc_init_event()
1571 * ibmvfc_map_sg_list - Initialize scatterlist
1590 * ibmvfc_map_sg_data - Maps dma for a scatterlist and initializes descriptor fields
1592 * @evt: ibmvfc event struct
1597 * 0 on success / non-zero on failure
1600 struct ibmvfc_event *evt, in ibmvfc_map_sg_data() argument
1605 struct srp_direct_buf *data = &vfc_cmd->ioba; in ibmvfc_map_sg_data()
1607 struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(evt->vhost, vfc_cmd); in ibmvfc_map_sg_data()
1610 vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR); in ibmvfc_map_sg_data()
1614 vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC); in ibmvfc_map_sg_data()
1617 if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) in ibmvfc_map_sg_data()
1622 if (scmd->sc_data_direction == DMA_TO_DEVICE) { in ibmvfc_map_sg_data()
1623 vfc_cmd->flags |= cpu_to_be16(IBMVFC_WRITE); in ibmvfc_map_sg_data()
1624 iu->add_cdb_len |= IBMVFC_WRDATA; in ibmvfc_map_sg_data()
1626 vfc_cmd->flags |= cpu_to_be16(IBMVFC_READ); in ibmvfc_map_sg_data()
1627 iu->add_cdb_len |= IBMVFC_RDDATA; in ibmvfc_map_sg_data()
1635 vfc_cmd->flags |= cpu_to_be16(IBMVFC_SCATTERLIST); in ibmvfc_map_sg_data()
1637 if (!evt->ext_list) { in ibmvfc_map_sg_data()
1638 evt->ext_list = dma_pool_alloc(vhost->sg_pool, GFP_ATOMIC, in ibmvfc_map_sg_data()
1639 &evt->ext_list_token); in ibmvfc_map_sg_data()
1641 if (!evt->ext_list) { in ibmvfc_map_sg_data()
1643 if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) in ibmvfc_map_sg_data()
1645 return -ENOMEM; in ibmvfc_map_sg_data()
1649 ibmvfc_map_sg_list(scmd, sg_mapped, evt->ext_list); in ibmvfc_map_sg_data()
1651 data->va = cpu_to_be64(evt->ext_list_token); in ibmvfc_map_sg_data()
1652 data->len = cpu_to_be32(sg_mapped * sizeof(struct srp_direct_buf)); in ibmvfc_map_sg_data()
1653 data->key = 0; in ibmvfc_map_sg_data()
1658 * ibmvfc_timeout - Internal command timeout handler
1665 struct ibmvfc_event *evt = from_timer(evt, t, timer); in ibmvfc_timeout() local
1666 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_timeout()
1667 dev_err(vhost->dev, "Command timed out (%p). Resetting connection\n", evt); in ibmvfc_timeout()
1672 * ibmvfc_send_event - Transforms event to u64 array and calls send_crq()
1673 * @evt: event to be sent
1675 * @timeout: timeout in seconds - 0 means do not time command
1679 static int ibmvfc_send_event(struct ibmvfc_event *evt, in ibmvfc_send_event() argument
1682 __be64 *crq_as_u64 = (__be64 *) &evt->crq; in ibmvfc_send_event()
1687 *evt->xfer_iu = evt->iu; in ibmvfc_send_event()
1688 if (evt->crq.format == IBMVFC_CMD_FORMAT) in ibmvfc_send_event()
1689 evt->xfer_iu->cmd.tag = cpu_to_be64((u64)evt); in ibmvfc_send_event()
1690 else if (evt->crq.format == IBMVFC_MAD_FORMAT) in ibmvfc_send_event()
1691 evt->xfer_iu->mad_common.tag = cpu_to_be64((u64)evt); in ibmvfc_send_event()
1695 timer_setup(&evt->timer, ibmvfc_timeout, 0); in ibmvfc_send_event()
1698 evt->timer.expires = jiffies + (timeout * HZ); in ibmvfc_send_event()
1699 add_timer(&evt->timer); in ibmvfc_send_event()
1702 spin_lock_irqsave(&evt->queue->l_lock, flags); in ibmvfc_send_event()
1703 list_add_tail(&evt->queue_list, &evt->queue->sent); in ibmvfc_send_event()
1704 atomic_set(&evt->active, 1); in ibmvfc_send_event()
1708 if (evt->queue->fmt == IBMVFC_SUB_CRQ_FMT) in ibmvfc_send_event()
1710 evt->queue->vios_cookie, in ibmvfc_send_event()
1719 atomic_set(&evt->active, 0); in ibmvfc_send_event()
1720 list_del(&evt->queue_list); in ibmvfc_send_event()
1721 spin_unlock_irqrestore(&evt->queue->l_lock, flags); in ibmvfc_send_event()
1722 del_timer(&evt->timer); in ibmvfc_send_event()
1731 dev_warn(vhost->dev, "Send warning. Receive queue closed, will retry.\n"); in ibmvfc_send_event()
1732 if (evt->cmnd) in ibmvfc_send_event()
1733 scsi_dma_unmap(evt->cmnd); in ibmvfc_send_event()
1734 ibmvfc_free_event(evt); in ibmvfc_send_event()
1738 dev_err(vhost->dev, "Send error (rc=%d)\n", rc); in ibmvfc_send_event()
1739 if (evt->cmnd) { in ibmvfc_send_event()
1740 evt->cmnd->result = DID_ERROR << 16; in ibmvfc_send_event()
1741 evt->done = ibmvfc_scsi_eh_done; in ibmvfc_send_event()
1743 evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_CRQ_ERROR); in ibmvfc_send_event()
1745 evt->done(evt); in ibmvfc_send_event()
1747 spin_unlock_irqrestore(&evt->queue->l_lock, flags); in ibmvfc_send_event()
1748 ibmvfc_trc_start(evt); in ibmvfc_send_event()
1755 * ibmvfc_log_error - Log an error for the failed command if appropriate
1756 * @evt: ibmvfc event to log
1759 static void ibmvfc_log_error(struct ibmvfc_event *evt) in ibmvfc_log_error() argument
1761 struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; in ibmvfc_log_error()
1762 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_log_error()
1764 struct scsi_cmnd *cmnd = evt->cmnd; in ibmvfc_log_error()
1766 int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error)); in ibmvfc_log_error()
1775 if (!logerr && (vhost->log_level <= (IBMVFC_DEFAULT_LOG_LEVEL + 1))) in ibmvfc_log_error()
1778 if (rsp->flags & FCP_RSP_LEN_VALID) in ibmvfc_log_error()
1779 rsp_code = rsp->data.info.rsp_code; in ibmvfc_log_error()
1783 cmnd->cmnd[0], err, be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error), in ibmvfc_log_error()
1784 rsp->flags, rsp_code, scsi_get_resid(cmnd), rsp->scsi_status); in ibmvfc_log_error()
1788 * ibmvfc_relogin - Log back into the specified device
1794 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_relogin()
1799 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_relogin()
1800 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_relogin()
1801 if (rport == tgt->rport) { in ibmvfc_relogin()
1808 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_relogin()
1812 * ibmvfc_scsi_done - Handle responses from commands
1813 * @evt: ibmvfc event to be handled
1817 static void ibmvfc_scsi_done(struct ibmvfc_event *evt) in ibmvfc_scsi_done() argument
1819 struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; in ibmvfc_scsi_done()
1820 struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(evt->vhost, vfc_cmd); in ibmvfc_scsi_done()
1821 struct scsi_cmnd *cmnd = evt->cmnd; in ibmvfc_scsi_done()
1823 u32 sense_len = be32_to_cpu(rsp->fcp_sense_len); in ibmvfc_scsi_done()
1826 if (be16_to_cpu(vfc_cmd->response_flags) & IBMVFC_ADAPTER_RESID_VALID) in ibmvfc_scsi_done()
1827 scsi_set_resid(cmnd, be32_to_cpu(vfc_cmd->adapter_resid)); in ibmvfc_scsi_done()
1828 else if (rsp->flags & FCP_RESID_UNDER) in ibmvfc_scsi_done()
1829 scsi_set_resid(cmnd, be32_to_cpu(rsp->fcp_resid)); in ibmvfc_scsi_done()
1833 if (vfc_cmd->status) { in ibmvfc_scsi_done()
1834 cmnd->result = ibmvfc_get_err_result(evt->vhost, vfc_cmd); in ibmvfc_scsi_done()
1836 if (rsp->flags & FCP_RSP_LEN_VALID) in ibmvfc_scsi_done()
1837 rsp_len = be32_to_cpu(rsp->fcp_rsp_len); in ibmvfc_scsi_done()
1839 sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len; in ibmvfc_scsi_done()
1840 if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8) in ibmvfc_scsi_done()
1841 memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len); in ibmvfc_scsi_done()
1842 if ((be16_to_cpu(vfc_cmd->status) & IBMVFC_VIOS_FAILURE) && in ibmvfc_scsi_done()
1843 (be16_to_cpu(vfc_cmd->error) == IBMVFC_PLOGI_REQUIRED)) in ibmvfc_scsi_done()
1844 ibmvfc_relogin(cmnd->device); in ibmvfc_scsi_done()
1846 if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER))) in ibmvfc_scsi_done()
1847 cmnd->result = (DID_ERROR << 16); in ibmvfc_scsi_done()
1849 ibmvfc_log_error(evt); in ibmvfc_scsi_done()
1852 if (!cmnd->result && in ibmvfc_scsi_done()
1853 (scsi_bufflen(cmnd) - scsi_get_resid(cmnd) < cmnd->underflow)) in ibmvfc_scsi_done()
1854 cmnd->result = (DID_ERROR << 16); in ibmvfc_scsi_done()
1860 ibmvfc_free_event(evt); in ibmvfc_scsi_done()
1864 * ibmvfc_host_chkready - Check if the host can accept commands
1874 switch (vhost->state) { in ibmvfc_host_chkready()
1893 static struct ibmvfc_cmd *ibmvfc_init_vfc_cmd(struct ibmvfc_event *evt, struct scsi_device *sdev) in ibmvfc_init_vfc_cmd() argument
1896 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_init_vfc_cmd()
1897 struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; in ibmvfc_init_vfc_cmd()
1905 vfc_cmd->target_wwpn = cpu_to_be64(rport->port_name); in ibmvfc_init_vfc_cmd()
1908 vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offset); in ibmvfc_init_vfc_cmd()
1909 vfc_cmd->resp.len = cpu_to_be32(sizeof(*rsp)); in ibmvfc_init_vfc_cmd()
1910 vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); in ibmvfc_init_vfc_cmd()
1911 vfc_cmd->payload_len = cpu_to_be32(sizeof(*iu)); in ibmvfc_init_vfc_cmd()
1912 vfc_cmd->resp_len = cpu_to_be32(sizeof(*rsp)); in ibmvfc_init_vfc_cmd()
1913 vfc_cmd->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); in ibmvfc_init_vfc_cmd()
1914 vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); in ibmvfc_init_vfc_cmd()
1915 int_to_scsilun(sdev->lun, &iu->lun); in ibmvfc_init_vfc_cmd()
1921 * ibmvfc_queuecommand - The queuecommand function of the scsi template
1931 struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); in ibmvfc_queuecommand()
1934 struct ibmvfc_event *evt; in ibmvfc_queuecommand() local
1942 cmnd->result = rc; in ibmvfc_queuecommand()
1947 cmnd->result = (DID_OK << 16); in ibmvfc_queuecommand()
1948 if (vhost->using_channels) { in ibmvfc_queuecommand()
1949 scsi_channel = hwq % vhost->scsi_scrqs.active_queues; in ibmvfc_queuecommand()
1950 evt = ibmvfc_get_event(&vhost->scsi_scrqs.scrqs[scsi_channel]); in ibmvfc_queuecommand()
1951 evt->hwq = hwq % vhost->scsi_scrqs.active_queues; in ibmvfc_queuecommand()
1953 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_queuecommand()
1955 ibmvfc_init_event(evt, ibmvfc_scsi_done, IBMVFC_CMD_FORMAT); in ibmvfc_queuecommand()
1956 evt->cmnd = cmnd; in ibmvfc_queuecommand()
1958 vfc_cmd = ibmvfc_init_vfc_cmd(evt, cmnd->device); in ibmvfc_queuecommand()
1961 iu->xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); in ibmvfc_queuecommand()
1962 memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len); in ibmvfc_queuecommand()
1964 if (cmnd->flags & SCMD_TAGGED) { in ibmvfc_queuecommand()
1965 vfc_cmd->task_tag = cpu_to_be64(scsi_cmd_to_rq(cmnd)->tag); in ibmvfc_queuecommand()
1966 iu->pri_task_attr = IBMVFC_SIMPLE_TASK; in ibmvfc_queuecommand()
1969 vfc_cmd->correlation = cpu_to_be64((u64)evt); in ibmvfc_queuecommand()
1971 if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev)))) in ibmvfc_queuecommand()
1972 return ibmvfc_send_event(evt, vhost, 0); in ibmvfc_queuecommand()
1974 ibmvfc_free_event(evt); in ibmvfc_queuecommand()
1975 if (rc == -ENOMEM) in ibmvfc_queuecommand()
1978 if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) in ibmvfc_queuecommand()
1982 cmnd->result = DID_ERROR << 16; in ibmvfc_queuecommand()
1988 * ibmvfc_sync_completion - Signal that a synchronous command has completed
1989 * @evt: ibmvfc event struct
1992 static void ibmvfc_sync_completion(struct ibmvfc_event *evt) in ibmvfc_sync_completion() argument
1995 if (evt->sync_iu) in ibmvfc_sync_completion()
1996 *evt->sync_iu = *evt->xfer_iu; in ibmvfc_sync_completion()
1998 complete(&evt->comp); in ibmvfc_sync_completion()
2002 * ibmvfc_bsg_timeout_done - Completion handler for cancelling BSG commands
2003 * @evt: struct ibmvfc_event
2006 static void ibmvfc_bsg_timeout_done(struct ibmvfc_event *evt) in ibmvfc_bsg_timeout_done() argument
2008 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_bsg_timeout_done()
2010 ibmvfc_free_event(evt); in ibmvfc_bsg_timeout_done()
2011 vhost->aborting_passthru = 0; in ibmvfc_bsg_timeout_done()
2012 dev_info(vhost->dev, "Passthru command cancelled\n"); in ibmvfc_bsg_timeout_done()
2016 * ibmvfc_bsg_timeout - Handle a BSG timeout
2025 unsigned long port_id = (unsigned long)job->dd_data; in ibmvfc_bsg_timeout()
2026 struct ibmvfc_event *evt; in ibmvfc_bsg_timeout() local
2032 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_bsg_timeout()
2033 if (vhost->aborting_passthru || vhost->state != IBMVFC_ACTIVE) { in ibmvfc_bsg_timeout()
2035 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_bsg_timeout()
2039 vhost->aborting_passthru = 1; in ibmvfc_bsg_timeout()
2040 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_bsg_timeout()
2041 ibmvfc_init_event(evt, ibmvfc_bsg_timeout_done, IBMVFC_MAD_FORMAT); in ibmvfc_bsg_timeout()
2043 tmf = &evt->iu.tmf; in ibmvfc_bsg_timeout()
2045 tmf->common.version = cpu_to_be32(1); in ibmvfc_bsg_timeout()
2046 tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); in ibmvfc_bsg_timeout()
2047 tmf->common.length = cpu_to_be16(sizeof(*tmf)); in ibmvfc_bsg_timeout()
2048 tmf->scsi_id = cpu_to_be64(port_id); in ibmvfc_bsg_timeout()
2049 tmf->cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY); in ibmvfc_bsg_timeout()
2050 tmf->my_cancel_key = cpu_to_be32(IBMVFC_INTERNAL_CANCEL_KEY); in ibmvfc_bsg_timeout()
2051 rc = ibmvfc_send_event(evt, vhost, default_timeout); in ibmvfc_bsg_timeout()
2054 vhost->aborting_passthru = 0; in ibmvfc_bsg_timeout()
2055 dev_err(vhost->dev, "Failed to send cancel event. rc=%d\n", rc); in ibmvfc_bsg_timeout()
2056 rc = -EIO; in ibmvfc_bsg_timeout()
2058 dev_info(vhost->dev, "Cancelling passthru command to port id 0x%lx\n", in ibmvfc_bsg_timeout()
2061 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_bsg_timeout()
2068 * ibmvfc_bsg_plogi - PLOGI into a target to handle a BSG command
2079 struct ibmvfc_event *evt; in ibmvfc_bsg_plogi() local
2085 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_bsg_plogi()
2086 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_bsg_plogi()
2087 if (tgt->scsi_id == port_id) { in ibmvfc_bsg_plogi()
2098 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_bsg_plogi()
2099 ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); in ibmvfc_bsg_plogi()
2100 plogi = &evt->iu.plogi; in ibmvfc_bsg_plogi()
2102 plogi->common.version = cpu_to_be32(1); in ibmvfc_bsg_plogi()
2103 plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN); in ibmvfc_bsg_plogi()
2104 plogi->common.length = cpu_to_be16(sizeof(*plogi)); in ibmvfc_bsg_plogi()
2105 plogi->scsi_id = cpu_to_be64(port_id); in ibmvfc_bsg_plogi()
2106 evt->sync_iu = &rsp_iu; in ibmvfc_bsg_plogi()
2107 init_completion(&evt->comp); in ibmvfc_bsg_plogi()
2109 rc = ibmvfc_send_event(evt, vhost, default_timeout); in ibmvfc_bsg_plogi()
2110 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_bsg_plogi()
2113 return -EIO; in ibmvfc_bsg_plogi()
2115 wait_for_completion(&evt->comp); in ibmvfc_bsg_plogi()
2118 rc = -EIO; in ibmvfc_bsg_plogi()
2120 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_bsg_plogi()
2121 ibmvfc_free_event(evt); in ibmvfc_bsg_plogi()
2123 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_bsg_plogi()
2129 * ibmvfc_bsg_request - Handle a BSG request
2140 struct ibmvfc_event *evt; in ibmvfc_bsg_request() local
2142 unsigned long flags, port_id = -1; in ibmvfc_bsg_request()
2143 struct fc_bsg_request *bsg_request = job->request; in ibmvfc_bsg_request()
2144 struct fc_bsg_reply *bsg_reply = job->reply; in ibmvfc_bsg_request()
2145 unsigned int code = bsg_request->msgcode; in ibmvfc_bsg_request()
2150 bsg_reply->reply_payload_rcv_len = 0; in ibmvfc_bsg_request()
2152 port_id = rport->port_id; in ibmvfc_bsg_request()
2156 port_id = (bsg_request->rqst_data.h_els.port_id[0] << 16) | in ibmvfc_bsg_request()
2157 (bsg_request->rqst_data.h_els.port_id[1] << 8) | in ibmvfc_bsg_request()
2158 bsg_request->rqst_data.h_els.port_id[2]; in ibmvfc_bsg_request()
2165 port_id = (bsg_request->rqst_data.h_ct.port_id[0] << 16) | in ibmvfc_bsg_request()
2166 (bsg_request->rqst_data.h_ct.port_id[1] << 8) | in ibmvfc_bsg_request()
2167 bsg_request->rqst_data.h_ct.port_id[2]; in ibmvfc_bsg_request()
2173 return -ENOTSUPP; in ibmvfc_bsg_request()
2176 if (port_id == -1) in ibmvfc_bsg_request()
2177 return -EINVAL; in ibmvfc_bsg_request()
2178 if (!mutex_trylock(&vhost->passthru_mutex)) in ibmvfc_bsg_request()
2179 return -EBUSY; in ibmvfc_bsg_request()
2181 job->dd_data = (void *)port_id; in ibmvfc_bsg_request()
2182 req_seg = dma_map_sg(vhost->dev, job->request_payload.sg_list, in ibmvfc_bsg_request()
2183 job->request_payload.sg_cnt, DMA_TO_DEVICE); in ibmvfc_bsg_request()
2186 mutex_unlock(&vhost->passthru_mutex); in ibmvfc_bsg_request()
2187 return -ENOMEM; in ibmvfc_bsg_request()
2190 rsp_seg = dma_map_sg(vhost->dev, job->reply_payload.sg_list, in ibmvfc_bsg_request()
2191 job->reply_payload.sg_cnt, DMA_FROM_DEVICE); in ibmvfc_bsg_request()
2194 dma_unmap_sg(vhost->dev, job->request_payload.sg_list, in ibmvfc_bsg_request()
2195 job->request_payload.sg_cnt, DMA_TO_DEVICE); in ibmvfc_bsg_request()
2196 mutex_unlock(&vhost->passthru_mutex); in ibmvfc_bsg_request()
2197 return -ENOMEM; in ibmvfc_bsg_request()
2201 rc = -EINVAL; in ibmvfc_bsg_request()
2208 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_bsg_request()
2212 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_bsg_request()
2216 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_bsg_request()
2217 ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); in ibmvfc_bsg_request()
2218 mad = &evt->iu.passthru; in ibmvfc_bsg_request()
2221 mad->common.version = cpu_to_be32(1); in ibmvfc_bsg_request()
2222 mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU); in ibmvfc_bsg_request()
2223 mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu)); in ibmvfc_bsg_request()
2225 mad->cmd_ioba.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + in ibmvfc_bsg_request()
2227 mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu)); in ibmvfc_bsg_request()
2229 mad->iu.cmd_len = cpu_to_be32(job->request_payload.payload_len); in ibmvfc_bsg_request()
2230 mad->iu.rsp_len = cpu_to_be32(job->reply_payload.payload_len); in ibmvfc_bsg_request()
2231 mad->iu.flags = cpu_to_be32(fc_flags); in ibmvfc_bsg_request()
2232 mad->iu.cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY); in ibmvfc_bsg_request()
2234 mad->iu.cmd.va = cpu_to_be64(sg_dma_address(job->request_payload.sg_list)); in ibmvfc_bsg_request()
2235 mad->iu.cmd.len = cpu_to_be32(sg_dma_len(job->request_payload.sg_list)); in ibmvfc_bsg_request()
2236 mad->iu.rsp.va = cpu_to_be64(sg_dma_address(job->reply_payload.sg_list)); in ibmvfc_bsg_request()
2237 mad->iu.rsp.len = cpu_to_be32(sg_dma_len(job->reply_payload.sg_list)); in ibmvfc_bsg_request()
2238 mad->iu.scsi_id = cpu_to_be64(port_id); in ibmvfc_bsg_request()
2239 mad->iu.tag = cpu_to_be64((u64)evt); in ibmvfc_bsg_request()
2240 rsp_len = be32_to_cpu(mad->iu.rsp.len); in ibmvfc_bsg_request()
2242 evt->sync_iu = &rsp_iu; in ibmvfc_bsg_request()
2243 init_completion(&evt->comp); in ibmvfc_bsg_request()
2244 rc = ibmvfc_send_event(evt, vhost, 0); in ibmvfc_bsg_request()
2245 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_bsg_request()
2248 rc = -EIO; in ibmvfc_bsg_request()
2252 wait_for_completion(&evt->comp); in ibmvfc_bsg_request()
2255 rc = -EIO; in ibmvfc_bsg_request()
2257 bsg_reply->reply_payload_rcv_len = rsp_len; in ibmvfc_bsg_request()
2259 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_bsg_request()
2260 ibmvfc_free_event(evt); in ibmvfc_bsg_request()
2261 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_bsg_request()
2262 bsg_reply->result = rc; in ibmvfc_bsg_request()
2263 bsg_job_done(job, bsg_reply->result, in ibmvfc_bsg_request()
2264 bsg_reply->reply_payload_rcv_len); in ibmvfc_bsg_request()
2267 dma_unmap_sg(vhost->dev, job->request_payload.sg_list, in ibmvfc_bsg_request()
2268 job->request_payload.sg_cnt, DMA_TO_DEVICE); in ibmvfc_bsg_request()
2269 dma_unmap_sg(vhost->dev, job->reply_payload.sg_list, in ibmvfc_bsg_request()
2270 job->reply_payload.sg_cnt, DMA_FROM_DEVICE); in ibmvfc_bsg_request()
2271 mutex_unlock(&vhost->passthru_mutex); in ibmvfc_bsg_request()
2277 * ibmvfc_reset_device - Reset the device with the specified reset type
2287 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_reset_device()
2290 struct ibmvfc_event *evt = NULL; in ibmvfc_reset_device() local
2294 int rsp_rc = -EBUSY; in ibmvfc_reset_device()
2298 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_reset_device()
2299 if (vhost->state == IBMVFC_ACTIVE) { in ibmvfc_reset_device()
2300 if (vhost->using_channels) in ibmvfc_reset_device()
2301 evt = ibmvfc_get_event(&vhost->scsi_scrqs.scrqs[0]); in ibmvfc_reset_device()
2303 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_reset_device()
2305 ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); in ibmvfc_reset_device()
2306 tmf = ibmvfc_init_vfc_cmd(evt, sdev); in ibmvfc_reset_device()
2309 tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); in ibmvfc_reset_device()
2311 tmf->target_wwpn = cpu_to_be64(rport->port_name); in ibmvfc_reset_device()
2312 iu->tmf_flags = type; in ibmvfc_reset_device()
2313 evt->sync_iu = &rsp_iu; in ibmvfc_reset_device()
2315 init_completion(&evt->comp); in ibmvfc_reset_device()
2316 rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); in ibmvfc_reset_device()
2318 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_reset_device()
2323 return -EIO; in ibmvfc_reset_device()
2327 wait_for_completion(&evt->comp); in ibmvfc_reset_device()
2333 if (fc_rsp->flags & FCP_RSP_LEN_VALID) in ibmvfc_reset_device()
2334 rsp_code = fc_rsp->data.info.rsp_code; in ibmvfc_reset_device()
2339 be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error), fc_rsp->flags, rsp_code, in ibmvfc_reset_device()
2340 fc_rsp->scsi_status); in ibmvfc_reset_device()
2341 rsp_rc = -EIO; in ibmvfc_reset_device()
2345 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_reset_device()
2346 ibmvfc_free_event(evt); in ibmvfc_reset_device()
2347 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_reset_device()
2352 * ibmvfc_match_rport - Match function for specified remote port
2353 * @evt: ibmvfc event struct
2359 static int ibmvfc_match_rport(struct ibmvfc_event *evt, void *rport) in ibmvfc_match_rport() argument
2363 if (evt->cmnd) { in ibmvfc_match_rport()
2364 cmd_rport = starget_to_rport(scsi_target(evt->cmnd->device)); in ibmvfc_match_rport()
2372 * ibmvfc_match_target - Match function for specified target
2373 * @evt: ibmvfc event struct
2379 static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) in ibmvfc_match_target() argument
2381 if (evt->cmnd && scsi_target(evt->cmnd->device) == device) in ibmvfc_match_target()
2387 * ibmvfc_match_lun - Match function for specified LUN
2388 * @evt: ibmvfc event struct
2394 static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) in ibmvfc_match_lun() argument
2396 if (evt->cmnd && evt->cmnd->device == device) in ibmvfc_match_lun()
2402 * ibmvfc_event_is_free - Check if event is free or not
2403 * @evt: ibmvfc event struct
2408 static bool ibmvfc_event_is_free(struct ibmvfc_event *evt) in ibmvfc_event_is_free() argument
2412 list_for_each_entry(loop_evt, &evt->queue->free, queue_list) in ibmvfc_event_is_free()
2413 if (loop_evt == evt) in ibmvfc_event_is_free()
2420 * ibmvfc_wait_for_ops - Wait for ops to complete
2431 struct ibmvfc_event *evt; in ibmvfc_wait_for_ops() local
2439 if (vhost->mq_enabled && vhost->using_channels) { in ibmvfc_wait_for_ops()
2440 queues = vhost->scsi_scrqs.scrqs; in ibmvfc_wait_for_ops()
2441 q_size = vhost->scsi_scrqs.active_queues; in ibmvfc_wait_for_ops()
2443 queues = &vhost->crq; in ibmvfc_wait_for_ops()
2449 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_wait_for_ops()
2453 evt = &queues[q_index].evt_pool.events[i]; in ibmvfc_wait_for_ops()
2454 if (!ibmvfc_event_is_free(evt)) { in ibmvfc_wait_for_ops()
2455 if (match(evt, device)) { in ibmvfc_wait_for_ops()
2456 evt->eh_comp = ∁ in ibmvfc_wait_for_ops()
2463 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_wait_for_ops()
2470 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_wait_for_ops()
2474 evt = &queues[q_index].evt_pool.events[i]; in ibmvfc_wait_for_ops()
2475 if (!ibmvfc_event_is_free(evt)) { in ibmvfc_wait_for_ops()
2476 if (match(evt, device)) { in ibmvfc_wait_for_ops()
2477 evt->eh_comp = NULL; in ibmvfc_wait_for_ops()
2484 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_wait_for_ops()
2486 dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); in ibmvfc_wait_for_ops()
2501 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_init_tmf()
2504 struct ibmvfc_event *evt; in ibmvfc_init_tmf() local
2507 evt = ibmvfc_get_event(queue); in ibmvfc_init_tmf()
2508 ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); in ibmvfc_init_tmf()
2510 tmf = &evt->iu.tmf; in ibmvfc_init_tmf()
2513 tmf->common.version = cpu_to_be32(2); in ibmvfc_init_tmf()
2514 tmf->target_wwpn = cpu_to_be64(rport->port_name); in ibmvfc_init_tmf()
2516 tmf->common.version = cpu_to_be32(1); in ibmvfc_init_tmf()
2518 tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); in ibmvfc_init_tmf()
2519 tmf->common.length = cpu_to_be16(sizeof(*tmf)); in ibmvfc_init_tmf()
2520 tmf->scsi_id = cpu_to_be64(rport->port_id); in ibmvfc_init_tmf()
2521 int_to_scsilun(sdev->lun, &tmf->lun); in ibmvfc_init_tmf()
2524 if (vhost->state == IBMVFC_ACTIVE) in ibmvfc_init_tmf()
2525 tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID)); in ibmvfc_init_tmf()
2527 tmf->flags = cpu_to_be32(((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID)); in ibmvfc_init_tmf()
2528 tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); in ibmvfc_init_tmf()
2529 tmf->my_cancel_key = cpu_to_be32((unsigned long)starget->hostdata); in ibmvfc_init_tmf()
2531 init_completion(&evt->comp); in ibmvfc_init_tmf()
2533 return evt; in ibmvfc_init_tmf()
2538 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_cancel_all_mq()
2539 struct ibmvfc_event *evt, *found_evt, *temp; in ibmvfc_cancel_all_mq() local
2540 struct ibmvfc_queue *queues = vhost->scsi_scrqs.scrqs; in ibmvfc_cancel_all_mq()
2548 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_cancel_all_mq()
2549 num_hwq = vhost->scsi_scrqs.active_queues; in ibmvfc_cancel_all_mq()
2554 list_for_each_entry(evt, &queues[i].sent, queue_list) { in ibmvfc_cancel_all_mq()
2555 if (evt->cmnd && evt->cmnd->device == sdev) { in ibmvfc_cancel_all_mq()
2556 found_evt = evt; in ibmvfc_cancel_all_mq()
2562 if (found_evt && vhost->logged_in) { in ibmvfc_cancel_all_mq()
2563 evt = ibmvfc_init_tmf(&queues[i], sdev, type); in ibmvfc_cancel_all_mq()
2564 evt->sync_iu = &queues[i].cancel_rsp; in ibmvfc_cancel_all_mq()
2565 ibmvfc_send_event(evt, vhost, default_timeout); in ibmvfc_cancel_all_mq()
2566 list_add_tail(&evt->cancel, &cancelq); in ibmvfc_cancel_all_mq()
2571 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_cancel_all_mq()
2574 if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) in ibmvfc_cancel_all_mq()
2581 list_for_each_entry_safe(evt, temp, &cancelq, cancel) { in ibmvfc_cancel_all_mq()
2582 wait_for_completion(&evt->comp); in ibmvfc_cancel_all_mq()
2583 status = be16_to_cpu(evt->queue->cancel_rsp.mad_common.status); in ibmvfc_cancel_all_mq()
2584 list_del(&evt->cancel); in ibmvfc_cancel_all_mq()
2585 ibmvfc_free_event(evt); in ibmvfc_cancel_all_mq()
2604 return -EIO; in ibmvfc_cancel_all_mq()
2613 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_cancel_all_sq()
2614 struct ibmvfc_event *evt, *found_evt; in ibmvfc_cancel_all_sq() local
2616 int rsp_rc = -EBUSY; in ibmvfc_cancel_all_sq()
2622 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_cancel_all_sq()
2623 spin_lock(&vhost->crq.l_lock); in ibmvfc_cancel_all_sq()
2624 list_for_each_entry(evt, &vhost->crq.sent, queue_list) { in ibmvfc_cancel_all_sq()
2625 if (evt->cmnd && evt->cmnd->device == sdev) { in ibmvfc_cancel_all_sq()
2626 found_evt = evt; in ibmvfc_cancel_all_sq()
2630 spin_unlock(&vhost->crq.l_lock); in ibmvfc_cancel_all_sq()
2633 if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) in ibmvfc_cancel_all_sq()
2635 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_cancel_all_sq()
2639 if (vhost->logged_in) { in ibmvfc_cancel_all_sq()
2640 evt = ibmvfc_init_tmf(&vhost->crq, sdev, type); in ibmvfc_cancel_all_sq()
2641 evt->sync_iu = &rsp; in ibmvfc_cancel_all_sq()
2642 rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); in ibmvfc_cancel_all_sq()
2645 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_cancel_all_sq()
2657 wait_for_completion(&evt->comp); in ibmvfc_cancel_all_sq()
2659 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_cancel_all_sq()
2660 ibmvfc_free_event(evt); in ibmvfc_cancel_all_sq()
2661 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_cancel_all_sq()
2672 return -EIO; in ibmvfc_cancel_all_sq()
2681 * ibmvfc_cancel_all - Cancel all outstanding commands to the device
2693 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_cancel_all()
2695 if (vhost->mq_enabled && vhost->using_channels) in ibmvfc_cancel_all()
2702 * ibmvfc_match_key - Match function for specified cancel key
2703 * @evt: ibmvfc event struct
2709 static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) in ibmvfc_match_key() argument
2713 if (evt->crq.format == IBMVFC_CMD_FORMAT && in ibmvfc_match_key()
2714 be32_to_cpu(evt->iu.cmd.cancel_key) == cancel_key) in ibmvfc_match_key()
2720 * ibmvfc_match_evt - Match function for specified event
2721 * @evt: ibmvfc event struct
2727 static int ibmvfc_match_evt(struct ibmvfc_event *evt, void *match) in ibmvfc_match_evt() argument
2729 if (evt == match) in ibmvfc_match_evt()
2735 * ibmvfc_abort_task_set - Abort outstanding commands to the device
2746 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_abort_task_set()
2749 struct ibmvfc_event *evt, *found_evt; in ibmvfc_abort_task_set() local
2753 int rc, rsp_rc = -EBUSY; in ibmvfc_abort_task_set()
2758 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_abort_task_set()
2759 spin_lock(&vhost->crq.l_lock); in ibmvfc_abort_task_set()
2760 list_for_each_entry(evt, &vhost->crq.sent, queue_list) { in ibmvfc_abort_task_set()
2761 if (evt->cmnd && evt->cmnd->device == sdev) { in ibmvfc_abort_task_set()
2762 found_evt = evt; in ibmvfc_abort_task_set()
2766 spin_unlock(&vhost->crq.l_lock); in ibmvfc_abort_task_set()
2769 if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) in ibmvfc_abort_task_set()
2771 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_abort_task_set()
2775 if (vhost->state == IBMVFC_ACTIVE) { in ibmvfc_abort_task_set()
2776 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_abort_task_set()
2777 ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); in ibmvfc_abort_task_set()
2778 tmf = ibmvfc_init_vfc_cmd(evt, sdev); in ibmvfc_abort_task_set()
2782 tmf->target_wwpn = cpu_to_be64(rport->port_name); in ibmvfc_abort_task_set()
2783 iu->tmf_flags = IBMVFC_ABORT_TASK_SET; in ibmvfc_abort_task_set()
2784 tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); in ibmvfc_abort_task_set()
2785 evt->sync_iu = &rsp_iu; in ibmvfc_abort_task_set()
2787 tmf->correlation = cpu_to_be64((u64)evt); in ibmvfc_abort_task_set()
2789 init_completion(&evt->comp); in ibmvfc_abort_task_set()
2790 rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); in ibmvfc_abort_task_set()
2793 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_abort_task_set()
2797 return -EIO; in ibmvfc_abort_task_set()
2801 timeout = wait_for_completion_timeout(&evt->comp, timeout); in ibmvfc_abort_task_set()
2806 rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); in ibmvfc_abort_task_set()
2814 rsp_rc = -EIO; in ibmvfc_abort_task_set()
2815 rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); in ibmvfc_abort_task_set()
2820 rc = ibmvfc_wait_for_ops(vhost, evt, ibmvfc_match_evt); in ibmvfc_abort_task_set()
2822 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_abort_task_set()
2824 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_abort_task_set()
2836 if (fc_rsp->flags & FCP_RSP_LEN_VALID) in ibmvfc_abort_task_set()
2837 rsp_code = fc_rsp->data.info.rsp_code; in ibmvfc_abort_task_set()
2842 be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error), fc_rsp->flags, rsp_code, in ibmvfc_abort_task_set()
2843 fc_rsp->scsi_status); in ibmvfc_abort_task_set()
2844 rsp_rc = -EIO; in ibmvfc_abort_task_set()
2849 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_abort_task_set()
2850 ibmvfc_free_event(evt); in ibmvfc_abort_task_set()
2851 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_abort_task_set()
2856 * ibmvfc_eh_abort_handler - Abort a command
2864 struct scsi_device *sdev = cmd->device; in ibmvfc_eh_abort_handler()
2865 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_eh_abort_handler()
2889 * ibmvfc_eh_device_reset_handler - Reset a single LUN
2897 struct scsi_device *sdev = cmd->device; in ibmvfc_eh_device_reset_handler()
2898 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_eh_device_reset_handler()
2922 * ibmvfc_dev_cancel_all_noreset - Device iterated cancel all function
2934 * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function
2946 * ibmvfc_eh_target_reset_handler - Reset the target
2954 struct scsi_device *sdev = cmd->device; in ibmvfc_eh_target_reset_handler()
2955 struct ibmvfc_host *vhost = shost_priv(sdev->host); in ibmvfc_eh_target_reset_handler()
2982 * ibmvfc_eh_host_reset_handler - Reset the connection to the server
2989 struct ibmvfc_host *vhost = shost_priv(cmd->device->host); in ibmvfc_eh_host_reset_handler()
2991 dev_err(vhost->dev, "Resetting connection due to error recovery\n"); in ibmvfc_eh_host_reset_handler()
2992 rc = ibmvfc_issue_fc_host_lip(vhost->host); in ibmvfc_eh_host_reset_handler()
2998 * ibmvfc_terminate_rport_io - Terminate all pending I/O to the rport.
3027 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_terminate_rport_io()
3029 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_terminate_rport_io()
3030 if (tgt->scsi_id == rport->port_id) { in ibmvfc_terminate_rport_io()
3036 if (found && tgt->action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) { in ibmvfc_terminate_rport_io()
3046 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_terminate_rport_io()
3054 { "N-Port SCN", IBMVFC_AE_SCN_NPORT, IBMVFC_DEFAULT_LOG_LEVEL + 1 },
3071 * ibmvfc_get_ae_desc - Get text description for async event
3097 * ibmvfc_get_link_state - Get text description for link state
3113 * ibmvfc_handle_async - Handle an async event from the adapter
3121 const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(be64_to_cpu(crq->event)); in ibmvfc_handle_async()
3124 ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx," in ibmvfc_handle_async()
3125 " node_name: %llx%s\n", desc->desc, be64_to_cpu(crq->scsi_id), in ibmvfc_handle_async()
3126 be64_to_cpu(crq->wwpn), be64_to_cpu(crq->node_name), in ibmvfc_handle_async()
3127 ibmvfc_get_link_state(crq->link_state)); in ibmvfc_handle_async()
3129 switch (be64_to_cpu(crq->event)) { in ibmvfc_handle_async()
3131 switch (crq->link_state) { in ibmvfc_handle_async()
3141 vhost->events_to_log |= IBMVFC_AE_LINKUP; in ibmvfc_handle_async()
3142 vhost->delay_init = 1; in ibmvfc_handle_async()
3149 vhost->events_to_log |= IBMVFC_AE_LINKUP; in ibmvfc_handle_async()
3150 vhost->delay_init = 1; in ibmvfc_handle_async()
3155 vhost->events_to_log |= IBMVFC_AE_RSCN; in ibmvfc_handle_async()
3156 if (vhost->state < IBMVFC_HALTED) { in ibmvfc_handle_async()
3157 vhost->delay_init = 1; in ibmvfc_handle_async()
3163 vhost->events_to_log |= IBMVFC_AE_RSCN; in ibmvfc_handle_async()
3169 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_handle_async()
3170 if (!crq->scsi_id && !crq->wwpn && !crq->node_name) in ibmvfc_handle_async()
3172 if (crq->scsi_id && cpu_to_be64(tgt->scsi_id) != crq->scsi_id) in ibmvfc_handle_async()
3174 if (crq->wwpn && cpu_to_be64(tgt->ids.port_name) != crq->wwpn) in ibmvfc_handle_async()
3176 if (crq->node_name && cpu_to_be64(tgt->ids.node_name) != crq->node_name) in ibmvfc_handle_async()
3178 if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO) in ibmvfc_handle_async()
3179 tgt->logo_rcvd = 1; in ibmvfc_handle_async()
3180 if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) { in ibmvfc_handle_async()
3197 dev_err(vhost->dev, "Unknown async event received: %lld\n", crq->event); in ibmvfc_handle_async()
3203 * ibmvfc_handle_crq - Handles and frees received events in the CRQ
3213 struct ibmvfc_event *evt = (struct ibmvfc_event *)be64_to_cpu(crq->ioba); in ibmvfc_handle_crq() local
3215 switch (crq->valid) { in ibmvfc_handle_crq()
3217 switch (crq->format) { in ibmvfc_handle_crq()
3219 dev_info(vhost->dev, "Partner initialized\n"); in ibmvfc_handle_crq()
3225 dev_err(vhost->dev, "Unable to send init rsp. rc=%ld\n", rc); in ibmvfc_handle_crq()
3228 dev_info(vhost->dev, "Partner initialization complete\n"); in ibmvfc_handle_crq()
3232 dev_err(vhost->dev, "Unknown crq message type: %d\n", crq->format); in ibmvfc_handle_crq()
3236 vhost->state = IBMVFC_NO_CRQ; in ibmvfc_handle_crq()
3237 vhost->logged_in = 0; in ibmvfc_handle_crq()
3239 if (crq->format == IBMVFC_PARTITION_MIGRATED) { in ibmvfc_handle_crq()
3240 /* We need to re-setup the interpartition connection */ in ibmvfc_handle_crq()
3241 dev_info(vhost->dev, "Partition migrated, Re-enabling adapter\n"); in ibmvfc_handle_crq()
3242 vhost->client_migrated = 1; in ibmvfc_handle_crq()
3244 scsi_block_requests(vhost->host); in ibmvfc_handle_crq()
3248 wake_up(&vhost->work_wait_q); in ibmvfc_handle_crq()
3249 } else if (crq->format == IBMVFC_PARTNER_FAILED || crq->format == IBMVFC_PARTNER_DEREGISTER) { in ibmvfc_handle_crq()
3250 dev_err(vhost->dev, "Host partner adapter deregistered or failed (rc=%d)\n", crq->format); in ibmvfc_handle_crq()
3255 dev_err(vhost->dev, "Received unknown transport event from partner (rc=%d)\n", crq->format); in ibmvfc_handle_crq()
3261 dev_err(vhost->dev, "Got an invalid message type 0x%02x\n", crq->valid); in ibmvfc_handle_crq()
3265 if (crq->format == IBMVFC_ASYNC_EVENT) in ibmvfc_handle_crq()
3272 if (unlikely(!ibmvfc_valid_event(&vhost->crq.evt_pool, evt))) { in ibmvfc_handle_crq()
3273 dev_err(vhost->dev, "Returned correlation_token 0x%08llx is invalid!\n", in ibmvfc_handle_crq()
3274 crq->ioba); in ibmvfc_handle_crq()
3278 if (unlikely(atomic_dec_if_positive(&evt->active))) { in ibmvfc_handle_crq()
3279 dev_err(vhost->dev, "Received duplicate correlation_token 0x%08llx!\n", in ibmvfc_handle_crq()
3280 crq->ioba); in ibmvfc_handle_crq()
3284 spin_lock(&evt->queue->l_lock); in ibmvfc_handle_crq()
3285 list_move_tail(&evt->queue_list, evt_doneq); in ibmvfc_handle_crq()
3286 spin_unlock(&evt->queue->l_lock); in ibmvfc_handle_crq()
3290 * ibmvfc_scan_finished - Check if the device scan is done.
3303 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_scan_finished()
3304 if (!vhost->scan_timeout) in ibmvfc_scan_finished()
3306 else if (time >= (vhost->scan_timeout * HZ)) { in ibmvfc_scan_finished()
3307 dev_info(vhost->dev, "Scan taking longer than %d seconds, " in ibmvfc_scan_finished()
3308 "continuing initialization\n", vhost->scan_timeout); in ibmvfc_scan_finished()
3312 if (vhost->scan_complete) { in ibmvfc_scan_finished()
3313 vhost->scan_timeout = init_timeout; in ibmvfc_scan_finished()
3316 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_scan_finished()
3321 * ibmvfc_slave_alloc - Setup the device's task set value
3328 * 0 on success / -ENXIO if device does not exist
3332 struct Scsi_Host *shost = sdev->host; in ibmvfc_slave_alloc()
3338 return -ENXIO; in ibmvfc_slave_alloc()
3340 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_slave_alloc()
3341 sdev->hostdata = (void *)(unsigned long)vhost->task_set++; in ibmvfc_slave_alloc()
3342 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_slave_alloc()
3347 * ibmvfc_target_alloc - Setup the target's task set value
3354 * 0 on success / -ENXIO if device does not exist
3358 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); in ibmvfc_target_alloc()
3362 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_target_alloc()
3363 starget->hostdata = (void *)(unsigned long)vhost->task_set++; in ibmvfc_target_alloc()
3364 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_target_alloc()
3369 * ibmvfc_slave_configure - Configure the device
3380 struct Scsi_Host *shost = sdev->host; in ibmvfc_slave_configure()
3383 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_slave_configure()
3384 if (sdev->type == TYPE_DISK) { in ibmvfc_slave_configure()
3385 sdev->allow_restart = 1; in ibmvfc_slave_configure()
3386 blk_queue_rq_timeout(sdev->request_queue, 120 * HZ); in ibmvfc_slave_configure()
3388 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_slave_configure()
3393 * ibmvfc_change_queue_depth - Change the device's queue depth
3415 vhost->login_buf->resp.partition_name); in ibmvfc_show_host_partition_name()
3425 vhost->login_buf->resp.device_name); in ibmvfc_show_host_device_name()
3435 vhost->login_buf->resp.port_loc_code); in ibmvfc_show_host_loc_code()
3445 vhost->login_buf->resp.drc_name); in ibmvfc_show_host_drc_name()
3453 return snprintf(buf, PAGE_SIZE, "%d\n", be32_to_cpu(vhost->login_buf->resp.version)); in ibmvfc_show_host_npiv_version()
3461 return snprintf(buf, PAGE_SIZE, "%llx\n", be64_to_cpu(vhost->login_buf->resp.capabilities)); in ibmvfc_show_host_capabilities()
3465 * ibmvfc_show_log_level - Show the adapter's error logging level
3481 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_show_log_level()
3482 len = snprintf(buf, PAGE_SIZE, "%d\n", vhost->log_level); in ibmvfc_show_log_level()
3483 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_show_log_level()
3488 * ibmvfc_store_log_level - Change the adapter's error logging level
3505 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_store_log_level()
3506 vhost->log_level = simple_strtoul(buf, NULL, 10); in ibmvfc_store_log_level()
3507 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_store_log_level()
3519 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_show_scsi_channels()
3520 len = snprintf(buf, PAGE_SIZE, "%d\n", vhost->client_scsi_channels); in ibmvfc_show_scsi_channels()
3521 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_show_scsi_channels()
3534 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_store_scsi_channels()
3536 vhost->client_scsi_channels = min(channels, nr_scsi_hw_queues); in ibmvfc_store_scsi_channels()
3538 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_store_scsi_channels()
3555 * ibmvfc_read_trace - Dump the adapter trace
3575 char *src = (char *)vhost->trace; in ibmvfc_read_trace()
3580 size -= off; in ibmvfc_read_trace()
3584 spin_lock_irqsave(shost->host_lock, flags); in ibmvfc_read_trace()
3586 spin_unlock_irqrestore(shost->host_lock, flags); in ibmvfc_read_trace()
3631 .this_id = -1,
3640 * ibmvfc_next_async_crq - Returns the next entry in async queue
3648 struct ibmvfc_queue *async_crq = &vhost->async_crq; in ibmvfc_next_async_crq()
3651 crq = &async_crq->msgs.async[async_crq->cur]; in ibmvfc_next_async_crq()
3652 if (crq->valid & 0x80) { in ibmvfc_next_async_crq()
3653 if (++async_crq->cur == async_crq->size) in ibmvfc_next_async_crq()
3654 async_crq->cur = 0; in ibmvfc_next_async_crq()
3663 * ibmvfc_next_crq - Returns the next entry in message queue
3671 struct ibmvfc_queue *queue = &vhost->crq; in ibmvfc_next_crq()
3674 crq = &queue->msgs.crq[queue->cur]; in ibmvfc_next_crq()
3675 if (crq->valid & 0x80) { in ibmvfc_next_crq()
3676 if (++queue->cur == queue->size) in ibmvfc_next_crq()
3677 queue->cur = 0; in ibmvfc_next_crq()
3686 * ibmvfc_interrupt - Interrupt handler
3698 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_interrupt()
3699 vio_disable_interrupts(to_vio_dev(vhost->dev)); in ibmvfc_interrupt()
3700 tasklet_schedule(&vhost->tasklet); in ibmvfc_interrupt()
3701 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_interrupt()
3706 * ibmvfc_tasklet - Interrupt handler tasklet
3715 struct vio_dev *vdev = to_vio_dev(vhost->dev); in ibmvfc_tasklet()
3718 struct ibmvfc_event *evt, *temp; in ibmvfc_tasklet() local
3723 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_tasklet()
3724 spin_lock(vhost->crq.q_lock); in ibmvfc_tasklet()
3729 async->valid = 0; in ibmvfc_tasklet()
3736 crq->valid = 0; in ibmvfc_tasklet()
3744 async->valid = 0; in ibmvfc_tasklet()
3749 crq->valid = 0; in ibmvfc_tasklet()
3755 spin_unlock(vhost->crq.q_lock); in ibmvfc_tasklet()
3756 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_tasklet()
3758 list_for_each_entry_safe(evt, temp, &evt_doneq, queue_list) { in ibmvfc_tasklet()
3759 del_timer(&evt->timer); in ibmvfc_tasklet()
3760 list_del(&evt->queue_list); in ibmvfc_tasklet()
3761 ibmvfc_trc_end(evt); in ibmvfc_tasklet()
3762 evt->done(evt); in ibmvfc_tasklet()
3768 struct device *dev = scrq->vhost->dev; in ibmvfc_toggle_scrq_irq()
3776 rc = plpar_hcall_norets(H_VIOCTL, vdev->unit_address, irq_action, in ibmvfc_toggle_scrq_irq()
3777 scrq->hw_irq, 0, 0); in ibmvfc_toggle_scrq_irq()
3780 dev_err(dev, "Couldn't %s sub-crq[%lu] irq. rc=%ld\n", in ibmvfc_toggle_scrq_irq()
3781 enable ? "enable" : "disable", scrq->hwq_id, rc); in ibmvfc_toggle_scrq_irq()
3789 struct ibmvfc_event *evt = (struct ibmvfc_event *)be64_to_cpu(crq->ioba); in ibmvfc_handle_scrq() local
3791 switch (crq->valid) { in ibmvfc_handle_scrq()
3797 dev_err(vhost->dev, "Got and invalid message type 0x%02x\n", crq->valid); in ibmvfc_handle_scrq()
3805 if (unlikely(!ibmvfc_valid_event(&evt->queue->evt_pool, evt))) { in ibmvfc_handle_scrq()
3806 dev_err(vhost->dev, "Returned correlation_token 0x%08llx is invalid!\n", in ibmvfc_handle_scrq()
3807 crq->ioba); in ibmvfc_handle_scrq()
3811 if (unlikely(atomic_dec_if_positive(&evt->active))) { in ibmvfc_handle_scrq()
3812 dev_err(vhost->dev, "Received duplicate correlation_token 0x%08llx!\n", in ibmvfc_handle_scrq()
3813 crq->ioba); in ibmvfc_handle_scrq()
3817 spin_lock(&evt->queue->l_lock); in ibmvfc_handle_scrq()
3818 list_move_tail(&evt->queue_list, evt_doneq); in ibmvfc_handle_scrq()
3819 spin_unlock(&evt->queue->l_lock); in ibmvfc_handle_scrq()
3826 crq = &scrq->msgs.scrq[scrq->cur].crq; in ibmvfc_next_scrq()
3827 if (crq->valid & 0x80) { in ibmvfc_next_scrq()
3828 if (++scrq->cur == scrq->size) in ibmvfc_next_scrq()
3829 scrq->cur = 0; in ibmvfc_next_scrq()
3840 struct ibmvfc_event *evt, *temp; in ibmvfc_drain_sub_crq() local
3845 spin_lock_irqsave(scrq->q_lock, flags); in ibmvfc_drain_sub_crq()
3848 ibmvfc_handle_scrq(crq, scrq->vhost, &evt_doneq); in ibmvfc_drain_sub_crq()
3849 crq->valid = 0; in ibmvfc_drain_sub_crq()
3856 ibmvfc_handle_scrq(crq, scrq->vhost, &evt_doneq); in ibmvfc_drain_sub_crq()
3857 crq->valid = 0; in ibmvfc_drain_sub_crq()
3862 spin_unlock_irqrestore(scrq->q_lock, flags); in ibmvfc_drain_sub_crq()
3864 list_for_each_entry_safe(evt, temp, &evt_doneq, queue_list) { in ibmvfc_drain_sub_crq()
3865 del_timer(&evt->timer); in ibmvfc_drain_sub_crq()
3866 list_del(&evt->queue_list); in ibmvfc_drain_sub_crq()
3867 ibmvfc_trc_end(evt); in ibmvfc_drain_sub_crq()
3868 evt->done(evt); in ibmvfc_drain_sub_crq()
3883 * ibmvfc_init_tgt - Set the next init job step for the target
3892 tgt->job_step = job_step; in ibmvfc_init_tgt()
3893 wake_up(&tgt->vhost->work_wait_q); in ibmvfc_init_tgt()
3897 * ibmvfc_retry_tgt_init - Attempt to retry a step in target initialization
3907 if (++tgt->init_retries > IBMVFC_MAX_TGT_INIT_RETRIES) { in ibmvfc_retry_tgt_init()
3909 wake_up(&tgt->vhost->work_wait_q); in ibmvfc_retry_tgt_init()
3916 /* Defined in FC-LS */
3934 * ibmvfc_get_prli_rsp - Find PRLI response index
3951 * ibmvfc_tgt_prli_done - Completion handler for Process Login
3952 * @evt: ibmvfc event struct
3955 static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) in ibmvfc_tgt_prli_done() argument
3957 struct ibmvfc_target *tgt = evt->tgt; in ibmvfc_tgt_prli_done()
3958 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_tgt_prli_done()
3959 struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli; in ibmvfc_tgt_prli_done()
3960 struct ibmvfc_prli_svc_parms *parms = &rsp->parms; in ibmvfc_tgt_prli_done()
3961 u32 status = be16_to_cpu(rsp->common.status); in ibmvfc_tgt_prli_done()
3964 vhost->discovery_threads--; in ibmvfc_tgt_prli_done()
3969 parms->type, parms->flags, parms->service_parms); in ibmvfc_tgt_prli_done()
3971 if (parms->type == IBMVFC_SCSI_FCP_TYPE) { in ibmvfc_tgt_prli_done()
3972 index = ibmvfc_get_prli_rsp(be16_to_cpu(parms->flags)); in ibmvfc_tgt_prli_done()
3974 if (be16_to_cpu(parms->flags) & IBMVFC_PRLI_EST_IMG_PAIR) { in ibmvfc_tgt_prli_done()
3975 tgt->need_login = 0; in ibmvfc_tgt_prli_done()
3976 tgt->ids.roles = 0; in ibmvfc_tgt_prli_done()
3977 if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_TARGET_FUNC) in ibmvfc_tgt_prli_done()
3978 tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET; in ibmvfc_tgt_prli_done()
3979 if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_INITIATOR_FUNC) in ibmvfc_tgt_prli_done()
3980 tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; in ibmvfc_tgt_prli_done()
3981 tgt->add_rport = 1; in ibmvfc_tgt_prli_done()
3998 if ((be16_to_cpu(rsp->status) & IBMVFC_VIOS_FAILURE) && in ibmvfc_tgt_prli_done()
3999 be16_to_cpu(rsp->error) == IBMVFC_PLOGI_REQUIRED) in ibmvfc_tgt_prli_done()
4001 else if (tgt->logo_rcvd) in ibmvfc_tgt_prli_done()
4003 else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) in ibmvfc_tgt_prli_done()
4009 ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), in ibmvfc_tgt_prli_done()
4010 be16_to_cpu(rsp->status), be16_to_cpu(rsp->error), status); in ibmvfc_tgt_prli_done()
4014 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_prli_done()
4015 ibmvfc_free_event(evt); in ibmvfc_tgt_prli_done()
4016 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_prli_done()
4020 * ibmvfc_tgt_send_prli - Send a process login
4027 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_tgt_send_prli()
4028 struct ibmvfc_event *evt; in ibmvfc_tgt_send_prli() local
4030 if (vhost->discovery_threads >= disc_threads) in ibmvfc_tgt_send_prli()
4033 kref_get(&tgt->kref); in ibmvfc_tgt_send_prli()
4034 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_tgt_send_prli()
4035 vhost->discovery_threads++; in ibmvfc_tgt_send_prli()
4036 ibmvfc_init_event(evt, ibmvfc_tgt_prli_done, IBMVFC_MAD_FORMAT); in ibmvfc_tgt_send_prli()
4037 evt->tgt = tgt; in ibmvfc_tgt_send_prli()
4038 prli = &evt->iu.prli; in ibmvfc_tgt_send_prli()
4041 prli->common.version = cpu_to_be32(2); in ibmvfc_tgt_send_prli()
4042 prli->target_wwpn = cpu_to_be64(tgt->wwpn); in ibmvfc_tgt_send_prli()
4044 prli->common.version = cpu_to_be32(1); in ibmvfc_tgt_send_prli()
4046 prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN); in ibmvfc_tgt_send_prli()
4047 prli->common.length = cpu_to_be16(sizeof(*prli)); in ibmvfc_tgt_send_prli()
4048 prli->scsi_id = cpu_to_be64(tgt->scsi_id); in ibmvfc_tgt_send_prli()
4050 prli->parms.type = IBMVFC_SCSI_FCP_TYPE; in ibmvfc_tgt_send_prli()
4051 prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR); in ibmvfc_tgt_send_prli()
4052 prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC); in ibmvfc_tgt_send_prli()
4053 prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED); in ibmvfc_tgt_send_prli()
4056 prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_RETRY); in ibmvfc_tgt_send_prli()
4059 if (ibmvfc_send_event(evt, vhost, default_timeout)) { in ibmvfc_tgt_send_prli()
4060 vhost->discovery_threads--; in ibmvfc_tgt_send_prli()
4062 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_send_prli()
4068 * ibmvfc_tgt_plogi_done - Completion handler for Port Login
4069 * @evt: ibmvfc event struct
4072 static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) in ibmvfc_tgt_plogi_done() argument
4074 struct ibmvfc_target *tgt = evt->tgt; in ibmvfc_tgt_plogi_done()
4075 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_tgt_plogi_done()
4076 struct ibmvfc_port_login *rsp = &evt->xfer_iu->plogi; in ibmvfc_tgt_plogi_done()
4077 u32 status = be16_to_cpu(rsp->common.status); in ibmvfc_tgt_plogi_done()
4080 vhost->discovery_threads--; in ibmvfc_tgt_plogi_done()
4085 if (tgt->ids.port_name && in ibmvfc_tgt_plogi_done()
4086 tgt->ids.port_name != wwn_to_u64(rsp->service_parms.port_name)) { in ibmvfc_tgt_plogi_done()
4087 vhost->reinit = 1; in ibmvfc_tgt_plogi_done()
4088 tgt_dbg(tgt, "Port re-init required\n"); in ibmvfc_tgt_plogi_done()
4091 tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name); in ibmvfc_tgt_plogi_done()
4092 tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name); in ibmvfc_tgt_plogi_done()
4093 tgt->ids.port_id = tgt->scsi_id; in ibmvfc_tgt_plogi_done()
4094 memcpy(&tgt->service_parms, &rsp->service_parms, in ibmvfc_tgt_plogi_done()
4095 sizeof(tgt->service_parms)); in ibmvfc_tgt_plogi_done()
4096 memcpy(&tgt->service_parms_change, &rsp->service_parms_change, in ibmvfc_tgt_plogi_done()
4097 sizeof(tgt->service_parms_change)); in ibmvfc_tgt_plogi_done()
4107 if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) in ibmvfc_tgt_plogi_done()
4113 ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), in ibmvfc_tgt_plogi_done()
4114 be16_to_cpu(rsp->status), be16_to_cpu(rsp->error), in ibmvfc_tgt_plogi_done()
4115 ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), be16_to_cpu(rsp->fc_type), in ibmvfc_tgt_plogi_done()
4116 ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), be16_to_cpu(rsp->fc_explain), status); in ibmvfc_tgt_plogi_done()
4120 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_plogi_done()
4121 ibmvfc_free_event(evt); in ibmvfc_tgt_plogi_done()
4122 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_plogi_done()
4126 * ibmvfc_tgt_send_plogi - Send PLOGI to the specified target
4133 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_tgt_send_plogi()
4134 struct ibmvfc_event *evt; in ibmvfc_tgt_send_plogi() local
4136 if (vhost->discovery_threads >= disc_threads) in ibmvfc_tgt_send_plogi()
4139 kref_get(&tgt->kref); in ibmvfc_tgt_send_plogi()
4140 tgt->logo_rcvd = 0; in ibmvfc_tgt_send_plogi()
4141 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_tgt_send_plogi()
4142 vhost->discovery_threads++; in ibmvfc_tgt_send_plogi()
4144 ibmvfc_init_event(evt, ibmvfc_tgt_plogi_done, IBMVFC_MAD_FORMAT); in ibmvfc_tgt_send_plogi()
4145 evt->tgt = tgt; in ibmvfc_tgt_send_plogi()
4146 plogi = &evt->iu.plogi; in ibmvfc_tgt_send_plogi()
4149 plogi->common.version = cpu_to_be32(2); in ibmvfc_tgt_send_plogi()
4150 plogi->target_wwpn = cpu_to_be64(tgt->wwpn); in ibmvfc_tgt_send_plogi()
4152 plogi->common.version = cpu_to_be32(1); in ibmvfc_tgt_send_plogi()
4154 plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN); in ibmvfc_tgt_send_plogi()
4155 plogi->common.length = cpu_to_be16(sizeof(*plogi)); in ibmvfc_tgt_send_plogi()
4156 plogi->scsi_id = cpu_to_be64(tgt->scsi_id); in ibmvfc_tgt_send_plogi()
4158 if (ibmvfc_send_event(evt, vhost, default_timeout)) { in ibmvfc_tgt_send_plogi()
4159 vhost->discovery_threads--; in ibmvfc_tgt_send_plogi()
4161 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_send_plogi()
4167 * ibmvfc_tgt_implicit_logout_done - Completion handler for Implicit Logout MAD
4168 * @evt: ibmvfc event struct
4171 static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt) in ibmvfc_tgt_implicit_logout_done() argument
4173 struct ibmvfc_target *tgt = evt->tgt; in ibmvfc_tgt_implicit_logout_done()
4174 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_tgt_implicit_logout_done()
4175 struct ibmvfc_implicit_logout *rsp = &evt->xfer_iu->implicit_logout; in ibmvfc_tgt_implicit_logout_done()
4176 u32 status = be16_to_cpu(rsp->common.status); in ibmvfc_tgt_implicit_logout_done()
4178 vhost->discovery_threads--; in ibmvfc_tgt_implicit_logout_done()
4179 ibmvfc_free_event(evt); in ibmvfc_tgt_implicit_logout_done()
4187 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_implicit_logout_done()
4188 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_implicit_logout_done()
4197 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_implicit_logout_done()
4198 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_implicit_logout_done()
4202 * __ibmvfc_tgt_get_implicit_logout_evt - Allocate and init an event for implicit logout
4213 struct ibmvfc_host *vhost = tgt->vhost; in __ibmvfc_tgt_get_implicit_logout_evt()
4214 struct ibmvfc_event *evt; in __ibmvfc_tgt_get_implicit_logout_evt() local
4216 kref_get(&tgt->kref); in __ibmvfc_tgt_get_implicit_logout_evt()
4217 evt = ibmvfc_get_event(&vhost->crq); in __ibmvfc_tgt_get_implicit_logout_evt()
4218 ibmvfc_init_event(evt, done, IBMVFC_MAD_FORMAT); in __ibmvfc_tgt_get_implicit_logout_evt()
4219 evt->tgt = tgt; in __ibmvfc_tgt_get_implicit_logout_evt()
4220 mad = &evt->iu.implicit_logout; in __ibmvfc_tgt_get_implicit_logout_evt()
4222 mad->common.version = cpu_to_be32(1); in __ibmvfc_tgt_get_implicit_logout_evt()
4223 mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT); in __ibmvfc_tgt_get_implicit_logout_evt()
4224 mad->common.length = cpu_to_be16(sizeof(*mad)); in __ibmvfc_tgt_get_implicit_logout_evt()
4225 mad->old_scsi_id = cpu_to_be64(tgt->scsi_id); in __ibmvfc_tgt_get_implicit_logout_evt()
4226 return evt; in __ibmvfc_tgt_get_implicit_logout_evt()
4230 * ibmvfc_tgt_implicit_logout - Initiate an Implicit Logout for specified target
4236 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_tgt_implicit_logout()
4237 struct ibmvfc_event *evt; in ibmvfc_tgt_implicit_logout() local
4239 if (vhost->discovery_threads >= disc_threads) in ibmvfc_tgt_implicit_logout()
4242 vhost->discovery_threads++; in ibmvfc_tgt_implicit_logout()
4243 evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, in ibmvfc_tgt_implicit_logout()
4247 if (ibmvfc_send_event(evt, vhost, default_timeout)) { in ibmvfc_tgt_implicit_logout()
4248 vhost->discovery_threads--; in ibmvfc_tgt_implicit_logout()
4250 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_implicit_logout()
4256 * ibmvfc_tgt_implicit_logout_and_del_done - Completion handler for Implicit Logout MAD
4257 * @evt: ibmvfc event struct
4260 static void ibmvfc_tgt_implicit_logout_and_del_done(struct ibmvfc_event *evt) in ibmvfc_tgt_implicit_logout_and_del_done() argument
4262 struct ibmvfc_target *tgt = evt->tgt; in ibmvfc_tgt_implicit_logout_and_del_done()
4263 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_tgt_implicit_logout_and_del_done()
4264 struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru; in ibmvfc_tgt_implicit_logout_and_del_done()
4265 u32 status = be16_to_cpu(mad->common.status); in ibmvfc_tgt_implicit_logout_and_del_done()
4267 vhost->discovery_threads--; in ibmvfc_tgt_implicit_logout_and_del_done()
4268 ibmvfc_free_event(evt); in ibmvfc_tgt_implicit_logout_and_del_done()
4277 if (status == IBMVFC_MAD_SUCCESS || vhost->state == IBMVFC_HOST_OFFLINE) in ibmvfc_tgt_implicit_logout_and_del_done()
4283 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_implicit_logout_and_del_done()
4284 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_implicit_logout_and_del_done()
4288 * ibmvfc_tgt_implicit_logout_and_del - Initiate an Implicit Logout for specified target
4294 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_tgt_implicit_logout_and_del()
4295 struct ibmvfc_event *evt; in ibmvfc_tgt_implicit_logout_and_del() local
4297 if (!vhost->logged_in) { in ibmvfc_tgt_implicit_logout_and_del()
4302 if (vhost->discovery_threads >= disc_threads) in ibmvfc_tgt_implicit_logout_and_del()
4305 vhost->discovery_threads++; in ibmvfc_tgt_implicit_logout_and_del()
4306 evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt, in ibmvfc_tgt_implicit_logout_and_del()
4310 if (ibmvfc_send_event(evt, vhost, default_timeout)) { in ibmvfc_tgt_implicit_logout_and_del()
4311 vhost->discovery_threads--; in ibmvfc_tgt_implicit_logout_and_del()
4313 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_implicit_logout_and_del()
4319 * ibmvfc_tgt_move_login_done - Completion handler for Move Login
4320 * @evt: ibmvfc event struct
4323 static void ibmvfc_tgt_move_login_done(struct ibmvfc_event *evt) in ibmvfc_tgt_move_login_done() argument
4325 struct ibmvfc_target *tgt = evt->tgt; in ibmvfc_tgt_move_login_done()
4326 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_tgt_move_login_done()
4327 struct ibmvfc_move_login *rsp = &evt->xfer_iu->move_login; in ibmvfc_tgt_move_login_done()
4328 u32 status = be16_to_cpu(rsp->common.status); in ibmvfc_tgt_move_login_done()
4331 vhost->discovery_threads--; in ibmvfc_tgt_move_login_done()
4335 tgt_dbg(tgt, "Move Login succeeded for new scsi_id: %llX\n", tgt->new_scsi_id); in ibmvfc_tgt_move_login_done()
4336 tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name); in ibmvfc_tgt_move_login_done()
4337 tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name); in ibmvfc_tgt_move_login_done()
4338 tgt->scsi_id = tgt->new_scsi_id; in ibmvfc_tgt_move_login_done()
4339 tgt->ids.port_id = tgt->scsi_id; in ibmvfc_tgt_move_login_done()
4340 memcpy(&tgt->service_parms, &rsp->service_parms, in ibmvfc_tgt_move_login_done()
4341 sizeof(tgt->service_parms)); in ibmvfc_tgt_move_login_done()
4342 memcpy(&tgt->service_parms_change, &rsp->service_parms_change, in ibmvfc_tgt_move_login_done()
4343 sizeof(tgt->service_parms_change)); in ibmvfc_tgt_move_login_done()
4357 tgt->new_scsi_id, be32_to_cpu(rsp->flags), be16_to_cpu(rsp->vios_flags), in ibmvfc_tgt_move_login_done()
4362 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_move_login_done()
4363 ibmvfc_free_event(evt); in ibmvfc_tgt_move_login_done()
4364 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_move_login_done()
4369 * ibmvfc_tgt_move_login - Initiate a move login for specified target
4375 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_tgt_move_login()
4377 struct ibmvfc_event *evt; in ibmvfc_tgt_move_login() local
4379 if (vhost->discovery_threads >= disc_threads) in ibmvfc_tgt_move_login()
4382 kref_get(&tgt->kref); in ibmvfc_tgt_move_login()
4383 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_tgt_move_login()
4384 vhost->discovery_threads++; in ibmvfc_tgt_move_login()
4386 ibmvfc_init_event(evt, ibmvfc_tgt_move_login_done, IBMVFC_MAD_FORMAT); in ibmvfc_tgt_move_login()
4387 evt->tgt = tgt; in ibmvfc_tgt_move_login()
4388 move = &evt->iu.move_login; in ibmvfc_tgt_move_login()
4390 move->common.version = cpu_to_be32(1); in ibmvfc_tgt_move_login()
4391 move->common.opcode = cpu_to_be32(IBMVFC_MOVE_LOGIN); in ibmvfc_tgt_move_login()
4392 move->common.length = cpu_to_be16(sizeof(*move)); in ibmvfc_tgt_move_login()
4394 move->old_scsi_id = cpu_to_be64(tgt->scsi_id); in ibmvfc_tgt_move_login()
4395 move->new_scsi_id = cpu_to_be64(tgt->new_scsi_id); in ibmvfc_tgt_move_login()
4396 move->wwpn = cpu_to_be64(tgt->wwpn); in ibmvfc_tgt_move_login()
4397 move->node_name = cpu_to_be64(tgt->ids.node_name); in ibmvfc_tgt_move_login()
4399 if (ibmvfc_send_event(evt, vhost, default_timeout)) { in ibmvfc_tgt_move_login()
4400 vhost->discovery_threads--; in ibmvfc_tgt_move_login()
4402 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_move_login()
4404 tgt_dbg(tgt, "Sent Move Login for new scsi_id: %llX\n", tgt->new_scsi_id); in ibmvfc_tgt_move_login()
4408 * ibmvfc_adisc_needs_plogi - Does device need PLOGI?
4418 if (wwn_to_u64((u8 *)&mad->fc_iu.response[2]) != tgt->ids.port_name) in ibmvfc_adisc_needs_plogi()
4420 if (wwn_to_u64((u8 *)&mad->fc_iu.response[4]) != tgt->ids.node_name) in ibmvfc_adisc_needs_plogi()
4422 if (be32_to_cpu(mad->fc_iu.response[6]) != tgt->scsi_id) in ibmvfc_adisc_needs_plogi()
4428 * ibmvfc_tgt_adisc_done - Completion handler for ADISC
4429 * @evt: ibmvfc event struct
4432 static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) in ibmvfc_tgt_adisc_done() argument
4434 struct ibmvfc_target *tgt = evt->tgt; in ibmvfc_tgt_adisc_done()
4435 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_tgt_adisc_done()
4436 struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru; in ibmvfc_tgt_adisc_done()
4437 u32 status = be16_to_cpu(mad->common.status); in ibmvfc_tgt_adisc_done()
4440 vhost->discovery_threads--; in ibmvfc_tgt_adisc_done()
4442 del_timer(&tgt->timer); in ibmvfc_tgt_adisc_done()
4455 fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16; in ibmvfc_tgt_adisc_done()
4456 fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8; in ibmvfc_tgt_adisc_done()
4458 ibmvfc_get_cmd_error(be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error)), in ibmvfc_tgt_adisc_done()
4459 be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error), in ibmvfc_tgt_adisc_done()
4465 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_adisc_done()
4466 ibmvfc_free_event(evt); in ibmvfc_tgt_adisc_done()
4467 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_adisc_done()
4471 * ibmvfc_init_passthru - Initialize an event struct for FC passthru
4472 * @evt: ibmvfc event struct
4475 static void ibmvfc_init_passthru(struct ibmvfc_event *evt) in ibmvfc_init_passthru() argument
4477 struct ibmvfc_passthru_mad *mad = &evt->iu.passthru; in ibmvfc_init_passthru()
4480 mad->common.version = cpu_to_be32(1); in ibmvfc_init_passthru()
4481 mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU); in ibmvfc_init_passthru()
4482 mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu)); in ibmvfc_init_passthru()
4483 mad->cmd_ioba.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + in ibmvfc_init_passthru()
4485 mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu)); in ibmvfc_init_passthru()
4486 mad->iu.cmd_len = cpu_to_be32(sizeof(mad->fc_iu.payload)); in ibmvfc_init_passthru()
4487 mad->iu.rsp_len = cpu_to_be32(sizeof(mad->fc_iu.response)); in ibmvfc_init_passthru()
4488 mad->iu.cmd.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + in ibmvfc_init_passthru()
4491 mad->iu.cmd.len = cpu_to_be32(sizeof(mad->fc_iu.payload)); in ibmvfc_init_passthru()
4492 mad->iu.rsp.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + in ibmvfc_init_passthru()
4495 mad->iu.rsp.len = cpu_to_be32(sizeof(mad->fc_iu.response)); in ibmvfc_init_passthru()
4499 * ibmvfc_tgt_adisc_cancel_done - Completion handler when cancelling an ADISC
4500 * @evt: ibmvfc event struct
4508 static void ibmvfc_tgt_adisc_cancel_done(struct ibmvfc_event *evt) in ibmvfc_tgt_adisc_cancel_done() argument
4510 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_tgt_adisc_cancel_done()
4511 struct ibmvfc_target *tgt = evt->tgt; in ibmvfc_tgt_adisc_cancel_done()
4514 vhost->abort_threads--; in ibmvfc_tgt_adisc_cancel_done()
4515 ibmvfc_free_event(evt); in ibmvfc_tgt_adisc_cancel_done()
4516 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_adisc_cancel_done()
4517 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_adisc_cancel_done()
4521 * ibmvfc_adisc_timeout - Handle an ADISC timeout
4531 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_adisc_timeout()
4532 struct ibmvfc_event *evt; in ibmvfc_adisc_timeout() local
4538 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_adisc_timeout()
4539 if (vhost->abort_threads >= disc_threads || in ibmvfc_adisc_timeout()
4540 tgt->action != IBMVFC_TGT_ACTION_INIT_WAIT || in ibmvfc_adisc_timeout()
4541 vhost->state != IBMVFC_INITIALIZING || in ibmvfc_adisc_timeout()
4542 vhost->action != IBMVFC_HOST_ACTION_QUERY_TGTS) { in ibmvfc_adisc_timeout()
4543 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_adisc_timeout()
4547 vhost->abort_threads++; in ibmvfc_adisc_timeout()
4548 kref_get(&tgt->kref); in ibmvfc_adisc_timeout()
4549 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_adisc_timeout()
4550 ibmvfc_init_event(evt, ibmvfc_tgt_adisc_cancel_done, IBMVFC_MAD_FORMAT); in ibmvfc_adisc_timeout()
4552 evt->tgt = tgt; in ibmvfc_adisc_timeout()
4553 tmf = &evt->iu.tmf; in ibmvfc_adisc_timeout()
4556 tmf->common.version = cpu_to_be32(2); in ibmvfc_adisc_timeout()
4557 tmf->target_wwpn = cpu_to_be64(tgt->wwpn); in ibmvfc_adisc_timeout()
4559 tmf->common.version = cpu_to_be32(1); in ibmvfc_adisc_timeout()
4561 tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); in ibmvfc_adisc_timeout()
4562 tmf->common.length = cpu_to_be16(sizeof(*tmf)); in ibmvfc_adisc_timeout()
4563 tmf->scsi_id = cpu_to_be64(tgt->scsi_id); in ibmvfc_adisc_timeout()
4564 tmf->cancel_key = cpu_to_be32(tgt->cancel_key); in ibmvfc_adisc_timeout()
4566 rc = ibmvfc_send_event(evt, vhost, default_timeout); in ibmvfc_adisc_timeout()
4570 vhost->abort_threads--; in ibmvfc_adisc_timeout()
4571 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_adisc_timeout()
4575 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_adisc_timeout()
4579 * ibmvfc_tgt_adisc - Initiate an ADISC for specified target
4592 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_tgt_adisc()
4593 struct ibmvfc_event *evt; in ibmvfc_tgt_adisc() local
4595 if (vhost->discovery_threads >= disc_threads) in ibmvfc_tgt_adisc()
4598 kref_get(&tgt->kref); in ibmvfc_tgt_adisc()
4599 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_tgt_adisc()
4600 vhost->discovery_threads++; in ibmvfc_tgt_adisc()
4601 ibmvfc_init_event(evt, ibmvfc_tgt_adisc_done, IBMVFC_MAD_FORMAT); in ibmvfc_tgt_adisc()
4602 evt->tgt = tgt; in ibmvfc_tgt_adisc()
4604 ibmvfc_init_passthru(evt); in ibmvfc_tgt_adisc()
4605 mad = &evt->iu.passthru; in ibmvfc_tgt_adisc()
4606 mad->iu.flags = cpu_to_be32(IBMVFC_FC_ELS); in ibmvfc_tgt_adisc()
4607 mad->iu.scsi_id = cpu_to_be64(tgt->scsi_id); in ibmvfc_tgt_adisc()
4608 mad->iu.cancel_key = cpu_to_be32(tgt->cancel_key); in ibmvfc_tgt_adisc()
4610 mad->fc_iu.payload[0] = cpu_to_be32(IBMVFC_ADISC); in ibmvfc_tgt_adisc()
4611 memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name, in ibmvfc_tgt_adisc()
4612 sizeof(vhost->login_buf->resp.port_name)); in ibmvfc_tgt_adisc()
4613 memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name, in ibmvfc_tgt_adisc()
4614 sizeof(vhost->login_buf->resp.node_name)); in ibmvfc_tgt_adisc()
4615 mad->fc_iu.payload[6] = cpu_to_be32(be64_to_cpu(vhost->login_buf->resp.scsi_id) & 0x00ffffff); in ibmvfc_tgt_adisc()
4617 if (timer_pending(&tgt->timer)) in ibmvfc_tgt_adisc()
4618 mod_timer(&tgt->timer, jiffies + (IBMVFC_ADISC_TIMEOUT * HZ)); in ibmvfc_tgt_adisc()
4620 tgt->timer.expires = jiffies + (IBMVFC_ADISC_TIMEOUT * HZ); in ibmvfc_tgt_adisc()
4621 add_timer(&tgt->timer); in ibmvfc_tgt_adisc()
4625 if (ibmvfc_send_event(evt, vhost, IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT)) { in ibmvfc_tgt_adisc()
4626 vhost->discovery_threads--; in ibmvfc_tgt_adisc()
4627 del_timer(&tgt->timer); in ibmvfc_tgt_adisc()
4629 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_adisc()
4635 * ibmvfc_tgt_query_target_done - Completion handler for Query Target MAD
4636 * @evt: ibmvfc event struct
4639 static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) in ibmvfc_tgt_query_target_done() argument
4641 struct ibmvfc_target *tgt = evt->tgt; in ibmvfc_tgt_query_target_done()
4642 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_tgt_query_target_done()
4643 struct ibmvfc_query_tgt *rsp = &evt->xfer_iu->query_tgt; in ibmvfc_tgt_query_target_done()
4644 u32 status = be16_to_cpu(rsp->common.status); in ibmvfc_tgt_query_target_done()
4647 vhost->discovery_threads--; in ibmvfc_tgt_query_target_done()
4652 if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id) in ibmvfc_tgt_query_target_done()
4664 if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED && in ibmvfc_tgt_query_target_done()
4665 be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ && in ibmvfc_tgt_query_target_done()
4666 be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG) in ibmvfc_tgt_query_target_done()
4668 else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) in ibmvfc_tgt_query_target_done()
4674 ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), in ibmvfc_tgt_query_target_done()
4675 be16_to_cpu(rsp->status), be16_to_cpu(rsp->error), in ibmvfc_tgt_query_target_done()
4676 ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), be16_to_cpu(rsp->fc_type), in ibmvfc_tgt_query_target_done()
4677 ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)), be16_to_cpu(rsp->fc_explain), in ibmvfc_tgt_query_target_done()
4682 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_query_target_done()
4683 ibmvfc_free_event(evt); in ibmvfc_tgt_query_target_done()
4684 wake_up(&vhost->work_wait_q); in ibmvfc_tgt_query_target_done()
4688 * ibmvfc_tgt_query_target - Initiate a Query Target for specified target
4695 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_tgt_query_target()
4696 struct ibmvfc_event *evt; in ibmvfc_tgt_query_target() local
4698 if (vhost->discovery_threads >= disc_threads) in ibmvfc_tgt_query_target()
4701 kref_get(&tgt->kref); in ibmvfc_tgt_query_target()
4702 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_tgt_query_target()
4703 vhost->discovery_threads++; in ibmvfc_tgt_query_target()
4704 evt->tgt = tgt; in ibmvfc_tgt_query_target()
4705 ibmvfc_init_event(evt, ibmvfc_tgt_query_target_done, IBMVFC_MAD_FORMAT); in ibmvfc_tgt_query_target()
4706 query_tgt = &evt->iu.query_tgt; in ibmvfc_tgt_query_target()
4708 query_tgt->common.version = cpu_to_be32(1); in ibmvfc_tgt_query_target()
4709 query_tgt->common.opcode = cpu_to_be32(IBMVFC_QUERY_TARGET); in ibmvfc_tgt_query_target()
4710 query_tgt->common.length = cpu_to_be16(sizeof(*query_tgt)); in ibmvfc_tgt_query_target()
4711 query_tgt->wwpn = cpu_to_be64(tgt->ids.port_name); in ibmvfc_tgt_query_target()
4714 if (ibmvfc_send_event(evt, vhost, default_timeout)) { in ibmvfc_tgt_query_target()
4715 vhost->discovery_threads--; in ibmvfc_tgt_query_target()
4717 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_query_target()
4723 * ibmvfc_alloc_target - Allocate and initialize an ibmvfc target
4737 u64 scsi_id = be32_to_cpu(target->scsi_id) & IBMVFC_DISC_TGT_SCSI_ID_MASK; in ibmvfc_alloc_target()
4738 u64 wwpn = be64_to_cpu(target->wwpn); in ibmvfc_alloc_target()
4741 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_alloc_target()
4742 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_alloc_target()
4743 if (tgt->wwpn == wwpn) { in ibmvfc_alloc_target()
4749 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_alloc_target()
4750 if (tgt->scsi_id == scsi_id) { in ibmvfc_alloc_target()
4770 if (wtgt->action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) { in ibmvfc_alloc_target()
4771 if (wtgt->move_login) { in ibmvfc_alloc_target()
4778 wtgt->new_scsi_id = scsi_id; in ibmvfc_alloc_target()
4779 wtgt->action = IBMVFC_TGT_ACTION_INIT; in ibmvfc_alloc_target()
4780 wtgt->init_retries = 0; in ibmvfc_alloc_target()
4786 wtgt->action, wtgt->rport); in ibmvfc_alloc_target()
4789 if (tgt->need_login) in ibmvfc_alloc_target()
4793 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_alloc_target()
4795 tgt = mempool_alloc(vhost->tgt_pool, GFP_NOIO); in ibmvfc_alloc_target()
4797 tgt->scsi_id = scsi_id; in ibmvfc_alloc_target()
4798 tgt->wwpn = wwpn; in ibmvfc_alloc_target()
4799 tgt->vhost = vhost; in ibmvfc_alloc_target()
4800 tgt->need_login = 1; in ibmvfc_alloc_target()
4801 timer_setup(&tgt->timer, ibmvfc_adisc_timeout, 0); in ibmvfc_alloc_target()
4802 kref_init(&tgt->kref); in ibmvfc_alloc_target()
4804 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_alloc_target()
4805 tgt->cancel_key = vhost->task_set++; in ibmvfc_alloc_target()
4806 list_add_tail(&tgt->queue, &vhost->targets); in ibmvfc_alloc_target()
4809 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_alloc_target()
4814 * ibmvfc_alloc_targets - Allocate and initialize ibmvfc targets
4824 for (i = 0, rc = 0; !rc && i < vhost->num_targets; i++) in ibmvfc_alloc_targets()
4825 rc = ibmvfc_alloc_target(vhost, &vhost->disc_buf[i]); in ibmvfc_alloc_targets()
4831 * ibmvfc_discover_targets_done - Completion handler for discover targets MAD
4832 * @evt: ibmvfc event struct
4835 static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt) in ibmvfc_discover_targets_done() argument
4837 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_discover_targets_done()
4838 struct ibmvfc_discover_targets *rsp = &evt->xfer_iu->discover_targets; in ibmvfc_discover_targets_done()
4839 u32 mad_status = be16_to_cpu(rsp->common.status); in ibmvfc_discover_targets_done()
4845 vhost->num_targets = be32_to_cpu(rsp->num_written); in ibmvfc_discover_targets_done()
4851 ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), in ibmvfc_discover_targets_done()
4852 be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)); in ibmvfc_discover_targets_done()
4857 dev_err(vhost->dev, "Invalid Discover Targets response: 0x%x\n", mad_status); in ibmvfc_discover_targets_done()
4862 ibmvfc_free_event(evt); in ibmvfc_discover_targets_done()
4863 wake_up(&vhost->work_wait_q); in ibmvfc_discover_targets_done()
4867 * ibmvfc_discover_targets - Send Discover Targets MAD
4874 struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_discover_targets() local
4876 ibmvfc_init_event(evt, ibmvfc_discover_targets_done, IBMVFC_MAD_FORMAT); in ibmvfc_discover_targets()
4877 mad = &evt->iu.discover_targets; in ibmvfc_discover_targets()
4879 mad->common.version = cpu_to_be32(1); in ibmvfc_discover_targets()
4880 mad->common.opcode = cpu_to_be32(IBMVFC_DISC_TARGETS); in ibmvfc_discover_targets()
4881 mad->common.length = cpu_to_be16(sizeof(*mad)); in ibmvfc_discover_targets()
4882 mad->bufflen = cpu_to_be32(vhost->disc_buf_sz); in ibmvfc_discover_targets()
4883 mad->buffer.va = cpu_to_be64(vhost->disc_buf_dma); in ibmvfc_discover_targets()
4884 mad->buffer.len = cpu_to_be32(vhost->disc_buf_sz); in ibmvfc_discover_targets()
4885 mad->flags = cpu_to_be32(IBMVFC_DISC_TGT_PORT_ID_WWPN_LIST); in ibmvfc_discover_targets()
4888 if (!ibmvfc_send_event(evt, vhost, default_timeout)) in ibmvfc_discover_targets()
4894 static void ibmvfc_channel_setup_done(struct ibmvfc_event *evt) in ibmvfc_channel_setup_done() argument
4896 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_channel_setup_done()
4897 struct ibmvfc_channel_setup *setup = vhost->channel_setup_buf; in ibmvfc_channel_setup_done()
4898 struct ibmvfc_scsi_channels *scrqs = &vhost->scsi_scrqs; in ibmvfc_channel_setup_done()
4899 u32 mad_status = be16_to_cpu(evt->xfer_iu->channel_setup.common.status); in ibmvfc_channel_setup_done()
4903 ibmvfc_free_event(evt); in ibmvfc_channel_setup_done()
4908 flags = be32_to_cpu(setup->flags); in ibmvfc_channel_setup_done()
4909 vhost->do_enquiry = 0; in ibmvfc_channel_setup_done()
4910 active_queues = be32_to_cpu(setup->num_scsi_subq_channels); in ibmvfc_channel_setup_done()
4911 scrqs->active_queues = active_queues; in ibmvfc_channel_setup_done()
4915 vhost->using_channels = 0; in ibmvfc_channel_setup_done()
4918 vhost->using_channels = 1; in ibmvfc_channel_setup_done()
4920 scrqs->scrqs[i].vios_cookie = in ibmvfc_channel_setup_done()
4921 be64_to_cpu(setup->channel_handles[i]); in ibmvfc_channel_setup_done()
4924 vhost->scsi_scrqs.active_queues); in ibmvfc_channel_setup_done()
4934 dev_err(vhost->dev, "Invalid Channel Setup response: 0x%x\n", in ibmvfc_channel_setup_done()
4941 wake_up(&vhost->work_wait_q); in ibmvfc_channel_setup_done()
4947 struct ibmvfc_channel_setup *setup_buf = vhost->channel_setup_buf; in ibmvfc_channel_setup()
4948 struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_channel_setup() local
4949 struct ibmvfc_scsi_channels *scrqs = &vhost->scsi_scrqs; in ibmvfc_channel_setup()
4951 min(vhost->client_scsi_channels, vhost->max_vios_scsi_channels); in ibmvfc_channel_setup()
4956 setup_buf->flags = cpu_to_be32(IBMVFC_CANCEL_CHANNELS); in ibmvfc_channel_setup()
4958 setup_buf->num_scsi_subq_channels = cpu_to_be32(num_channels); in ibmvfc_channel_setup()
4960 setup_buf->channel_handles[i] = cpu_to_be64(scrqs->scrqs[i].cookie); in ibmvfc_channel_setup()
4963 ibmvfc_init_event(evt, ibmvfc_channel_setup_done, IBMVFC_MAD_FORMAT); in ibmvfc_channel_setup()
4964 mad = &evt->iu.channel_setup; in ibmvfc_channel_setup()
4966 mad->common.version = cpu_to_be32(1); in ibmvfc_channel_setup()
4967 mad->common.opcode = cpu_to_be32(IBMVFC_CHANNEL_SETUP); in ibmvfc_channel_setup()
4968 mad->common.length = cpu_to_be16(sizeof(*mad)); in ibmvfc_channel_setup()
4969 mad->buffer.va = cpu_to_be64(vhost->channel_setup_dma); in ibmvfc_channel_setup()
4970 mad->buffer.len = cpu_to_be32(sizeof(*vhost->channel_setup_buf)); in ibmvfc_channel_setup()
4974 if (!ibmvfc_send_event(evt, vhost, default_timeout)) in ibmvfc_channel_setup()
4980 static void ibmvfc_channel_enquiry_done(struct ibmvfc_event *evt) in ibmvfc_channel_enquiry_done() argument
4982 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_channel_enquiry_done()
4983 struct ibmvfc_channel_enquiry *rsp = &evt->xfer_iu->channel_enquiry; in ibmvfc_channel_enquiry_done()
4984 u32 mad_status = be16_to_cpu(rsp->common.status); in ibmvfc_channel_enquiry_done()
4990 vhost->max_vios_scsi_channels = be32_to_cpu(rsp->num_scsi_subq_channels); in ibmvfc_channel_enquiry_done()
4991 ibmvfc_free_event(evt); in ibmvfc_channel_enquiry_done()
4998 ibmvfc_free_event(evt); in ibmvfc_channel_enquiry_done()
5001 dev_err(vhost->dev, "Invalid Channel Enquiry response: 0x%x\n", in ibmvfc_channel_enquiry_done()
5004 ibmvfc_free_event(evt); in ibmvfc_channel_enquiry_done()
5014 struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_channel_enquiry() local
5016 ibmvfc_init_event(evt, ibmvfc_channel_enquiry_done, IBMVFC_MAD_FORMAT); in ibmvfc_channel_enquiry()
5017 mad = &evt->iu.channel_enquiry; in ibmvfc_channel_enquiry()
5019 mad->common.version = cpu_to_be32(1); in ibmvfc_channel_enquiry()
5020 mad->common.opcode = cpu_to_be32(IBMVFC_CHANNEL_ENQUIRY); in ibmvfc_channel_enquiry()
5021 mad->common.length = cpu_to_be16(sizeof(*mad)); in ibmvfc_channel_enquiry()
5024 mad->flags |= cpu_to_be32(IBMVFC_NO_CHANNELS_TO_CRQ_SUPPORT); in ibmvfc_channel_enquiry()
5026 mad->flags |= cpu_to_be32(IBMVFC_NO_N_TO_M_CHANNELS_SUPPORT); in ibmvfc_channel_enquiry()
5030 if (!ibmvfc_send_event(evt, vhost, default_timeout)) in ibmvfc_channel_enquiry()
5037 * ibmvfc_npiv_login_done - Completion handler for NPIV Login
5038 * @evt: ibmvfc event struct
5041 static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) in ibmvfc_npiv_login_done() argument
5043 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_npiv_login_done()
5044 u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_login.common.status); in ibmvfc_npiv_login_done()
5045 struct ibmvfc_npiv_login_resp *rsp = &vhost->login_buf->resp; in ibmvfc_npiv_login_done()
5051 ibmvfc_free_event(evt); in ibmvfc_npiv_login_done()
5054 if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) in ibmvfc_npiv_login_done()
5059 ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), in ibmvfc_npiv_login_done()
5060 be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)); in ibmvfc_npiv_login_done()
5061 ibmvfc_free_event(evt); in ibmvfc_npiv_login_done()
5067 ibmvfc_free_event(evt); in ibmvfc_npiv_login_done()
5070 dev_err(vhost->dev, "Invalid NPIV Login response: 0x%x\n", mad_status); in ibmvfc_npiv_login_done()
5072 ibmvfc_free_event(evt); in ibmvfc_npiv_login_done()
5076 vhost->client_migrated = 0; in ibmvfc_npiv_login_done()
5078 if (!(be32_to_cpu(rsp->flags) & IBMVFC_NATIVE_FC)) { in ibmvfc_npiv_login_done()
5079 dev_err(vhost->dev, "Virtual adapter does not support FC. %x\n", in ibmvfc_npiv_login_done()
5080 rsp->flags); in ibmvfc_npiv_login_done()
5082 wake_up(&vhost->work_wait_q); in ibmvfc_npiv_login_done()
5086 if (be32_to_cpu(rsp->max_cmds) <= IBMVFC_NUM_INTERNAL_REQ) { in ibmvfc_npiv_login_done()
5087 dev_err(vhost->dev, "Virtual adapter supported queue depth too small: %d\n", in ibmvfc_npiv_login_done()
5088 rsp->max_cmds); in ibmvfc_npiv_login_done()
5090 wake_up(&vhost->work_wait_q); in ibmvfc_npiv_login_done()
5094 vhost->logged_in = 1; in ibmvfc_npiv_login_done()
5095 npiv_max_sectors = min((uint)(be64_to_cpu(rsp->max_dma_len) >> 9), IBMVFC_MAX_SECTORS); in ibmvfc_npiv_login_done()
5096 dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n", in ibmvfc_npiv_login_done()
5097 rsp->partition_name, rsp->device_name, rsp->port_loc_code, in ibmvfc_npiv_login_done()
5098 rsp->drc_name, npiv_max_sectors); in ibmvfc_npiv_login_done()
5100 fc_host_fabric_name(vhost->host) = be64_to_cpu(rsp->node_name); in ibmvfc_npiv_login_done()
5101 fc_host_node_name(vhost->host) = be64_to_cpu(rsp->node_name); in ibmvfc_npiv_login_done()
5102 fc_host_port_name(vhost->host) = be64_to_cpu(rsp->port_name); in ibmvfc_npiv_login_done()
5103 fc_host_port_id(vhost->host) = be64_to_cpu(rsp->scsi_id); in ibmvfc_npiv_login_done()
5104 fc_host_port_type(vhost->host) = FC_PORTTYPE_NPIV; in ibmvfc_npiv_login_done()
5105 fc_host_supported_classes(vhost->host) = 0; in ibmvfc_npiv_login_done()
5106 if (be32_to_cpu(rsp->service_parms.class1_parms[0]) & 0x80000000) in ibmvfc_npiv_login_done()
5107 fc_host_supported_classes(vhost->host) |= FC_COS_CLASS1; in ibmvfc_npiv_login_done()
5108 if (be32_to_cpu(rsp->service_parms.class2_parms[0]) & 0x80000000) in ibmvfc_npiv_login_done()
5109 fc_host_supported_classes(vhost->host) |= FC_COS_CLASS2; in ibmvfc_npiv_login_done()
5110 if (be32_to_cpu(rsp->service_parms.class3_parms[0]) & 0x80000000) in ibmvfc_npiv_login_done()
5111 fc_host_supported_classes(vhost->host) |= FC_COS_CLASS3; in ibmvfc_npiv_login_done()
5112 fc_host_maxframe_size(vhost->host) = in ibmvfc_npiv_login_done()
5113 be16_to_cpu(rsp->service_parms.common.bb_rcv_sz) & 0x0fff; in ibmvfc_npiv_login_done()
5115 vhost->host->can_queue = be32_to_cpu(rsp->max_cmds) - IBMVFC_NUM_INTERNAL_REQ; in ibmvfc_npiv_login_done()
5116 vhost->host->max_sectors = npiv_max_sectors; in ibmvfc_npiv_login_done()
5118 if (ibmvfc_check_caps(vhost, IBMVFC_CAN_SUPPORT_CHANNELS) && vhost->do_enquiry) { in ibmvfc_npiv_login_done()
5121 vhost->do_enquiry = 0; in ibmvfc_npiv_login_done()
5123 wake_up(&vhost->work_wait_q); in ibmvfc_npiv_login_done()
5128 * ibmvfc_npiv_login - Sends NPIV login
5135 struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_npiv_login() local
5139 ibmvfc_init_event(evt, ibmvfc_npiv_login_done, IBMVFC_MAD_FORMAT); in ibmvfc_npiv_login()
5141 memcpy(vhost->login_buf, &vhost->login_info, sizeof(vhost->login_info)); in ibmvfc_npiv_login()
5142 mad = &evt->iu.npiv_login; in ibmvfc_npiv_login()
5144 mad->common.version = cpu_to_be32(1); in ibmvfc_npiv_login()
5145 mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGIN); in ibmvfc_npiv_login()
5146 mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_login_mad)); in ibmvfc_npiv_login()
5147 mad->buffer.va = cpu_to_be64(vhost->login_buf_dma); in ibmvfc_npiv_login()
5148 mad->buffer.len = cpu_to_be32(sizeof(*vhost->login_buf)); in ibmvfc_npiv_login()
5152 if (!ibmvfc_send_event(evt, vhost, default_timeout)) in ibmvfc_npiv_login()
5159 * ibmvfc_npiv_logout_done - Completion handler for NPIV Logout
5160 * @evt: ibmvfc event struct
5163 static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt) in ibmvfc_npiv_logout_done() argument
5165 struct ibmvfc_host *vhost = evt->vhost; in ibmvfc_npiv_logout_done()
5166 u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_logout.common.status); in ibmvfc_npiv_logout_done()
5168 ibmvfc_free_event(evt); in ibmvfc_npiv_logout_done()
5172 if (list_empty(&vhost->crq.sent) && in ibmvfc_npiv_logout_done()
5173 vhost->action == IBMVFC_HOST_ACTION_LOGO_WAIT) { in ibmvfc_npiv_logout_done()
5191 * ibmvfc_npiv_logout - Issue an NPIV Logout
5198 struct ibmvfc_event *evt; in ibmvfc_npiv_logout() local
5200 evt = ibmvfc_get_event(&vhost->crq); in ibmvfc_npiv_logout()
5201 ibmvfc_init_event(evt, ibmvfc_npiv_logout_done, IBMVFC_MAD_FORMAT); in ibmvfc_npiv_logout()
5203 mad = &evt->iu.npiv_logout; in ibmvfc_npiv_logout()
5205 mad->common.version = cpu_to_be32(1); in ibmvfc_npiv_logout()
5206 mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGOUT); in ibmvfc_npiv_logout()
5207 mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_logout_mad)); in ibmvfc_npiv_logout()
5211 if (!ibmvfc_send_event(evt, vhost, default_timeout)) in ibmvfc_npiv_logout()
5218 * ibmvfc_dev_init_to_do - Is there target initialization work to do?
5228 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_dev_init_to_do()
5229 if (tgt->action == IBMVFC_TGT_ACTION_INIT || in ibmvfc_dev_init_to_do()
5230 tgt->action == IBMVFC_TGT_ACTION_INIT_WAIT) in ibmvfc_dev_init_to_do()
5238 * ibmvfc_dev_logo_to_do - Is there target logout work to do?
5248 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_dev_logo_to_do()
5249 if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT || in ibmvfc_dev_logo_to_do()
5250 tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT) in ibmvfc_dev_logo_to_do()
5257 * __ibmvfc_work_to_do - Is there task level work to do? (no locking)
5269 switch (vhost->action) { in __ibmvfc_work_to_do()
5276 if (vhost->discovery_threads == disc_threads) in __ibmvfc_work_to_do()
5278 list_for_each_entry(tgt, &vhost->targets, queue) in __ibmvfc_work_to_do()
5279 if (tgt->action == IBMVFC_TGT_ACTION_INIT) in __ibmvfc_work_to_do()
5281 list_for_each_entry(tgt, &vhost->targets, queue) in __ibmvfc_work_to_do()
5282 if (tgt->action == IBMVFC_TGT_ACTION_INIT_WAIT) in __ibmvfc_work_to_do()
5287 if (vhost->discovery_threads == disc_threads) in __ibmvfc_work_to_do()
5289 list_for_each_entry(tgt, &vhost->targets, queue) in __ibmvfc_work_to_do()
5290 if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) in __ibmvfc_work_to_do()
5292 list_for_each_entry(tgt, &vhost->targets, queue) in __ibmvfc_work_to_do()
5293 if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT) in __ibmvfc_work_to_do()
5310 * ibmvfc_work_to_do - Is there task level work to do?
5321 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_work_to_do()
5323 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_work_to_do()
5328 * ibmvfc_log_ae - Log async events if necessary
5336 fc_host_post_event(vhost->host, fc_get_event_number(), FCH_EVT_RSCN, 0); in ibmvfc_log_ae()
5338 vhost->state >= IBMVFC_HALTED) in ibmvfc_log_ae()
5339 fc_host_post_event(vhost->host, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); in ibmvfc_log_ae()
5341 vhost->state == IBMVFC_INITIALIZING) in ibmvfc_log_ae()
5342 fc_host_post_event(vhost->host, fc_get_event_number(), FCH_EVT_LINKUP, 0); in ibmvfc_log_ae()
5346 * ibmvfc_tgt_add_rport - Tell the FC transport about a new remote port
5352 struct ibmvfc_host *vhost = tgt->vhost; in ibmvfc_tgt_add_rport()
5357 rport = fc_remote_port_add(vhost->host, 0, &tgt->ids); in ibmvfc_tgt_add_rport()
5358 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_tgt_add_rport()
5360 if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { in ibmvfc_tgt_add_rport()
5362 list_del(&tgt->queue); in ibmvfc_tgt_add_rport()
5364 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_tgt_add_rport()
5366 del_timer_sync(&tgt->timer); in ibmvfc_tgt_add_rport()
5367 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_tgt_add_rport()
5369 } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) { in ibmvfc_tgt_add_rport()
5372 tgt->rport = NULL; in ibmvfc_tgt_add_rport()
5373 tgt->init_retries = 0; in ibmvfc_tgt_add_rport()
5374 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_tgt_add_rport()
5377 } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) { in ibmvfc_tgt_add_rport()
5378 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_tgt_add_rport()
5384 tgt->rport = rport; in ibmvfc_tgt_add_rport()
5385 rport->maxframe_size = be16_to_cpu(tgt->service_parms.common.bb_rcv_sz) & 0x0fff; in ibmvfc_tgt_add_rport()
5386 rport->supported_classes = 0; in ibmvfc_tgt_add_rport()
5387 tgt->target_id = rport->scsi_target_id; in ibmvfc_tgt_add_rport()
5388 if (be32_to_cpu(tgt->service_parms.class1_parms[0]) & 0x80000000) in ibmvfc_tgt_add_rport()
5389 rport->supported_classes |= FC_COS_CLASS1; in ibmvfc_tgt_add_rport()
5390 if (be32_to_cpu(tgt->service_parms.class2_parms[0]) & 0x80000000) in ibmvfc_tgt_add_rport()
5391 rport->supported_classes |= FC_COS_CLASS2; in ibmvfc_tgt_add_rport()
5392 if (be32_to_cpu(tgt->service_parms.class3_parms[0]) & 0x80000000) in ibmvfc_tgt_add_rport()
5393 rport->supported_classes |= FC_COS_CLASS3; in ibmvfc_tgt_add_rport()
5394 if (rport->rqst_q) in ibmvfc_tgt_add_rport()
5395 blk_queue_max_segments(rport->rqst_q, 1); in ibmvfc_tgt_add_rport()
5398 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_tgt_add_rport()
5402 * ibmvfc_do_work - Do task level work
5414 ibmvfc_log_ae(vhost, vhost->events_to_log); in ibmvfc_do_work()
5415 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_do_work()
5416 vhost->events_to_log = 0; in ibmvfc_do_work()
5417 switch (vhost->action) { in ibmvfc_do_work()
5423 list_splice_init(&vhost->purge, &purge); in ibmvfc_do_work()
5424 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5428 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_do_work()
5430 vio_enable_interrupts(to_vio_dev(vhost->dev)); in ibmvfc_do_work()
5431 if (vhost->action == IBMVFC_HOST_ACTION_RESET) { in ibmvfc_do_work()
5435 * this path and wait until we've done the re-enable in ibmvfc_do_work()
5438 vhost->action = IBMVFC_HOST_ACTION_TGT_DEL; in ibmvfc_do_work()
5441 (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) { in ibmvfc_do_work()
5443 dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc); in ibmvfc_do_work()
5448 list_splice_init(&vhost->purge, &purge); in ibmvfc_do_work()
5449 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5453 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_do_work()
5454 if (vhost->action == IBMVFC_HOST_ACTION_REENABLE) { in ibmvfc_do_work()
5461 vhost->action = IBMVFC_HOST_ACTION_TGT_DEL; in ibmvfc_do_work()
5464 dev_err(vhost->dev, "Error after enable (rc=%d)\n", rc); in ibmvfc_do_work()
5469 vhost->job_step(vhost); in ibmvfc_do_work()
5472 BUG_ON(vhost->state != IBMVFC_INITIALIZING); in ibmvfc_do_work()
5473 if (vhost->delay_init) { in ibmvfc_do_work()
5474 vhost->delay_init = 0; in ibmvfc_do_work()
5475 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5479 vhost->job_step(vhost); in ibmvfc_do_work()
5482 list_for_each_entry(tgt, &vhost->targets, queue) in ibmvfc_do_work()
5487 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_do_work()
5488 if (tgt->action == IBMVFC_TGT_ACTION_INIT) { in ibmvfc_do_work()
5489 tgt->job_step(tgt); in ibmvfc_do_work()
5499 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_do_work()
5500 if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) { in ibmvfc_do_work()
5501 tgt->job_step(tgt); in ibmvfc_do_work()
5507 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5511 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_do_work()
5512 if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { in ibmvfc_do_work()
5514 rport = tgt->rport; in ibmvfc_do_work()
5515 tgt->rport = NULL; in ibmvfc_do_work()
5516 list_del(&tgt->queue); in ibmvfc_do_work()
5518 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5521 del_timer_sync(&tgt->timer); in ibmvfc_do_work()
5522 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_do_work()
5524 } else if (tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) { in ibmvfc_do_work()
5526 rport = tgt->rport; in ibmvfc_do_work()
5527 tgt->rport = NULL; in ibmvfc_do_work()
5528 tgt->init_retries = 0; in ibmvfc_do_work()
5540 if (rport && rport->fast_io_fail_tmo == -1) in ibmvfc_do_work()
5541 tgt->move_login = 1; in ibmvfc_do_work()
5542 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5549 if (vhost->state == IBMVFC_INITIALIZING) { in ibmvfc_do_work()
5550 if (vhost->action == IBMVFC_HOST_ACTION_TGT_DEL_FAILED) { in ibmvfc_do_work()
5551 if (vhost->reinit) { in ibmvfc_do_work()
5552 vhost->reinit = 0; in ibmvfc_do_work()
5553 scsi_block_requests(vhost->host); in ibmvfc_do_work()
5555 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5559 wake_up(&vhost->init_wait_q); in ibmvfc_do_work()
5560 schedule_work(&vhost->rport_add_work_q); in ibmvfc_do_work()
5561 vhost->init_retries = 0; in ibmvfc_do_work()
5562 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5563 scsi_unblock_requests(vhost->host); in ibmvfc_do_work()
5569 vhost->job_step = ibmvfc_discover_targets; in ibmvfc_do_work()
5573 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5574 scsi_unblock_requests(vhost->host); in ibmvfc_do_work()
5575 wake_up(&vhost->init_wait_q); in ibmvfc_do_work()
5581 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5583 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_do_work()
5586 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_do_work()
5587 if (tgt->action == IBMVFC_TGT_ACTION_INIT) { in ibmvfc_do_work()
5588 tgt->job_step(tgt); in ibmvfc_do_work()
5600 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_do_work()
5604 * ibmvfc_work - Do task level work
5618 rc = wait_event_interruptible(vhost->work_wait_q, in ibmvfc_work()
5634 * ibmvfc_alloc_queue - Allocate queue
5640 * 0 on success / non-zero on failure
5646 struct device *dev = vhost->dev; in ibmvfc_alloc_queue()
5651 spin_lock_init(&queue->_lock); in ibmvfc_alloc_queue()
5652 queue->q_lock = &queue->_lock; in ibmvfc_alloc_queue()
5656 fmt_size = sizeof(*queue->msgs.crq); in ibmvfc_alloc_queue()
5660 fmt_size = sizeof(*queue->msgs.async); in ibmvfc_alloc_queue()
5663 fmt_size = sizeof(*queue->msgs.scrq); in ibmvfc_alloc_queue()
5669 return -EINVAL; in ibmvfc_alloc_queue()
5674 return -ENOMEM; in ibmvfc_alloc_queue()
5677 queue->msgs.handle = (void *)get_zeroed_page(GFP_KERNEL); in ibmvfc_alloc_queue()
5678 if (!queue->msgs.handle) in ibmvfc_alloc_queue()
5679 return -ENOMEM; in ibmvfc_alloc_queue()
5681 queue->msg_token = dma_map_single(dev, queue->msgs.handle, PAGE_SIZE, in ibmvfc_alloc_queue()
5684 if (dma_mapping_error(dev, queue->msg_token)) { in ibmvfc_alloc_queue()
5685 free_page((unsigned long)queue->msgs.handle); in ibmvfc_alloc_queue()
5686 queue->msgs.handle = NULL; in ibmvfc_alloc_queue()
5687 return -ENOMEM; in ibmvfc_alloc_queue()
5690 queue->cur = 0; in ibmvfc_alloc_queue()
5691 queue->fmt = fmt; in ibmvfc_alloc_queue()
5692 queue->size = PAGE_SIZE / fmt_size; in ibmvfc_alloc_queue()
5694 queue->vhost = vhost; in ibmvfc_alloc_queue()
5699 * ibmvfc_init_crq - Initializes and registers CRQ with hypervisor
5710 int rc, retrc = -ENOMEM; in ibmvfc_init_crq()
5711 struct device *dev = vhost->dev; in ibmvfc_init_crq()
5713 struct ibmvfc_queue *crq = &vhost->crq; in ibmvfc_init_crq()
5717 return -ENOMEM; in ibmvfc_init_crq()
5719 retrc = rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address, in ibmvfc_init_crq()
5720 crq->msg_token, PAGE_SIZE); in ibmvfc_init_crq()
5735 tasklet_init(&vhost->tasklet, (void *)ibmvfc_tasklet, (unsigned long)vhost); in ibmvfc_init_crq()
5737 if ((rc = request_irq(vdev->irq, ibmvfc_interrupt, 0, IBMVFC_NAME, vhost))) { in ibmvfc_init_crq()
5738 dev_err(dev, "Couldn't register irq 0x%x. rc=%d\n", vdev->irq, rc); in ibmvfc_init_crq()
5751 tasklet_kill(&vhost->tasklet); in ibmvfc_init_crq()
5753 rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); in ibmvfc_init_crq()
5763 struct device *dev = vhost->dev; in ibmvfc_register_scsi_channel()
5765 struct ibmvfc_queue *scrq = &vhost->scsi_scrqs.scrqs[index]; in ibmvfc_register_scsi_channel()
5766 int rc = -ENOMEM; in ibmvfc_register_scsi_channel()
5770 rc = h_reg_sub_crq(vdev->unit_address, scrq->msg_token, PAGE_SIZE, in ibmvfc_register_scsi_channel()
5771 &scrq->cookie, &scrq->hw_irq); in ibmvfc_register_scsi_channel()
5775 dev_warn(dev, "Error registering sub-crq: %d\n", rc); in ibmvfc_register_scsi_channel()
5781 scrq->irq = irq_create_mapping(NULL, scrq->hw_irq); in ibmvfc_register_scsi_channel()
5783 if (!scrq->irq) { in ibmvfc_register_scsi_channel()
5784 rc = -EINVAL; in ibmvfc_register_scsi_channel()
5785 dev_err(dev, "Error mapping sub-crq[%d] irq\n", index); in ibmvfc_register_scsi_channel()
5789 snprintf(scrq->name, sizeof(scrq->name), "ibmvfc-%x-scsi%d", in ibmvfc_register_scsi_channel()
5790 vdev->unit_address, index); in ibmvfc_register_scsi_channel()
5791 rc = request_irq(scrq->irq, ibmvfc_interrupt_scsi, 0, scrq->name, scrq); in ibmvfc_register_scsi_channel()
5794 dev_err(dev, "Couldn't register sub-crq[%d] irq\n", index); in ibmvfc_register_scsi_channel()
5795 irq_dispose_mapping(scrq->irq); in ibmvfc_register_scsi_channel()
5799 scrq->hwq_id = index; in ibmvfc_register_scsi_channel()
5806 rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq->cookie); in ibmvfc_register_scsi_channel()
5815 struct device *dev = vhost->dev; in ibmvfc_deregister_scsi_channel()
5817 struct ibmvfc_queue *scrq = &vhost->scsi_scrqs.scrqs[index]; in ibmvfc_deregister_scsi_channel()
5822 free_irq(scrq->irq, scrq); in ibmvfc_deregister_scsi_channel()
5823 irq_dispose_mapping(scrq->irq); in ibmvfc_deregister_scsi_channel()
5824 scrq->irq = 0; in ibmvfc_deregister_scsi_channel()
5827 rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, in ibmvfc_deregister_scsi_channel()
5828 scrq->cookie); in ibmvfc_deregister_scsi_channel()
5832 dev_err(dev, "Failed to free sub-crq[%d]: rc=%ld\n", index, rc); in ibmvfc_deregister_scsi_channel()
5835 memset(scrq->msgs.crq, 0, PAGE_SIZE); in ibmvfc_deregister_scsi_channel()
5836 scrq->cur = 0; in ibmvfc_deregister_scsi_channel()
5846 if (!vhost->mq_enabled || !vhost->scsi_scrqs.scrqs) in ibmvfc_reg_sub_crqs()
5851 for (j = i; j > 0; j--) in ibmvfc_reg_sub_crqs()
5852 ibmvfc_deregister_scsi_channel(vhost, j - 1); in ibmvfc_reg_sub_crqs()
5853 vhost->do_enquiry = 0; in ibmvfc_reg_sub_crqs()
5866 if (!vhost->mq_enabled || !vhost->scsi_scrqs.scrqs) in ibmvfc_dereg_sub_crqs()
5881 if (!vhost->mq_enabled) in ibmvfc_init_sub_crqs()
5884 vhost->scsi_scrqs.scrqs = kcalloc(nr_scsi_hw_queues, in ibmvfc_init_sub_crqs()
5885 sizeof(*vhost->scsi_scrqs.scrqs), in ibmvfc_init_sub_crqs()
5887 if (!vhost->scsi_scrqs.scrqs) { in ibmvfc_init_sub_crqs()
5888 vhost->do_enquiry = 0; in ibmvfc_init_sub_crqs()
5893 scrq = &vhost->scsi_scrqs.scrqs[i]; in ibmvfc_init_sub_crqs()
5895 for (j = i; j > 0; j--) { in ibmvfc_init_sub_crqs()
5896 scrq = &vhost->scsi_scrqs.scrqs[j - 1]; in ibmvfc_init_sub_crqs()
5899 kfree(vhost->scsi_scrqs.scrqs); in ibmvfc_init_sub_crqs()
5900 vhost->scsi_scrqs.scrqs = NULL; in ibmvfc_init_sub_crqs()
5901 vhost->scsi_scrqs.active_queues = 0; in ibmvfc_init_sub_crqs()
5902 vhost->do_enquiry = 0; in ibmvfc_init_sub_crqs()
5903 vhost->mq_enabled = 0; in ibmvfc_init_sub_crqs()
5919 if (!vhost->scsi_scrqs.scrqs) in ibmvfc_release_sub_crqs()
5925 scrq = &vhost->scsi_scrqs.scrqs[i]; in ibmvfc_release_sub_crqs()
5929 kfree(vhost->scsi_scrqs.scrqs); in ibmvfc_release_sub_crqs()
5930 vhost->scsi_scrqs.scrqs = NULL; in ibmvfc_release_sub_crqs()
5931 vhost->scsi_scrqs.active_queues = 0; in ibmvfc_release_sub_crqs()
5936 * ibmvfc_free_mem - Free memory for vhost
5944 struct ibmvfc_queue *async_q = &vhost->async_crq; in ibmvfc_free_mem()
5947 mempool_destroy(vhost->tgt_pool); in ibmvfc_free_mem()
5948 kfree(vhost->trace); in ibmvfc_free_mem()
5949 dma_free_coherent(vhost->dev, vhost->disc_buf_sz, vhost->disc_buf, in ibmvfc_free_mem()
5950 vhost->disc_buf_dma); in ibmvfc_free_mem()
5951 dma_free_coherent(vhost->dev, sizeof(*vhost->login_buf), in ibmvfc_free_mem()
5952 vhost->login_buf, vhost->login_buf_dma); in ibmvfc_free_mem()
5953 dma_free_coherent(vhost->dev, sizeof(*vhost->channel_setup_buf), in ibmvfc_free_mem()
5954 vhost->channel_setup_buf, vhost->channel_setup_dma); in ibmvfc_free_mem()
5955 dma_pool_destroy(vhost->sg_pool); in ibmvfc_free_mem()
5961 * ibmvfc_alloc_mem - Allocate memory for vhost
5965 * 0 on success / non-zero on failure
5969 struct ibmvfc_queue *async_q = &vhost->async_crq; in ibmvfc_alloc_mem()
5970 struct device *dev = vhost->dev; in ibmvfc_alloc_mem()
5978 vhost->sg_pool = dma_pool_create(IBMVFC_NAME, dev, in ibmvfc_alloc_mem()
5982 if (!vhost->sg_pool) { in ibmvfc_alloc_mem()
5987 vhost->login_buf = dma_alloc_coherent(dev, sizeof(*vhost->login_buf), in ibmvfc_alloc_mem()
5988 &vhost->login_buf_dma, GFP_KERNEL); in ibmvfc_alloc_mem()
5990 if (!vhost->login_buf) { in ibmvfc_alloc_mem()
5995 vhost->disc_buf_sz = sizeof(*vhost->disc_buf) * max_targets; in ibmvfc_alloc_mem()
5996 vhost->disc_buf = dma_alloc_coherent(dev, vhost->disc_buf_sz, in ibmvfc_alloc_mem()
5997 &vhost->disc_buf_dma, GFP_KERNEL); in ibmvfc_alloc_mem()
5999 if (!vhost->disc_buf) { in ibmvfc_alloc_mem()
6004 vhost->trace = kcalloc(IBMVFC_NUM_TRACE_ENTRIES, in ibmvfc_alloc_mem()
6006 atomic_set(&vhost->trace_index, -1); in ibmvfc_alloc_mem()
6008 if (!vhost->trace) in ibmvfc_alloc_mem()
6011 vhost->tgt_pool = mempool_create_kmalloc_pool(IBMVFC_TGT_MEMPOOL_SZ, in ibmvfc_alloc_mem()
6014 if (!vhost->tgt_pool) { in ibmvfc_alloc_mem()
6019 vhost->channel_setup_buf = dma_alloc_coherent(dev, sizeof(*vhost->channel_setup_buf), in ibmvfc_alloc_mem()
6020 &vhost->channel_setup_dma, in ibmvfc_alloc_mem()
6023 if (!vhost->channel_setup_buf) { in ibmvfc_alloc_mem()
6032 mempool_destroy(vhost->tgt_pool); in ibmvfc_alloc_mem()
6034 kfree(vhost->trace); in ibmvfc_alloc_mem()
6036 dma_free_coherent(dev, vhost->disc_buf_sz, vhost->disc_buf, in ibmvfc_alloc_mem()
6037 vhost->disc_buf_dma); in ibmvfc_alloc_mem()
6039 dma_free_coherent(dev, sizeof(*vhost->login_buf), in ibmvfc_alloc_mem()
6040 vhost->login_buf, vhost->login_buf_dma); in ibmvfc_alloc_mem()
6042 dma_pool_destroy(vhost->sg_pool); in ibmvfc_alloc_mem()
6047 return -ENOMEM; in ibmvfc_alloc_mem()
6051 * ibmvfc_rport_add_thread - Worker thread for rport adds
6065 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_rport_add_thread()
6068 if (vhost->state != IBMVFC_ACTIVE) in ibmvfc_rport_add_thread()
6071 list_for_each_entry(tgt, &vhost->targets, queue) { in ibmvfc_rport_add_thread()
6072 if (tgt->add_rport) { in ibmvfc_rport_add_thread()
6074 tgt->add_rport = 0; in ibmvfc_rport_add_thread()
6075 kref_get(&tgt->kref); in ibmvfc_rport_add_thread()
6076 rport = tgt->rport; in ibmvfc_rport_add_thread()
6078 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_rport_add_thread()
6080 } else if (get_device(&rport->dev)) { in ibmvfc_rport_add_thread()
6081 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_rport_add_thread()
6083 fc_remote_port_rolechg(rport, tgt->ids.roles); in ibmvfc_rport_add_thread()
6084 put_device(&rport->dev); in ibmvfc_rport_add_thread()
6086 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_rport_add_thread()
6089 kref_put(&tgt->kref, ibmvfc_release_tgt); in ibmvfc_rport_add_thread()
6090 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_rport_add_thread()
6096 if (vhost->state == IBMVFC_ACTIVE) in ibmvfc_rport_add_thread()
6097 vhost->scan_complete = 1; in ibmvfc_rport_add_thread()
6098 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_rport_add_thread()
6103 * ibmvfc_probe - Adapter hot plug add entry point
6108 * 0 on success / non-zero on failure
6114 struct device *dev = &vdev->dev; in ibmvfc_probe()
6115 int rc = -ENOMEM; in ibmvfc_probe()
6125 shost->transportt = ibmvfc_transport_template; in ibmvfc_probe()
6126 shost->can_queue = max_requests; in ibmvfc_probe()
6127 shost->max_lun = max_lun; in ibmvfc_probe()
6128 shost->max_id = max_targets; in ibmvfc_probe()
6129 shost->max_sectors = IBMVFC_MAX_SECTORS; in ibmvfc_probe()
6130 shost->max_cmd_len = IBMVFC_MAX_CDB_LEN; in ibmvfc_probe()
6131 shost->unique_id = shost->host_no; in ibmvfc_probe()
6132 shost->nr_hw_queues = mq_enabled ? min(max_scsi_queues, nr_scsi_hw_queues) : 1; in ibmvfc_probe()
6135 INIT_LIST_HEAD(&vhost->targets); in ibmvfc_probe()
6136 INIT_LIST_HEAD(&vhost->purge); in ibmvfc_probe()
6137 sprintf(vhost->name, IBMVFC_NAME); in ibmvfc_probe()
6138 vhost->host = shost; in ibmvfc_probe()
6139 vhost->dev = dev; in ibmvfc_probe()
6140 vhost->partition_number = -1; in ibmvfc_probe()
6141 vhost->log_level = log_level; in ibmvfc_probe()
6142 vhost->task_set = 1; in ibmvfc_probe()
6144 vhost->mq_enabled = mq_enabled; in ibmvfc_probe()
6145 vhost->client_scsi_channels = min(shost->nr_hw_queues, nr_scsi_channels); in ibmvfc_probe()
6146 vhost->using_channels = 0; in ibmvfc_probe()
6147 vhost->do_enquiry = 1; in ibmvfc_probe()
6148 vhost->scan_timeout = 0; in ibmvfc_probe()
6150 strcpy(vhost->partition_name, "UNKNOWN"); in ibmvfc_probe()
6151 init_waitqueue_head(&vhost->work_wait_q); in ibmvfc_probe()
6152 init_waitqueue_head(&vhost->init_wait_q); in ibmvfc_probe()
6153 INIT_WORK(&vhost->rport_add_work_q, ibmvfc_rport_add_thread); in ibmvfc_probe()
6154 mutex_init(&vhost->passthru_mutex); in ibmvfc_probe()
6159 vhost->work_thread = kthread_run(ibmvfc_work, vhost, "%s_%d", IBMVFC_NAME, in ibmvfc_probe()
6160 shost->host_no); in ibmvfc_probe()
6162 if (IS_ERR(vhost->work_thread)) { in ibmvfc_probe()
6164 PTR_ERR(vhost->work_thread)); in ibmvfc_probe()
6165 rc = PTR_ERR(vhost->work_thread); in ibmvfc_probe()
6179 if ((rc = ibmvfc_create_trace_file(&shost->shost_dev.kobj, in ibmvfc_probe()
6187 if (shost_to_fc_host(shost)->rqst_q) in ibmvfc_probe()
6188 blk_queue_max_segments(shost_to_fc_host(shost)->rqst_q, 1); in ibmvfc_probe()
6191 list_add_tail(&vhost->queue, &ibmvfc_head); in ibmvfc_probe()
6203 kthread_stop(vhost->work_thread); in ibmvfc_probe()
6214 * ibmvfc_remove - Adapter hot plug remove entry point
6222 struct ibmvfc_host *vhost = dev_get_drvdata(&vdev->dev); in ibmvfc_remove()
6227 ibmvfc_remove_trace_file(&vhost->host->shost_dev.kobj, &ibmvfc_trace_attr); in ibmvfc_remove()
6229 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_remove()
6231 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_remove()
6234 kthread_stop(vhost->work_thread); in ibmvfc_remove()
6235 fc_remove_host(vhost->host); in ibmvfc_remove()
6236 scsi_remove_host(vhost->host); in ibmvfc_remove()
6238 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_remove()
6240 list_splice_init(&vhost->purge, &purge); in ibmvfc_remove()
6241 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_remove()
6248 list_del(&vhost->queue); in ibmvfc_remove()
6250 scsi_host_put(vhost->host); in ibmvfc_remove()
6255 * ibmvfc_resume - Resume from suspend
6268 spin_lock_irqsave(vhost->host->host_lock, flags); in ibmvfc_resume()
6270 tasklet_schedule(&vhost->tasklet); in ibmvfc_resume()
6271 spin_unlock_irqrestore(vhost->host->host_lock, flags); in ibmvfc_resume()
6276 * ibmvfc_get_desired_dma - Calculate DMA resources needed by the driver
6290 {"fcp", "IBM,vfc-client"},
6346 * ibmvfc_module_init - Initialize the ibmvfc module
6356 return -ENODEV; in ibmvfc_module_init()
6363 return -ENOMEM; in ibmvfc_module_init()
6372 * ibmvfc_module_exit - Teardown the ibmvfc module