aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/fungible/funcore/fun_dev.h
blob: 9e8c17ce8887fd8b9e5889ab69064a06f4f85445 (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
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */

#ifndef _FUNDEV_H
#define _FUNDEV_H

#include <linux/sbitmap.h>
#include <linux/spinlock_types.h>
#include <linux/workqueue.h>
#include "fun_hci.h"

struct pci_dev;
struct fun_dev;
struct fun_queue;
struct fun_cmd_ctx;
struct fun_queue_alloc_req;

/* doorbell fields */
enum {
	FUN_DB_QIDX_S = 0,
	FUN_DB_INTCOAL_ENTRIES_S = 16,
	FUN_DB_INTCOAL_ENTRIES_M = 0x7f,
	FUN_DB_INTCOAL_USEC_S = 23,
	FUN_DB_INTCOAL_USEC_M = 0x7f,
	FUN_DB_IRQ_S = 30,
	FUN_DB_IRQ_F = 1 << FUN_DB_IRQ_S,
	FUN_DB_IRQ_ARM_S = 31,
	FUN_DB_IRQ_ARM_F = 1U << FUN_DB_IRQ_ARM_S
};

/* Callback for asynchronous admin commands.
 * Invoked on reception of command response.
 */
typedef void (*fun_admin_callback_t)(struct fun_dev *fdev, void *rsp,
				     void *cb_data);

/* Callback for events/notifications received by an admin queue. */
typedef void (*fun_admin_event_cb)(struct fun_dev *fdev, void *cqe);

/* Callback for pending work handled by the service task. */
typedef void (*fun_serv_cb)(struct fun_dev *fd);

/* service task flags */
enum {
	FUN_SERV_DISABLED,    /* service task is disabled */
	FUN_SERV_FIRST_AVAIL
};

/* Driver state associated with a PCI function. */
struct fun_dev {
	struct device *dev;

	void __iomem *bar;            /* start of BAR0 mapping */
	u32 __iomem *dbs;             /* start of doorbells in BAR0 mapping */

	/* admin queue */
	struct fun_queue *admin_q;
	struct sbitmap_queue admin_sbq;
	struct fun_cmd_ctx *cmd_ctx;
	fun_admin_event_cb adminq_cb;
	bool suppress_cmds;           /* if set don't write commands to SQ */

	/* address increment between consecutive doorbells, in 4B units */
	unsigned int db_stride;

	/* SW versions of device registers */
	u32 cc_reg;         /* CC register */
	u64 cap_reg;        /* CAPability register */

	unsigned int q_depth;    /* max queue depth supported by device */
	unsigned int max_qid;    /* = #queues - 1, separately for SQs and CQs */
	unsigned int kern_end_qid; /* last qid in the kernel range + 1 */

	unsigned int fw_handle;

	/* IRQ manager */
	unsigned int num_irqs;
	unsigned int irqs_avail;
	spinlock_t irqmgr_lock;
	unsigned long *irq_map;

	/* The service task handles work that needs a process context */
	struct work_struct service_task;
	unsigned long service_flags;
	fun_serv_cb serv_cb;
};

struct fun_dev_params {
	u8  cqe_size_log2; /* admin q CQE size */
	u8  sqe_size_log2; /* admin q SQE size */

	/* admin q depths */
	u16 cq_depth;
	u16 sq_depth;
	u16 rq_depth;

	u16 min_msix; /* min vectors needed by requesting driver */

	fun_admin_event_cb event_cb;
	fun_serv_cb serv_cb;
};

/* Return the BAR address of a doorbell. */
static inline u32 __iomem *fun_db_addr(const struct fun_dev *fdev,
				       unsigned int db_index)
{
	return &fdev->dbs[db_index * fdev->db_stride];
}

/* Return the BAR address of an SQ doorbell. SQ and CQ DBs alternate,
 * SQs have even DB indices.
 */
static inline u32 __iomem *fun_sq_db_addr(const struct fun_dev *fdev,
					  unsigned int sqid)
{
	return fun_db_addr(fdev, sqid * 2);
}

static inline u32 __iomem *fun_cq_db_addr(const struct fun_dev *fdev,
					  unsigned int cqid)
{
	return fun_db_addr(fdev, cqid * 2 + 1);
}

int fun_get_res_count(struct fun_dev *fdev, enum fun_admin_op res);
int fun_res_destroy(struct fun_dev *fdev, enum fun_admin_op res,
		    unsigned int flags, u32 id);
int fun_bind(struct fun_dev *fdev, enum fun_admin_bind_type type0,
	     unsigned int id0, enum fun_admin_bind_type type1,
	     unsigned int id1);

int fun_submit_admin_cmd(struct fun_dev *fdev, struct fun_admin_req_common *cmd,
			 fun_admin_callback_t cb, void *cb_data, bool wait_ok);
int fun_submit_admin_sync_cmd(struct fun_dev *fdev,
			      struct fun_admin_req_common *cmd, void *rsp,
			      size_t rspsize, unsigned int timeout);

int fun_dev_enable(struct fun_dev *fdev, struct pci_dev *pdev,
		   const struct fun_dev_params *areq, const char *name);
void fun_dev_disable(struct fun_dev *fdev);

int fun_reserve_irqs(struct fun_dev *fdev, unsigned int nirqs,
		     u16 *irq_indices);
void fun_release_irqs(struct fun_dev *fdev, unsigned int nirqs,
		      u16 *irq_indices);

void fun_serv_stop(struct fun_dev *fd);
void fun_serv_restart(struct fun_dev *fd);
void fun_serv_sched(struct fun_dev *fd);

#endif /* _FUNDEV_H */