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
|
/*
* Hardware queues handle header
*
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
*
* Contact: Prabhu Kuttiyam <pkuttiyam@ti.com>
* Cyril Chemparathy <cyril@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __HWQUEUE_HWQUEUE_H
#define __HWQUEUE_HWQUEUE_H
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/hwqueue.h>
struct hwqueue_instance {
struct list_head handles;
struct hwqueue_device *hdev;
struct timer_list poll_timer;
wait_queue_head_t wait;
void *priv;
char name[32];
atomic_t num_notifiers;
struct hwqueue_inst_ops *ops;
};
struct hwqueue_device_ops {
/*
* Return a match quotient (0 = best .. UINT_MAX-1) for a set of
* option flags. Negative error values imply "do not allocate"
*/
int (*match)(struct hwqueue_instance *inst, unsigned flags);
/* Initialize a queue inst when opened for the first time */
int (*open)(struct hwqueue_instance *inst, unsigned flags);
/* Close a queue inst when closed by the last user */
void (*close)(struct hwqueue_instance *inst);
/* Enable or disable notification */
void (*set_notify)(struct hwqueue_instance *inst, bool enabled);
/* Get a hardware identifier for a queue */
int (*get_hw_id)(struct hwqueue_instance *inst);
};
struct hwqueue_inst_ops {
/* Push something into the queue */
int (*push)(struct hwqueue_instance *inst, dma_addr_t dma,
unsigned size, unsigned flags);
/* Pop something from the queue */
dma_addr_t (*pop)(struct hwqueue_instance *inst, unsigned *size,
unsigned flags);
/* Flush a queue */
int (*flush)(struct hwqueue_instance *inst);
/* Poll number of elements on the queue */
int (*get_count)(struct hwqueue_instance *inst);
/* Perform DMA mapping on objects to be pushed */
int (*map)(struct hwqueue_instance *inst, void *data,
unsigned size, dma_addr_t *dma_ptr, unsigned *size_ptr);
/* Perform DMA unmapping on objects that have been pulled */
void *(*unmap)(struct hwqueue_instance *inst, dma_addr_t dma,
unsigned desc_size);
};
struct hwqueue_device {
unsigned base_id;
unsigned num_queues;
unsigned inst_shift;
void *instances;
struct hwqueue_device_ops *ops;
unsigned priv_size;
struct list_head list;
struct device *dev;
};
static inline int hwqueue_inst_to_id(struct hwqueue_instance *inst)
{
struct hwqueue_device *hdev = inst->hdev;
int offset = (void *)inst - hdev->instances;
int inst_size = 1 << hdev->inst_shift;
BUG_ON(offset & (inst_size - 1));
return offset >> hdev->inst_shift;
}
static inline struct hwqueue_instance *
hwqueue_id_to_inst(struct hwqueue_device *hdev, unsigned id)
{
return hdev->instances + (id << hdev->inst_shift);
}
static inline void *hwqueue_inst_to_priv(struct hwqueue_instance *inst)
{
return (void *)(inst + 1);
}
static inline struct hwqueue *rcu_to_handle(struct rcu_head *rcu)
{
return container_of(rcu, struct hwqueue, rcu);
}
int hwqueue_device_register(struct hwqueue_device *dev);
int hwqueue_device_unregister(struct hwqueue_device *dev);
void hwqueue_notify(struct hwqueue_instance *inst);
void hwqueue_set_poll(struct hwqueue_instance *inst, bool enabled);
#endif /* __HWQUEUE_HWQUEUE_H */
|