summaryrefslogtreecommitdiffstats
path: root/drivers/staging/gasket/gasket_interrupt.h
blob: f0586a6898ec62ced1d067f5306c10ce7d0c70ea (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
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Gasket common interrupt module. Defines functions for enabling
 * eventfd-triggered interrupts between a Gasket device and a host process.
 *
 * Copyright (C) 2018 Google, Inc.
 */
#ifndef __GASKET_INTERRUPT_H__
#define __GASKET_INTERRUPT_H__

#include <linux/eventfd.h>
#include <linux/pci.h>

#include "gasket_core.h"

/* Note that this currently assumes that device interrupts are a dense set,
 * numbered from 0 - (num_interrupts - 1). Should this have to change, these
 * APIs will have to be updated.
 */

/* Opaque type used to hold interrupt subsystem data. */
struct gasket_interrupt_data;

/*
 * Initialize the interrupt module.
 * @gasket_dev: The Gasket device structure for the device to be initted.
 * @type: Type of the interrupt. (See gasket_interrupt_type).
 * @name: The name to associate with these interrupts.
 * @interrupts: An array of all interrupt descriptions for this device.
 * @num_interrupts: The length of the @interrupts array.
 * @pack_width: The width, in bits, of a single field in a packed interrupt reg.
 * @bar_index: The bar containing all interrupt registers.
 *
 * Allocates and initializes data to track interrupt state for a device.
 * After this call, no interrupts will be configured/delivered; call
 * gasket_interrupt_set_vector[_packed] to associate each interrupt with an
 * __iomem location, then gasket_interrupt_set_eventfd to associate an eventfd
 * with an interrupt.
 *
 * If num_interrupts interrupts are not available, this call will return a
 * negative error code. In that case, gasket_interrupt_cleanup should still be
 * called. Returns 0 on success (which can include a device where interrupts
 * are not possible to set up, but is otherwise OK; that device will report
 * status LAMED.)
 */
int gasket_interrupt_init(
	struct gasket_dev *gasket_dev, const char *name, int type,
	const struct gasket_interrupt_desc *interrupts,
	int num_interrupts, int pack_width, int bar_index,
	const struct gasket_wire_interrupt_offsets *wire_int_offsets);

/*
 * Clean up a device's interrupt structure.
 * @gasket_dev: The Gasket information structure for this device.
 *
 * Cleans up the device's interrupts and deallocates data.
 */
void gasket_interrupt_cleanup(struct gasket_dev *gasket_dev);

/*
 * Clean up and re-initialize the MSI-x subsystem.
 * @gasket_dev: The Gasket information structure for this device.
 *
 * Performs a teardown of the MSI-x subsystem and re-initializes it. Does not
 * free the underlying data structures. Returns 0 on success and an error code
 * on error.
 */
int gasket_interrupt_reinit(struct gasket_dev *gasket_dev);

/*
 * Reset the counts stored in the interrupt subsystem.
 * @gasket_dev: The Gasket information structure for this device.
 *
 * Sets the counts of all interrupts in the subsystem to 0.
 */
int gasket_interrupt_reset_counts(struct gasket_dev *gasket_dev);

/*
 * Associates an eventfd with a device interrupt.
 * @data: Pointer to device interrupt data.
 * @interrupt: The device interrupt to configure.
 * @event_fd: The eventfd to associate with the interrupt.
 *
 * Prepares the host to receive notification of device interrupts by associating
 * event_fd with interrupt. Upon receipt of a device interrupt, event_fd will be
 * signaled, after successful configuration.
 *
 * Returns 0 on success, a negative error code otherwise.
 */
int gasket_interrupt_set_eventfd(
	struct gasket_interrupt_data *interrupt_data, int interrupt,
	int event_fd);

/*
 * Removes an interrupt-eventfd association.
 * @data: Pointer to device interrupt data.
 * @interrupt: The device interrupt to de-associate.
 *
 * Removes any eventfd associated with the specified interrupt, if any.
 */
int gasket_interrupt_clear_eventfd(
	struct gasket_interrupt_data *interrupt_data, int interrupt);

/*
 * Signals the eventfd associated with interrupt.
 * @data: Pointer to device interrupt data.
 * @interrupt: The device interrupt to signal for.
 *
 * Simulates a device interrupt by signaling the eventfd associated with
 * interrupt, if any.
 * Returns 0 if the eventfd was successfully triggered, a negative error code
 * otherwise (if, for example, no eventfd was associated with interrupt).
 */
int gasket_interrupt_trigger_eventfd(
	struct gasket_interrupt_data *interrupt_data, int interrupt);

/*
 * The below functions exist for backwards compatibility.
 * No new uses should be written.
 */
/*
 * Retrieve a pointer to data's MSI-X
 * entries.
 * @data: The interrupt data from which to extract.
 *
 * Returns the internal pointer to data's MSI-X entries.
 */
struct msix_entry *gasket_interrupt_get_msix_entries(
	struct gasket_interrupt_data *interrupt_data);

/*
 * Get the health of the interrupt subsystem.
 * @gasket_dev: The Gasket device struct.
 *
 * Returns DEAD if not set up, LAMED if initialization failed, and ALIVE
 * otherwise.
 */

int gasket_interrupt_system_status(struct gasket_dev *gasket_dev);

#endif