Ejemplo n.º 1
0
// Associate client to PSL
static int _client_associate(struct client *client, uint8_t id, char afu_type)
{
    struct psl *psl;
    uint32_t mmio_offset, mmio_size;
    uint8_t major, minor;
    int i, context, clients;
    uint8_t rc[2];

    // Associate with PSL
    rc[0] = PSLSE_DETACH;
    psl = _find_psl(id, &major, &minor);
    if (!psl) {
        info_msg("Did not find valid PSL for afu%d.%d\n", major, minor);
        put_bytes(client->fd, 1, &(rc[0]), fp, -1, -1);
        close_socket(&(client->fd));
        return -1;
    }

    // Check AFU type is valid for connection
    switch (afu_type) {
    case 'd':
        if (!dedicated_mode_support(psl->mmio)) {
            warn_msg
            ("afu%d.%d is does not support dedicated mode\n",
             major, minor);
            put_bytes(client->fd, 1, &(rc[0]), fp, psl->dbg_id, -1);
            close_socket(&(client->fd));
            return -1;
        }
        break;
    case 'm':
    case 's':
        if (!directed_mode_support(psl->mmio)) {
            warn_msg("afu%d.%d is does not support directed mode\n",
                     major, minor);
            put_bytes(client->fd, 1, &(rc[0]), fp, psl->dbg_id, -1);
            close_socket(&(client->fd));
            return -1;
        }
        break;
    default:
        warn_msg("AFU device type '%c' is not valid\n", afu_type);
        put_bytes(client->fd, 1, &(rc[0]), fp, psl->dbg_id, -1);
        close_socket(&(client->fd));
        return -1;
    }

    // check to see if device is already open
    // lgt - I think I can open any combination of m/s upto max
    if ( afu_type == 'd' /* | afu_type == 'm' */ ) {
        if (psl->client[0] != NULL) {
            warn_msg
            ("afu%d.%d%c is already open\n",
             major, minor, afu_type);
            put_bytes(client->fd, 1, &(rc[0]), fp, psl->dbg_id, -1);
            // should I really close the socket in this case?
            close_socket(&(client->fd));
            return -1;
        }
    }

    // Look for open client slot
    // dedicated - client[0] is the only client.
    // afu-directed - is client[0] the master? not necessarily
    assert(psl->max_clients > 0);
    clients = 0;
    context = -1;
    for (i = 0; i < psl->max_clients; i++) {
        if (psl->client[i] != NULL)
            ++clients;
        if ((context < 0) && (psl->client[i] == NULL)) {
            client->context = context = i;
            client->state = CLIENT_VALID;
            client->pending = 0;
            psl->client[i] = client;
            break;
        }
    }
    if (context < 0) {
        info_msg("No room for new client on afu%d.%d\n", major, minor);
        put_bytes(client->fd, 1, &(rc[0]), fp, psl->dbg_id, -1);
        close_socket(&(client->fd));
        return -1;
    }

    // Attach to PSL
    // i should point to an open slot
    rc[0] = PSLSE_OPEN;
    rc[1] = context;
    mmio_offset = 0;
    if (psl->mmio->desc.PerProcessPSA & PROCESS_PSA_REQUIRED) {
        mmio_size = psl->mmio->desc.PerProcessPSA & PSA_MASK;
        mmio_size *= FOUR_K;
        mmio_offset = psl->mmio->desc.PerProcessPSA_offset;
        mmio_offset += mmio_size * i;
    } else {
        mmio_size = MMIO_FULL_RANGE;
    }
    client->mmio_size = mmio_size;
    client->mmio_offset = mmio_offset;
    client->max_irqs = PSL_MAX_IRQS / psl->mmio->desc.num_of_processes;
    client->type = afu_type;

    // Send reset to AFU, if no other clients already connected
    // hmmm...  this might be a problem...
    // I need only do this on the very first client in m/s mode...
    // if this is dedicated client (only one), send a reset
    // if this an an afu-directed client, only send a reset on the very first open...
    // don't even send a reset if we've dropped to 0 clients and are now opening a new one
    switch ( afu_type ) {
    case 'd':
        // send a reset
        debug_msg( "_client_associate: adding reset for open of dedicated device", afu_type );
        add_job(psl->job, PSL_JOB_RESET, 0L);
        // ignores psl->has_been_reset
        break;
    case 'm':
    case 's':
        // send a reset the very first time we associate a client
        if ( psl->has_been_reset == 0 ) {
            debug_msg( "_client_associate: adding reset for first open of afu-directed device", afu_type );
            add_job(psl->job, PSL_JOB_RESET, 0L);
            psl->has_been_reset = 1;
        }
        break;
    default:
        debug_msg( "_client_associate: invalid afu_type: %c", afu_type );
    }

    // Acknowledge to client
    if (put_bytes(client->fd, 2, &(rc[0]), fp, psl->dbg_id, context) < 0) {
        close_socket(&(client->fd));
        return -1;
    }
    debug_context_add(fp, psl->dbg_id, context);

    return 0;
}
Ejemplo n.º 2
0
Archivo: psl.c Proyecto: open-cpu/pslse
// 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;
}
Ejemplo n.º 3
0
Archivo: psl.c Proyecto: ibm-capi/pslse
// Handle events from AFU
static void _handle_afu(struct psl *psl)
{
	struct client *client;
	uint64_t error;
	uint8_t *buffer;
	int reset_done;
	int i;
	size_t size;

	reset_done = _handle_aux2(psl, &(psl->parity_enabled),
				 &(psl->latency), &error);
//printf("after reset_done in handle_afu \n");
	if (error) {
	  if (dedicated_mode_support(psl->mmio)) {
		client = psl->client[0];
		size = 1 + sizeof(uint64_t);
		buffer = (uint8_t *) malloc(size);
		buffer[0] = PSLSE_AFU_ERROR;
		error = htonll(error);
		memcpy((char *)&(buffer[1]), (char *)&error, sizeof(error));
	        warn_msg("%s: Received JERROR: 0x%016"PRIx64" in afu-dedicated mode", psl->name, error);
		if (put_bytes
		    (client->fd, size, buffer, psl->dbg_fp, psl->dbg_id,
		     0) < 0) {
			client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
		}
	  }
	  if (directed_mode_support(psl->mmio)) {
	        // afu error gets logged by OS. - print warning message
                // no interrupt/event is sent up to the application - don't "put_bytes" back to client(s)
	        // all clients lose connection to afu but how is this observered by the client?
	        warn_msg("%s: Received JERROR: 0x%016"PRIx64" in afu-directed mode", psl->name, error);
		for (i = 0; i < psl->max_clients; i++) {
			if (psl->client[i] == NULL)
				continue;
			client_drop(psl->client[i], PSL_IDLE_CYCLES, CLIENT_NONE);
		}
	  }
	}
	handle_mmio_ack(psl->mmio, psl->parity_enabled);
	if (psl->cmd != NULL) {
		if (reset_done)
			psl->cmd->credits = psl->cmd->parms->credits;
#if defined PSL9lite || defined PSL9
		handle_caia2_cmds(psl->cmd);
#endif /* ifdef PSL9 or PSL9lite */
#ifdef PSL9
		handle_dma0_port(psl->cmd);
		handle_dma0_write(psl->cmd);
		handle_dma0_sent_sts(psl->cmd);
		handle_dma0_read(psl->cmd);
#endif /* ifdef PSL9 */

		handle_response(psl->cmd);
		handle_buffer_write(psl->cmd);
		handle_buffer_read(psl->cmd);
		handle_buffer_data(psl->cmd, psl->parity_enabled);
		handle_mem_write(psl->cmd);
		handle_touch(psl->cmd);
		handle_cmd(psl->cmd, psl->parity_enabled, psl->latency);
		handle_interrupt(psl->cmd);

	}
}