FreeBSD/sys/dev/mrsas/mrsas.c
/*
 * mrsas_complete_cmd:	Process reply request
 * input:				Adapter instance soft state
 *
 * This function is called from mrsas_isr() to process reply request and clear
 * response interrupt. Processing of the reply request entails walking
 * through the reply descriptor array for the command request  pended from
 * Firmware.  We look at the Function field to determine the command type and
 * perform the appropriate action.  Before we return, we clear the response
 * interrupt.
 */
Process reply request
input:                               Adapter instance soft state

This function is called from mrsas_isr() to process reply request and clear
response interrupt. Processing of the reply request entails walking
through the reply descriptor array for the command request  pended from
Firmware.  We look at the Function field to determine the command type and
perform the appropriate action.  Before we return, we clear the response
interrupt.
Process reply request input : Adapter instance soft state This function is called from mrsas_isr () to process reply request and clear response interrupt . Processing of the reply request entails walking through the reply descriptor array for the command request pended from Firmware . We look at the Function field to determine the command type and perform the appropriate action . Before we return we clear the response interrupt .
int
mrsas_complete_cmd(struct mrsas_softc *sc, u_int32_t MSIxIndex)
{
	Mpi2ReplyDescriptorsUnion_t *desc;
	MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc;
	MRSAS_RAID_SCSI_IO_REQUEST *scsi_io_req;
	struct mrsas_mpt_cmd *cmd_mpt;
	struct mrsas_mfi_cmd *cmd_mfi;
	u_int8_t reply_descript_type;
	u_int16_t smid, num_completed;
	u_int8_t status, extStatus;
	union desc_value desc_val;
	PLD_LOAD_BALANCE_INFO lbinfo;
	u_int32_t device_id;
	int threshold_reply_count = 0;
	if (sc->adprecovery == MRSAS_HW_CRITICAL_ERROR)
		return (DONE);
	desc = sc->reply_desc_mem;
	desc += ((MSIxIndex * sc->reply_alloc_sz) / sizeof(MPI2_REPLY_DESCRIPTORS_UNION))
	    + sc->last_reply_idx[MSIxIndex];
	reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *) desc;
	desc_val.word = desc->Words;
	num_completed = 0;
	reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
	while ((desc_val.u.low != 0xFFFFFFFF) && (desc_val.u.high != 0xFFFFFFFF)) {
		smid = reply_desc->SMID;
		cmd_mpt = sc->mpt_cmd_list[smid - 1];
		scsi_io_req = (MRSAS_RAID_SCSI_IO_REQUEST *) cmd_mpt->io_request;
		status = scsi_io_req->RaidContext.status;
		extStatus = scsi_io_req->RaidContext.exStatus;
		switch (scsi_io_req->Function) {
		case MPI2_FUNCTION_SCSI_IO_REQUEST:	
			device_id = cmd_mpt->ccb_ptr->ccb_h.target_id;
			lbinfo = &sc->load_balance_info[device_id];
			if (cmd_mpt->load_balance == MRSAS_LOAD_BALANCE_FLAG) {
				mrsas_atomic_dec(&lbinfo->scsi_pending_cmds[cmd_mpt->pd_r1_lb]);
				cmd_mpt->load_balance &= ~MRSAS_LOAD_BALANCE_FLAG;
			}
		case MRSAS_MPI2_FUNCTION_LD_IO_REQUEST:
			mrsas_map_mpt_cmd_status(cmd_mpt, status, extStatus);
			mrsas_cmd_done(sc, cmd_mpt);
			scsi_io_req->RaidContext.status = 0;
			scsi_io_req->RaidContext.exStatus = 0;
			mrsas_atomic_dec(&sc->fw_outstanding);
			break;
		case MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST:	
			cmd_mfi = sc->mfi_cmd_list[cmd_mpt->sync_cmd_idx];
			mrsas_complete_mptmfi_passthru(sc, cmd_mfi, status);
			cmd_mpt->flags = 0;
			mrsas_release_mpt_cmd(cmd_mpt);
			break;
		}
		sc->last_reply_idx[MSIxIndex]++;
		if (sc->last_reply_idx[MSIxIndex] >= sc->reply_q_depth)
			sc->last_reply_idx[MSIxIndex] = 0;
		desc->Words = ~((uint64_t)0x00);	
		num_completed++;
		threshold_reply_count++;
		if (!sc->last_reply_idx[MSIxIndex]) {
			desc = sc->reply_desc_mem;
			desc += ((MSIxIndex * sc->reply_alloc_sz) / sizeof(MPI2_REPLY_DESCRIPTORS_UNION));
		} else
			desc++;
		reply_desc = (MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *) desc;
		desc_val.word = desc->Words;
		reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
		if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
			break;
		if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
			if (sc->msix_enable) {
				if ((sc->device_id == MRSAS_INVADER) ||
				    (sc->device_id == MRSAS_FURY) ||
				    (sc->device_id == MRSAS_INTRUDER) ||
				    (sc->device_id == MRSAS_INTRUDER_24) ||
				    (sc->device_id == MRSAS_CUTLASS_52) ||
				    (sc->device_id == MRSAS_CUTLASS_53))
					mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8],
					    ((MSIxIndex & 0x7) << 24) |
					    sc->last_reply_idx[MSIxIndex]);
				else
					mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) |
					    sc->last_reply_idx[MSIxIndex]);
			} else
				mrsas_write_reg(sc, offsetof(mrsas_reg_set,
				    reply_post_host_index), sc->last_reply_idx[0]);
			threshold_reply_count = 0;
		}
	}
	if (num_completed == 0)
		return (DONE);
	if (sc->msix_enable) {
		if ((sc->device_id == MRSAS_INVADER) ||
		    (sc->device_id == MRSAS_FURY) ||
		    (sc->device_id == MRSAS_INTRUDER) ||
		    (sc->device_id == MRSAS_INTRUDER_24) ||
		    (sc->device_id == MRSAS_CUTLASS_52) ||
		    (sc->device_id == MRSAS_CUTLASS_53)) {
			mrsas_write_reg(sc, sc->msix_reg_offset[MSIxIndex / 8],
			    ((MSIxIndex & 0x7) << 24) |
			    sc->last_reply_idx[MSIxIndex]);
		} else
			mrsas_write_reg(sc, sc->msix_reg_offset[0], (MSIxIndex << 24) |
			    sc->last_reply_idx[MSIxIndex]);
	} else
		mrsas_write_reg(sc, offsetof(mrsas_reg_set,
		    reply_post_host_index), sc->last_reply_idx[0]);
	return (0);
}
int mrsas_complete_cmd ( struct mrsas_softc * sc , u_int32_t MSIxIndex ) { Mpi2ReplyDescriptorsUnion_t * desc ; MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR * reply_desc ; MRSAS_RAID_SCSI_IO_REQUEST * scsi_io_req ; struct mrsas_mpt_cmd * cmd_mpt ; struct mrsas_mfi_cmd * cmd_mfi ; u_int8_t reply_descript_type ; u_int16_t smid , num_completed ; u_int8_t status , extStatus ; union desc_value desc_val ; PLD_LOAD_BALANCE_INFO lbinfo ; u_int32_t device_id ; int threshold_reply_count = 0 ; if ( sc -> adprecovery == MRSAS_HW_CRITICAL_ERROR ) return ( DONE ) ; desc = sc -> reply_desc_mem ; desc += ( ( MSIxIndex * sc -> reply_alloc_sz ) / sizeof ( MPI2_REPLY_DESCRIPTORS_UNION ) ) + sc -> last_reply_idx [ MSIxIndex ] ; reply_desc = ( MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR * ) desc ; desc_val . word = desc -> Words ; num_completed = 0 ; reply_descript_type = reply_desc -> ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK ; while ( ( desc_val . u . low != 0xFFFFFFFF ) && ( desc_val . u . high != 0xFFFFFFFF ) ) { smid = reply_desc -> SMID ; cmd_mpt = sc -> mpt_cmd_list [ smid - 1 ] ; scsi_io_req = ( MRSAS_RAID_SCSI_IO_REQUEST * ) cmd_mpt -> io_request ; status = scsi_io_req -> RaidContext . status ; extStatus = scsi_io_req -> RaidContext . exStatus ; switch ( scsi_io_req -> Function ) { case MPI2_FUNCTION_SCSI_IO_REQUEST : device_id = cmd_mpt -> ccb_ptr -> ccb_h . target_id ; lbinfo = & sc -> load_balance_info [ device_id ] ; if ( cmd_mpt -> load_balance == MRSAS_LOAD_BALANCE_FLAG ) { mrsas_atomic_dec ( & lbinfo -> scsi_pending_cmds [ cmd_mpt -> pd_r1_lb ] ) ; cmd_mpt -> load_balance &= ~ MRSAS_LOAD_BALANCE_FLAG ; } case MRSAS_MPI2_FUNCTION_LD_IO_REQUEST : mrsas_map_mpt_cmd_status ( cmd_mpt , status , extStatus ) ; mrsas_cmd_done ( sc , cmd_mpt ) ; scsi_io_req -> RaidContext . status = 0 ; scsi_io_req -> RaidContext . exStatus = 0 ; mrsas_atomic_dec ( & sc -> fw_outstanding ) ; break ; case MRSAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST : cmd_mfi = sc -> mfi_cmd_list [ cmd_mpt -> sync_cmd_idx ] ; mrsas_complete_mptmfi_passthru ( sc , cmd_mfi , status ) ; cmd_mpt -> flags = 0 ; mrsas_release_mpt_cmd ( cmd_mpt ) ; break ; } sc -> last_reply_idx [ MSIxIndex ] ++ ; if ( sc -> last_reply_idx [ MSIxIndex ] >= sc -> reply_q_depth ) sc -> last_reply_idx [ MSIxIndex ] = 0 ; desc -> Words = ~ ( ( uint64_t ) 0x00 ) ; num_completed ++ ; threshold_reply_count ++ ; if ( ! sc -> last_reply_idx [ MSIxIndex ] ) { desc = sc -> reply_desc_mem ; desc += ( ( MSIxIndex * sc -> reply_alloc_sz ) / sizeof ( MPI2_REPLY_DESCRIPTORS_UNION ) ) ; } else desc ++ ; reply_desc = ( MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR * ) desc ; desc_val . word = desc -> Words ; reply_descript_type = reply_desc -> ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK ; if ( reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED ) break ; if ( threshold_reply_count >= THRESHOLD_REPLY_COUNT ) { if ( sc -> msix_enable ) { if ( ( sc -> device_id == MRSAS_INVADER ) || ( sc -> device_id == MRSAS_FURY ) || ( sc -> device_id == MRSAS_INTRUDER ) || ( sc -> device_id == MRSAS_INTRUDER_24 ) || ( sc -> device_id == MRSAS_CUTLASS_52 ) || ( sc -> device_id == MRSAS_CUTLASS_53 ) ) mrsas_write_reg ( sc , sc -> msix_reg_offset [ MSIxIndex / 8 ] , ( ( MSIxIndex & 0x7 ) << 24 ) | sc -> last_reply_idx [ MSIxIndex ] ) ; else mrsas_write_reg ( sc , sc -> msix_reg_offset [ 0 ] , ( MSIxIndex << 24 ) | sc -> last_reply_idx [ MSIxIndex ] ) ; } else mrsas_write_reg ( sc , offsetof ( mrsas_reg_set , reply_post_host_index ) , sc -> last_reply_idx [ 0 ] ) ; threshold_reply_count = 0 ; } } if ( num_completed == 0 ) return ( DONE ) ; if ( sc -> msix_enable ) { if ( ( sc -> device_id == MRSAS_INVADER ) || ( sc -> device_id == MRSAS_FURY ) || ( sc -> device_id == MRSAS_INTRUDER ) || ( sc -> device_id == MRSAS_INTRUDER_24 ) || ( sc -> device_id == MRSAS_CUTLASS_52 ) || ( sc -> device_id == MRSAS_CUTLASS_53 ) ) { mrsas_write_reg ( sc , sc -> msix_reg_offset [ MSIxIndex / 8 ] , ( ( MSIxIndex & 0x7 ) << 24 ) | sc -> last_reply_idx [ MSIxIndex ] ) ; } else mrsas_write_reg ( sc , sc -> msix_reg_offset [ 0 ] , ( MSIxIndex << 24 ) | sc -> last_reply_idx [ MSIxIndex ] ) ; } else mrsas_write_reg ( sc , offsetof ( mrsas_reg_set , reply_post_host_index ) , sc -> last_reply_idx [ 0 ] ) ; return ( 0 ) ; }
mrsas_complete_cmd:  Process reply request
 input:                               Adapter instance soft state
mrsas_complete_cmd : Process reply request input : Adapter instance soft state
/* If we have a hardware error, not need to continue */ /* Find our reply descriptor for the command and process */ /* Fast Path IO. */ /* Fall thru and complete IO */ /* MFI command */ /* set it back to all
							 * 0xFFFFFFFFs */ /* Get the next reply descriptor */ /*
		 * Write to reply post index after completing threshold reply
		 * count and still there are more replies in reply queue
		 * pending to be completed.
		 */ /* No match, just return */ /* Clear response interrupt */