Ejemplo n.º 1
0
void
pppt_xfer_read_complete(pppt_task_t *pppt_task, stmf_status_t status)
{
	pppt_buf_t		*pppt_buf;
	stmf_data_buf_t		*dbuf;

	/*
	 * Caller should have taken a task hold (likely via pppt_task_lookup)
	 *
	 * Get pppt_buf_t and stmf_data_buf_t pointers
	 */
	pppt_buf = pppt_task->pt_read_buf;
	dbuf = pppt_buf->pbuf_stmf_buf;
	dbuf->db_xfer_status = (status == STMF_SUCCESS) ?
	    STMF_SUCCESS : STMF_FAILURE;

	/*
	 * COMSTAR currently requires port providers to support
	 * the DB_SEND_STATUS_GOOD flag even if phase collapse is
	 * not supported.  So we will roll our own... pretend we are
	 * COMSTAR and ask for a status message.
	 */
	if ((dbuf->db_flags & DB_SEND_STATUS_GOOD) &&
	    (status == STMF_SUCCESS)) {
		/*
		 * It's possible the task has been aborted since the time we
		 * looked it up.  We need to release the hold before calling
		 * pppt_lport_send_status and as soon as we release the hold
		 * the task may disappear.  Calling pppt_task_done allows us
		 * to determine whether the task has been aborted (in which
		 * case we will stop processing and return) and mark the task
		 * "done" which will prevent the task from being aborted while
		 * we are trying to send the status.
		 */
		if (pppt_task_done(pppt_task) != PPPT_STATUS_SUCCESS) {
			/* STMF will free task and buffer(s) */
			pppt_task_rele(pppt_task);
			return;
		}
		pppt_task_rele(pppt_task);

		if (pppt_lport_send_status(pppt_task->pt_stmf_task, 0)
		    != STMF_SUCCESS) {
			/* Failed to send status */
			dbuf->db_xfer_status = STMF_FAILURE;
			stmf_data_xfer_done(pppt_task->pt_stmf_task, dbuf,
			    STMF_IOF_LPORT_DONE);
		}
	} else {
		pppt_task_rele(pppt_task);
		stmf_data_xfer_done(pppt_task->pt_stmf_task, dbuf, 0);
	}
}
Ejemplo n.º 2
0
/*ARGSUSED*/
stmf_status_t
pppt_lport_xfer_data(scsi_task_t *task, stmf_data_buf_t *dbuf,
    uint32_t ioflags)
{
	pppt_task_t		*pppt_task = task->task_port_private;
	pppt_buf_t		*pbuf = dbuf->db_port_private;
	stmf_ic_msg_t		*msg;
	stmf_ic_msg_status_t	ic_msg_status;

	/*
	 * If we are aborting then we can ignore this request, otherwise
	 * add a reference.
	 */
	if (pppt_task_hold(pppt_task) != PPPT_STATUS_SUCCESS) {
		return (STMF_SUCCESS);
	}

	/*
	 * If it's not immediate data then start the transfer
	 */
	ASSERT(pbuf->pbuf_is_immed == B_FALSE);
	if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {

		/* Send read data */
		msg = stmf_ic_scsi_data_msg_alloc(
		    pppt_task->pt_task_id,
		    pppt_task->pt_sess->ps_session_id,
		    pppt_task->pt_lun_id,
		    dbuf->db_sglist[0].seg_length,
		    dbuf->db_sglist[0].seg_addr, 0);

		pppt_task->pt_read_buf = pbuf;
		pppt_task->pt_read_xfer_msgid = msg->icm_msgid;

		ic_msg_status = stmf_ic_tx_msg(msg);
		pppt_task_rele(pppt_task);
		if (ic_msg_status != STMF_IC_MSG_SUCCESS) {
			return (STMF_FAILURE);
		} else {
			return (STMF_SUCCESS);
		}
	} else if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) {
		pppt_task_rele(pppt_task);
		return (STMF_FAILURE);
	}

	pppt_task_rele(pppt_task);

	return (STMF_INVALID_ARG);
}
Ejemplo n.º 3
0
pppt_status_t
pppt_task_done(pppt_task_t *ptask)
{
	pppt_status_t	pppt_status = PPPT_STATUS_SUCCESS;
	boolean_t	remove = B_FALSE;

	mutex_enter(&ptask->pt_mutex);

	switch (ptask->pt_state) {
	case PTS_ACTIVE:
		remove = B_TRUE;
		pppt_task_update_state(ptask, PTS_DONE);
		break;
	case PTS_ABORTED:
		pppt_status = PPPT_STATUS_ABORTED;
		break;
	case PTS_DONE:
		/* Repeat calls are OK.  Do nothing, return success */
		break;
	default:
		ASSERT(0);
	}

	mutex_exit(&ptask->pt_mutex);

	if (remove) {
		mutex_enter(&ptask->pt_sess->ps_mutex);
		avl_remove(&ptask->pt_sess->ps_task_list, ptask);
		mutex_exit(&ptask->pt_sess->ps_mutex);
		/* Out of the AVL tree, so drop a reference. */
		pppt_task_rele(ptask);
	}

	return (pppt_status);
}
Ejemplo n.º 4
0
void
pppt_lport_task_free(scsi_task_t *task)
{
	pppt_task_t *ptask = task->task_port_private;
	pppt_sess_t *ps = ptask->pt_sess;

	pppt_task_rele(ptask);
	pppt_sess_rele(ps);
}
Ejemplo n.º 5
0
static pppt_status_t
pppt_task_try_abort(pppt_task_t *ptask)
{
	boolean_t	remove = B_FALSE;
	pppt_status_t	pppt_status = PPPT_STATUS_SUCCESS;

	mutex_enter(&ptask->pt_mutex);

	switch (ptask->pt_state) {
	case PTS_ACTIVE:
		remove = B_TRUE;
		pppt_task_update_state(ptask, PTS_ABORTED);
		break;
	case PTS_DONE:
		pppt_status = PPPT_STATUS_DONE;
		break;
	case PTS_SENT_STATUS:
		/*
		 * Already removed so leave remove set to B_FALSE
		 * and leave status set to PPPT_STATUS_SUCCESS.
		 */
		pppt_task_update_state(ptask, PTS_ABORTED);
		break;
	case PTS_ABORTED:
		break;
	default:
		ASSERT(0);
	}

	mutex_exit(&ptask->pt_mutex);

	if (remove) {
		mutex_enter(&ptask->pt_sess->ps_mutex);
		avl_remove(&ptask->pt_sess->ps_task_list, ptask);
		mutex_exit(&ptask->pt_sess->ps_mutex);
		/* Out of the AVL tree, so drop a reference. */
		pppt_task_rele(ptask);
	}

	return (pppt_status);
}