@@ -420,6 +420,74 @@ static bool mpi3mr_flush_scmd(struct request *rq,
420420 return (true);
421421}
422422
423+ /**
424+ * mpi3mr_count_dev_pending - Count commands pending for a lun
425+ * @rq: Block request
426+ * @data: SCSI device reference
427+ * @reserved: Unused
428+ *
429+ * This is an iterator function called for each SCSI command in
430+ * a host and if the command is pending in the LLD for the
431+ * specific device(lun) then device specific pending I/O counter
432+ * is updated in the device structure.
433+ *
434+ * Return: true always.
435+ */
436+
437+ static bool mpi3mr_count_dev_pending (struct request * rq ,
438+ void * data , bool reserved )
439+ {
440+ struct scsi_device * sdev = (struct scsi_device * )data ;
441+ struct mpi3mr_sdev_priv_data * sdev_priv_data = sdev -> hostdata ;
442+ struct scsi_cmnd * scmd = blk_mq_rq_to_pdu (rq );
443+ struct scmd_priv * priv ;
444+
445+ if (scmd ) {
446+ priv = scsi_cmd_priv (scmd );
447+ if (!priv -> in_lld_scope )
448+ goto out ;
449+ if (scmd -> device == sdev )
450+ sdev_priv_data -> pend_count ++ ;
451+ }
452+
453+ out :
454+ return true;
455+ }
456+
457+ /**
458+ * mpi3mr_count_tgt_pending - Count commands pending for target
459+ * @rq: Block request
460+ * @data: SCSI target reference
461+ * @reserved: Unused
462+ *
463+ * This is an iterator function called for each SCSI command in
464+ * a host and if the command is pending in the LLD for the
465+ * specific target then target specific pending I/O counter is
466+ * updated in the target structure.
467+ *
468+ * Return: true always.
469+ */
470+
471+ static bool mpi3mr_count_tgt_pending (struct request * rq ,
472+ void * data , bool reserved )
473+ {
474+ struct scsi_target * starget = (struct scsi_target * )data ;
475+ struct mpi3mr_stgt_priv_data * stgt_priv_data = starget -> hostdata ;
476+ struct scsi_cmnd * scmd = blk_mq_rq_to_pdu (rq );
477+ struct scmd_priv * priv ;
478+
479+ if (scmd ) {
480+ priv = scsi_cmd_priv (scmd );
481+ if (!priv -> in_lld_scope )
482+ goto out ;
483+ if (scmd -> device && (scsi_target (scmd -> device ) == starget ))
484+ stgt_priv_data -> pend_count ++ ;
485+ }
486+
487+ out :
488+ return true;
489+ }
490+
423491/**
424492 * mpi3mr_flush_host_io - Flush host I/Os
425493 * @mrioc: Adapter instance reference
@@ -2847,16 +2915,28 @@ static const char *mpi3mr_tm_response_name(u8 resp_code)
28472915 return desc ;
28482916}
28492917
2918+ inline void mpi3mr_poll_pend_io_completions (struct mpi3mr_ioc * mrioc )
2919+ {
2920+ int i ;
2921+ int num_of_reply_queues =
2922+ mrioc -> num_op_reply_q + mrioc -> op_reply_q_offset ;
2923+
2924+ for (i = mrioc -> op_reply_q_offset ; i < num_of_reply_queues ; i ++ )
2925+ mpi3mr_process_op_reply_q (mrioc ,
2926+ mrioc -> intr_info [i ].op_reply_q );
2927+ }
2928+
28502929/**
28512930 * mpi3mr_issue_tm - Issue Task Management request
28522931 * @mrioc: Adapter instance reference
28532932 * @tm_type: Task Management type
28542933 * @handle: Device handle
28552934 * @lun: lun ID
28562935 * @htag: Host tag of the TM request
2936+ * @timeout: TM timeout value
28572937 * @drv_cmd: Internal command tracker
28582938 * @resp_code: Response code place holder
2859- * @cmd_priv : SCSI command private data
2939+ * @scmd : SCSI command
28602940 *
28612941 * Issues a Task Management Request to the controller for a
28622942 * specified target, lun and command and wait for its completion
@@ -2868,14 +2948,16 @@ static const char *mpi3mr_tm_response_name(u8 resp_code)
28682948static int mpi3mr_issue_tm (struct mpi3mr_ioc * mrioc , u8 tm_type ,
28692949 u16 handle , uint lun , u16 htag , ulong timeout ,
28702950 struct mpi3mr_drv_cmd * drv_cmd ,
2871- u8 * resp_code , struct scmd_priv * cmd_priv )
2951+ u8 * resp_code , struct scsi_cmnd * scmd )
28722952{
28732953 struct mpi3_scsi_task_mgmt_request tm_req ;
28742954 struct mpi3_scsi_task_mgmt_reply * tm_reply = NULL ;
28752955 int retval = 0 ;
28762956 struct mpi3mr_tgt_dev * tgtdev = NULL ;
28772957 struct mpi3mr_stgt_priv_data * scsi_tgt_priv_data = NULL ;
2878- struct op_req_qinfo * op_req_q = NULL ;
2958+ struct scmd_priv * cmd_priv = NULL ;
2959+ struct scsi_device * sdev = NULL ;
2960+ struct mpi3mr_sdev_priv_data * sdev_priv_data = NULL ;
28792961
28802962 ioc_info (mrioc , "%s :Issue TM: TM type (0x%x) for devhandle 0x%04x\n" ,
28812963 __func__ , tm_type , handle );
@@ -2912,16 +2994,21 @@ static int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
29122994 tm_req .function = MPI3_FUNCTION_SCSI_TASK_MGMT ;
29132995
29142996 tgtdev = mpi3mr_get_tgtdev_by_handle (mrioc , handle );
2915- if (tgtdev && tgtdev -> starget && tgtdev -> starget -> hostdata ) {
2916- scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data * )
2917- tgtdev -> starget -> hostdata ;
2918- atomic_inc (& scsi_tgt_priv_data -> block_io );
2919- }
2920- if (cmd_priv ) {
2921- op_req_q = & mrioc -> req_qinfo [cmd_priv -> req_q_idx ];
2922- tm_req .task_host_tag = cpu_to_le16 (cmd_priv -> host_tag );
2923- tm_req .task_request_queue_id = cpu_to_le16 (op_req_q -> qid );
2997+
2998+ if (scmd ) {
2999+ sdev = scmd -> device ;
3000+ sdev_priv_data = sdev -> hostdata ;
3001+ scsi_tgt_priv_data = ((sdev_priv_data ) ?
3002+ sdev_priv_data -> tgt_priv_data : NULL );
3003+ } else {
3004+ if (tgtdev && tgtdev -> starget && tgtdev -> starget -> hostdata )
3005+ scsi_tgt_priv_data = (struct mpi3mr_stgt_priv_data * )
3006+ tgtdev -> starget -> hostdata ;
29243007 }
3008+
3009+ if (scsi_tgt_priv_data )
3010+ atomic_inc (& scsi_tgt_priv_data -> block_io );
3011+
29253012 if (tgtdev && (tgtdev -> dev_type == MPI3_DEVICE_DEVFORM_PCIE )) {
29263013 if (cmd_priv && tgtdev -> dev_spec .pcie_inf .abort_to )
29273014 timeout = tgtdev -> dev_spec .pcie_inf .abort_to ;
@@ -2938,35 +3025,44 @@ static int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
29383025 wait_for_completion_timeout (& drv_cmd -> done , (timeout * HZ ));
29393026
29403027 if (!(drv_cmd -> state & MPI3MR_CMD_COMPLETE )) {
2941- ioc_err (mrioc , "%s :Issue TM: command timed out\n" , __func__ );
29423028 drv_cmd -> is_waiting = 0 ;
29433029 retval = -1 ;
2944- if (!(drv_cmd -> state & MPI3MR_CMD_RESET ))
3030+ if (!(drv_cmd -> state & MPI3MR_CMD_RESET )) {
3031+ dprint_tm (mrioc ,
3032+ "task management request timed out after %ld seconds\n" ,
3033+ timeout );
3034+ if (mrioc -> logging_level & MPI3_DEBUG_TM )
3035+ dprint_dump_req (& tm_req , sizeof (tm_req )/4 );
29453036 mpi3mr_soft_reset_handler (mrioc ,
29463037 MPI3MR_RESET_FROM_TM_TIMEOUT , 1 );
3038+ }
29473039 goto out_unlock ;
29483040 }
29493041
2950- if (drv_cmd -> state & MPI3MR_CMD_REPLY_VALID )
2951- tm_reply = (struct mpi3_scsi_task_mgmt_reply * )drv_cmd -> reply ;
2952-
2953- if (drv_cmd -> ioc_status != MPI3_IOCSTATUS_SUCCESS ) {
2954- ioc_err (mrioc ,
2955- "%s :Issue TM: handle(0x%04x) Failed ioc_status(0x%04x) Loginfo(0x%08x)\n" ,
2956- __func__ , handle , drv_cmd -> ioc_status ,
2957- drv_cmd -> ioc_loginfo );
3042+ if (!(drv_cmd -> state & MPI3MR_CMD_REPLY_VALID )) {
3043+ dprint_tm (mrioc , "invalid task management reply message\n" );
29583044 retval = -1 ;
29593045 goto out_unlock ;
29603046 }
29613047
2962- if (!tm_reply ) {
2963- ioc_err (mrioc , "%s :Issue TM: No TM Reply message\n" , __func__ );
3048+ tm_reply = (struct mpi3_scsi_task_mgmt_reply * )drv_cmd -> reply ;
3049+
3050+ switch (drv_cmd -> ioc_status ) {
3051+ case MPI3_IOCSTATUS_SUCCESS :
3052+ * resp_code = le32_to_cpu (tm_reply -> response_data ) &
3053+ MPI3MR_RI_MASK_RESPCODE ;
3054+ break ;
3055+ case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED :
3056+ * resp_code = MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE ;
3057+ break ;
3058+ default :
3059+ dprint_tm (mrioc ,
3060+ "task management request to handle(0x%04x) is failed with ioc_status(0x%04x) log_info(0x%08x)\n" ,
3061+ handle , drv_cmd -> ioc_status , drv_cmd -> ioc_loginfo );
29643062 retval = -1 ;
29653063 goto out_unlock ;
29663064 }
29673065
2968- * resp_code = le32_to_cpu (tm_reply -> response_data ) &
2969- MPI3MR_RI_MASK_RESPCODE ;
29703066 switch (* resp_code ) {
29713067 case MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED :
29723068 case MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE :
@@ -2986,21 +3082,39 @@ static int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
29863082 le32_to_cpu (tm_reply -> termination_count ),
29873083 mpi3mr_tm_response_name (* resp_code ), * resp_code );
29883084
3085+ if (!retval ) {
3086+ mpi3mr_ioc_disable_intr (mrioc );
3087+ mpi3mr_poll_pend_io_completions (mrioc );
3088+ mpi3mr_ioc_enable_intr (mrioc );
3089+ mpi3mr_poll_pend_io_completions (mrioc );
3090+ }
3091+ switch (tm_type ) {
3092+ case MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET :
3093+ if (!scsi_tgt_priv_data )
3094+ break ;
3095+ scsi_tgt_priv_data -> pend_count = 0 ;
3096+ blk_mq_tagset_busy_iter (& mrioc -> shost -> tag_set ,
3097+ mpi3mr_count_tgt_pending ,
3098+ (void * )scsi_tgt_priv_data -> starget );
3099+ break ;
3100+ case MPI3_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET :
3101+ if (!sdev_priv_data )
3102+ break ;
3103+ sdev_priv_data -> pend_count = 0 ;
3104+ blk_mq_tagset_busy_iter (& mrioc -> shost -> tag_set ,
3105+ mpi3mr_count_dev_pending , (void * )sdev );
3106+ break ;
3107+ default :
3108+ break ;
3109+ }
3110+
29893111out_unlock :
29903112 drv_cmd -> state = MPI3MR_CMD_NOTUSED ;
29913113 mutex_unlock (& drv_cmd -> mutex );
29923114 if (scsi_tgt_priv_data )
29933115 atomic_dec_if_positive (& scsi_tgt_priv_data -> block_io );
29943116 if (tgtdev )
29953117 mpi3mr_tgtdev_put (tgtdev );
2996- if (!retval ) {
2997- /*
2998- * Flush all IRQ handlers by calling synchronize_irq().
2999- * mpi3mr_ioc_disable_intr() takes care of it.
3000- */
3001- mpi3mr_ioc_disable_intr (mrioc );
3002- mpi3mr_ioc_enable_intr (mrioc );
3003- }
30043118out :
30053119 return retval ;
30063120}
@@ -3250,22 +3364,36 @@ static int mpi3mr_eh_target_reset(struct scsi_cmnd *scmd)
32503364
32513365 stgt_priv_data = sdev_priv_data -> tgt_priv_data ;
32523366 dev_handle = stgt_priv_data -> dev_handle ;
3367+ if (stgt_priv_data -> dev_removed ) {
3368+ sdev_printk (KERN_INFO , scmd -> device ,
3369+ "%s:target(handle = 0x%04x) is removed, target reset is not issued\n" ,
3370+ mrioc -> name , dev_handle );
3371+ retval = FAILED ;
3372+ goto out ;
3373+ }
32533374 sdev_printk (KERN_INFO , scmd -> device ,
32543375 "Target Reset is issued to handle(0x%04x)\n" ,
32553376 dev_handle );
32563377
32573378 ret = mpi3mr_issue_tm (mrioc ,
32583379 MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET , dev_handle ,
32593380 sdev_priv_data -> lun_id , MPI3MR_HOSTTAG_BLK_TMS ,
3260- MPI3MR_RESETTM_TIMEOUT , & mrioc -> host_tm_cmds , & resp_code , NULL );
3381+ MPI3MR_RESETTM_TIMEOUT , & mrioc -> host_tm_cmds , & resp_code , scmd );
32613382
32623383 if (ret )
32633384 goto out ;
32643385
3386+ if (stgt_priv_data -> pend_count ) {
3387+ sdev_printk (KERN_INFO , scmd -> device ,
3388+ "%s: target has %d pending commands, target reset is failed\n" ,
3389+ mrioc -> name , sdev_priv_data -> pend_count );
3390+ goto out ;
3391+ }
3392+
32653393 retval = SUCCESS ;
32663394out :
32673395 sdev_printk (KERN_INFO , scmd -> device ,
3268- "Target reset is %s for scmd(%p)\n" ,
3396+ "%s: target reset is %s for scmd(%p)\n" , mrioc -> name ,
32693397 ((retval == SUCCESS ) ? "SUCCESS" : "FAILED" ), scmd );
32703398
32713399 return retval ;
@@ -3304,21 +3432,34 @@ static int mpi3mr_eh_dev_reset(struct scsi_cmnd *scmd)
33043432
33053433 stgt_priv_data = sdev_priv_data -> tgt_priv_data ;
33063434 dev_handle = stgt_priv_data -> dev_handle ;
3435+ if (stgt_priv_data -> dev_removed ) {
3436+ sdev_printk (KERN_INFO , scmd -> device ,
3437+ "%s: device(handle = 0x%04x) is removed, device(LUN) reset is not issued\n" ,
3438+ mrioc -> name , dev_handle );
3439+ retval = FAILED ;
3440+ goto out ;
3441+ }
33073442 sdev_printk (KERN_INFO , scmd -> device ,
33083443 "Device(lun) Reset is issued to handle(0x%04x)\n" , dev_handle );
33093444
33103445 ret = mpi3mr_issue_tm (mrioc ,
33113446 MPI3_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET , dev_handle ,
33123447 sdev_priv_data -> lun_id , MPI3MR_HOSTTAG_BLK_TMS ,
3313- MPI3MR_RESETTM_TIMEOUT , & mrioc -> host_tm_cmds , & resp_code , NULL );
3448+ MPI3MR_RESETTM_TIMEOUT , & mrioc -> host_tm_cmds , & resp_code , scmd );
33143449
33153450 if (ret )
33163451 goto out ;
33173452
3453+ if (sdev_priv_data -> pend_count ) {
3454+ sdev_printk (KERN_INFO , scmd -> device ,
3455+ "%s: device has %d pending commands, device(LUN) reset is failed\n" ,
3456+ mrioc -> name , sdev_priv_data -> pend_count );
3457+ goto out ;
3458+ }
33183459 retval = SUCCESS ;
33193460out :
33203461 sdev_printk (KERN_INFO , scmd -> device ,
3321- "Device(lun ) reset is %s for scmd(%p)\n" ,
3462+ "%s: device(LUN ) reset is %s for scmd(%p)\n" , mrioc -> name ,
33223463 ((retval == SUCCESS ) ? "SUCCESS" : "FAILED" ), scmd );
33233464
33243465 return retval ;
0 commit comments