/* * Function name: tw_cli_submit_pending_queue * Description: Kick starts any requests in the pending queue. * * Input: ctlr -- ptr to CL internal ctlr context * Output: None * Return value: 0 -- all pending requests submitted successfully * non-zero-- otherwise */ TW_INT32 tw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr) { struct tw_cli_req_context *req; TW_INT32 error = TW_OSL_ESUCCESS; tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); /* * Pull requests off the pending queue, and submit them. */ while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) != TW_CL_NULL) { if ((error = tw_cli_submit_cmd(req))) { if (error == TW_OSL_EBUSY) { tw_cli_dbg_printf(2, ctlr->ctlr_handle, tw_osl_cur_func(), "Requeueing pending request"); req->state = TW_CLI_REQ_STATE_PENDING; /* * Queue the request at the head of the pending * queue, and break away, so we don't try to * submit any more requests. */ tw_cli_req_q_insert_head(req, TW_CLI_PENDING_Q); break; } else { tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE, TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR, 0x1202, 0x1, TW_CL_SEVERITY_ERROR_STRING, "Could not start request " "in pending queue", "request = %p, opcode = 0x%x, " "error = %d", req, GET_OPCODE(req->cmd_pkt-> command.cmd_pkt_9k.res__opcode), error); /* * Set the appropriate error and call the CL * internal callback if there's one. If the * request originator is polling for completion, * he should be checking req->error to * determine that the request did not go * through. The request originators are * responsible for the clean-up. */ req->error_code = error; req->state = TW_CLI_REQ_STATE_COMPLETE; if (req->tw_cli_callback) req->tw_cli_callback(req); error = TW_OSL_ESUCCESS; } } } return(error); }
/* * Function name: tw_cli_process_complete_queue * Description: Calls the CL internal callback routine, if any, for * each request in the complete queue. * * Input: ctlr -- ptr to CL internal ctlr context * Output: None * Return value: None */ TW_VOID tw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr) { struct tw_cli_req_context *req; tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); /* * Pull commands off the completed list, dispatch them appropriately. */ while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) != TW_CL_NULL) { /* Call the CL internal callback, if there's one. */ if (req->tw_cli_callback) req->tw_cli_callback(req); } }
/* * Function name: tw_cli_get_request * Description: Gets a request pkt from the free queue. * * Input: ctlr -- ptr to CL internal ctlr context * req_pkt -- ptr to OSL built req_pkt, if there's one * Output: None * Return value: ptr to request pkt -- success * TW_CL_NULL -- failure */ struct tw_cli_req_context * tw_cli_get_request(struct tw_cli_ctlr_context *ctlr ) { struct tw_cli_req_context *req; tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); { /* Get a free request packet. */ req = tw_cli_req_q_remove_head(ctlr, TW_CLI_FREE_Q); } /* Initialize some fields to their defaults. */ if (req) { req->req_handle = TW_CL_NULL; req->data = TW_CL_NULL; req->length = 0; req->data_phys = 0; req->state = TW_CLI_REQ_STATE_INIT; /* req being initialized */ req->flags = 0; req->error_code = 0; req->orig_req = TW_CL_NULL; req->tw_cli_callback = TW_CL_NULL; /* * Look at the status field in the command packet to see how * it completed the last time it was used, and zero out only * the portions that might have changed. Note that we don't * care to zero out the sglist. */ if (req->cmd_pkt->command.cmd_pkt_9k.status) tw_osl_memzero(req->cmd_pkt, sizeof(struct tw_cl_command_header) + 28 /* max bytes before sglist */); else tw_osl_memzero(&(req->cmd_pkt->command), 28 /* max bytes before sglist */); } return(req); }
TW_VOID tw_cli_drain_pending_queue(struct tw_cli_ctlr_context *ctlr) { struct tw_cli_req_context *req; struct tw_cl_req_packet *req_pkt; tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered"); /* * Pull requests off the pending queue, and complete them. */ while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) != TW_CL_NULL) { if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) { /* * It's an internal request. Set the appropriate * error and call the CL internal callback if there's * one. If the request originator is polling for * completion, he should be checking req->error to * determine that the request did not go through. * The request originators are responsible for the * clean-up. */ req->error_code = TW_CL_ERR_REQ_BUS_RESET; if (req->tw_cli_callback) req->tw_cli_callback(req); } else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) { /* It's a passthru request. Complete it. */ if ((req_pkt = req->orig_req) != TW_CL_NULL) { req_pkt->status = TW_CL_ERR_REQ_BUS_RESET; if (req_pkt->tw_osl_callback) req_pkt->tw_osl_callback(req->req_handle); } tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q); } else { /* It's an external (SCSI) request. Add it to the reset queue. */ tw_osl_untimeout(req->req_handle); tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q); } } /* End of while loop */ }