// Initialize and start PSL thread // // The return value is encode int a 16-bit value divided into 4 for each // possible adapter. Then the 4 bits in each adapter represent the 4 possible // AFUs on an adapter. For example: afu0.0 is 0x8000 and afu3.0 is 0x0008. uint16_t psl_init(struct psl **head, struct parms *parms, char *id, char *host, int port, pthread_mutex_t * lock, FILE * dbg_fp) { struct psl *psl; struct job_event *reset; uint16_t location; location = 0x8000; if ((psl = (struct psl *)calloc(1, sizeof(struct psl))) == NULL) { perror("malloc"); error_msg("Unable to allocation memory for psl"); goto init_fail; } psl->timeout = parms->timeout; if ((strlen(id) != 6) || strncmp(id, "afu", 3) || (id[4] != '.')) { warn_msg("Invalid afu name: %s", id); goto init_fail; } if ((id[3] < '0') || (id[3] > '3')) { warn_msg("Invalid afu major: %c", id[3]); goto init_fail; } if ((id[5] < '0') || (id[5] > '3')) { warn_msg("Invalid afu minor: %c", id[5]); goto init_fail; } psl->dbg_fp = dbg_fp; psl->major = id[3] - '0'; psl->minor = id[5] - '0'; psl->dbg_id = psl->major << 4; psl->dbg_id |= psl->minor; location >>= (4 * psl->major); location >>= psl->minor; if ((psl->name = (char *)malloc(strlen(id) + 1)) == NULL) { perror("malloc"); error_msg("Unable to allocation memory for psl->name"); goto init_fail; } strcpy(psl->name, id); if ((psl->host = (char *)malloc(strlen(host) + 1)) == NULL) { perror("malloc"); error_msg("Unable to allocation memory for psl->host"); goto init_fail; } strcpy(psl->host, host); psl->port = port; psl->client = NULL; psl->idle_cycles = PSL_IDLE_CYCLES; psl->lock = lock; // Connect to AFU psl->afu_event = (struct AFU_EVENT *)malloc(sizeof(struct AFU_EVENT)); if (psl->afu_event == NULL) { perror("malloc"); goto init_fail; } info_msg("Attempting to connect AFU: %s @ %s:%d", psl->name, psl->host, psl->port); if (psl_init_afu_event(psl->afu_event, psl->host, psl->port) != PSL_SUCCESS) { warn_msg("Unable to connect AFU: %s @ %s:%d", psl->name, psl->host, psl->port); goto init_fail; } // DEBUG debug_afu_connect(psl->dbg_fp, psl->dbg_id); // Initialize job handler if ((psl->job = job_init(psl->afu_event, &(psl->state), psl->name, psl->dbg_fp, psl->dbg_id)) == NULL) { perror("job_init"); goto init_fail; } // Initialize mmio handler if ((psl->mmio = mmio_init(psl->afu_event, psl->timeout, psl->name, psl->dbg_fp, psl->dbg_id)) == NULL) { perror("mmio_init"); goto init_fail; } // Initialize cmd handler if ((psl->cmd = cmd_init(psl->afu_event, parms, psl->mmio, &(psl->state), psl->name, psl->dbg_fp, psl->dbg_id)) == NULL) { perror("cmd_init"); goto init_fail; } // Set credits for AFU if (psl_aux1_change(psl->afu_event, psl->cmd->credits) != PSL_SUCCESS) { warn_msg("Unable to set credits"); goto init_fail; } // Start psl loop thread if (pthread_create(&(psl->thread), NULL, _psl_loop, psl)) { perror("pthread_create"); goto init_fail; } // Add psl to list while ((*head != NULL) && ((*head)->major < psl->major)) { head = &((*head)->_next); } while ((*head != NULL) && ((*head)->major == psl->major) && ((*head)->minor < psl->minor)) { head = &((*head)->_next); } psl->_next = *head; if (psl->_next != NULL) psl->_next->_prev = psl; *head = psl; // Send reset to AFU reset = add_job(psl->job, PSL_JOB_RESET, 0L); while (psl->job->job == reset) { /*infinite loop */ lock_delay(psl->lock); } // Read AFU descriptor psl->state = PSLSE_DESC; read_descriptor(psl->mmio, psl->lock); // Finish PSL configuration psl->state = PSLSE_IDLE; if (dedicated_mode_support(psl->mmio)) { // AFU supports Dedicated Mode psl->max_clients = 1; } if (directed_mode_support(psl->mmio)) { // AFU supports Directed Mode psl->max_clients = psl->mmio->desc.num_of_processes; } if (psl->max_clients == 0) { error_msg("AFU programming model is invalid"); goto init_fail; } psl->client = (struct client **)calloc(psl->max_clients, sizeof(struct client *)); psl->cmd->client = psl->client; psl->cmd->max_clients = psl->max_clients; return location; init_fail: if (psl) { if (psl->afu_event) { psl_close_afu_event(psl->afu_event); free(psl->afu_event); } if (psl->host) free(psl->host); if (psl->name) free(psl->name); free(psl); } pthread_mutex_unlock(lock); return 0; }
struct cxl_afu_h * cxl_afu_open_dev(char *path) { char *x, *comment, *afu_id, *host, *port_str; struct cxl_afu_h *afu; FILE *fp; char hostdata[MAX_LINE_CHARS]; int port; uint64_t value; // Isolate AFU id from full path x = strrchr (path, '/'); x++; // Allocate AFU struct afu = (struct cxl_afu_h *) malloc (sizeof (struct cxl_afu_h)); if (!afu) { perror ("malloc"); return NULL; } // Allocate AFU_EVENT struct status.event = (struct AFU_EVENT *) malloc (sizeof (struct AFU_EVENT)); if (!status.event ) { perror ("malloc"); free (afu); return NULL; } psl_event_reset (status.event); // Connect to AFU server fp = fopen ("shim_host.dat", "r"); if (!fp) { perror ("fopen shim_host.dat"); free (status.event); free (afu); return NULL; } afu_id = x+1; host = NULL; port_str = NULL; while (strcmp (afu_id, x) && fgets (hostdata, MAX_LINE_CHARS, fp)) { afu_id = hostdata; comment = strchr(hostdata, '#'); if (comment) continue; host = strchr(hostdata, ','); if (host) { *host = '\0'; ++host; } else { printf ("Invalid format in shim_host.dat. Expected ',' :%s\n", hostdata); fclose (fp); free (status.event); free (afu); return NULL; } port_str = strchr(host, ':'); if (port_str) { *port_str = '\0'; ++port_str; } else { printf ("Invalid format in shim_host.dat. Expected ':' :%s\n", hostdata); fclose (fp); free (status.event); free (afu); return NULL; } } fclose (fp); // Convert port to int port = atoi (port_str); // Connect to AFU server printf ("Attempting to connect to %s:%d\n", host, port); if (psl_init_afu_event (status.event, host, port) != PSL_SUCCESS) { printf ("Unable to connect to %s:%d\n", host, port); free (status.event); free (afu); return NULL; } // Start PSL thread status.psl_state = PSL_INIT; status.event_occurred = 0; status.credits = 64; status.first_br = NULL; status.last_br = NULL; afu->id = afu_id; afu->mmio_size = 0; afu->attached = 0; afu->running = 0; pthread_create(&(afu->thread), NULL, psl, (void *) afu); psl_aux1_change (status.event, status.credits); // Reset AFU status.cmd.code = PSL_JOB_RESET; status.cmd.addr = 0; status.cmd.request = AFU_REQUEST; // FIXME: Add timeout while (status.cmd.request != AFU_IDLE) short_delay(); // Read AFU descriptor status.mmio.rnw = 1; status.mmio.dw = 1; status.mmio.desc = 1; // Offset 0x00 status.mmio.addr = 0; status.mmio.request = AFU_REQUEST; // FIXME: Add timeout while (status.mmio.request != AFU_IDLE) short_delay(); value = be64toh(status.mmio.data); afu->desc.req_prog_model = value && 0xffff; value >>= 16; afu->desc.num_of_afu_CRs = value && 0xffff; value >>= 16; afu->desc.num_of_processes = value && 0xffff; value >>= 16; afu->desc.num_ints_per_process = value && 0xffff; // Offset 0x20 status.mmio.addr = 8; status.mmio.request = AFU_REQUEST; // FIXME: Add timeout while (status.mmio.request != AFU_IDLE) short_delay(); afu->desc.AFU_CR_len = be64toh(status.mmio.data); // Offset 0x28 status.mmio.addr = 10; status.mmio.request = AFU_REQUEST; // FIXME: Add timeout while (status.mmio.request != AFU_IDLE) short_delay(); afu->desc.AFU_CR_offset = be64toh(status.mmio.data); // Offset 0x30 status.mmio.addr = 12; status.mmio.request = AFU_REQUEST; // FIXME: Add timeout while (status.mmio.request != AFU_IDLE) short_delay(); afu->desc.PerProcessPSA = be64toh(status.mmio.data); // Offset 0x38 status.mmio.addr = 14; status.mmio.request = AFU_REQUEST; // FIXME: Add timeout while (status.mmio.request != AFU_IDLE) short_delay(); afu->desc.PerProcessPSA_offset = be64toh(status.mmio.data); // Offset 0x40 status.mmio.addr = 16; status.mmio.request = AFU_REQUEST; // FIXME: Add timeout while (status.mmio.request != AFU_IDLE) short_delay(); afu->desc.AFU_EB_len = be64toh(status.mmio.data); // Offset 0x48 status.mmio.addr = 18; status.mmio.request = AFU_REQUEST; // FIXME: Add timeout while (status.mmio.request != AFU_IDLE) short_delay(); afu->desc.AFU_EB_offset = be64toh(status.mmio.data); status.mmio.desc = 0; return afu; }