FreeBSD/sys/dev/mps/mps.c
/*
 * The locking is overly broad and simplistic, but easy to deal with for now.
 */
The locking is overly broad and simplistic, but easy to deal with for now.
The locking is overly broad and simplistic but easy to deal with for now .
void
mps_intr_locked(void *data)
{
	MPI2_REPLY_DESCRIPTORS_UNION *desc;
	struct mps_softc *sc;
	struct mps_command *cm = NULL;
	uint8_t flags;
	u_int pq;
	MPI2_DIAG_RELEASE_REPLY *rel_rep;
	mps_fw_diagnostic_buffer_t *pBuffer;
	sc = (struct mps_softc *)data;
	pq = sc->replypostindex;
	mps_dprint(sc, MPS_TRACE,
	    "%s sc %p starting with replypostindex %u\n", 
	    __func__, sc, sc->replypostindex);
	for ( ;; ) {
		cm = NULL;
		desc = &sc->post_queue[sc->replypostindex];
		flags = desc->Default.ReplyFlags &
		    MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
		if ((flags == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
		 || (le32toh(desc->Words.High) == 0xffffffff))
			break;
		if (++sc->replypostindex >= sc->pqdepth)
			sc->replypostindex = 0;
		switch (flags) {
		case MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS:
			cm = &sc->commands[le16toh(desc->SCSIIOSuccess.SMID)];
			cm->cm_reply = NULL;
			break;
		case MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY:
		{
			uint32_t baddr;
			uint8_t *reply;
			baddr = le32toh(desc->AddressReply.ReplyFrameAddress);
			reply = sc->reply_frames +
				(baddr - ((uint32_t)sc->reply_busaddr));
			if ((reply < sc->reply_frames)
			 || (reply > (sc->reply_frames +
			     (sc->fqdepth * sc->facts->ReplyFrameSize * 4)))) {
				printf("%s: WARNING: reply %p out of range!\n",
				       __func__, reply);
				printf("%s: reply_frames %p, fqdepth %d, "
				       "frame size %d\n", __func__,
				       sc->reply_frames, sc->fqdepth,
				       sc->facts->ReplyFrameSize * 4);
				printf("%s: baddr %#x,\n", __func__, baddr);
				panic("Reply address out of range");
			}
			if (le16toh(desc->AddressReply.SMID) == 0) {
				if (((MPI2_DEFAULT_REPLY *)reply)->Function ==
				    MPI2_FUNCTION_DIAG_BUFFER_POST) {
					rel_rep =
					    (MPI2_DIAG_RELEASE_REPLY *)reply;
					if ((le16toh(rel_rep->IOCStatus) &
					    MPI2_IOCSTATUS_MASK) ==
					    MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED)
					{
						pBuffer =
						    &sc->fw_diag_buffer_list[
						    rel_rep->BufferType];
						pBuffer->valid_data = TRUE;
						pBuffer->owned_by_firmware =
						    FALSE;
						pBuffer->immediate = FALSE;
					}
				} else
					mps_dispatch_event(sc, baddr,
					    (MPI2_EVENT_NOTIFICATION_REPLY *)
					    reply);
			} else {
				cm = &sc->commands[le16toh(desc->AddressReply.SMID)];
				cm->cm_reply = reply;
				cm->cm_reply_data =
				    le32toh(desc->AddressReply.ReplyFrameAddress);
			}
			break;
		}
		case MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS:
		case MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER:
		case MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS:
		default:
			mps_dprint(sc, MPS_ERROR, "Unhandled reply 0x%x\n",
			    desc->Default.ReplyFlags);
			cm = NULL;
			break;
		}
		if (cm != NULL) {
			if (cm->cm_reply)
				mps_display_reply_info(sc,cm->cm_reply);
			mps_complete_command(sc, cm);
		}
		desc->Words.Low = 0xffffffff;
		desc->Words.High = 0xffffffff;
	}
	if (pq != sc->replypostindex) {
		mps_dprint(sc, MPS_TRACE,
		    "%s sc %p writing postindex %d\n",
		    __func__, sc, sc->replypostindex);
		mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, sc->replypostindex);
	}
	return;
}
void mps_intr_locked ( void * data ) { MPI2_REPLY_DESCRIPTORS_UNION * desc ; struct mps_softc * sc ; struct mps_command * cm = NULL ; uint8_t flags ; u_int pq ; MPI2_DIAG_RELEASE_REPLY * rel_rep ; mps_fw_diagnostic_buffer_t * pBuffer ; sc = ( struct mps_softc * ) data ; pq = sc -> replypostindex ; mps_dprint ( sc , MPS_TRACE , " \n " , __func__ , sc , sc -> replypostindex ) ; for ( ; ; ) { cm = NULL ; desc = & sc -> post_queue [ sc -> replypostindex ] ; flags = desc -> Default . ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK ; if ( ( flags == MPI2_RPY_DESCRIPT_FLAGS_UNUSED ) || ( le32toh ( desc -> Words . High ) == 0xffffffff ) ) break ; if ( ++ sc -> replypostindex >= sc -> pqdepth ) sc -> replypostindex = 0 ; switch ( flags ) { case MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS : cm = & sc -> commands [ le16toh ( desc -> SCSIIOSuccess . SMID ) ] ; cm -> cm_reply = NULL ; break ; case MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY : { uint32_t baddr ; uint8_t * reply ; baddr = le32toh ( desc -> AddressReply . ReplyFrameAddress ) ; reply = sc -> reply_frames + ( baddr - ( ( uint32_t ) sc -> reply_busaddr ) ) ; if ( ( reply < sc -> reply_frames ) || ( reply > ( sc -> reply_frames + ( sc -> fqdepth * sc -> facts -> ReplyFrameSize * 4 ) ) ) ) { printf ( " \n " , __func__ , reply ) ; printf ( " " " \n " , __func__ , sc -> reply_frames , sc -> fqdepth , sc -> facts -> ReplyFrameSize * 4 ) ; printf ( " \n " , __func__ , baddr ) ; panic ( " " ) ; } if ( le16toh ( desc -> AddressReply . SMID ) == 0 ) { if ( ( ( MPI2_DEFAULT_REPLY * ) reply ) -> Function == MPI2_FUNCTION_DIAG_BUFFER_POST ) { rel_rep = ( MPI2_DIAG_RELEASE_REPLY * ) reply ; if ( ( le16toh ( rel_rep -> IOCStatus ) & MPI2_IOCSTATUS_MASK ) == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED ) { pBuffer = & sc -> fw_diag_buffer_list [ rel_rep -> BufferType ] ; pBuffer -> valid_data = TRUE ; pBuffer -> owned_by_firmware = FALSE ; pBuffer -> immediate = FALSE ; } } else mps_dispatch_event ( sc , baddr , ( MPI2_EVENT_NOTIFICATION_REPLY * ) reply ) ; } else { cm = & sc -> commands [ le16toh ( desc -> AddressReply . SMID ) ] ; cm -> cm_reply = reply ; cm -> cm_reply_data = le32toh ( desc -> AddressReply . ReplyFrameAddress ) ; } break ; } case MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS : case MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER : case MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS : default : mps_dprint ( sc , MPS_ERROR , " \n " , desc -> Default . ReplyFlags ) ; cm = NULL ; break ; } if ( cm != NULL ) { if ( cm -> cm_reply ) mps_display_reply_info ( sc , cm -> cm_reply ) ; mps_complete_command ( sc , cm ) ; } desc -> Words . Low = 0xffffffff ; desc -> Words . High = 0xffffffff ; } if ( pq != sc -> replypostindex ) { mps_dprint ( sc , MPS_TRACE , " \n " , __func__ , sc , sc -> replypostindex ) ; mps_regwrite ( sc , MPI2_REPLY_POST_HOST_INDEX_OFFSET , sc -> replypostindex ) ; } return ; }
The locking is overly broad and simplistic, but easy to deal with for now.
The locking is overly broad and simplistic but easy to deal with for now .
/* increment the replypostindex now, so that event handlers
		 * and cm completion handlers which decide to do a diag
		 * reset can zero it without it getting incremented again
		 * afterwards, and we break out of this loop on the next
		 * iteration since the reply post queue has been cleared to
		 * 0xFF and all descriptors look unused (which they are).
		 */ /*
			 * Re-compose the reply address from the address
			 * sent back from the chip.  The ReplyFrameAddress
			 * is the lower 32 bits of the physical address of
			 * particular reply frame.  Convert that address to
			 * host format, and then use that to provide the
			 * offset against the virtual address base
			 * (sc->reply_frames).
			 */ /*
			 * Make sure the reply we got back is in a valid
			 * range.  If not, go ahead and panic here, since
			 * we'll probably panic as soon as we deference the
			 * reply pointer anyway.
			 */ /* LSI-TODO. See Linux Code. Need Graceful exit*/ /*
					 * If SMID is 0 for Diag Buffer Post,
					 * this implies that the reply is due to
					 * a release function with a status that
					 * the buffer has been released.  Set
					 * the buffer flags accordingly.
					 */ /* Unhandled */ // Print Error reply frame