Example #1
0
void
mpssas_firmware_event_work(void *arg, int pending)
{
	struct mps_fw_event_work *fw_event;
	struct mps_softc *sc;

	sc = (struct mps_softc *)arg;
	mps_lock(sc);
	while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) {
		TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link);
		mpssas_fw_work(sc, fw_event);
	}
	mps_unlock(sc);
}
Example #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);
}
Example #3
0
static int
mps_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag)
{
	struct mps_softc *sc;
	struct mps_cfg_page_req *page_req;
	struct mps_ext_cfg_page_req *ext_page_req;
	void *mps_page;
	int error;

	mps_page = NULL;
	sc = dev->si_drv1;
	page_req = (void *)arg;
	ext_page_req = (void *)arg;

	switch (cmd) {
	case MPSIO_READ_CFG_HEADER:
		mps_lock(sc);
		error = mps_user_read_cfg_header(sc, page_req);
		mps_unlock(sc);
		break;
	case MPSIO_READ_CFG_PAGE:
		mps_page = kmalloc(page_req->len, M_MPSUSER, M_WAITOK | M_ZERO);
		error = copyin(page_req->buf, mps_page,
		    sizeof(MPI2_CONFIG_PAGE_HEADER));
		if (error)
			break;
		mps_lock(sc);
		error = mps_user_read_cfg_page(sc, page_req, mps_page);
		mps_unlock(sc);
		if (error)
			break;
		error = copyout(mps_page, page_req->buf, page_req->len);
		break;
	case MPSIO_READ_EXT_CFG_HEADER:
		mps_lock(sc);
		error = mps_user_read_extcfg_header(sc, ext_page_req);
		mps_unlock(sc);
		break;
	case MPSIO_READ_EXT_CFG_PAGE:
		mps_page = kmalloc(ext_page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
		error = copyin(ext_page_req->buf, mps_page,
		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
		if (error)
			break;
		mps_lock(sc);
		error = mps_user_read_extcfg_page(sc, ext_page_req, mps_page);
		mps_unlock(sc);
		if (error)
			break;
		error = copyout(mps_page, ext_page_req->buf, ext_page_req->len);
		break;
	case MPSIO_WRITE_CFG_PAGE:
		mps_page = kmalloc(page_req->len, M_MPSUSER, M_WAITOK|M_ZERO);
		error = copyin(page_req->buf, mps_page, page_req->len);
		if (error)
			break;
		mps_lock(sc);
		error = mps_user_write_cfg_page(sc, page_req, mps_page);
		mps_unlock(sc);
		break;
	case MPSIO_MPS_COMMAND:
		error = mps_user_command(sc, (struct mps_usr_command *)arg);
		break;
	default:
		error = ENOIOCTL;
		break;
	}

	if (mps_page != NULL)
		kfree(mps_page, M_MPSUSER);

	return (error);
}
Example #4
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;
	target_id_t targetid;
	struct mpssas_target *target;

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

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

	/* 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 out;

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

	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_lock(sc);
	mps_wait_command(sc, cm, 5, CAN_SLEEP);
	mps_unlock(sc);

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

out:
	/*
	 * All of the targets must have the correct value set for
	 * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable.
	 *
	 * The possible values for the 'enable_ssu' variable are:
	 * 0: disable to SSD and HDD
	 * 1: disable only to HDD (default)
	 * 2: disable only to SSD
	 * 3: enable to SSD and HDD
	 * anything else will default to 1.
	 */
	for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
		target = &sc->sassc->targets[targetid];
		if (target->handle == 0x0) {
			continue;
		}

		if (target->supports_SSU) {
			switch (sc->enable_ssu) {
			case MPS_SSU_DISABLE_SSD_DISABLE_HDD:
				target->stop_at_shutdown = FALSE;
				break;
			case MPS_SSU_DISABLE_SSD_ENABLE_HDD:
				target->stop_at_shutdown = TRUE;
				if (target->flags & MPS_TARGET_IS_SATA_SSD) {
					target->stop_at_shutdown = FALSE;
				}
				break;
			case MPS_SSU_ENABLE_SSD_ENABLE_HDD:
				target->stop_at_shutdown = TRUE;
				break;
			case MPS_SSU_ENABLE_SSD_DISABLE_HDD:
			default:
				target->stop_at_shutdown = TRUE;
				if ((target->flags &
				    MPS_TARGET_IS_SATA_SSD) == 0) {
					target->stop_at_shutdown = FALSE;
				}
				break;
			}
		}
	}
	mpssas_SSU_to_SATA_devices(sc);
}
Example #5
0
static int
mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
{
	MPI2_REQUEST_HEADER *hdr;
	MPI2_DEFAULT_REPLY *rpl;
	void *buf = NULL;
	struct mps_command *cm = NULL;
	int err = 0;
	int sz;

	mps_lock(sc);
	cm = mps_alloc_command(sc);

	if (cm == NULL) {
		mps_printf(sc, "mps_user_command: no mps requests\n");
		err = ENOMEM;
		goto Ret;
	}
	mps_unlock(sc);

	hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;

	mps_dprint(sc, MPS_INFO, "mps_user_command: req %p %d  rpl %p %d\n",
		    cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len );

	if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) {
		err = EINVAL;
		goto RetFreeUnlocked;
	}
	err = copyin(cmd->req, hdr, cmd->req_len);
	if (err != 0)
		goto RetFreeUnlocked;

	mps_dprint(sc, MPS_INFO, "mps_user_command: Function %02X  "
	    "MsgFlags %02X\n", hdr->Function, hdr->MsgFlags );

	err = mps_user_setup_request(cm, cmd);
	if (err != 0) {
		mps_printf(sc, "mps_user_command: unsupported function 0x%X\n",
		    hdr->Function );
		goto RetFreeUnlocked;
	}

	if (cmd->len > 0) {
		buf = kmalloc(cmd->len, M_MPSUSER, M_WAITOK|M_ZERO);
		cm->cm_data = buf;
		cm->cm_length = cmd->len;
	} else {
		cm->cm_data = NULL;
		cm->cm_length = 0;
	}

	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_WAKEUP;
	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;

	mps_lock(sc);
	err = mps_map_command(sc, cm);

	if (err != 0 && err != EINPROGRESS) {
		mps_printf(sc, "%s: invalid request: error %d\n",
		    __func__, err);
		goto Ret;
	}
	lksleep(cm, &sc->mps_lock, 0, "mpsuser", 0);

	rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
	sz = rpl->MsgLength * 4;

	if (sz > cmd->rpl_len) {
		mps_printf(sc,
		    "mps_user_command: reply buffer too small %d required %d\n",
		    cmd->rpl_len, sz );
		err = EINVAL;
		sz = cmd->rpl_len;
	}

	mps_unlock(sc);
	copyout(rpl, cmd->rpl, sz);
	if (buf != NULL)
		copyout(buf, cmd->buf, cmd->len);
	mps_dprint(sc, MPS_INFO, "mps_user_command: reply size %d\n", sz );

RetFreeUnlocked:
	mps_lock(sc);
	if (cm != NULL)
		mps_free_command(sc, cm);
Ret:
	mps_unlock(sc);
	if (buf != NULL)
		kfree(buf, M_MPSUSER);
	return (err);
}