2121#include <linux/bsg-lib.h>
2222#include <asm/firmware.h>
2323#include <asm/irq.h>
24+ #include <asm/rtas.h>
2425#include <asm/vio.h>
2526#include <scsi/scsi.h>
2627#include <scsi/scsi_cmnd.h>
@@ -158,6 +159,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *);
158159static void ibmvfc_tgt_implicit_logout_and_del (struct ibmvfc_target * );
159160static void ibmvfc_tgt_move_login (struct ibmvfc_target * );
160161
162+ static void ibmvfc_release_sub_crqs (struct ibmvfc_host * );
163+ static void ibmvfc_init_sub_crqs (struct ibmvfc_host * );
164+
161165static const char * unknown_error = "unknown error" ;
162166
163167static long h_reg_sub_crq (unsigned long unit_address , unsigned long ioba ,
@@ -899,6 +903,9 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
899903{
900904 int rc = 0 ;
901905 struct vio_dev * vdev = to_vio_dev (vhost -> dev );
906+ unsigned long flags ;
907+
908+ ibmvfc_release_sub_crqs (vhost );
902909
903910 /* Re-enable the CRQ */
904911 do {
@@ -910,6 +917,15 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
910917 if (rc )
911918 dev_err (vhost -> dev , "Error enabling adapter (rc=%d)\n" , rc );
912919
920+ spin_lock_irqsave (vhost -> host -> host_lock , flags );
921+ spin_lock (vhost -> crq .q_lock );
922+ vhost -> do_enquiry = 1 ;
923+ vhost -> using_channels = 0 ;
924+ spin_unlock (vhost -> crq .q_lock );
925+ spin_unlock_irqrestore (vhost -> host -> host_lock , flags );
926+
927+ ibmvfc_init_sub_crqs (vhost );
928+
913929 return rc ;
914930}
915931
@@ -926,8 +942,8 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
926942 unsigned long flags ;
927943 struct vio_dev * vdev = to_vio_dev (vhost -> dev );
928944 struct ibmvfc_queue * crq = & vhost -> crq ;
929- struct ibmvfc_queue * scrq ;
930- int i ;
945+
946+ ibmvfc_release_sub_crqs ( vhost ) ;
931947
932948 /* Close the CRQ */
933949 do {
@@ -947,16 +963,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
947963 memset (crq -> msgs .crq , 0 , PAGE_SIZE );
948964 crq -> cur = 0 ;
949965
950- if (vhost -> scsi_scrqs .scrqs ) {
951- for (i = 0 ; i < nr_scsi_hw_queues ; i ++ ) {
952- scrq = & vhost -> scsi_scrqs .scrqs [i ];
953- spin_lock (scrq -> q_lock );
954- memset (scrq -> msgs .scrq , 0 , PAGE_SIZE );
955- scrq -> cur = 0 ;
956- spin_unlock (scrq -> q_lock );
957- }
958- }
959-
960966 /* And re-open it again */
961967 rc = plpar_hcall_norets (H_REG_CRQ , vdev -> unit_address ,
962968 crq -> msg_token , PAGE_SIZE );
@@ -966,9 +972,12 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
966972 dev_warn (vhost -> dev , "Partner adapter not ready\n" );
967973 else if (rc != 0 )
968974 dev_warn (vhost -> dev , "Couldn't register crq (rc=%d)\n" , rc );
975+
969976 spin_unlock (vhost -> crq .q_lock );
970977 spin_unlock_irqrestore (vhost -> host -> host_lock , flags );
971978
979+ ibmvfc_init_sub_crqs (vhost );
980+
972981 return rc ;
973982}
974983
@@ -5642,7 +5651,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
56425651 rc = h_reg_sub_crq (vdev -> unit_address , scrq -> msg_token , PAGE_SIZE ,
56435652 & scrq -> cookie , & scrq -> hw_irq );
56445653
5645- if (rc ) {
5654+ /* H_CLOSED indicates successful register, but no CRQ partner */
5655+ if (rc && rc != H_CLOSED ) {
56465656 dev_warn (dev , "Error registering sub-crq: %d\n" , rc );
56475657 if (rc == H_PARAMETER )
56485658 dev_warn_once (dev , "Firmware may not support MQ\n" );
@@ -5675,8 +5685,8 @@ static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
56755685
56765686irq_failed :
56775687 do {
5678- plpar_hcall_norets (H_FREE_SUB_CRQ , vdev -> unit_address , scrq -> cookie );
5679- } while (rc == H_BUSY || H_IS_LONG_BUSY (rc ));
5688+ rc = plpar_hcall_norets (H_FREE_SUB_CRQ , vdev -> unit_address , scrq -> cookie );
5689+ } while (rtas_busy_delay (rc ));
56805690reg_failed :
56815691 ibmvfc_free_queue (vhost , scrq );
56825692 LEAVE ;
@@ -5694,6 +5704,7 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index)
56945704
56955705 free_irq (scrq -> irq , scrq );
56965706 irq_dispose_mapping (scrq -> irq );
5707+ scrq -> irq = 0 ;
56975708
56985709 do {
56995710 rc = plpar_hcall_norets (H_FREE_SUB_CRQ , vdev -> unit_address ,
@@ -5707,17 +5718,21 @@ static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int index)
57075718 LEAVE ;
57085719}
57095720
5710- static int ibmvfc_init_sub_crqs (struct ibmvfc_host * vhost )
5721+ static void ibmvfc_init_sub_crqs (struct ibmvfc_host * vhost )
57115722{
57125723 int i , j ;
57135724
57145725 ENTER ;
5726+ if (!vhost -> mq_enabled )
5727+ return ;
57155728
57165729 vhost -> scsi_scrqs .scrqs = kcalloc (nr_scsi_hw_queues ,
57175730 sizeof (* vhost -> scsi_scrqs .scrqs ),
57185731 GFP_KERNEL );
5719- if (!vhost -> scsi_scrqs .scrqs )
5720- return -1 ;
5732+ if (!vhost -> scsi_scrqs .scrqs ) {
5733+ vhost -> do_enquiry = 0 ;
5734+ return ;
5735+ }
57215736
57225737 for (i = 0 ; i < nr_scsi_hw_queues ; i ++ ) {
57235738 if (ibmvfc_register_scsi_channel (vhost , i )) {
@@ -5726,13 +5741,12 @@ static int ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
57265741 kfree (vhost -> scsi_scrqs .scrqs );
57275742 vhost -> scsi_scrqs .scrqs = NULL ;
57285743 vhost -> scsi_scrqs .active_queues = 0 ;
5729- LEAVE ;
5730- return -1 ;
5744+ vhost -> do_enquiry = 0 ;
5745+ break ;
57315746 }
57325747 }
57335748
57345749 LEAVE ;
5735- return 0 ;
57365750}
57375751
57385752static void ibmvfc_release_sub_crqs (struct ibmvfc_host * vhost )
@@ -5999,11 +6013,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
59996013 goto remove_shost ;
60006014 }
60016015
6002- if (vhost -> mq_enabled ) {
6003- rc = ibmvfc_init_sub_crqs (vhost );
6004- if (rc )
6005- dev_warn (dev , "Failed to allocate Sub-CRQs. rc=%d\n" , rc );
6006- }
6016+ ibmvfc_init_sub_crqs (vhost );
60076017
60086018 if (shost_to_fc_host (shost )-> rqst_q )
60096019 blk_queue_max_segments (shost_to_fc_host (shost )-> rqst_q , 1 );
0 commit comments