fsl_usdpaa.h 13.3 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 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 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
/* Copyright 2011-2012 Freescale Semiconductor, Inc.
 * Copyright 2020 NXP
 * This file is licensed under the terms of the GNU General Public License
 * version 2.  This program is licensed "as is" without any warranty of any
 * kind, whether express or implied.
 */

#ifndef FSL_USDPAA_H
#define FSL_USDPAA_H

#ifdef __cplusplus
extern "C" {
#endif

#include <linux/uaccess.h>
#include <linux/ioctl.h>
#include <linux/fsl_qman.h> /* For "enum qm_channel" */
#include <linux/compat.h>

#ifdef CONFIG_FSL_USDPAA

/******************************/
/* Allocation of resource IDs */
/******************************/

/* This enum is used to distinguish between the type of underlying object being
 * manipulated. */
enum usdpaa_id_type {
	usdpaa_id_fqid,
	usdpaa_id_bpid,
	usdpaa_id_qpool,
	usdpaa_id_cgrid,
	usdpaa_id_ceetm0_lfqid,
	usdpaa_id_ceetm0_channelid,
	usdpaa_id_ceetm1_lfqid,
	usdpaa_id_ceetm1_channelid,
	usdpaa_id_max /* <-- not a valid type, represents the number of types */
};
#define USDPAA_IOCTL_MAGIC 'u'
struct usdpaa_ioctl_id_alloc {
	uint32_t base; /* Return value, the start of the allocated range */
	enum usdpaa_id_type id_type; /* what kind of resource(s) to allocate */
	uint32_t num; /* how many IDs to allocate (and return value) */
	uint32_t align; /* must be a power of 2, 0 is treated like 1 */
	int partial; /* whether to allow less than 'num' */
};
struct usdpaa_ioctl_id_release {
	/* Input; */
	enum usdpaa_id_type id_type;
	uint32_t base;
	uint32_t num;
};
struct usdpaa_ioctl_id_reserve {
	enum usdpaa_id_type id_type;
	uint32_t base;
	uint32_t num;
};


/* ioctl() commands */
#define USDPAA_IOCTL_ID_ALLOC \
	_IOWR(USDPAA_IOCTL_MAGIC, 0x01, struct usdpaa_ioctl_id_alloc)
#define USDPAA_IOCTL_ID_RELEASE \
	_IOW(USDPAA_IOCTL_MAGIC, 0x02, struct usdpaa_ioctl_id_release)
#define USDPAA_IOCTL_ID_RESERVE \
	_IOW(USDPAA_IOCTL_MAGIC, 0x0A, struct usdpaa_ioctl_id_reserve)

/**********************/
/* Mapping DMA memory */
/**********************/

/* Maximum length for a map name, including NULL-terminator */
#define USDPAA_DMA_NAME_MAX 16
/* Flags for requesting DMA maps. Maps are private+unnamed or sharable+named.
 * For a sharable and named map, specify _SHARED (whether creating one or
 * binding to an existing one). If _SHARED is specified and _CREATE is not, then
 * the mapping must already exist. If _SHARED and _CREATE are specified and the
 * mapping doesn't already exist, it will be created. If _SHARED and _CREATE are
 * specified and the mapping already exists, the mapping will fail unless _LAZY
 * is specified. When mapping to a pre-existing sharable map, the length must be
 * an exact match. Lengths must be a power-of-4 multiple of page size.
 *
 * Note that this does not actually map the memory to user-space, that is done
 * by a subsequent mmap() using the page offset returned from this ioctl(). The
 * ioctl() is what gives the process permission to do this, and a page-offset
 * with which to do so.
 */
#define USDPAA_DMA_FLAG_SHARE    0x01
#define USDPAA_DMA_FLAG_CREATE   0x02
#define USDPAA_DMA_FLAG_LAZY     0x04
#define USDPAA_DMA_FLAG_RDONLY   0x08
struct usdpaa_ioctl_dma_map {
	/* Output parameters - virtual and physical addresses */
	void *ptr;
	uint64_t phys_addr;
	/* Input parameter, the length of the region to be created (or if
	 * mapping an existing region, this must match it). Must be a power-of-4
	 * multiple of page size. */
	uint64_t len;
	/* Input parameter, the USDPAA_DMA_FLAG_* settings. */
	uint32_t flags;
	/* If _FLAG_SHARE is specified, the name of the region to be created (or
	 * of the existing mapping to use). */
	char name[USDPAA_DMA_NAME_MAX];
	/* If this ioctl() creates the mapping, this is an input parameter
	 * stating whether the region supports locking. If mapping an existing
	 * region, this is a return value indicating the same thing. */
	int has_locking;
	/* In the case of a successful map with _CREATE and _LAZY, this return
	 * value indicates whether we created the mapped region or whether it
	 * already existed. */
	int did_create;
};

#ifdef CONFIG_COMPAT
struct usdpaa_ioctl_dma_map_compat {
	/* Output parameters - virtual and physical addresses */
	compat_uptr_t ptr;
	uint64_t phys_addr;
	/* Input parameter, the length of the region to be created (or if
	 * mapping an existing region, this must match it). Must be a power-of-4
	 * multiple of page size. */
	uint64_t len;
	/* Input parameter, the USDPAA_DMA_FLAG_* settings. */
	uint32_t flags;
	/* If _FLAG_SHARE is specified, the name of the region to be created (or
	 * of the existing mapping to use). */
	char name[USDPAA_DMA_NAME_MAX];
	/* If this ioctl() creates the mapping, this is an input parameter
	 * stating whether the region supports locking. If mapping an existing
	 * region, this is a return value indicating the same thing. */
	int has_locking;
	/* In the case of a successful map with _CREATE and _LAZY, this return
	 * value indicates whether we created the mapped region or whether it
	 * already existed. */
	int did_create;
};

#define USDPAA_IOCTL_DMA_MAP_COMPAT \
	_IOWR(USDPAA_IOCTL_MAGIC, 0x03, struct usdpaa_ioctl_dma_map_compat)
#endif


#define USDPAA_IOCTL_DMA_MAP \
	_IOWR(USDPAA_IOCTL_MAGIC, 0x03, struct usdpaa_ioctl_dma_map)
/* munmap() does not remove the DMA map, just the user-space mapping to it.
 * This ioctl will do both (though you can munmap() before calling the ioctl
 * too). */
#define USDPAA_IOCTL_DMA_UNMAP \
	_IOW(USDPAA_IOCTL_MAGIC, 0x04, unsigned char)
/* We implement a cross-process locking scheme per DMA map. Call this ioctl()
 * with a mmap()'d address, and the process will (interruptible) sleep if the
 * lock is already held by another process. Process destruction will
 * automatically clean up any held locks. */
#define USDPAA_IOCTL_DMA_LOCK \
	_IOW(USDPAA_IOCTL_MAGIC, 0x05, unsigned char)
#define USDPAA_IOCTL_DMA_UNLOCK \
	_IOW(USDPAA_IOCTL_MAGIC, 0x06, unsigned char)

/***************************************/
/* Mapping and using QMan/BMan portals */
/***************************************/
enum usdpaa_portal_type {
	 usdpaa_portal_qman,
	 usdpaa_portal_bman,
};

#define QBMAN_ANY_PORTAL_IDX 0xffffffff

struct usdpaa_ioctl_portal_map {
	/* Input parameter, is a qman or bman portal required. */

	enum usdpaa_portal_type type;
	/* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX
	   for don't care.  The portal index will be populated by the
	   driver when the ioctl() successfully completes */
	uint32_t index;

	/* Return value if the map succeeds, this gives the mapped
	 * cache-inhibited (cinh) and cache-enabled (cena) addresses. */
	struct usdpaa_portal_map {
		void *cinh;
		void *cena;
	} addr;
	/* Qman-specific return values */
	uint16_t channel;
	uint32_t pools;
};

#ifdef CONFIG_COMPAT
struct compat_usdpaa_ioctl_portal_map {
	/* Input parameter, is a qman or bman portal required. */
	enum usdpaa_portal_type type;
	/* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX
	   for don't care.  The portal index will be populated by the
	   driver when the ioctl() successfully completes */
	uint32_t index;
	/* Return value if the map succeeds, this gives the mapped
	 * cache-inhibited (cinh) and cache-enabled (cena) addresses. */
	struct usdpaa_portal_map_compat {
		compat_uptr_t cinh;
		compat_uptr_t cena;
	} addr;
	/* Qman-specific return values */
	uint16_t channel;
	uint32_t pools;
};
#define USDPAA_IOCTL_PORTAL_MAP_COMPAT \
	_IOWR(USDPAA_IOCTL_MAGIC, 0x07, struct compat_usdpaa_ioctl_portal_map)
#define USDPAA_IOCTL_PORTAL_UNMAP_COMPAT \
	_IOW(USDPAA_IOCTL_MAGIC, 0x08, struct usdpaa_portal_map_compat)
#endif

#define USDPAA_IOCTL_PORTAL_MAP \
	_IOWR(USDPAA_IOCTL_MAGIC, 0x07, struct usdpaa_ioctl_portal_map)
#define USDPAA_IOCTL_PORTAL_UNMAP \
	_IOW(USDPAA_IOCTL_MAGIC, 0x08, struct usdpaa_portal_map)

struct usdpaa_ioctl_irq_map {
	enum usdpaa_portal_type type; /* Type of portal to map */
	int fd; /* File descriptor that contains the portal */
	void *portal_cinh; /* Cache inhibited area to identify the portal */
};

#define USDPAA_IOCTL_PORTAL_IRQ_MAP \
	_IOW(USDPAA_IOCTL_MAGIC, 0x09, struct usdpaa_ioctl_irq_map)

#ifdef CONFIG_COMPAT

struct compat_ioctl_irq_map {
	enum usdpaa_portal_type type; /* Type of portal to map */
	compat_int_t fd; /* File descriptor that contains the portal */
	compat_uptr_t portal_cinh; /* Used identify the portal */};

#define USDPAA_IOCTL_PORTAL_IRQ_MAP_COMPAT \
	_IOW(USDPAA_IOCTL_MAGIC, 0x09, struct compat_ioctl_irq_map)
#endif

/* ioctl to query the amount of DMA memory used in the system */
struct usdpaa_ioctl_dma_used {
	uint64_t free_bytes;
	uint64_t total_bytes;
};
#define USDPAA_IOCTL_DMA_USED \
	_IOR(USDPAA_IOCTL_MAGIC, 0x0B, struct usdpaa_ioctl_dma_used)

/* ioctl to allocate a raw portal */
struct usdpaa_ioctl_raw_portal {
	/* inputs */
	enum usdpaa_portal_type type; /* Type of portal to allocate */

	 /* set to non zero to turn on stashing */
	uint8_t enable_stash;
	/* Stashing attributes for the portal */
	uint32_t cpu;
	uint32_t cache;
	uint32_t window;

	/* Specifies the stash request queue this portal should use */
	uint8_t sdest;

	/* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX
	 * for don't care.  The portal index will be populated by the
	 * driver when the ioctl() successfully completes */
	uint32_t index;

	/* outputs */
	uint64_t cinh;
	uint64_t cena;
};

#define USDPAA_IOCTL_ALLOC_RAW_PORTAL \
	_IOWR(USDPAA_IOCTL_MAGIC, 0x0C, struct usdpaa_ioctl_raw_portal)

#define USDPAA_IOCTL_FREE_RAW_PORTAL \
	_IOR(USDPAA_IOCTL_MAGIC, 0x0D, struct usdpaa_ioctl_raw_portal)

#ifdef CONFIG_COMPAT

struct compat_ioctl_raw_portal {
	/* inputs */
	enum usdpaa_portal_type type; /* Type of portal to allocate */

	 /* set to non zero to turn on stashing */
	uint8_t enable_stash;
	/* Stashing attributes for the portal */
	uint32_t cpu;
	uint32_t cache;
	uint32_t window;
	/* Specifies the stash request queue this portal should use */
	uint8_t sdest;

	/* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX
	 * for don't care.  The portal index will be populated by the
	 * driver when the ioctl() successfully completes */
	uint32_t index;

	/* outputs */
	uint64_t cinh;
	uint64_t cena;
};

#define USDPAA_IOCTL_ALLOC_RAW_PORTAL_COMPAT \
	_IOWR(USDPAA_IOCTL_MAGIC, 0x0C, struct compat_ioctl_raw_portal)

#define USDPAA_IOCTL_FREE_RAW_PORTAL_COMPAT \
	_IOR(USDPAA_IOCTL_MAGIC, 0x0D, struct compat_ioctl_raw_portal)

#endif

#ifdef __KERNEL__

/* Early-boot hook */
int __init fsl_usdpaa_init_early(void);

/* Fault-handling in arch/powerpc/mm/mem.c gives USDPAA an opportunity to detect
 * faults within its ranges via this hook. */
int usdpaa_test_fault(unsigned long pfn, u64 *phys_addr, u64 *size);

#endif /* __KERNEL__ */

#endif /* CONFIG_FSL_USDPAA */

#ifdef __KERNEL__
/* This interface is needed in a few places and though it's not specific to
 * USDPAA as such, creating a new header for it doesn't make any sense. The
 * qbman kernel driver implements this interface and uses it as the backend for
 * both the FQID and BPID allocators. The fsl_usdpaa driver also uses this
 * interface for tracking per-process allocations handed out to user-space. */
struct dpa_alloc {
	struct list_head free;
	spinlock_t lock;
	struct list_head used;
};
#define DECLARE_DPA_ALLOC(name) \
	struct dpa_alloc name = { \
		.free = { \
			.prev = &name.free, \
			.next = &name.free \
		}, \
		.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
		.used = { \
			 .prev = &name.used, \
			 .next = &name.used \
		 } \
	}
static inline void dpa_alloc_init(struct dpa_alloc *alloc)
{
	INIT_LIST_HEAD(&alloc->free);
	INIT_LIST_HEAD(&alloc->used);
	spin_lock_init(&alloc->lock);
}
int dpa_alloc_new(struct dpa_alloc *alloc, u32 *result, u32 count, u32 align,
		  int partial);
void dpa_alloc_free(struct dpa_alloc *alloc, u32 base_id, u32 count);
void dpa_alloc_seed(struct dpa_alloc *alloc, u32 fqid, u32 count);

/* Like 'new' but specifies the desired range, returns -ENOMEM if the entire
 * desired range is not available, or 0 for success. */
int dpa_alloc_reserve(struct dpa_alloc *alloc, u32 base_id, u32 count);
/* Pops and returns contiguous ranges from the allocator. Returns -ENOMEM when
 * 'alloc' is empty. */
int dpa_alloc_pop(struct dpa_alloc *alloc, u32 *result, u32 *count);
/* Returns 1 if the specified id is alloced, 0 otherwise */
int dpa_alloc_check(struct dpa_alloc *list, u32 id);
#endif /* __KERNEL__ */


/************************************
 * Link Status support for user space
 * interface
 ************************************/
#define IF_NAME_MAX_LEN 16
#define NODE_NAME_LEN	32
#define ETH_LINK_DOWN 0
#define ETH_LINK_UP 1

struct usdpaa_ioctl_link_status {
	/* network device node name */
	char		if_name[IF_NAME_MAX_LEN];
	/* Eventfd value */
	uint32_t	efd;
};

#define USDPAA_IOCTL_ENABLE_LINK_STATUS_INTERRUPT \
	_IOW(USDPAA_IOCTL_MAGIC, 0x0E, struct usdpaa_ioctl_link_status)

#define USDPAA_IOCTL_DISABLE_LINK_STATUS_INTERRUPT \
	_IOW(USDPAA_IOCTL_MAGIC, 0x0F, char *)

struct usdpaa_ioctl_link_status_args {
	/* network device node name */
	char    if_name[IF_NAME_MAX_LEN];
	/* link status(UP/DOWN) */
	int     link_status;
};

struct usdpaa_ioctl_update_link_status {
	/* network device node name */
	char    if_name[IF_NAME_MAX_LEN];
	/* link status(ETH_LINK_UP/DOWN) */
	int     set_link_status;
};

#define USDPAA_IOCTL_GET_LINK_STATUS \
	_IOWR(USDPAA_IOCTL_MAGIC, 0x10, struct usdpaa_ioctl_link_status_args)

#define USDPAA_IOCTL_UPDATE_LINK_STATUS \
	_IOW(USDPAA_IOCTL_MAGIC, 0x11, struct usdpaa_ioctl_update_link_status)

#ifdef __cplusplus
}
#endif

#endif /* FSL_USDPAA_H */