dma_linux_seq.c 5.56 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
	/* init the request */
89
	if (type == AML_DMA_REQUEST_TYPE_COPY) {
90 91 92
		struct aml_tiling *dt, *st;
		void *dptr, *sptr;
		int dtid, stid;
93

94 95 96 97 98 99
		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

	/* execute */
139
	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

	/* 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:
 ******************************************************************************/

157
int aml_dma_linux_seq_create(struct aml_dma **dma, size_t nbreqs)
158 159
{
	struct aml_dma *ret = NULL;
160
	struct aml_dma_linux_seq *d;
161

162
	if (dma == NULL)
163
		return -AML_EINVAL;
164

165 166
	*dma = NULL;

167
	ret = AML_INNER_MALLOC_2(struct aml_dma, struct aml_dma_linux_seq);
168
	if (ret == NULL)
169
		return -AML_ENOMEM;
170

171 172
	ret->data = AML_INNER_MALLOC_NEXTPTR(ret, struct aml_dma,
					     struct aml_dma_linux_seq);
173 174
	ret->ops = &aml_dma_linux_seq_ops;
	d = (struct aml_dma_linux_seq *)ret->data;
175

176 177 178 179 180 181
	d->ops = aml_dma_linux_seq_inner_ops;
	aml_vector_create(&d->data.requests, nbreqs,
			  sizeof(struct aml_dma_request_linux_seq),
			  offsetof(struct aml_dma_request_linux_seq, type),
			  AML_DMA_REQUEST_TYPE_INVALID);
	pthread_mutex_init(&d->data.lock, NULL);
182

183
	*dma = ret;
184 185 186
	return 0;
}

187
void aml_dma_linux_seq_destroy(struct aml_dma **dma)
188
{
189 190
	struct aml_dma *d;
	struct aml_dma_linux_seq *l;
191

192 193 194
	if (dma == NULL)
		return;
	d = *dma;
195
	if (d == NULL)
196
		return;
197 198

	assert(d->data != NULL);
199 200 201 202 203
	l = (struct aml_dma_linux_seq *)d->data;
	aml_vector_destroy(&l->data.requests);
	pthread_mutex_destroy(&l->data.lock);
	free(d);
	*dma = NULL;
204
}