[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