/* Update the system EPOW status */ static void fsp_epow_update(u8 *epow, int epow_type) { int16_t old_epow_status[OPAL_SYSEPOW_MAX]; bool epow_changed = false; int rc; lock(&epow_lock); /* Copy over and clear system EPOW status */ memcpy(old_epow_status, epow_status, sizeof(old_epow_status)); switch(epow_type) { case EPOW_NORMAL: epow_process_base_event(epow); /* FIXME: IPL mode information present but not used */ break; case EPOW_EX1: epow_process_base_event(epow); epow_process_ex1_event(epow); /* FIXME: IPL mode information present but not used */ /* FIXME: Key position information present but not used */ break; case EPOW_EX2: /*FIXME: IPL mode information present but not used */ /*FIXME: Key position information present but not used */ break; default: prlog(PR_WARNING, "Unknown EPOW event notification\n"); break; } unlock(&epow_lock); if (memcmp(epow_status, old_epow_status, sizeof(epow_status))) epow_changed = true; /* Send OPAL message notification */ if (epow_changed) { rc = opal_queue_msg(OPAL_MSG_EPOW, NULL, NULL); if (rc) { prlog(PR_ERR, "OPAL EPOW message queuing failed\n"); return; } } }
static int64_t opal_flash_op(enum flash_op op, uint64_t id, uint64_t offset, uint64_t buf, uint64_t size, uint64_t token) { struct flash *flash = NULL; int rc; if (!try_lock(&flash_lock)) return OPAL_BUSY; list_for_each(&flashes, flash, list) if (flash->id == id) break; if (flash->id != id) { /* Couldn't find the flash */ rc = OPAL_PARAMETER; goto err; } if (flash->busy) { rc = OPAL_BUSY; goto err; } if (size >= flash->size || offset >= flash->size || offset + size > flash->size) { rc = OPAL_PARAMETER; goto err; } /* * These ops intentionally have no smarts (ecc correction or erase * before write) to them. * Skiboot is simply exposing the PNOR flash to the host. * The host is expected to understand that this is a raw flash * device and treat it as such. */ switch (op) { case FLASH_OP_READ: rc = blocklevel_raw_read(flash->bl, offset, (void *)buf, size); break; case FLASH_OP_WRITE: rc = blocklevel_raw_write(flash->bl, offset, (void *)buf, size); break; case FLASH_OP_ERASE: rc = blocklevel_erase(flash->bl, offset, size); break; default: assert(0); } if (rc) { rc = OPAL_HARDWARE; goto err; } unlock(&flash_lock); opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL, token, rc); return OPAL_ASYNC_COMPLETION; err: unlock(&flash_lock); return rc; }
int main(void) { struct opal_msg_entry* entry; int free_size = OPAL_MAX_MSGS; int nfree = free_size; int npending = 0; int r; static struct opal_msg m; uint64_t *m_ptr = (uint64_t *)&m; zalloc_should_fail = true; zalloc_should_fail_after = 3; opal_init_msg(); zalloc_should_fail = false; opal_init_msg(); assert(list_count(&msg_pending_list) == npending); assert(list_count(&msg_free_list) == nfree); /* Callback. */ r = opal_queue_msg(0, &magic, callback, (u64)0, (u64)1, (u64)2); assert(r == 0); assert(list_count(&msg_pending_list) == ++npending); assert(list_count(&msg_free_list) == --nfree); r = opal_get_msg(m_ptr, sizeof(m)); assert(r == 0); assert(m.params[0] == 0); assert(m.params[1] == 1); assert(m.params[2] == 2); assert(list_count(&msg_pending_list) == --npending); assert(list_count(&msg_free_list) == ++nfree); /* No params. */ r = opal_queue_msg(0, NULL, NULL); assert(r == 0); assert(list_count(&msg_pending_list) == ++npending); assert(list_count(&msg_free_list) == --nfree); r = opal_get_msg(m_ptr, sizeof(m)); assert(r == 0); assert(list_count(&msg_pending_list) == --npending); assert(list_count(&msg_free_list) == ++nfree); /* > 8 params (ARRAY_SIZE(entry->msg.params) */ r = opal_queue_msg(0, NULL, NULL, 0, 1, 2, 3, 4, 5, 6, 7, 0xBADDA7A); assert(r == 0); assert(list_count(&msg_pending_list) == ++npending); assert(list_count(&msg_free_list) == --nfree); r = opal_get_msg(m_ptr, sizeof(m)); assert(r == 0); assert(list_count(&msg_pending_list) == --npending); assert(list_count(&msg_free_list) == ++nfree); assert(m.params[0] == 0); assert(m.params[1] == 1); assert(m.params[2] == 2); assert(m.params[3] == 3); assert(m.params[4] == 4); assert(m.params[5] == 5); assert(m.params[6] == 6); assert(m.params[7] == 7); /* 8 params (ARRAY_SIZE(entry->msg.params) */ r = opal_queue_msg(0, NULL, NULL, 0, 10, 20, 30, 40, 50, 60, 70); assert(r == 0); assert(list_count(&msg_pending_list) == ++npending); assert(list_count(&msg_free_list) == --nfree); r = opal_get_msg(m_ptr, sizeof(m)); assert(r == 0); assert(list_count(&msg_pending_list) == --npending); assert(list_count(&msg_free_list) == ++nfree); assert(m.params[0] == 0); assert(m.params[1] == 10); assert(m.params[2] == 20); assert(m.params[3] == 30); assert(m.params[4] == 40); assert(m.params[5] == 50); assert(m.params[6] == 60); assert(m.params[7] == 70); /* Full list (no free nodes in pending). */ while (nfree > 0) { r = opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL); assert(r == 0); assert(list_count(&msg_pending_list) == ++npending); assert(list_count(&msg_free_list) == --nfree); } assert(list_count(&msg_free_list) == 0); assert(nfree == 0); assert(npending == OPAL_MAX_MSGS); r = opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL); assert(r == 0); assert(list_count(&msg_pending_list) == OPAL_MAX_MSGS+1); assert(list_count(&msg_pending_list) == ++npending); assert(list_count(&msg_free_list) == nfree); /* Make zalloc fail to test error handling. */ zalloc_should_fail = true; r = opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL); assert(r == OPAL_RESOURCE); assert(list_count(&msg_pending_list) == OPAL_MAX_MSGS+1); assert(list_count(&msg_pending_list) == npending); assert(list_count(&msg_free_list) == nfree); /* Empty list (no nodes). */ while(!list_empty(&msg_pending_list)) { r = opal_get_msg(m_ptr, sizeof(m)); assert(r == 0); npending--; nfree++; } assert(list_count(&msg_pending_list) == npending); assert(list_count(&msg_free_list) == nfree); assert(npending == 0); assert(nfree == OPAL_MAX_MSGS+1); r = opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL); assert(r == 0); assert(list_count(&msg_pending_list) == ++npending); assert(list_count(&msg_free_list) == --nfree); /* Request invalid size. */ r = opal_get_msg(m_ptr, sizeof(m) - 1); assert(r == OPAL_PARAMETER); /* Pass null buffer. */ r = opal_get_msg(NULL, sizeof(m)); assert(r == OPAL_PARAMETER); /* Get msg when none are pending. */ r = opal_get_msg(m_ptr, sizeof(m)); assert(r == 0); r = opal_get_msg(m_ptr, sizeof(m)); assert(r == OPAL_RESOURCE); #define test_queue_num(type, val) \ r = opal_queue_msg(0, NULL, NULL, \ (type)val, (type)val, (type)val, (type)val, \ (type)val, (type)val, (type)val, (type)val); \ assert(r == 0); \ opal_get_msg(m_ptr, sizeof(m)); \ assert(r == OPAL_SUCCESS); \ assert(m.params[0] == (type)val); \ assert(m.params[1] == (type)val); \ assert(m.params[2] == (type)val); \ assert(m.params[3] == (type)val); \ assert(m.params[4] == (type)val); \ assert(m.params[5] == (type)val); \ assert(m.params[6] == (type)val); \ assert(m.params[7] == (type)val) /* Test types of various widths */ test_queue_num(u64, -1); test_queue_num(s64, -1); test_queue_num(u32, -1); test_queue_num(s32, -1); test_queue_num(u16, -1); test_queue_num(s16, -1); test_queue_num(u8, -1); test_queue_num(s8, -1); /* Clean up the list to keep valgrind happy. */ while(!list_empty(&msg_free_list)) { entry = list_pop(&msg_free_list, struct opal_msg_entry, link); assert(entry); free(entry); } while(!list_empty(&msg_pending_list)) { entry = list_pop(&msg_pending_list, struct opal_msg_entry, link); assert(entry); free(entry); } return 0; }