/* * visorchannel_create() - creates the struct visorchannel abstraction for a * data area in memory, but does NOT modify this data * area * @physaddr: physical address of start of channel * @gfp: gfp_t to use when allocating memory for the data struct * @guid: GUID that identifies channel type; * @needs_lock: must specify true if you have multiple threads of execution * that will be calling visorchannel methods of this * visorchannel at the same time * * Return: pointer to visorchannel that was created if successful, * otherwise NULL */ struct visorchannel *visorchannel_create(u64 physaddr, gfp_t gfp, const guid_t *guid, bool needs_lock) { struct visorchannel *channel; int err; size_t size = sizeof(struct channel_header); if (physaddr == 0) return NULL; channel = kzalloc(sizeof(*channel), gfp); if (!channel) return NULL; channel->needs_lock = needs_lock; spin_lock_init(&channel->insert_lock); spin_lock_init(&channel->remove_lock); /* * Video driver constains the efi framebuffer so it will get a conflict * resource when requesting its full mem region. Since we are only * using the efi framebuffer for video we can ignore this. Remember that * we haven't requested it so we don't try to release later on. */ channel->requested = request_mem_region(physaddr, size, VISOR_DRV_NAME); if (!channel->requested && !guid_equal(guid, &visor_video_guid)) /* we only care about errors if this is not the video channel */ goto err_destroy_channel; channel->mapped = memremap(physaddr, size, MEMREMAP_WB); if (!channel->mapped) { release_mem_region(physaddr, size); goto err_destroy_channel; } channel->physaddr = physaddr; channel->nbytes = size; err = visorchannel_read(channel, 0, &channel->chan_hdr, size); if (err) goto err_destroy_channel; size = (ulong)channel->chan_hdr.size; memunmap(channel->mapped); if (channel->requested) release_mem_region(channel->physaddr, channel->nbytes); channel->mapped = NULL; channel->requested = request_mem_region(channel->physaddr, size, VISOR_DRV_NAME); if (!channel->requested && !guid_equal(guid, &visor_video_guid)) /* we only care about errors if this is not the video channel */ goto err_destroy_channel; channel->mapped = memremap(channel->physaddr, size, MEMREMAP_WB); if (!channel->mapped) { release_mem_region(channel->physaddr, size); goto err_destroy_channel; } channel->nbytes = size; guid_copy(&channel->guid, guid); return channel; err_destroy_channel: visorchannel_destroy(channel); return NULL; }
/* Creates the VISORCHANNEL abstraction for a data area in memory, but does * NOT modify this data area. */ static VISORCHANNEL * visorchannel_create_guts(HOSTADDRESS physaddr, ulong channelBytes, VISORCHANNEL *parent, ulong off, uuid_le guid, BOOL needs_lock) { VISORCHANNEL *p = NULL; void *rc = NULL; p = kmalloc(sizeof(VISORCHANNEL), GFP_KERNEL|__GFP_NORETRY); if (p == NULL) { ERRDRV("allocation failed: (status=0)\n"); rc = NULL; goto Away; } p->memregion = NULL; p->needs_lock = needs_lock; spin_lock_init(&p->insert_lock); spin_lock_init(&p->remove_lock); /* prepare chan_hdr (abstraction to read/write channel memory) */ if (parent == NULL) p->memregion = visor_memregion_create(physaddr, sizeof(CHANNEL_HEADER)); else p->memregion = visor_memregion_create_overlapped(parent->memregion, off, sizeof(CHANNEL_HEADER)); if (p->memregion == NULL) { ERRDRV("visor_memregion_create failed failed: (status=0)\n"); rc = NULL; goto Away; } if (visor_memregion_read(p->memregion, 0, &p->chan_hdr, sizeof(CHANNEL_HEADER)) < 0) { ERRDRV("visor_memregion_read failed: (status=0)\n"); rc = NULL; goto Away; } if (channelBytes == 0) /* we had better be a CLIENT of this channel */ channelBytes = (ulong) p->chan_hdr.Size; if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) /* we had better be a CLIENT of this channel */ guid = p->chan_hdr.Type; if (visor_memregion_resize(p->memregion, channelBytes) < 0) { ERRDRV("visor_memregion_resize failed: (status=0)\n"); rc = NULL; goto Away; } p->size = channelBytes; p->guid = guid; rc = p; Away: if (rc == NULL) { if (p != NULL) { visorchannel_destroy(p); p = NULL; } } return rc; }
/* * visorchannel_create_guts() - creates the struct visorchannel abstraction * for a data area in memory, but does NOT modify * this data area * @physaddr: physical address of start of channel * @channel_bytes: size of the channel in bytes; this may 0 if the channel has * already been initialized in memory (which is true for all * channels provided to guest environments by the s-Par * back-end), in which case the actual channel size will be * read from the channel header in memory * @gfp: gfp_t to use when allocating memory for the data struct * @guid: uuid that identifies channel type; this may 0 if the channel * has already been initialized in memory (which is true for all * channels provided to guest environments by the s-Par * back-end), in which case the actual channel guid will be * read from the channel header in memory * @needs_lock: must specify true if you have multiple threads of execution * that will be calling visorchannel methods of this * visorchannel at the same time * * Return: pointer to visorchannel that was created if successful, * otherwise NULL */ static struct visorchannel * visorchannel_create_guts(u64 physaddr, unsigned long channel_bytes, gfp_t gfp, uuid_le guid, bool needs_lock) { struct visorchannel *channel; int err; size_t size = sizeof(struct channel_header); if (physaddr == 0) return NULL; channel = kzalloc(sizeof(*channel), gfp); if (!channel) return NULL; channel->needs_lock = needs_lock; spin_lock_init(&channel->insert_lock); spin_lock_init(&channel->remove_lock); /* * Video driver constains the efi framebuffer so it will get a * conflict resource when requesting its full mem region. Since * we are only using the efi framebuffer for video we can ignore * this. Remember that we haven't requested it so we don't try to * release later on. */ channel->requested = request_mem_region(physaddr, size, MYDRVNAME); if (!channel->requested && uuid_le_cmp(guid, spar_video_guid)) /* we only care about errors if this is not the video channel */ goto err_destroy_channel; channel->mapped = memremap(physaddr, size, MEMREMAP_WB); if (!channel->mapped) { release_mem_region(physaddr, size); goto err_destroy_channel; } channel->physaddr = physaddr; channel->nbytes = size; err = visorchannel_read(channel, 0, &channel->chan_hdr, sizeof(struct channel_header)); if (err) goto err_destroy_channel; /* we had better be a CLIENT of this channel */ if (channel_bytes == 0) channel_bytes = (ulong)channel->chan_hdr.size; if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) guid = channel->chan_hdr.chtype; memunmap(channel->mapped); if (channel->requested) release_mem_region(channel->physaddr, channel->nbytes); channel->mapped = NULL; channel->requested = request_mem_region(channel->physaddr, channel_bytes, MYDRVNAME); if (!channel->requested && uuid_le_cmp(guid, spar_video_guid)) /* we only care about errors if this is not the video channel */ goto err_destroy_channel; channel->mapped = memremap(channel->physaddr, channel_bytes, MEMREMAP_WB); if (!channel->mapped) { release_mem_region(channel->physaddr, channel_bytes); goto err_destroy_channel; } channel->nbytes = channel_bytes; channel->guid = guid; return channel; err_destroy_channel: visorchannel_destroy(channel); return NULL; }