dma_linux_seq.c 5.75 KB
Newer Older
Swann Perarnau's avatar
Swann Perarnau committed
1 2 3 4 5 6 7 8 9 10
/*******************************************************************************
 * Copyright 2019 UChicago Argonne, LLC.
 * (c.f. AUTHORS, LICENSE)
 *
 * This file is part of the AML project.
 * For more info, see https://xgitlab.cels.anl.gov/argo/aml
 *
 * SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/

11
#include "aml.h"
12 13
#include "aml/dma/linux-seq.h"

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
#include <assert.h>
#include <errno.h>
#include <sys/mman.h>

/*******************************************************************************
 * Linux-backed, sequential dma
 * The dma itself is organized into several different components
 * - request types: copy or move
 * - implementation of the request
 * - user API (i.e. generic request creation and call)
 * - how to init the dma
 ******************************************************************************/

/*******************************************************************************
 * Requests:
 ******************************************************************************/

31
int aml_dma_request_linux_seq_copy_init(struct aml_dma_request_linux_seq *req,
Kamil Iskra's avatar
Kamil Iskra committed
32
					const struct aml_tiling *dt,
33
					void *dptr, int dtid,
Kamil Iskra's avatar
Kamil Iskra committed
34 35
					const struct aml_tiling *st,
					const void *sptr, int stid)
36
{
37
	assert(req != NULL);
38

39
	req->type = AML_DMA_REQUEST_TYPE_COPY;
40
	/* figure out pointers */
41 42 43
	req->dest = aml_tiling_tilestart(dt, dptr, dtid);
	req->src = aml_tiling_tilestart(st, sptr, stid);
	req->size = aml_tiling_tilesize(st, stid);
44 45 46 47
	/* TODO: assert size match */
	return 0;
}

48
int aml_dma_request_linux_seq_copy_destroy(struct aml_dma_request_linux_seq *r)
49 50 51 52 53 54 55 56
{
	assert(r != NULL);
	return 0;
}

/*******************************************************************************
 * Internal functions
 ******************************************************************************/
57 58 59 60 61 62 63 64 65
int aml_dma_linux_seq_do_copy(struct aml_dma_linux_seq_data *dma,
			      struct aml_dma_request_linux_seq *req)
{
	assert(dma != NULL);
	assert(req != NULL);
	memcpy(req->dest, req->src, req->size);
	return 0;
}

66
struct aml_dma_linux_seq_ops aml_dma_linux_seq_inner_ops = {
67
	aml_dma_linux_seq_do_copy,
68 69 70 71 72 73 74
};

/*******************************************************************************
 * Public API
 ******************************************************************************/

int aml_dma_linux_seq_create_request(struct aml_dma_data *d,
75
				     struct aml_dma_request **r,
76 77 78 79 80 81 82
				     int type, va_list ap)
{
	assert(d != NULL);
	assert(r != NULL);
	struct aml_dma_linux_seq *dma =
		(struct aml_dma_linux_seq *)d;

83
	struct aml_dma_request_linux_seq *req;
84

85
	pthread_mutex_lock(&dma->data.lock);
86
	req = aml_vector_add(&dma->data.requests);
87

88 89 90 91 92 93 94 95 96 97 98 99
	/* init the request */
	if(type == AML_DMA_REQUEST_TYPE_COPY)
	{
		struct aml_tiling *dt, *st;
		void *dptr, *sptr;
		int dtid, stid;
		dt = va_arg(ap, struct aml_tiling *);
		dptr = va_arg(ap, void *);
		dtid = va_arg(ap, int);
		st = va_arg(ap, struct aml_tiling *);
		sptr = va_arg(ap, void *);
		stid = va_arg(ap, int);
100
		aml_dma_request_linux_seq_copy_init(req, dt, dptr, dtid,
101 102
						    st, sptr, stid);
	}
103
	pthread_mutex_unlock(&dma->data.lock);
104
	*r = (struct aml_dma_request *)req;
105 106 107 108 109 110 111 112 113 114 115
	return 0;
}

int aml_dma_linux_seq_destroy_request(struct aml_dma_data *d,
				      struct aml_dma_request *r)
{
	assert(d != NULL);
	assert(r != NULL);
	struct aml_dma_linux_seq *dma =
		(struct aml_dma_linux_seq *)d;

116 117
	struct aml_dma_request_linux_seq *req =
		(struct aml_dma_request_linux_seq *)r;
118 119

	if(req->type == AML_DMA_REQUEST_TYPE_COPY)
120
		aml_dma_request_linux_seq_copy_destroy(req);
121

122
	/* enough to remove from request vector */
123
	pthread_mutex_lock(&dma->data.lock);
124
	aml_vector_remove(&dma->data.requests, req);
125
	pthread_mutex_unlock(&dma->data.lock);
126 127 128 129 130 131 132 133
	return 0;
}

int aml_dma_linux_seq_wait_request(struct aml_dma_data *d,
				   struct aml_dma_request *r)
{
	assert(d != NULL);
	assert(r != NULL);
134 135 136
	struct aml_dma_linux_seq *dma = (struct aml_dma_linux_seq *)d;
	struct aml_dma_request_linux_seq *req =
		(struct aml_dma_request_linux_seq *)r;
137 138 139

	/* execute */
	if(req->type == AML_DMA_REQUEST_TYPE_COPY)
140
		dma->ops.do_copy(&dma->data, req);
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

	/* destroy a completed request */
	aml_dma_linux_seq_destroy_request(d, r);
	return 0;
}

struct aml_dma_ops aml_dma_linux_seq_ops = {
	aml_dma_linux_seq_create_request,
	aml_dma_linux_seq_destroy_request,
	aml_dma_linux_seq_wait_request,
};

/*******************************************************************************
 * Init functions:
 ******************************************************************************/

int aml_dma_linux_seq_create(struct aml_dma **d, ...)
{
	va_list ap;
	struct aml_dma *ret = NULL;
	intptr_t baseptr, dataptr;
	va_start(ap, d);

	/* alloc */
	baseptr = (intptr_t) calloc(1, AML_DMA_LINUX_SEQ_ALLOCSIZE);
	dataptr = baseptr + sizeof(struct aml_dma);

	ret = (struct aml_dma *)baseptr;
	ret->data = (struct aml_dma_data *)dataptr;

	aml_dma_linux_seq_vinit(ret, ap);

	va_end(ap);
	*d = ret;
	return 0;
}
int aml_dma_linux_seq_vinit(struct aml_dma *d, va_list ap)
{
	d->ops = &aml_dma_linux_seq_ops;
	struct aml_dma_linux_seq *dma = (struct aml_dma_linux_seq *)d->data;

	dma->ops = aml_dma_linux_seq_inner_ops;
183 184 185 186 187 188 189

	/* request vector */
	size_t nbreqs = va_arg(ap, size_t);
	aml_vector_init(&dma->data.requests, nbreqs,
			sizeof(struct aml_dma_request_linux_seq),
			offsetof(struct aml_dma_request_linux_seq, type),
			AML_DMA_REQUEST_TYPE_INVALID);
190
	pthread_mutex_init(&dma->data.lock, NULL);
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
	return 0;
}
int aml_dma_linux_seq_init(struct aml_dma *d, ...)
{
	int err;
	va_list ap;
	va_start(ap, d);
	err = aml_dma_linux_seq_vinit(d, ap);
	va_end(ap);
	return err;
}

int aml_dma_linux_seq_destroy(struct aml_dma *d)
{
	struct aml_dma_linux_seq *dma = (struct aml_dma_linux_seq *)d->data;
206
	aml_vector_destroy(&dma->data.requests);
207
	pthread_mutex_destroy(&dma->data.lock);
208 209
	return 0;
}