static void *_client_loop(void *ptr) { struct client *client = (struct client *)ptr; uint8_t data[2]; int rc; pthread_mutex_lock(&lock); while (client->pending) { rc = bytes_ready(client->fd, client->timeout, &(client->abort)); if (rc == 0) { lock_delay(&lock); continue; } if ((rc < 0) || get_bytes(client->fd, 1, data, 10, &(client->abort), fp, -1, -1) < 0) { client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE); break; } if (data[0] == PSLSE_QUERY) { if (get_bytes_silent(client->fd, 1, data, timeout, &(client->abort)) < 0) { debug_msg("_client_loop failed PSLSE_QUERY"); client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE); break; } _query(client, data[0]); lock_delay(&lock); continue; } if (data[0] == PSLSE_MAX_INT) { if (get_bytes(client->fd, 2, data, timeout, &(client->abort), fp, -1, -1) < 0) { client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE); break; } _max_irqs(client, data[0]); lock_delay(&lock); continue; } if (data[0] == PSLSE_OPEN) { if (get_bytes_silent(client->fd, 2, data, timeout, &(client->abort)) < 0) { client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE); debug_msg("_client_loop: client associate failed; could not communicate with socket"); break; } _client_associate(client, data[0], (char)data[1]); debug_msg("_client_loop: client associated"); break; } client->pending = 0; break; lock_delay(&lock); } pthread_mutex_unlock(&lock); // Terminate thread pthread_exit(NULL); }
static void _handle_client(struct psl *psl, struct client *client) { struct mmio_event *mmio; struct cmd_event *cmd; uint8_t buffer[MAX_LINE_CHARS]; int dw = 0; // Handle MMIO done if (client->mmio_access != NULL) { client->idle_cycles = PSL_IDLE_CYCLES; client->mmio_access = handle_mmio_done(psl->mmio, client); } // Client disconnected if (client->state == CLIENT_NONE) return; // Check for event from application cmd = (struct cmd_event *)client->mem_access; mmio = NULL; if (bytes_ready(client->fd, 1, &(client->abort))) { if (get_bytes(client->fd, 1, buffer, psl->timeout, &(client->abort), psl->dbg_fp, psl->dbg_id, client->context) < 0) { client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE); return; } switch (buffer[0]) { case PSLSE_DETACH: client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE); break; case PSLSE_ATTACH: _attach(psl, client); break; case PSLSE_MEM_FAILURE: if (client->mem_access != NULL) handle_aerror(psl->cmd, cmd); client->mem_access = NULL; break; case PSLSE_MEM_SUCCESS: if (client->mem_access != NULL) handle_mem_return(psl->cmd, cmd, client->fd); client->mem_access = NULL; break; case PSLSE_MMIO_MAP: handle_mmio_map(psl->mmio, client); break; case PSLSE_MMIO_WRITE64: dw = 1; case PSLSE_MMIO_WRITE32: /*fall through */ mmio = handle_mmio(psl->mmio, client, 0, dw); break; case PSLSE_MMIO_READ64: dw = 1; case PSLSE_MMIO_READ32: /*fall through */ mmio = handle_mmio(psl->mmio, client, 1, dw); break; default: error_msg("Unexpected 0x%02x from client", buffer[0]); } if (mmio) client->mmio_access = (void *)mmio; if (client->state == CLIENT_VALID) client->idle_cycles = PSL_IDLE_CYCLES; } }
static void *_psl_loop(void *ptr) { struct cxl_afu_h *afu = (struct cxl_afu_h *)ptr; uint8_t buffer[MAX_LINE_CHARS]; uint8_t size; uint64_t addr; uint16_t value; uint32_t lvalue; int rc; if (!afu) fatal_msg("NULL afu passed to libcxl.c:_psl_loop"); afu->opened = 1; while (afu->opened) { _delay_1ms(); // Send any requests to PSLSE over socket if (afu->int_req.state == LIBCXL_REQ_REQUEST) _req_max_int(afu); if (afu->attach.state == LIBCXL_REQ_REQUEST) _pslse_attach(afu); if (afu->mmio.state == LIBCXL_REQ_REQUEST) { switch (afu->mmio.type) { case PSLSE_MMIO_MAP: _mmio_map(afu); break; case PSLSE_MMIO_WRITE64: _mmio_write64(afu); break; case PSLSE_MMIO_WRITE32: _mmio_write32(afu); break; case PSLSE_MMIO_EBREAD: case PSLSE_MMIO_READ64: case PSLSE_MMIO_READ32: /*fall through */ _mmio_read(afu); break; default: break; } } // Process socket input from PSLSE rc = bytes_ready(afu->fd, 1000, 0); if (rc == 0) continue; if (rc < 0) { warn_msg("Socket failure testing bytes_ready"); _all_idle(afu); break; } if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) { warn_msg("Socket failure getting PSL event"); _all_idle(afu); break; } DPRINTF("PSL EVENT\n"); switch (buffer[0]) { case PSLSE_OPEN: if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) { warn_msg("Socket failure getting OPEN context"); _all_idle(afu); break; } afu->context = (uint16_t) buffer[0]; afu->open.state = LIBCXL_REQ_IDLE; break; case PSLSE_ATTACH: afu->attach.state = LIBCXL_REQ_IDLE; break; case PSLSE_DETACH: info_msg("detach response from from pslse"); afu->mapped = 0; afu->attached = 0; afu->opened = 0; afu->open.state = LIBCXL_REQ_IDLE; afu->attach.state = LIBCXL_REQ_IDLE; afu->mmio.state = LIBCXL_REQ_IDLE; afu->int_req.state = LIBCXL_REQ_IDLE; break; case PSLSE_MAX_INT: size = sizeof(uint16_t); if (get_bytes_silent(afu->fd, size, buffer, 1000, 0) < 0) { warn_msg ("Socket failure getting max interrupt acknowledge"); _all_idle(afu); break; } memcpy((char *)&value, (char *)buffer, sizeof(uint16_t)); afu->irqs_max = ntohs(value); afu->int_req.state = LIBCXL_REQ_IDLE; break; case PSLSE_QUERY: { size = sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t); if (get_bytes_silent(afu->fd, size, buffer, 1000, 0) < 0) { warn_msg("Socket failure getting PSLSE query"); _all_idle(afu); break; } memcpy((char *)&value, (char *)&(buffer[0]), 2); afu->irqs_min = (long)(value); memcpy((char *)&value, (char *)&(buffer[2]), 2); afu->irqs_max = (long)(value); memcpy((char *)&value, (char *)&(buffer[4]), 2); afu->modes_supported = (long)(value); memcpy((char *)&value, (char *)&(buffer[6]), 8); afu->mmio_len = (long)(value); memcpy((char *)&value, (char *)&(buffer[14]), 8); afu->mmio_off = (long)(value); memcpy((char *)&value, (char *)&(buffer[22]), 8); //afu->eb_len = (long)ntohll(value); afu->eb_len = (long)(value); memcpy((char *)&value, (char *)&(buffer[30]), 2); afu->cr_device = (long)ntohs(value); memcpy((char *)&value, (char *)&(buffer[32]), 2); afu->cr_vendor = (long)ntohs(value); memcpy((char *)&lvalue, (char *)&(buffer[34]), 4); afu->cr_class = ntohl(lvalue); //no better place to put this right now afu->prefault_mode = CXL_PREFAULT_MODE_NONE; break; } case PSLSE_MEMORY_READ: DPRINTF("AFU MEMORY READ\n"); if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) { warn_msg ("Socket failure getting memory read size"); _all_idle(afu); break; } size = (uint8_t) buffer[0]; if (get_bytes_silent(afu->fd, sizeof(uint64_t), buffer, -1, 0) < 0) { warn_msg ("Socket failure getting memory read addr"); _all_idle(afu); break; } memcpy((char *)&addr, (char *)buffer, sizeof(uint64_t)); addr = ntohll(addr); _handle_read(afu, addr, size); break; case PSLSE_MEMORY_WRITE: DPRINTF("AFU MEMORY WRITE\n"); if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) { warn_msg ("Socket failure getting memory write size"); _all_idle(afu); break; } size = (uint8_t) buffer[0]; if (get_bytes_silent(afu->fd, sizeof(uint64_t), buffer, -1, 0) < 0) { _all_idle(afu); break; } memcpy((char *)&addr, (char *)buffer, sizeof(uint64_t)); addr = ntohll(addr); if (get_bytes_silent(afu->fd, size, buffer, 1000, 0) < 0) { warn_msg ("Socket failure getting memory write data"); _all_idle(afu); break; } _handle_write(afu, addr, size, buffer); break; case PSLSE_MEMORY_TOUCH: DPRINTF("AFU MEMORY TOUCH\n"); if (get_bytes_silent(afu->fd, 1, buffer, 1000, 0) < 0) { warn_msg ("Socket failure getting memory touch size"); _all_idle(afu); break; } size = buffer[0]; if (get_bytes_silent(afu->fd, sizeof(uint64_t), buffer, -1, 0) < 0) { warn_msg ("Socket failure getting memory touch addr"); _all_idle(afu); break; } memcpy((char *)&addr, (char *)buffer, sizeof(uint64_t)); addr = ntohll(addr); _handle_touch(afu, addr, size); break; case PSLSE_MMIO_ACK: _handle_ack(afu); break; case PSLSE_INTERRUPT: if (_handle_interrupt(afu) < 0) { perror("Interrupt Failure"); goto psl_fail; } break; case PSLSE_AFU_ERROR: if (_handle_afu_error(afu) < 0) { perror("AFU ERROR Failure"); goto psl_fail; } break; default: break; } } psl_fail: afu->attached = 0; pthread_exit(NULL); }