Beispiel #1
0
static u_int64_t
get_row_from_strip(struct mrsas_softc *sc,
    u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map)
{
	MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
	LD_SPAN_SET *span_set;
	PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
	u_int32_t info, strip_offset, span, span_offset;
	u_int64_t span_set_Strip, span_set_Row;

	for (info = 0; info < MAX_QUAD_DEPTH; info++) {
		span_set = &(ldSpanInfo[ld].span_set[info]);

		if (span_set->span_row_data_width == 0)
			break;
		if (strip > span_set->data_strip_end)
			continue;

		span_set_Strip = strip - span_set->data_strip_start;
		strip_offset = mega_mod64(span_set_Strip,
		    span_set->span_row_data_width);
		span_set_Row = mega_div64_32(span_set_Strip,
		    span_set->span_row_data_width) * span_set->diff;
		for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
			if (map->raidMap.ldSpanMap[ld].spanBlock[span].
			    block_span_info.noElements >= info + 1) {
				if (strip_offset >=
				    span_set->strip_offset[span])
					span_offset++;
				else
					break;
			}
		mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : Strip 0x%llx, span_set_Strip 0x%llx, span_set_Row 0x%llx "
		    "data width 0x%llx span offset 0x%llx\n", (unsigned long long)strip,
		    (unsigned long long)span_set_Strip,
		    (unsigned long long)span_set_Row,
		    (unsigned long long)span_set->span_row_data_width, (unsigned long long)span_offset);
		mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : For strip 0x%llx row is 0x%llx\n", (unsigned long long)strip,
		    (unsigned long long)span_set->data_row_start +
		    (unsigned long long)span_set_Row + (span_offset - 1));
		return (span_set->data_row_start + span_set_Row + (span_offset - 1));
	}
	return -1LLU;
}
Beispiel #2
0
static u_int32_t
get_arm_from_strip(struct mrsas_softc *sc,
    u_int32_t ld, u_int64_t strip, MR_DRV_RAID_MAP_ALL * map)
{
	MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
	LD_SPAN_SET *span_set;
	PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
	u_int32_t info, strip_offset, span, span_offset;

	for (info = 0; info < MAX_QUAD_DEPTH; info++) {
		span_set = &(ldSpanInfo[ld].span_set[info]);

		if (span_set->span_row_data_width == 0)
			break;
		if (strip > span_set->data_strip_end)
			continue;

		strip_offset = (u_int32_t)mega_mod64
		    ((strip - span_set->data_strip_start),
		    span_set->span_row_data_width);

		for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
			if (map->raidMap.ldSpanMap[ld].spanBlock[span].
			    block_span_info.noElements >= info + 1) {
				if (strip_offset >= span_set->strip_offset[span])
					span_offset = span_set->strip_offset[span];
				else
					break;
			}
		mrsas_dprint(sc, MRSAS_PRL11, "LSI PRL11: get_arm_from_strip: "
		    "for ld=0x%x strip=0x%lx arm is  0x%x\n", ld,
		    (long unsigned int)strip, (strip_offset - span_offset));
		return (strip_offset - span_offset);
	}

	mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: - get_arm_from_strip: returns invalid arm"
	    " for ld=%x strip=%lx\n", ld, (long unsigned int)strip);

	return -1;
}
Beispiel #3
0
static u_int64_t
get_strip_from_row(struct mrsas_softc *sc,
    u_int32_t ld, u_int64_t row, MR_DRV_RAID_MAP_ALL * map)
{
	MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
	LD_SPAN_SET *span_set;
	MR_QUAD_ELEMENT *quad;
	PLD_SPAN_INFO ldSpanInfo = sc->log_to_span;
	u_int32_t span, info;
	u_int64_t strip;

	for (info = 0; info < MAX_QUAD_DEPTH; info++) {
		span_set = &(ldSpanInfo[ld].span_set[info]);

		if (span_set->span_row_data_width == 0)
			break;
		if (row > span_set->data_row_end)
			continue;

		for (span = 0; span < raid->spanDepth; span++)
			if (map->raidMap.ldSpanMap[ld].spanBlock[span].
			    block_span_info.noElements >= info + 1) {
				quad = &map->raidMap.ldSpanMap[ld].
				    spanBlock[span].block_span_info.quad[info];
				if (quad->logStart <= row &&
				    row <= quad->logEnd &&
				    mega_mod64((row - quad->logStart),
				    quad->diff) == 0) {
					strip = mega_div64_32
					    (((row - span_set->data_row_start)
					    - quad->logStart),
					    quad->diff);
					strip *= span_set->span_row_data_width;
					strip += span_set->data_strip_start;
					strip += span_set->strip_offset[span];
					return strip;
				}
			}
	}
	mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug - get_strip_from_row: returns invalid "
	    "strip for ld=%x, row=%lx\n", ld, (long unsigned int)row);
	return -1;
}
/**
 * mrsas_setup_io:             Set up data including Fast Path I/O  
 * input:                      Adapter instance soft state
 *                             Pointer to command packet
 *                             Pointer to CCB 
 *
 * This function builds the DCDB inquiry command.  It returns 0 if the 
 * command is built successfully, otherwise it returns a 1. 
 */
int mrsas_setup_io(struct mrsas_softc *sc, struct mrsas_mpt_cmd *cmd,
                    union ccb *ccb, u_int32_t device_id,
                    MRSAS_RAID_SCSI_IO_REQUEST *io_request)
{
    struct ccb_hdr *ccb_h = &(ccb->ccb_h);
    struct ccb_scsiio *csio = &(ccb->csio);
    struct IO_REQUEST_INFO io_info;
    MR_FW_RAID_MAP_ALL *map_ptr;
    u_int8_t fp_possible;
    u_int32_t start_lba_hi, start_lba_lo, ld_block_size;
    u_int32_t datalength = 0;
     
    start_lba_lo = 0;
    start_lba_hi = 0;
    fp_possible = 0;
     
    /*
     * READ_6 (0x08) or WRITE_6 (0x0A) cdb
     */
    if (csio->cdb_len == 6) {
        datalength = (u_int32_t)csio->cdb_io.cdb_bytes[4];
        start_lba_lo = ((u_int32_t) csio->cdb_io.cdb_bytes[1] << 16) |
                       ((u_int32_t) csio->cdb_io.cdb_bytes[2] << 8) |
                        (u_int32_t) csio->cdb_io.cdb_bytes[3];
        start_lba_lo &= 0x1FFFFF;
    }
    /*
     * READ_10 (0x28) or WRITE_6 (0x2A) cdb
     */
    else if (csio->cdb_len == 10) {
        datalength = (u_int32_t)csio->cdb_io.cdb_bytes[8] |
                       ((u_int32_t)csio->cdb_io.cdb_bytes[7] << 8);
        start_lba_lo = ((u_int32_t) csio->cdb_io.cdb_bytes[2] << 24) |
                       ((u_int32_t) csio->cdb_io.cdb_bytes[3] << 16) |
                        (u_int32_t) csio->cdb_io.cdb_bytes[4] << 8 |
                        ((u_int32_t) csio->cdb_io.cdb_bytes[5]);
    }
    /*
     * READ_12 (0xA8) or WRITE_12 (0xAA) cdb
     */
    else if (csio->cdb_len == 12) {
        datalength = (u_int32_t)csio->cdb_io.cdb_bytes[6] << 24 |
                       ((u_int32_t)csio->cdb_io.cdb_bytes[7] << 16) |
                       ((u_int32_t)csio->cdb_io.cdb_bytes[8] << 8) |
                       ((u_int32_t)csio->cdb_io.cdb_bytes[9]);
        start_lba_lo = ((u_int32_t) csio->cdb_io.cdb_bytes[2] << 24) |
                       ((u_int32_t) csio->cdb_io.cdb_bytes[3] << 16) |
                        (u_int32_t) csio->cdb_io.cdb_bytes[4] << 8 |
                        ((u_int32_t) csio->cdb_io.cdb_bytes[5]);
    }
    /*
     * READ_16 (0x88) or WRITE_16 (0xx8A) cdb
     */
    else if (csio->cdb_len == 16) {
        datalength = (u_int32_t)csio->cdb_io.cdb_bytes[10] << 24 |
                       ((u_int32_t)csio->cdb_io.cdb_bytes[11] << 16) |
                       ((u_int32_t)csio->cdb_io.cdb_bytes[12] << 8) |
                       ((u_int32_t)csio->cdb_io.cdb_bytes[13]);
        start_lba_lo = ((u_int32_t) csio->cdb_io.cdb_bytes[6] << 24) |
                       ((u_int32_t) csio->cdb_io.cdb_bytes[7] << 16) |
                        (u_int32_t) csio->cdb_io.cdb_bytes[8] << 8 |
                        ((u_int32_t) csio->cdb_io.cdb_bytes[9]);
        start_lba_hi = ((u_int32_t) csio->cdb_io.cdb_bytes[2] << 24) |
                       ((u_int32_t) csio->cdb_io.cdb_bytes[3] << 16) |
                        (u_int32_t) csio->cdb_io.cdb_bytes[4] << 8 |
                        ((u_int32_t) csio->cdb_io.cdb_bytes[5]);
    }

    memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO));
    io_info.ldStartBlock = ((u_int64_t)start_lba_hi << 32) | start_lba_lo;
    io_info.numBlocks = datalength;
    io_info.ldTgtId = device_id;

    switch (ccb_h->flags & CAM_DIR_MASK) {
	case CAM_DIR_IN:
		io_info.isRead = 1;
		break;
	case CAM_DIR_OUT:
		io_info.isRead = 0;
		break;
	case CAM_DIR_NONE:
	default:
    	mrsas_dprint(sc, MRSAS_TRACE, "From %s : DMA Flag is %d \n", __func__, ccb_h->flags & CAM_DIR_MASK);
		break;
    }

    map_ptr = sc->raidmap_mem[(sc->map_id & 1)];
    ld_block_size = MR_LdBlockSizeGet(device_id, map_ptr, sc);

    if ((MR_TargetIdToLdGet(device_id, map_ptr) >= MAX_LOGICAL_DRIVES) || 
            (!sc->fast_path_io)) {
        io_request->RaidContext.regLockFlags = 0;
        fp_possible = 0;
    } 
    else 
    {
        if (MR_BuildRaidContext(sc, &io_info, &io_request->RaidContext, map_ptr))
            fp_possible = io_info.fpOkForIo;
    }

    if (fp_possible) {
        mrsas_set_pd_lba(io_request, csio->cdb_len, &io_info, ccb, map_ptr, 
            start_lba_lo, ld_block_size);
        io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
        cmd->request_desc->SCSIIO.RequestFlags =
                        (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
                         << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
	    if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
		    if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)
                cmd->request_desc->SCSIIO.RequestFlags = (MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
            io_request->RaidContext.Type = MPI2_TYPE_CUDA;
            io_request->RaidContext.nseg = 0x1;
            io_request->IoFlags |= MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH;
            io_request->RaidContext.regLockFlags |= (MR_RL_FLAGS_GRANT_DESTINATION_CUDA | MR_RL_FLAGS_SEQ_NUM_ENABLE);
        }
        if ((sc->load_balance_info[device_id].loadBalanceFlag) && (io_info.isRead)) {
            io_info.devHandle = mrsas_get_updated_dev_handle(&sc->load_balance_info[device_id], 
                &io_info);
            cmd->load_balance = MRSAS_LOAD_BALANCE_FLAG;
        } 
        else
            cmd->load_balance = 0;
        cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
        io_request->DevHandle = io_info.devHandle;
    } 
    else {
        /* Not FP IO */
        io_request->RaidContext.timeoutValue = map_ptr->raidMap.fpPdIoTimeoutSec;
        cmd->request_desc->SCSIIO.RequestFlags =
            (MRSAS_REQ_DESCRIPT_FLAGS_LD_IO << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
	    if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY)) {
            if (io_request->RaidContext.regLockFlags == REGION_TYPE_UNUSED)
                cmd->request_desc->SCSIIO.RequestFlags = (MRSAS_REQ_DESCRIPT_FLAGS_NO_LOCK << MRSAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
            io_request->RaidContext.Type = MPI2_TYPE_CUDA;
            io_request->RaidContext.regLockFlags |= (MR_RL_FLAGS_GRANT_DESTINATION_CPU0 | MR_RL_FLAGS_SEQ_NUM_ENABLE);
            io_request->RaidContext.nseg = 0x1;
        }
        io_request->Function = MRSAS_MPI2_FUNCTION_LD_IO_REQUEST;
        io_request->DevHandle = device_id;
    }
    return(0);
}
Beispiel #5
0
/*
 * MR_BuildRaidContext:	Set up Fast path RAID context
 *
 * This function will initiate command processing.  The start/end row and strip
 * information is calculated then the lock is acquired. This function will
 * return 0 if region lock was acquired OR return num strips.
 */
u_int8_t
MR_BuildRaidContext(struct mrsas_softc *sc, struct IO_REQUEST_INFO *io_info,
    RAID_CONTEXT * pRAID_Context, MR_DRV_RAID_MAP_ALL * map)
{
	MR_LD_RAID *raid;
	u_int32_t ld, stripSize, stripe_mask;
	u_int64_t endLba, endStrip, endRow, start_row, start_strip;
	REGION_KEY regStart;
	REGION_LEN regSize;
	u_int8_t num_strips, numRows;
	u_int16_t ref_in_start_stripe, ref_in_end_stripe;
	u_int64_t ldStartBlock;
	u_int32_t numBlocks, ldTgtId;
	u_int8_t isRead, stripIdx;
	u_int8_t retval = 0;
	u_int8_t startlba_span = SPAN_INVALID;
	u_int64_t *pdBlock = &io_info->pdBlock;
	int error_code = 0;

	ldStartBlock = io_info->ldStartBlock;
	numBlocks = io_info->numBlocks;
	ldTgtId = io_info->ldTgtId;
	isRead = io_info->isRead;

	io_info->IoforUnevenSpan = 0;
	io_info->start_span = SPAN_INVALID;

	ld = MR_TargetIdToLdGet(ldTgtId, map);
	raid = MR_LdRaidGet(ld, map);

	if (raid->rowDataSize == 0) {
		if (MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize == 0)
			return FALSE;
		else if (sc->UnevenSpanSupport) {
			io_info->IoforUnevenSpan = 1;
		} else {
			mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: raid->rowDataSize is 0, but has SPAN[0] rowDataSize = 0x%0x,"
			    " but there is _NO_ UnevenSpanSupport\n",
			    MR_LdSpanPtrGet(ld, 0, map)->spanRowDataSize);
			return FALSE;
		}
	}
	stripSize = 1 << raid->stripeShift;
	stripe_mask = stripSize - 1;
	/*
	 * calculate starting row and stripe, and number of strips and rows
	 */
	start_strip = ldStartBlock >> raid->stripeShift;
	ref_in_start_stripe = (u_int16_t)(ldStartBlock & stripe_mask);
	endLba = ldStartBlock + numBlocks - 1;
	ref_in_end_stripe = (u_int16_t)(endLba & stripe_mask);
	endStrip = endLba >> raid->stripeShift;
	num_strips = (u_int8_t)(endStrip - start_strip + 1);	/* End strip */
	if (io_info->IoforUnevenSpan) {
		start_row = get_row_from_strip(sc, ld, start_strip, map);
		endRow = get_row_from_strip(sc, ld, endStrip, map);
		if (raid->spanDepth == 1) {
			startlba_span = 0;
			*pdBlock = start_row << raid->stripeShift;
		} else {
			startlba_span = (u_int8_t)mr_spanset_get_span_block(sc, ld, start_row,
			    pdBlock, map, &error_code);
			if (error_code == 1) {
				mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d. Send IO w/o region lock.\n",
				    __func__, __LINE__);
				return FALSE;
			}
		}
		if (startlba_span == SPAN_INVALID) {
			mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: return from %s %d for row 0x%llx,"
			    "start strip %llx endSrip %llx\n", __func__,
			    __LINE__, (unsigned long long)start_row,
			    (unsigned long long)start_strip,
			    (unsigned long long)endStrip);
			return FALSE;
		}
		io_info->start_span = startlba_span;
		io_info->start_row = start_row;
		mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug: Check Span number from %s %d for row 0x%llx, "
		    " start strip 0x%llx endSrip 0x%llx span 0x%x\n",
		    __func__, __LINE__, (unsigned long long)start_row,
		    (unsigned long long)start_strip,
		    (unsigned long long)endStrip, startlba_span);
		mrsas_dprint(sc, MRSAS_PRL11, "LSI Debug : 1. start_row 0x%llx endRow 0x%llx Start span 0x%x\n",
		    (unsigned long long)start_row, (unsigned long long)endRow, startlba_span);
	} else {
		start_row = mega_div64_32(start_strip, raid->rowDataSize);
		endRow = mega_div64_32(endStrip, raid->rowDataSize);
	}

	numRows = (u_int8_t)(endRow - start_row + 1);	/* get the row count */

	/*
	 * Calculate region info.  (Assume region at start of first row, and
	 * assume this IO needs the full row - will adjust if not true.)
	 */
	regStart = start_row << raid->stripeShift;
	regSize = stripSize;

	/* Check if we can send this I/O via FastPath */
	if (raid->capability.fpCapable) {
		if (isRead)
			io_info->fpOkForIo = (raid->capability.fpReadCapable &&
			    ((num_strips == 1) ||
			    raid->capability.fpReadAcrossStripe));
		else
			io_info->fpOkForIo = (raid->capability.fpWriteCapable &&
			    ((num_strips == 1) ||
			    raid->capability.fpWriteAcrossStripe));
	} else
		io_info->fpOkForIo = FALSE;

	if (numRows == 1) {
		if (num_strips == 1) {
			regStart += ref_in_start_stripe;
			regSize = numBlocks;
		}
	} else if (io_info->IoforUnevenSpan == 0) {
		/*
		 * For Even span region lock optimization. If the start strip
		 * is the last in the start row
		 */
		if (start_strip == (start_row + 1) * raid->rowDataSize - 1) {
			regStart += ref_in_start_stripe;
			/*
			 * initialize count to sectors from startRef to end
			 * of strip
			 */
			regSize = stripSize - ref_in_start_stripe;
		}
		/* add complete rows in the middle of the transfer */
		if (numRows > 2)
			regSize += (numRows - 2) << raid->stripeShift;

		/* if IO ends within first strip of last row */
		if (endStrip == endRow * raid->rowDataSize)
			regSize += ref_in_end_stripe + 1;
		else
			regSize += stripSize;
	} else {
		if (start_strip == (get_strip_from_row(sc, ld, start_row, map) +
		    SPAN_ROW_DATA_SIZE(map, ld, startlba_span) - 1)) {
			regStart += ref_in_start_stripe;
			/*
			 * initialize count to sectors from startRef to end
			 * of strip
			 */
			regSize = stripSize - ref_in_start_stripe;
		}
		/* add complete rows in the middle of the transfer */
		if (numRows > 2)
			regSize += (numRows - 2) << raid->stripeShift;

		/* if IO ends within first strip of last row */
		if (endStrip == get_strip_from_row(sc, ld, endRow, map))
			regSize += ref_in_end_stripe + 1;
		else
			regSize += stripSize;
	}
	pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec;
	if ((sc->device_id == MRSAS_INVADER) || (sc->device_id == MRSAS_FURY))
		pRAID_Context->regLockFlags = (isRead) ? raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
	else
		pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite;
	pRAID_Context->VirtualDiskTgtId = raid->targetId;
	pRAID_Context->regLockRowLBA = regStart;
	pRAID_Context->regLockLength = regSize;
	pRAID_Context->configSeqNum = raid->seqNum;

	/*
	 * Get Phy Params only if FP capable, or else leave it to MR firmware
	 * to do the calculation.
	 */
	if (io_info->fpOkForIo) {
		retval = io_info->IoforUnevenSpan ?
		    mr_spanset_get_phy_params(sc, ld, start_strip,
		    ref_in_start_stripe, io_info, pRAID_Context, map) :
		    MR_GetPhyParams(sc, ld, start_strip,
		    ref_in_start_stripe, io_info, pRAID_Context, map);
		/* If IO on an invalid Pd, then FP is not possible */
		if (io_info->devHandle == MR_PD_INVALID)
			io_info->fpOkForIo = FALSE;
		return retval;
	} else if (isRead) {
		for (stripIdx = 0; stripIdx < num_strips; stripIdx++) {
			retval = io_info->IoforUnevenSpan ?
			    mr_spanset_get_phy_params(sc, ld, start_strip + stripIdx,
			    ref_in_start_stripe, io_info, pRAID_Context, map) :
			    MR_GetPhyParams(sc, ld, start_strip + stripIdx,
			    ref_in_start_stripe, io_info, pRAID_Context, map);
			if (!retval)
				return TRUE;
		}
	}
#if SPAN_DEBUG
	/* Just for testing what arm we get for strip. */
	get_arm_from_strip(sc, ld, start_strip, map);
#endif
	return TRUE;
}