static void push_resp () { if (status.first_resp == NULL) return; if (psl_response (status.event, status.first_resp->tag, status.first_resp->code, 1, 0, 0) == PSL_SUCCESS) { struct afu_resp *temp; temp = status.first_resp; status.first_resp = status.first_resp->_next; if (status.first_resp == NULL) { status.last_resp = NULL; } free (temp); } }
// Send a randomly selected pending response back to AFU void handle_response(struct cmd *cmd) { struct cmd_event **head; struct cmd_event *event; struct client *client; int rc; // Select a random pending response (or none) client = NULL; head = &cmd->list; while (*head != NULL) { // Fast track error responses if (((*head)->resp == PSL_RESPONSE_PAGED) || ((*head)->resp == PSL_RESPONSE_NRES) || ((*head)->resp == PSL_RESPONSE_NLOCK) || ((*head)->resp == PSL_RESPONSE_FAILED) || ((*head)->resp == PSL_RESPONSE_FLUSHED)) { event = *head; goto drive_resp; } if (((*head)->state == MEM_DONE) && !allow_reorder(cmd->parms)) { break; } head = &((*head)->_next); } // Randomly decide not to drive response yet event = *head; if ((event == NULL) || ((event->client_state == CLIENT_VALID) && !allow_resp(cmd->parms))) { return; } // Test for client disconnect if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL)) return; // Send response, remove command from list and free memory if ((event->resp == PSL_RESPONSE_PAGED) || (event->resp == PSL_RESPONSE_AERROR) || (event->resp == PSL_RESPONSE_DERROR)) { client->flushing = FLUSH_FLUSHING; _update_pending_resps(cmd, PSL_RESPONSE_FLUSHED); } drive_resp: // Check for pending buffer activity if (event == cmd->buffer_read) { fatal_msg("Driving response when buffer read still active"); _print_event(event); assert(event != cmd->buffer_read); } rc = psl_response(cmd->afu_event, event->tag, event->resp, 1, 0, 0); if (rc == PSL_SUCCESS) { debug_msg("%s:RESPONSE tag=0x%02x code=0x%x", cmd->afu_name, event->tag, event->resp); debug_cmd_response(cmd->dbg_fp, cmd->dbg_id, event->tag); if ((client != NULL) && (event->command == PSL_COMMAND_RESTART)) client->flushing = FLUSH_NONE; *head = event->_next; free(event->data); free(event->parity); free(event); cmd->credits++; } }