/*
 * 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;
}
Exemple #2
0
/* 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;
}
Exemple #3
0
/*
 * 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;
}