FreeBSD/sys/dev/mrsas/mrsas.c
/*
 * mrsas_init_fw:	Initialize Firmware
 * input:			Adapter soft state
 *
 * Calls transition_to_ready() to make sure Firmware is in operational state and
 * calls mrsas_init_adapter() to send IOC_INIT command to Firmware.  It
 * issues internal commands to get the controller info after the IOC_INIT
 * command response is received by Firmware.  Note:  code relating to
 * get_pdlist, get_ld_list and max_sectors are currently not being used, it
 * is left here as placeholder.
 */
Initialize Firmware
input:                       Adapter soft state

Calls transition_to_ready() to make sure Firmware is in operational state and
calls mrsas_init_adapter() to send IOC_INIT command to Firmware.  It
issues internal commands to get the controller info after the IOC_INIT
command response is received by Firmware.  Note:  code relating to
get_pdlist, get_ld_list and max_sectors are currently not being used, it
is left here as placeholder.
Initialize Firmware input : Adapter soft state Calls transition_to_ready () to make sure Firmware is in operational state and calls mrsas_init_adapter () to send IOC_INIT command to Firmware . It issues internal commands to get the controller info after the IOC_INIT command response is received by Firmware . Note : code relating to get_pdlist get_ld_list and max_sectors are currently not being used it is left here as placeholder .
static int
mrsas_init_fw(struct mrsas_softc *sc)
{
	int ret, loop, ocr = 0;
	u_int32_t max_sectors_1;
	u_int32_t max_sectors_2;
	u_int32_t tmp_sectors;
	u_int32_t scratch_pad_2;
	int msix_enable = 0;
	int fw_msix_count = 0;
	ret = mrsas_transition_to_ready(sc, ocr);
	if (ret != SUCCESS) {
		return (ret);
	}
	sc->msix_reg_offset[0] = MPI2_REPLY_POST_HOST_INDEX_OFFSET;
	msix_enable = (mrsas_read_reg(sc, offsetof(mrsas_reg_set, outbound_scratch_pad)) & 0x4000000) >> 0x1a;
	if (msix_enable) {
		scratch_pad_2 = mrsas_read_reg(sc, offsetof(mrsas_reg_set,
		    outbound_scratch_pad_2));
		if (sc->device_id == MRSAS_TBOLT) {
			sc->msix_vectors = (scratch_pad_2
			    & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
			fw_msix_count = sc->msix_vectors;
		} else {
			sc->msix_vectors = ((scratch_pad_2
			    & MR_MAX_REPLY_QUEUES_EXT_OFFSET)
			    >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
			fw_msix_count = sc->msix_vectors;
			for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY;
			    loop++) {
				sc->msix_reg_offset[loop] =
				    MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET +
				    (loop * 0x10);
			}
		}
		sc->msix_vectors = min(sc->msix_vectors,
		    mp_ncpus);
		if (mrsas_allocate_msix(sc) == SUCCESS)
			sc->msix_enable = 1;
		else
			sc->msix_enable = 0;
		device_printf(sc->mrsas_dev, "FW supports <%d> MSIX vector,"
		    "Online CPU %d Current MSIX <%d>\n",
		    fw_msix_count, mp_ncpus, sc->msix_vectors);
	}
	if (mrsas_init_adapter(sc) != SUCCESS) {
		device_printf(sc->mrsas_dev, "Adapter initialize Fail.\n");
		return (1);
	}
	if (mrsas_alloc_mfi_cmds(sc) != SUCCESS) {
		device_printf(sc->mrsas_dev, "Allocate MFI cmd failed.\n");
		return (1);
	}
	sc->ctrl_info = malloc(sizeof(struct mrsas_ctrl_info), M_MRSAS, M_NOWAIT);
	if (!sc->ctrl_info) {
		device_printf(sc->mrsas_dev, "Malloc for ctrl_info failed.\n");
		return (1);
	}
	if (mrsas_get_ctrl_info(sc)) {
		device_printf(sc->mrsas_dev, "Unable to get FW ctrl_info.\n");
		return (1);
	}
	sc->secure_jbod_support =
	    (u_int8_t)sc->ctrl_info->adapterOperations3.supportSecurityonJBOD;
	if (sc->secure_jbod_support)
		device_printf(sc->mrsas_dev, "FW supports SED \n");
	if (sc->use_seqnum_jbod_fp)
		device_printf(sc->mrsas_dev, "FW supports JBOD Map \n");
	if (mrsas_setup_raidmap(sc) != SUCCESS) {
		device_printf(sc->mrsas_dev, "Error: RAID map setup FAILED !!! "
		    "There seems to be some problem in the controller\n"
		    "Please contact to the SUPPORT TEAM if the problem persists\n");
	}
	megasas_setup_jbod_map(sc);
	memset(sc->pd_list, 0,
	    MRSAS_MAX_PD * sizeof(struct mrsas_pd_list));
	if (mrsas_get_pd_list(sc) != SUCCESS) {
		device_printf(sc->mrsas_dev, "Get PD list failed.\n");
		return (1);
	}
	memset(sc->ld_ids, 0xff, MRSAS_MAX_LD_IDS);
	if (mrsas_get_ld_list(sc) != SUCCESS) {
		device_printf(sc->mrsas_dev, "Get LD lsit failed.\n");
		return (1);
	}
	tmp_sectors = 0;
	max_sectors_1 = (1 << sc->ctrl_info->stripe_sz_ops.min) *
	    sc->ctrl_info->max_strips_per_io;
	max_sectors_2 = sc->ctrl_info->max_request_size;
	tmp_sectors = min(max_sectors_1, max_sectors_2);
	sc->max_sectors_per_req = sc->max_num_sge * MRSAS_PAGE_SIZE / 512;
	if (tmp_sectors && (sc->max_sectors_per_req > tmp_sectors))
		sc->max_sectors_per_req = tmp_sectors;
	sc->disableOnlineCtrlReset =
	    sc->ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
	sc->UnevenSpanSupport =
	    sc->ctrl_info->adapterOperations2.supportUnevenSpans;
	if (sc->UnevenSpanSupport) {
		device_printf(sc->mrsas_dev, "FW supports: UnevenSpanSupport=%x\n\n",
		    sc->UnevenSpanSupport);
		if (MR_ValidateMapInfo(sc))
			sc->fast_path_io = 1;
		else
			sc->fast_path_io = 0;
	}
	return (0);
}
static int mrsas_init_fw ( struct mrsas_softc * sc ) { int ret , loop , ocr = 0 ; u_int32_t max_sectors_1 ; u_int32_t max_sectors_2 ; u_int32_t tmp_sectors ; u_int32_t scratch_pad_2 ; int msix_enable = 0 ; int fw_msix_count = 0 ; ret = mrsas_transition_to_ready ( sc , ocr ) ; if ( ret != SUCCESS ) { return ( ret ) ; } sc -> msix_reg_offset [ 0 ] = MPI2_REPLY_POST_HOST_INDEX_OFFSET ; msix_enable = ( mrsas_read_reg ( sc , offsetof ( mrsas_reg_set , outbound_scratch_pad ) ) & 0x4000000 ) >> 0x1a ; if ( msix_enable ) { scratch_pad_2 = mrsas_read_reg ( sc , offsetof ( mrsas_reg_set , outbound_scratch_pad_2 ) ) ; if ( sc -> device_id == MRSAS_TBOLT ) { sc -> msix_vectors = ( scratch_pad_2 & MR_MAX_REPLY_QUEUES_OFFSET ) + 1 ; fw_msix_count = sc -> msix_vectors ; } else { sc -> msix_vectors = ( ( scratch_pad_2 & MR_MAX_REPLY_QUEUES_EXT_OFFSET ) >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT ) + 1 ; fw_msix_count = sc -> msix_vectors ; for ( loop = 1 ; loop < MR_MAX_MSIX_REG_ARRAY ; loop ++ ) { sc -> msix_reg_offset [ loop ] = MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET + ( loop * 0x10 ) ; } } sc -> msix_vectors = min ( sc -> msix_vectors , mp_ncpus ) ; if ( mrsas_allocate_msix ( sc ) == SUCCESS ) sc -> msix_enable = 1 ; else sc -> msix_enable = 0 ; device_printf ( sc -> mrsas_dev , " " " \n " , fw_msix_count , mp_ncpus , sc -> msix_vectors ) ; } if ( mrsas_init_adapter ( sc ) != SUCCESS ) { device_printf ( sc -> mrsas_dev , " \n " ) ; return ( 1 ) ; } if ( mrsas_alloc_mfi_cmds ( sc ) != SUCCESS ) { device_printf ( sc -> mrsas_dev , " \n " ) ; return ( 1 ) ; } sc -> ctrl_info = malloc ( sizeof ( struct mrsas_ctrl_info ) , M_MRSAS , M_NOWAIT ) ; if ( ! sc -> ctrl_info ) { device_printf ( sc -> mrsas_dev , " \n " ) ; return ( 1 ) ; } if ( mrsas_get_ctrl_info ( sc ) ) { device_printf ( sc -> mrsas_dev , " \n " ) ; return ( 1 ) ; } sc -> secure_jbod_support = ( u_int8_t ) sc -> ctrl_info -> adapterOperations3 . supportSecurityonJBOD ; if ( sc -> secure_jbod_support ) device_printf ( sc -> mrsas_dev , " \n " ) ; if ( sc -> use_seqnum_jbod_fp ) device_printf ( sc -> mrsas_dev , " \n " ) ; if ( mrsas_setup_raidmap ( sc ) != SUCCESS ) { device_printf ( sc -> mrsas_dev , " " " \n " " \n " ) ; } megasas_setup_jbod_map ( sc ) ; memset ( sc -> pd_list , 0 , MRSAS_MAX_PD * sizeof ( struct mrsas_pd_list ) ) ; if ( mrsas_get_pd_list ( sc ) != SUCCESS ) { device_printf ( sc -> mrsas_dev , " \n " ) ; return ( 1 ) ; } memset ( sc -> ld_ids , 0xff , MRSAS_MAX_LD_IDS ) ; if ( mrsas_get_ld_list ( sc ) != SUCCESS ) { device_printf ( sc -> mrsas_dev , " \n " ) ; return ( 1 ) ; } tmp_sectors = 0 ; max_sectors_1 = ( 1 << sc -> ctrl_info -> stripe_sz_ops . min ) * sc -> ctrl_info -> max_strips_per_io ; max_sectors_2 = sc -> ctrl_info -> max_request_size ; tmp_sectors = min ( max_sectors_1 , max_sectors_2 ) ; sc -> max_sectors_per_req = sc -> max_num_sge * MRSAS_PAGE_SIZE / 512 ; if ( tmp_sectors && ( sc -> max_sectors_per_req > tmp_sectors ) ) sc -> max_sectors_per_req = tmp_sectors ; sc -> disableOnlineCtrlReset = sc -> ctrl_info -> properties . OnOffProperties . disableOnlineCtrlReset ; sc -> UnevenSpanSupport = sc -> ctrl_info -> adapterOperations2 . supportUnevenSpans ; if ( sc -> UnevenSpanSupport ) { device_printf ( sc -> mrsas_dev , " \n \n " , sc -> UnevenSpanSupport ) ; if ( MR_ValidateMapInfo ( sc ) ) sc -> fast_path_io = 1 ; else sc -> fast_path_io = 0 ; } return ( 0 ) ; }
mrsas_init_fw:       Initialize Firmware
 input:                       Adapter soft state
mrsas_init_fw : Initialize Firmware input : Adapter soft state
/* Make sure Firmware is ready */ /* MSI-x index 0- reply post host index register */ /* Check if MSI-X is supported while in ready state */ /* Check max MSI-X vectors */ /* Invader/Fury supports 96 MSI-X vectors */ /* Don't bother allocating more MSI-X vectors than cpus */ /* Allocate MSI-x vectors */ /* Allocate internal commands for pass-thru */ /*
	 * Get the controller info from FW, so that the MAX VD support
	 * availability can be decided.
	 */ /* For pass-thru, get PD/LD list and controller info */ /*
	 * Compute the max allowed sectors per IO: The controller info has
	 * two limits on max sectors. Driver should use the minimum of these
	 * two.
	 *
	 * 1 << stripe_sz_ops.min = max sectors per strip
	 *
	 * Note that older firmwares ( < FW ver 30) didn't report information to
	 * calculate max_sectors_1. So the number ended up as zero always.
	 */