static void unassign_storage(SCLPDevice *sclp, SCCB *sccb) { MemoryRegion *mr = NULL; AssignStorage *assign_info = (AssignStorage *) sccb; sclpMemoryHotplugDev *mhd = get_sclp_memory_hotplug_dev(); ram_addr_t unassign_addr; MemoryRegion *sysmem = get_system_memory(); if (!mhd) { sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND); return; } unassign_addr = (assign_info->rn - 1) * mhd->rzm; /* if the addr is a multiple of 256 MB */ if ((unassign_addr % MEM_SECTION_SIZE == 0) && (unassign_addr >= mhd->padded_ram_size)) { mhd->standby_state_map[(unassign_addr - mhd->padded_ram_size) / MEM_SECTION_SIZE] = 0; /* find the specified memory region and destroy it */ mr = memory_region_find(sysmem, unassign_addr, 1).mr; memory_region_unref(mr); if (mr) { int i; int is_removable = 1; ram_addr_t map_offset = (unassign_addr - mhd->padded_ram_size - (unassign_addr - mhd->padded_ram_size) % mhd->standby_subregion_size); /* Mark all affected subregions as 'standby' once again */ for (i = 0; i < (mhd->standby_subregion_size / MEM_SECTION_SIZE); i++) { if (mhd->standby_state_map[i + map_offset / MEM_SECTION_SIZE]) { is_removable = 0; break; } } if (is_removable) { memory_region_del_subregion(sysmem, mr); object_unref(OBJECT(mr)); } } } sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION); }