aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/misc/ocxl/ocxl_internal.h
blob: 81086534dab57dd0d4d55d20a587ed703a4d5c41 (plain) (blame)
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
// SPDX-License-Identifier: GPL-2.0+
// Copyright 2017 IBM Corp.
#ifndef _OCXL_INTERNAL_H_
#define _OCXL_INTERNAL_H_

#include <linux/pci.h>
#include <linux/cdev.h>
#include <linux/list.h>
#include <misc/ocxl.h>

#define MAX_IRQ_PER_LINK	2000
#define MAX_IRQ_PER_CONTEXT	MAX_IRQ_PER_LINK

#define to_ocxl_function(d) container_of(d, struct ocxl_fn, dev)
#define to_ocxl_afu(d) container_of(d, struct ocxl_afu, dev)

extern struct pci_driver ocxl_pci_driver;

struct ocxl_fn {
	struct device dev;
	int bar_used[3];
	struct ocxl_fn_config config;
	struct list_head afu_list;
	int pasid_base;
	int actag_base;
	int actag_enabled;
	int actag_supported;
	struct list_head pasid_list;
	struct list_head actag_list;
	void *link;
};

struct ocxl_afu {
	struct ocxl_fn *fn;
	struct list_head list;
	struct device dev;
	struct cdev cdev;
	struct ocxl_afu_config config;
	int pasid_base;
	int pasid_count; /* opened contexts */
	int pasid_max; /* maximum number of contexts */
	int actag_base;
	int actag_enabled;
	struct mutex contexts_lock;
	struct idr contexts_idr;
	struct mutex afu_control_lock;
	u64 global_mmio_start;
	u64 irq_base_offset;
	void __iomem *global_mmio_ptr;
	u64 pp_mmio_start;
	struct bin_attribute attr_global_mmio;
};

enum ocxl_context_status {
	CLOSED,
	OPENED,
	ATTACHED,
};

// Contains metadata about a translation fault
struct ocxl_xsl_error {
	u64 addr; // The address that triggered the fault
	u64 dsisr; // the value of the dsisr register
	u64 count; // The number of times this fault has been triggered
};

struct ocxl_context {
	struct ocxl_afu *afu;
	int pasid;
	struct mutex status_mutex;
	enum ocxl_context_status status;
	struct address_space *mapping;
	struct mutex mapping_lock;
	wait_queue_head_t events_wq;
	struct mutex xsl_error_lock;
	struct ocxl_xsl_error xsl_error;
	struct mutex irq_lock;
	struct idr irq_idr;
	u16 tidr; // Thread ID used for P9 wait implementation
};

struct ocxl_process_element {
	__be64 config_state;
	__be32 reserved1[11];
	__be32 lpid;
	__be32 tid;
	__be32 pid;
	__be32 reserved2[10];
	__be64 amr;
	__be32 reserved3[3];
	__be32 software_state;
};

struct ocxl_afu *ocxl_afu_get(struct ocxl_afu *afu);
void ocxl_afu_put(struct ocxl_afu *afu);

int ocxl_create_cdev(struct ocxl_afu *afu);
void ocxl_destroy_cdev(struct ocxl_afu *afu);
int ocxl_register_afu(struct ocxl_afu *afu);
void ocxl_unregister_afu(struct ocxl_afu *afu);

int ocxl_file_init(void);
void ocxl_file_exit(void);

int ocxl_pasid_afu_alloc(struct ocxl_fn *fn, u32 size);
void ocxl_pasid_afu_free(struct ocxl_fn *fn, u32 start, u32 size);
int ocxl_actag_afu_alloc(struct ocxl_fn *fn, u32 size);
void ocxl_actag_afu_free(struct ocxl_fn *fn, u32 start, u32 size);

/*
 * Get the max PASID value that can be used by the function
 */
int ocxl_config_get_pasid_info(struct pci_dev *dev, int *count);

/*
 * Check if an AFU index is valid for the given function.
 *
 * AFU indexes can be sparse, so a driver should check all indexes up
 * to the maximum found in the function description
 */
int ocxl_config_check_afu_index(struct pci_dev *dev,
				struct ocxl_fn_config *fn, int afu_idx);

/**
 * Update values within a Process Element
 *
 * link_handle: the link handle associated with the process element
 * pasid: the PASID for the AFU context
 * tid: the new thread id for the process element
 */
int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid);

struct ocxl_context *ocxl_context_alloc(void);
int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu,
			struct address_space *mapping);
int ocxl_context_attach(struct ocxl_context *ctx, u64 amr);
int ocxl_context_mmap(struct ocxl_context *ctx,
			struct vm_area_struct *vma);
int ocxl_context_detach(struct ocxl_context *ctx);
void ocxl_context_detach_all(struct ocxl_afu *afu);
void ocxl_context_free(struct ocxl_context *ctx);

int ocxl_sysfs_add_afu(struct ocxl_afu *afu);
void ocxl_sysfs_remove_afu(struct ocxl_afu *afu);

int ocxl_afu_irq_alloc(struct ocxl_context *ctx, u64 *irq_offset);
int ocxl_afu_irq_free(struct ocxl_context *ctx, u64 irq_offset);
void ocxl_afu_irq_free_all(struct ocxl_context *ctx);
int ocxl_afu_irq_set_fd(struct ocxl_context *ctx, u64 irq_offset,
			int eventfd);
u64 ocxl_afu_irq_get_addr(struct ocxl_context *ctx, u64 irq_offset);

struct ocxl_fn *init_function(struct pci_dev *dev);
void remove_function(struct ocxl_fn *fn);
int init_afu(struct pci_dev *dev, struct ocxl_fn *fn, u8 afu_idx);
void remove_afu(struct ocxl_afu *afu);

#endif /* _OCXL_INTERNAL_H_ */