summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/meta/fbnic/fbnic.h
blob: d0715695c43e751ca73b41c9aa75280dcac7853b (plain)
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
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) Meta Platforms, Inc. and affiliates. */

#ifndef _FBNIC_H_
#define _FBNIC_H_

#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/types.h>
#include <linux/workqueue.h>

#include "fbnic_csr.h"
#include "fbnic_fw.h"
#include "fbnic_fw_log.h"
#include "fbnic_hw_stats.h"
#include "fbnic_mac.h"
#include "fbnic_rpc.h"

struct fbnic_napi_vector;

#define FBNIC_MAX_NAPI_VECTORS		128u
#define FBNIC_MBX_CMPL_SLOTS		4

struct fbnic_dev {
	struct device *dev;
	struct net_device *netdev;
	struct dentry *dbg_fbd;
	struct device *hwmon;
	struct devlink_health_reporter *fw_reporter;
	struct devlink_health_reporter *otp_reporter;

	u32 __iomem *uc_addr0;
	u32 __iomem *uc_addr4;
	const struct fbnic_mac *mac;
	unsigned int fw_msix_vector;
	unsigned int mac_msix_vector;
	unsigned short num_irqs;

	struct {
		u8 users;
		char name[IFNAMSIZ + 9];
	} napi_irq[FBNIC_MAX_NAPI_VECTORS];

	struct delayed_work service_task;

	struct fbnic_fw_mbx mbx[FBNIC_IPC_MBX_INDICES];
	struct fbnic_fw_cap fw_cap;
	struct fbnic_fw_completion *cmpl_data[FBNIC_MBX_CMPL_SLOTS];
	/* Lock protecting Tx Mailbox queue to prevent possible races */
	spinlock_t fw_tx_lock;

	unsigned long last_heartbeat_request;
	unsigned long last_heartbeat_response;
	u8 fw_heartbeat_enabled;

	u64 dsn;
	u32 mps;
	u32 readrq;
	u8 relaxed_ord;

	/* Local copy of the devices TCAM */
	struct fbnic_act_tcam act_tcam[FBNIC_RPC_TCAM_ACT_NUM_ENTRIES];
	struct fbnic_mac_addr mac_addr[FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES];
	u8 mac_addr_boundary;
	u8 tce_tcam_last;

	/* IP TCAM */
	struct fbnic_ip_addr ip_src[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];
	struct fbnic_ip_addr ip_dst[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];
	struct fbnic_ip_addr ipo_src[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];
	struct fbnic_ip_addr ipo_dst[FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES];

	/* Number of TCQs/RCQs available on hardware */
	u16 max_num_queues;

	/* Lock protecting writes to @time_high, @time_offset of fbnic_netdev,
	 * and the HW time CSR machinery.
	 */
	spinlock_t time_lock;
	/* Externally accessible PTP clock, may be NULL */
	struct ptp_clock *ptp;
	struct ptp_clock_info ptp_info;
	/* Last @time_high refresh time in jiffies (to catch stalls) */
	unsigned long last_read;

	/* PMD specific data */
	unsigned long end_of_pmd_training;
	u8 pmd_state;

	/* Local copy of hardware statistics */
	struct fbnic_hw_stats hw_stats;

	/* Firmware time since boot in milliseconds */
	u64 firmware_time;
	u64 prev_firmware_time;

	struct fbnic_fw_log fw_log;

	/* MDIO bus for PHYs */
	struct mii_bus *mdio_bus;

	/* In units of ms since API supports values in ms */
	u16 ps_timeout;
};

/* Reserve entry 0 in the MSI-X "others" array until we have filled all
 * 32 of the possible interrupt slots. By doing this we can avoid any
 * potential conflicts should we need to enable one of the debug interrupt
 * causes later.
 */
enum {
	FBNIC_FW_MSIX_ENTRY,
	FBNIC_PCS_MSIX_ENTRY,
	FBNIC_NON_NAPI_VECTORS
};

static inline bool fbnic_present(struct fbnic_dev *fbd)
{
	return !!READ_ONCE(fbd->uc_addr0);
}

static inline void fbnic_wr32(struct fbnic_dev *fbd, u32 reg, u32 val)
{
	u32 __iomem *csr = READ_ONCE(fbd->uc_addr0);

	if (csr)
		writel(val, csr + reg);
}

u32 fbnic_rd32(struct fbnic_dev *fbd, u32 reg);

static inline void fbnic_wrfl(struct fbnic_dev *fbd)
{
	fbnic_rd32(fbd, FBNIC_MASTER_SPARE_0);
}

static inline void
fbnic_rmw32(struct fbnic_dev *fbd, u32 reg, u32 mask, u32 val)
{
	u32 v;

	v = fbnic_rd32(fbd, reg);
	v &= ~mask;
	v |= val;
	fbnic_wr32(fbd, reg, v);
}

#define wr32(_f, _r, _v)	fbnic_wr32(_f, _r, _v)
#define rd32(_f, _r)		fbnic_rd32(_f, _r)
#define wrfl(_f)		fbnic_wrfl(_f)

bool fbnic_fw_present(struct fbnic_dev *fbd);
u32 fbnic_fw_rd32(struct fbnic_dev *fbd, u32 reg);
void fbnic_fw_wr32(struct fbnic_dev *fbd, u32 reg, u32 val);

#define fw_rd32(_f, _r)		fbnic_fw_rd32(_f, _r)
#define fw_wr32(_f, _r, _v)	fbnic_fw_wr32(_f, _r, _v)
#define fw_wrfl(_f)		fbnic_fw_rd32(_f, FBNIC_FW_ZERO_REG)

static inline bool fbnic_bmc_present(struct fbnic_dev *fbd)
{
	return fbd->fw_cap.bmc_present;
}

static inline bool fbnic_init_failure(struct fbnic_dev *fbd)
{
	return !fbd->netdev;
}

extern char fbnic_driver_name[];

void fbnic_devlink_free(struct fbnic_dev *fbd);
struct fbnic_dev *fbnic_devlink_alloc(struct pci_dev *pdev);
int fbnic_devlink_health_create(struct fbnic_dev *fbd);
void fbnic_devlink_health_destroy(struct fbnic_dev *fbd);
void fbnic_devlink_register(struct fbnic_dev *fbd);
void fbnic_devlink_unregister(struct fbnic_dev *fbd);
void __printf(2, 3)
fbnic_devlink_fw_report(struct fbnic_dev *fbd, const char *format, ...);
void fbnic_devlink_otp_check(struct fbnic_dev *fbd, const char *msg);

int fbnic_fw_request_mbx(struct fbnic_dev *fbd);
void fbnic_fw_free_mbx(struct fbnic_dev *fbd);

void fbnic_hwmon_register(struct fbnic_dev *fbd);
void fbnic_hwmon_unregister(struct fbnic_dev *fbd);

int fbnic_mac_request_irq(struct fbnic_dev *fbd);
void fbnic_mac_free_irq(struct fbnic_dev *fbd);

void fbnic_napi_name_irqs(struct fbnic_dev *fbd);
int fbnic_napi_request_irq(struct fbnic_dev *fbd,
			   struct fbnic_napi_vector *nv);
void fbnic_napi_free_irq(struct fbnic_dev *fbd,
			 struct fbnic_napi_vector *nv);
void fbnic_synchronize_irq(struct fbnic_dev *fbd, int nr);
int fbnic_request_irq(struct fbnic_dev *dev, int nr, irq_handler_t handler,
		      unsigned long flags, const char *name, void *data);
void fbnic_free_irq(struct fbnic_dev *dev, int nr, void *data);

/**
 * enum fbnic_msix_self_test_codes - return codes from self test routines
 *
 * These are the codes returned from the self test routines and
 * stored in the test result array indexed by the specific
 * test name.
 *
 * @FBNIC_TEST_MSIX_SUCCESS: no errors
 * @FBNIC_TEST_MSIX_NOMEM: allocation failure
 * @FBNIC_TEST_MSIX_IRQ_REQ_FAIL: IRQ request failure
 * @FBNIC_TEST_MSIX_MASK: masking failed to prevent IRQ
 * @FBNIC_TEST_MSIX_UNMASK: unmasking failure w/ sw status set
 * @FBNIC_TEST_MSIX_IRQ_CLEAR: interrupt when clearing mask
 * @FBNIC_TEST_MSIX_NO_INTERRUPT: no interrupt when not masked
 * @FBNIC_TEST_MSIX_NO_CLEAR_OR_MASK: status not cleared, or mask not set
 * @FBNIC_TEST_MSIX_BITS_SET_AFTER_TEST: Bits are set after test
 */
enum fbnic_msix_self_test_codes {
	FBNIC_TEST_MSIX_SUCCESS = 0,
	FBNIC_TEST_MSIX_NOMEM = 5,
	FBNIC_TEST_MSIX_IRQ_REQ_FAIL = 10,
	FBNIC_TEST_MSIX_MASK = 20,
	FBNIC_TEST_MSIX_UNMASK = 30,
	FBNIC_TEST_MSIX_IRQ_CLEAR = 40,
	FBNIC_TEST_MSIX_NO_INTERRUPT = 50,
	FBNIC_TEST_MSIX_NO_CLEAR_OR_MASK = 60,
	FBNIC_TEST_MSIX_BITS_SET_AFTER_TEST = 70,
};

enum fbnic_msix_self_test_codes fbnic_msix_test(struct fbnic_dev *fbd);

void fbnic_free_irqs(struct fbnic_dev *fbd);
int fbnic_alloc_irqs(struct fbnic_dev *fbd);

void fbnic_get_fw_ver_commit_str(struct fbnic_dev *fbd, char *fw_version,
				 const size_t str_sz);

void fbnic_dbg_fbd_init(struct fbnic_dev *fbd);
void fbnic_dbg_fbd_exit(struct fbnic_dev *fbd);
void fbnic_dbg_init(void);
void fbnic_dbg_exit(void);

void fbnic_rpc_reset_valid_entries(struct fbnic_dev *fbd);

int fbnic_mdiobus_create(struct fbnic_dev *fbd);

void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_version);
int fbnic_csr_regs_len(struct fbnic_dev *fbd);

void fbnic_config_txrx_usecs(struct fbnic_napi_vector *nv, u32 arm);
void fbnic_config_rx_frames(struct fbnic_napi_vector *nv);

enum fbnic_boards {
	fbnic_board_asic
};

struct fbnic_info {
	unsigned int max_num_queues;
	unsigned int bar_mask;
};

#endif /* _FBNIC_H_ */