Пример #1
0
static int
mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
    Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo)
{
	Mpi2SataPassthroughRequest_t *mpi_request;
	Mpi2SataPassthroughReply_t *reply;
	struct mps_command *cm;
	char *buffer;
	int error = 0;

	buffer = kmalloc( sz, M_MPT2, M_NOWAIT | M_ZERO);
	if (!buffer)
		return ENOMEM;

	if ((cm = mps_alloc_command(sc)) == NULL) {
		kfree(buffer, M_MPT2);
		return (EBUSY);
	}
	mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req;
	bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST));
	mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH;
	mpi_request->VF_ID = 0;
	mpi_request->DevHandle = htole16(handle);
	mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO |
	    MPI2_SATA_PT_REQ_PT_FLAGS_READ);
	mpi_request->DataLength = htole32(sz);
	mpi_request->CommandFIS[0] = 0x27;
	mpi_request->CommandFIS[1] = 0x80;
	mpi_request->CommandFIS[2] =  (devinfo &
	    MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC;
	cm->cm_sge = &mpi_request->SGL;
	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
	cm->cm_data = buffer;
	cm->cm_length = htole32(sz);
	error = mps_request_polled(sc, cm);
	reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
	if (error || (reply == NULL)) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */
		kprintf("%s: poll for page completed with error %d",
		    __func__, error);
		error = ENXIO;
		goto out;
	}
	bcopy(buffer, id_buffer, sz);
	bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t));
	if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) !=
	    MPI2_IOCSTATUS_SUCCESS) {
		kprintf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n",
		    __func__, reply->IOCStatus);
		error = ENXIO;
		goto out;
	}
out:
	mps_free_command(sc, cm);
	kfree(buffer, M_MPT2);
	return (error);
}
Пример #2
0
/**
 * mpssas_ir_shutdown - IR shutdown notification
 * @sc: per adapter object
 *
 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
 * the host system is shutting down.
 *
 * Return nothing.
 */
void
mpssas_ir_shutdown(struct mps_softc *sc)
{
	u16 volume_mapping_flags;
	u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
	struct dev_mapping_table *mt_entry;
	u32 start_idx, end_idx;
	unsigned int id, found_volume = 0;
	struct mps_command *cm;
	Mpi2RaidActionRequest_t	*action;

	mps_lock(sc);

	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);

	/* is IR firmware build loaded? */
	if (!sc->ir_firmware)
		goto back;

	/* are there any volumes?  Look at IR target IDs. */
	// TODO-later, this should be looked up in the RAID config structure
	// when it is implemented.
	volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
	    MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
	if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
		start_idx = 0;
		if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
			start_idx = 1;
	} else
		start_idx = sc->max_devices - sc->max_volumes;
	end_idx = start_idx + sc->max_volumes - 1;

	for (id = start_idx; id < end_idx; id++) {
		mt_entry = &sc->mapping_table[id];
		if ((mt_entry->physical_id != 0) &&
		    (mt_entry->missing_count == 0)) {
			found_volume = 1;
			break;
		}
	}

	if (!found_volume)
		goto back;

	if ((cm = mps_alloc_command(sc)) == NULL) {
		kprintf("%s: command alloc failed\n", __func__);
		goto back;
	}

	action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
	action->Function = MPI2_FUNCTION_RAID_ACTION;
	action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
	mps_request_polled(sc, cm);

	/*
	 * Don't check for reply, just leave.
	 */
	if (cm)
		mps_free_command(sc, cm);

back:
	mps_unlock(sc);
}
Пример #3
0
/**
 * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
 *   accordingly.  Currently, this page does not need to return to caller.
 * @sc: per adapter object
 * @mpi_reply: reply mf payload returned from firmware
 * Context: sleep.
 *
 * Returns 0 for success, non-zero for failure.
 */
int
mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
{
	MPI2_CONFIG_REQUEST *request;
	MPI2_CONFIG_REPLY *reply;
	struct mps_command *cm;
	pMpi2ManufacturingPagePS_t page = NULL;
	uint32_t *pPS_info;
	uint8_t OEM_Value = 0;
	int error = 0;
	u16 ioc_status;

	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);

	if ((cm = mps_alloc_command(sc)) == NULL) {
		printf("%s: command alloc failed @ line %d\n", __func__,
		    __LINE__);
		error = EBUSY;
		goto out;
	}
	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
	request->Function = MPI2_FUNCTION_CONFIG;
	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
	request->Header.PageNumber = 10;
	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
	cm->cm_data = NULL;

	/*
	 * This page must be polled because the IOC isn't ready yet when this
	 * page is needed.
	 */  
	error = mps_request_polled(sc, cm);
	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
	if (error || (reply == NULL)) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */ 
		printf("%s: poll for header completed with error %d",
		    __func__, error);
		error = ENXIO;
		goto out;
	}
	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */ 
		printf("%s: header read with error; iocstatus = 0x%x\n",
		    __func__, ioc_status);
		error = ENXIO;
		goto out;
	}
	/* We have to do free and alloc for the reply-free and reply-post
	 * counters to match - Need to review the reply FIFO handling.
	 */
	mps_free_command(sc, cm);
	
	if ((cm = mps_alloc_command(sc)) == NULL) {
		printf("%s: command alloc failed @ line %d\n", __func__,
		    __LINE__);
		error = EBUSY;
		goto out;
	}
	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
	request->Function = MPI2_FUNCTION_CONFIG;
	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
	request->Header.PageNumber = 10;
	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
	request->Header.PageLength = mpi_reply->Header.PageLength;
	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
	cm->cm_sge = &request->PageBufferSGE;
	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
	page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT);
	if (!page) {
		printf("%s: page alloc failed\n", __func__);
		error = ENOMEM;
		goto out;
	}
	cm->cm_data = page;

	/*
	 * This page must be polled because the IOC isn't ready yet when this
	 * page is needed.
	 */  
	error = mps_request_polled(sc, cm);
	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
	if (error || (reply == NULL)) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */ 
		printf("%s: poll for page completed with error %d",
		    __func__, error);
		error = ENXIO;
		goto out;
	}
	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */ 
		printf("%s: page read with error; iocstatus = 0x%x\n",
		    __func__, ioc_status);
		error = ENXIO;
		goto out;
	}

	/*
	 * If OEM ID is unknown, fail the request.
	 */
	sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
	OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
	if (OEM_Value != MPS_WD_LSI_OEM) {
		mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
		    "(0x%x)\n", OEM_Value);
		error = ENXIO;
		goto out;
	}

	/*
	 * Set the phys disks hide/expose value.
	 */
	pPS_info = &page->ProductSpecificInfo;
	sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
	sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
	if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
	    (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
	    (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
		mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
		    "hide/expose: 0x%x\n", sc->WD_hide_expose);
		error = ENXIO;
		goto out;
	}

out:
	free(page, M_MPT2);
	if (cm)
		mps_free_command(sc, cm);
	return (error);
}
Пример #4
0
/**
 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
 * @sc: per adapter object
 * @mpi_reply: reply mf payload returned from firmware
 * @config_page: contents of the config page
 * @page_address: form and handle value used to get page
 * Context: sleep.
 *
 * Returns 0 for success, non-zero for failure.
 */
int
mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
    Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
{
	MPI2_CONFIG_REQUEST *request;
	MPI2_CONFIG_REPLY *reply;
	struct mps_command *cm;
	Mpi2RaidPhysDiskPage0_t *page = NULL;
	int error = 0;
	u16 ioc_status;

	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);

	if ((cm = mps_alloc_command(sc)) == NULL) {
		printf("%s: command alloc failed @ line %d\n", __func__,
		    __LINE__);
		error = EBUSY;
		goto out;
	}
	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
	request->Function = MPI2_FUNCTION_CONFIG;
	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
	request->Header.PageNumber = 0;
	request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
	cm->cm_data = NULL;

	/*
	 * This page must be polled because the IOC isn't ready yet when this
	 * page is needed.
	 */  
	error = mps_request_polled(sc, cm);
	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
	if (error || (reply == NULL)) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */ 
		printf("%s: poll for header completed with error %d",
		    __func__, error);
		error = ENXIO;
		goto out;
	}
	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */ 
		printf("%s: header read with error; iocstatus = 0x%x\n",
		    __func__, ioc_status);
		error = ENXIO;
		goto out;
	}
	/* We have to do free and alloc for the reply-free and reply-post
	 * counters to match - Need to review the reply FIFO handling.
	 */
	mps_free_command(sc, cm);

	if ((cm = mps_alloc_command(sc)) == NULL) {
		printf("%s: command alloc failed @ line %d\n", __func__,
		    __LINE__);
		error = EBUSY;
		goto out;
	}
	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
	request->Function = MPI2_FUNCTION_CONFIG;
	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
	request->Header.PageNumber = 0;
	request->Header.PageLength = mpi_reply->Header.PageLength;
	request->Header.PageVersion = mpi_reply->Header.PageVersion;
	request->PageAddress = page_address;
	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
	cm->cm_sge = &request->PageBufferSGE;
	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
	if (!page) {
		printf("%s: page alloc failed\n", __func__);
		error = ENOMEM;
		goto out;
	}
	cm->cm_data = page;

	/*
	 * This page must be polled because the IOC isn't ready yet when this
	 * page is needed.
	 */  
	error = mps_request_polled(sc, cm);
	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
	if (error || (reply == NULL)) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */ 
		printf("%s: poll for page completed with error %d",
		    __func__, error);
		error = ENXIO;
		goto out;
	}
	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
		/* FIXME */
		/* If the poll returns error then we need to do diag reset */ 
		printf("%s: page read with error; iocstatus = 0x%x\n",
		    __func__, ioc_status);
		error = ENXIO;
		goto out;
	}
	bcopy(page, config_page, MIN(cm->cm_length,
	    sizeof(Mpi2RaidPhysDiskPage0_t)));
out:
	free(page, M_MPT2);
	if (cm)
		mps_free_command(sc, cm);
	return (error);
}