[Skiboot] [PATCH 2/2] Asynchronous LID/Resource loading for FSP systems

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Mon Mar 30 23:09:33 AEDT 2015


On 03/24/2015 09:01 AM, Stewart Smith wrote:
> This moves away from using fsp_sync_msg in fsp_fetch_data and instead
> using the platform hooks for start_preload_resource() to actually queue
> up a load and having the plumbing for checking if a resource is loaded yet.
> 
> This gets rid of the "pollers called with locks held" warning we got
> heaps of previously. You can now boot some FSP systems without getting
> this warning at all.
> 
> This also sets the stage for starting load of LIDs much earlier to when
> they're needed, improving boot time.
> 
> Signed-off-by: Stewart Smith <stewart at linux.vnet.ibm.com>
> ---

.../...

>  
>  /*
>   * Asynchronous fsp fetch data call
> @@ -2275,12 +2224,156 @@ static struct {
>  	{ RESOURCE_ID_CAPP,	CAPP_IDX_VENICE_DD20,	0x80a02004 },
>  };
>  
> +static void fsp_start_fetching_next_lid(void);
> +static void fsp_fetch_lid_next_chunk(struct fsp_fetch_lid_item *last);
> +
> +static void fsp_fetch_lid_complete(struct fsp_msg *msg)
> +{
> +	struct fsp_fetch_lid_item *last;
> +	uint32_t woffset, wlen;
> +	uint8_t rc;
> +
> +	lock(&fsp_fetch_lock);
> +	last = list_top(&fsp_fetch_lid_queue, struct fsp_fetch_lid_item, link);
> +	fsp_tce_unmap(PSI_DMA_FETCH, last->bsize);
> +
> +	woffset = msg->resp->data.words[1];
> +	wlen = msg->resp->data.words[2];
> +	rc = (msg->resp->word1 >> 8) & 0xff;
> +
> +	/* Fall back to a PHYP LID for kernel loads */
> +	if (rc && last->lid_no == KERNEL_LID_OPAL) {
> +		const char *ltype = dt_prop_get_def(dt_root, "lid-type", NULL);
> +		if (!ltype || strcmp(ltype, "opal")) {
> +			prerror("Failed to load in OPAL mode...\n");
> +			last->result = OPAL_PARAMETER;
> +			last = list_pop(&fsp_fetch_lid_queue,
> +					struct fsp_fetch_lid_item, link);
> +			list_add_tail(&fsp_fetched_lid, &last->link);
> +			fsp_start_fetching_next_lid();
> +			unlock(&fsp_fetch_lock);

fsp_freemsg(msg);

> +			return;
> +		}
> +		printf("Trying to load as PHYP LID...\n");
> +		last->lid = KERNEL_LID_PHYP;

You have to reset last structure here (like remaining, size etc).


> +		/* Retry with different LID */
> +		fsp_fetch_lid_next_chunk(last);

and return here?

> +	}
> +
> +	if (rc !=0 && rc != 2) {
> +		last->result = -EIO;
> +		last = list_pop(&fsp_fetch_lid_queue, struct fsp_fetch_lid_item, link);
> +		list_add_tail(&fsp_fetched_lid, &last->link);
> +		fsp_start_fetching_next_lid();
> +		unlock(&fsp_fetch_lock);

fsp_freemsg(msg);

> +		return;
> +	}
> +
> +	if (rc == 0)
> +		last->result = OPAL_SUCCESS;
> +
> +	fsp_freemsg(msg);
> +
> +	last->remaining -= wlen;
> +	*(last->length) += wlen;
> +	last->buffer += wlen;
> +	last->offset += wlen;
> +
> +	prlog(PR_DEBUG, "FSP: LID %x Chunk read -> rc=0x%02x off: %08x"
> +	      " twritten: %08x\n", last->lid, rc, woffset, wlen);
> +
> +	fsp_fetch_lid_next_chunk(last);
> +
> +	unlock(&fsp_fetch_lock);
> +}
> +


.../...


>  int fsp_start_preload_resource(enum resource_id id, uint32_t idx,
>  				void *buf, size_t *size)
>  {
> -	uint32_t lid_no = 0, lid;
> -	size_t tmp_size;
> -	int rc, i;
> +	struct fsp_fetch_lid_item *resource;
> +	uint32_t lid_no = 0;
> +	int i;
> +
> +	resource = malloc(sizeof(struct fsp_fetch_lid_item));
> +	assert(resource != NULL);
> +
> +	resource->id = id;
> +	resource->idx = idx;
> +
> +	resource->offset = 0;
> +	resource->buffer = buf;
> +	resource->remaining = *size;
> +	*size = 0;
> +	resource->length = size;
> +	resource->result = OPAL_BUSY;
>  
>  	for (i = 0; i < ARRAY_SIZE(fsp_lid_map); i++) {
>  		if (id != fsp_lid_map[i].id)
> @@ -2294,34 +2387,111 @@ int fsp_start_preload_resource(enum resource_id id, uint32_t idx,
>  	if (lid_no == 0)

Free resource before return?

>  		return OPAL_PARAMETER;
>  
> -retry:
> -	tmp_size = *size;
> -
>  	printf("Trying to load OPAL LID %08x...\n", lid_no);
> -	lid = fsp_adjust_lid_side(lid_no);
> -	rc = fsp_fetch_data(0, FSP_DATASET_NONSP_LID, lid, 0, buf, &tmp_size);
> +	resource->lid_no = lid_no;
> +	resource->lid = fsp_adjust_lid_side(lid_no);
>  
> -	/* Fall back to a PHYP LID for kernel loads */
> -	if (rc && lid_no == KERNEL_LID_OPAL) {
> -		const char *ltype = dt_prop_get_def(dt_root, "lid-type", NULL);
> -		if (!ltype || strcmp(ltype, "opal")) {
> -			prerror("Failed to load in OPAL mode...\n");
> -			return OPAL_PARAMETER;
> +	lock(&fsp_fetch_lock);
> +	list_add_tail(&fsp_fetch_lid_queue, &resource->link);
> +	fsp_start_fetching_next_lid();
> +	unlock(&fsp_fetch_lock);
> +
> +	return OPAL_SUCCESS;
> +}
> +
> +int fsp_resource_loaded(enum resource_id id, uint32_t idx)
> +{
> +	struct fsp_fetch_lid_item *resource = NULL;
> +	struct fsp_fetch_lid_item *r;
> +	int rc = OPAL_BUSY;
> +
> +	lock(&fsp_fetch_lock);
> +	list_for_each(&fsp_fetched_lid, r, link) {
> +		if (r->id == id && r->idx == idx) {
> +			resource = r;
> +			break;
>  		}
> -		printf("Trying to load as PHYP LID...\n");
> -		lid_no = KERNEL_LID_PHYP;
> -		goto retry;
>  	}
>  
> -	if (rc) {
> -		prerror("Failed to load LID\n");
> -		return rc;
> +	if (resource) {
> +		rc = resource->result;
> +		if (rc == OPAL_SUCCESS) {

I think this should be rc != OPAL_BUSY.. else we won't be deleting resource in
case of load failure.



> +			list_del(&resource->link);
> +			free(resource);
> +		}
>  	}
> -	if (*size < tmp_size)
> -		return OPAL_INTERNAL_ERROR;
> -	*size = tmp_size;
> +	unlock(&fsp_fetch_lock);
> +
> +	return rc;
> +}
> +
> +static int fsp_lid_loaded(uint32_t lid_no)
> +{
> +	struct fsp_fetch_lid_item *resource = NULL;
> +	struct fsp_fetch_lid_item *r;
> +	int rc = OPAL_BUSY;
> +
> +	lock(&fsp_fetch_lock);
> +	list_for_each(&fsp_fetched_lid, r, link) {
> +		if (r->lid_no == lid_no) {
> +			resource = r;
> +			break;
> +		}
> +	}
> +
> +	if (resource) {
> +		rc = resource->result;
> +		if (rc == OPAL_SUCCESS) {

Ditto.

> +			list_del(&resource->link);
> +			free(resource);
> +		}
> +	}
> +	unlock(&fsp_fetch_lock);
> +
> +	return rc;
> +}
> +
> +int fsp_load_lid(uint32_t lid_no, char *buf, size_t *size)
> +{
> +	struct fsp_fetch_lid_item *resource;
> +	int r;
> +
> +	resource = malloc(sizeof(struct fsp_fetch_lid_item));
> +	assert(resource != NULL);
> +
> +	resource->id = -1;
> +	resource->idx = -1;
> +
> +	resource->offset = 0;
> +	resource->buffer = buf;
> +	resource->remaining = *size;
> +	*size = 0;
> +	resource->length = size;
> +	resource->result = OPAL_BUSY;
> +
> +	if (lid_no == 0)

Free resource before return?

-Vasant



More information about the Skiboot mailing list