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); } }
/*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); }
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); }
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); }
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); }