summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/marvell/prestera/prestera.h
blob: 903e2e13e687a7fa95a89cade1fd5b186cd7db91 (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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved. */

#ifndef _PRESTERA_H_
#define _PRESTERA_H_

#include <linux/notifier.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/phylink.h>
#include <net/devlink.h>
#include <uapi/linux/if_ether.h>

#define PRESTERA_DRV_NAME	"prestera"

#define PRESTERA_DEFAULT_VID    1

struct prestera_fw_rev {
	u16 maj;
	u16 min;
	u16 sub;
};

struct prestera_flood_domain {
	struct prestera_switch *sw;
	struct list_head flood_domain_port_list;
	u32 idx;
};

struct prestera_mdb_entry {
	struct prestera_switch *sw;
	struct prestera_flood_domain *flood_domain;
	unsigned char addr[ETH_ALEN];
	u16 vid;
};

struct prestera_flood_domain_port {
	struct prestera_flood_domain *flood_domain;
	struct net_device *dev;
	struct list_head flood_domain_port_node;
	u16 vid;
};

struct prestera_port_stats {
	u64 good_octets_received;
	u64 bad_octets_received;
	u64 mac_trans_error;
	u64 broadcast_frames_received;
	u64 multicast_frames_received;
	u64 frames_64_octets;
	u64 frames_65_to_127_octets;
	u64 frames_128_to_255_octets;
	u64 frames_256_to_511_octets;
	u64 frames_512_to_1023_octets;
	u64 frames_1024_to_max_octets;
	u64 excessive_collision;
	u64 multicast_frames_sent;
	u64 broadcast_frames_sent;
	u64 fc_sent;
	u64 fc_received;
	u64 buffer_overrun;
	u64 undersize;
	u64 fragments;
	u64 oversize;
	u64 jabber;
	u64 rx_error_frame_received;
	u64 bad_crc;
	u64 collisions;
	u64 late_collision;
	u64 unicast_frames_received;
	u64 unicast_frames_sent;
	u64 sent_multiple;
	u64 sent_deferred;
	u64 good_octets_sent;
};

#define PRESTERA_AP_PORT_MAX   (10)

struct prestera_port_caps {
	u64 supp_link_modes;
	u8 supp_fec;
	u8 type;
	u8 transceiver;
};

struct prestera_lag {
	struct net_device *dev;
	struct list_head members;
	u16 member_count;
	u16 lag_id;
};

struct prestera_flow_block;

struct prestera_port_mac_state {
	bool valid;
	u32 mode;
	u32 speed;
	bool oper;
	u8 duplex;
	u8 fc;
	u8 fec;
};

struct prestera_port_phy_state {
	u64 lmode_bmap;
	struct {
		bool pause;
		bool asym_pause;
	} remote_fc;
	u8 mdix;
};

struct prestera_port_mac_config {
	u32 mode;
	u32 speed;
	bool admin;
	u8 inband;
	u8 duplex;
	u8 fec;
};

struct prestera_port_phy_config {
	u32 mode;
	bool admin;
	u8 mdix;
};

struct prestera_port {
	struct net_device *dev;
	struct prestera_switch *sw;
	struct prestera_flow_block *ingress_flow_block;
	struct prestera_flow_block *egress_flow_block;
	struct devlink_port dl_port;
	struct list_head lag_member;
	struct prestera_lag *lag;
	u32 id;
	u32 hw_id;
	u32 dev_id;
	u16 fp_id;
	u16 pvid;
	bool autoneg;
	u64 adver_link_modes;
	u8 adver_fec;
	struct prestera_port_caps caps;
	struct list_head list;
	struct list_head vlans_list;
	struct {
		struct prestera_port_stats stats;
		struct delayed_work caching_dw;
	} cached_hw_stats;
	struct prestera_port_mac_config cfg_mac;
	struct prestera_port_phy_config cfg_phy;
	struct prestera_port_mac_state state_mac;
	struct prestera_port_phy_state state_phy;

	struct phylink_config phy_config;
	struct phylink *phy_link;
	struct phylink_pcs phylink_pcs;

	/* protects state_mac */
	spinlock_t state_mac_lock;
};

struct prestera_device {
	struct device *dev;
	u8 __iomem *ctl_regs;
	u8 __iomem *pp_regs;
	struct prestera_fw_rev fw_rev;
	void *priv;

	/* called by device driver to handle received packets */
	void (*recv_pkt)(struct prestera_device *dev);

	/* called by device driver to pass event up to the higher layer */
	int (*recv_msg)(struct prestera_device *dev, void *msg, size_t size);

	/* called by higher layer to send request to the firmware */
	int (*send_req)(struct prestera_device *dev, int qid, void *in_msg,
			size_t in_size, void *out_msg, size_t out_size,
			unsigned int wait);
};

enum prestera_event_type {
	PRESTERA_EVENT_TYPE_UNSPEC,

	PRESTERA_EVENT_TYPE_PORT,
	PRESTERA_EVENT_TYPE_FDB,
	PRESTERA_EVENT_TYPE_RXTX,

	PRESTERA_EVENT_TYPE_MAX
};

enum prestera_rxtx_event_id {
	PRESTERA_RXTX_EVENT_UNSPEC,
	PRESTERA_RXTX_EVENT_RCV_PKT,
};

enum prestera_port_event_id {
	PRESTERA_PORT_EVENT_UNSPEC,
	PRESTERA_PORT_EVENT_MAC_STATE_CHANGED,
};

struct prestera_port_event {
	u32 port_id;
	union {
		struct {
			u32 mode;
			u32 speed;
			u8 oper;
			u8 duplex;
			u8 fc;
			u8 fec;
		} mac;
		struct {
			u64 lmode_bmap;
			struct {
				bool pause;
				bool asym_pause;
			} remote_fc;
			u8 mdix;
		} phy;
	} data;
};

enum prestera_fdb_entry_type {
	PRESTERA_FDB_ENTRY_TYPE_REG_PORT,
	PRESTERA_FDB_ENTRY_TYPE_LAG,
	PRESTERA_FDB_ENTRY_TYPE_MAX
};

enum prestera_fdb_event_id {
	PRESTERA_FDB_EVENT_UNSPEC,
	PRESTERA_FDB_EVENT_LEARNED,
	PRESTERA_FDB_EVENT_AGED,
};

struct prestera_fdb_event {
	enum prestera_fdb_entry_type type;
	union {
		u32 port_id;
		u16 lag_id;
	} dest;
	u32 vid;
	union {
		u8 mac[ETH_ALEN];
	} data;
};

struct prestera_event {
	u16 id;
	union {
		struct prestera_port_event port_evt;
		struct prestera_fdb_event fdb_evt;
	};
};

enum prestera_if_type {
	/* the interface is of port type (dev,port) */
	PRESTERA_IF_PORT_E = 0,

	/* the interface is of lag type (lag-id) */
	PRESTERA_IF_LAG_E = 1,

	/* the interface is of Vid type (vlan-id) */
	PRESTERA_IF_VID_E = 3,
};

struct prestera_iface {
	enum prestera_if_type type;
	struct {
		u32 hw_dev_num;
		u32 port_num;
	} dev_port;
	u32 hw_dev_num;
	u16 vr_id;
	u16 lag_id;
	u16 vlan_id;
};

struct prestera_switchdev;
struct prestera_span;
struct prestera_rxtx;
struct prestera_trap_data;
struct prestera_acl;

struct prestera_switch {
	struct prestera_device *dev;
	struct prestera_switchdev *swdev;
	struct prestera_rxtx *rxtx;
	struct prestera_acl *acl;
	struct prestera_span *span;
	struct list_head event_handlers;
	struct notifier_block netdev_nb;
	struct prestera_trap_data *trap_data;
	char base_mac[ETH_ALEN];
	struct list_head port_list;
	rwlock_t port_list_lock;
	u32 port_count;
	u32 mtu_min;
	u32 mtu_max;
	u8 id;
	struct device_node *np;
	struct prestera_router *router;
	struct prestera_lag *lags;
	struct prestera_counter *counter;
	u8 lag_member_max;
	u8 lag_max;
	u32 size_tbl_router_nexthop;
};

struct prestera_router {
	struct prestera_switch *sw;
	struct list_head vr_list;
	struct list_head rif_entry_list;
	struct rhashtable nh_neigh_ht;
	struct rhashtable nexthop_group_ht;
	struct rhashtable fib_ht;
	struct rhashtable kern_fib_cache_ht;
	struct notifier_block inetaddr_nb;
	struct notifier_block inetaddr_valid_nb;
	struct notifier_block fib_nb;
	u8 *nhgrp_hw_state_cache; /* Bitmap cached hw state of nhs */
	unsigned long nhgrp_hw_cache_kick; /* jiffies */
};

struct prestera_rxtx_params {
	bool use_sdma;
	u32 map_addr;
};

#define prestera_dev(sw)		((sw)->dev->dev)

static inline void prestera_write(const struct prestera_switch *sw,
				  unsigned int reg, u32 val)
{
	writel(val, sw->dev->pp_regs + reg);
}

static inline u32 prestera_read(const struct prestera_switch *sw,
				unsigned int reg)
{
	return readl(sw->dev->pp_regs + reg);
}

int prestera_device_register(struct prestera_device *dev);
void prestera_device_unregister(struct prestera_device *dev);

struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
						 u32 dev_id, u32 hw_id);

int prestera_port_autoneg_set(struct prestera_port *port, u64 link_modes);

int prestera_router_init(struct prestera_switch *sw);
void prestera_router_fini(struct prestera_switch *sw);

struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id);

struct prestera_switch *prestera_switch_get(struct net_device *dev);

int prestera_port_cfg_mac_read(struct prestera_port *port,
			       struct prestera_port_mac_config *cfg);

int prestera_port_cfg_mac_write(struct prestera_port *port,
				struct prestera_port_mac_config *cfg);

struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev);

void prestera_queue_work(struct work_struct *work);

int prestera_port_learning_set(struct prestera_port *port, bool learn_enable);
int prestera_port_uc_flood_set(struct prestera_port *port, bool flood);
int prestera_port_mc_flood_set(struct prestera_port *port, bool flood);

int prestera_port_br_locked_set(struct prestera_port *port, bool br_locked);

int prestera_port_pvid_set(struct prestera_port *port, u16 vid);

bool prestera_netdev_check(const struct net_device *dev);

int prestera_is_valid_mac_addr(struct prestera_port *port, const u8 *addr);

bool prestera_port_is_lag_member(const struct prestera_port *port);
int prestera_lag_id(struct prestera_switch *sw,
		    struct net_device *lag_dev, u16 *lag_id);

struct prestera_lag *prestera_lag_by_id(struct prestera_switch *sw, u16 id);

u16 prestera_port_lag_id(const struct prestera_port *port);

struct prestera_mdb_entry *
prestera_mdb_entry_create(struct prestera_switch *sw,
			  const unsigned char *addr, u16 vid);
void prestera_mdb_entry_destroy(struct prestera_mdb_entry *mdb_entry);

struct prestera_flood_domain *
prestera_flood_domain_create(struct prestera_switch *sw);
void prestera_flood_domain_destroy(struct prestera_flood_domain *flood_domain);

int
prestera_flood_domain_port_create(struct prestera_flood_domain *flood_domain,
				  struct net_device *dev,
				  u16 vid);
void
prestera_flood_domain_port_destroy(struct prestera_flood_domain_port *port);
struct prestera_flood_domain_port *
prestera_flood_domain_port_find(struct prestera_flood_domain *flood_domain,
				struct net_device *dev, u16 vid);

#endif /* _PRESTERA_H_ */