1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (C) 2019 Chelsio Communications.  All rights reserved. */
3
4#include "cxgb4.h"
5#include "cxgb4_tc_matchall.h"
6#include "sched.h"
7#include "cxgb4_uld.h"
8#include "cxgb4_filter.h"
9#include "cxgb4_tc_flower.h"
10
11static int cxgb4_policer_validate(const struct flow_action *action,
12				  const struct flow_action_entry *act,
13				  struct netlink_ext_ack *extack)
14{
15	if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
16		NL_SET_ERR_MSG_MOD(extack,
17				   "Offload not supported when exceed action is not drop");
18		return -EOPNOTSUPP;
19	}
20
21	if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
22	    act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
23		NL_SET_ERR_MSG_MOD(extack,
24				   "Offload not supported when conform action is not pipe or ok");
25		return -EOPNOTSUPP;
26	}
27
28	if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
29	    !flow_action_is_last_entry(action, act)) {
30		NL_SET_ERR_MSG_MOD(extack,
31				   "Offload not supported when conform action is ok, but action is not last");
32		return -EOPNOTSUPP;
33	}
34
35	if (act->police.peakrate_bytes_ps ||
36	    act->police.avrate || act->police.overhead) {
37		NL_SET_ERR_MSG_MOD(extack,
38				   "Offload not supported when peakrate/avrate/overhead is configured");
39		return -EOPNOTSUPP;
40	}
41
42	if (act->police.rate_pkt_ps) {
43		NL_SET_ERR_MSG_MOD(extack,
44				   "QoS offload not support packets per second");
45		return -EOPNOTSUPP;
46	}
47
48	return 0;
49}
50
51static int cxgb4_matchall_egress_validate(struct net_device *dev,
52					  struct tc_cls_matchall_offload *cls)
53{
54	struct netlink_ext_ack *extack = cls->common.extack;
55	struct flow_action *actions = &cls->rule->action;
56	struct port_info *pi = netdev2pinfo(dev);
57	struct flow_action_entry *entry;
58	struct ch_sched_queue qe;
59	struct sched_class *e;
60	u64 max_link_rate;
61	u32 i, speed;
62	int ret;
63
64	if (!flow_action_has_entries(actions)) {
65		NL_SET_ERR_MSG_MOD(extack,
66				   "Egress MATCHALL offload needs at least 1 policing action");
67		return -EINVAL;
68	} else if (!flow_offload_has_one_action(actions)) {
69		NL_SET_ERR_MSG_MOD(extack,
70				   "Egress MATCHALL offload only supports 1 policing action");
71		return -EINVAL;
72	} else if (pi->tc_block_shared) {
73		NL_SET_ERR_MSG_MOD(extack,
74				   "Egress MATCHALL offload not supported with shared blocks");
75		return -EINVAL;
76	}
77
78	ret = t4_get_link_params(pi, NULL, &speed, NULL);
79	if (ret) {
80		NL_SET_ERR_MSG_MOD(extack,
81				   "Failed to get max speed supported by the link");
82		return -EINVAL;
83	}
84
85	/* Convert from Mbps to bps */
86	max_link_rate = (u64)speed * 1000 * 1000;
87
88	flow_action_for_each(i, entry, actions) {
89		switch (entry->id) {
90		case FLOW_ACTION_POLICE:
91			ret = cxgb4_policer_validate(actions, entry, extack);
92			if (ret)
93				return ret;
94
95			/* Convert bytes per second to bits per second */
96			if (entry->police.rate_bytes_ps * 8 > max_link_rate) {
97				NL_SET_ERR_MSG_MOD(extack,
98						   "Specified policing max rate is larger than underlying link speed");
99				return -ERANGE;
100			}
101			break;
102		default:
103			NL_SET_ERR_MSG_MOD(extack,
104					   "Only policing action supported with Egress MATCHALL offload");
105			return -EOPNOTSUPP;
106		}
107	}
108
109	for (i = 0; i < pi->nqsets; i++) {
110		memset(&qe, 0, sizeof(qe));
111		qe.queue = i;
112
113		e = cxgb4_sched_queue_lookup(dev, &qe);
114		if (e && e->info.u.params.level != SCHED_CLASS_LEVEL_CH_RL) {
115			NL_SET_ERR_MSG_MOD(extack,
116					   "Some queues are already bound to different class");
117			return -EBUSY;
118		}
119	}
120
121	return 0;
122}
123
124static int cxgb4_matchall_tc_bind_queues(struct net_device *dev, u32 tc)
125{
126	struct port_info *pi = netdev2pinfo(dev);
127	struct ch_sched_queue qe;
128	int ret;
129	u32 i;
130
131	for (i = 0; i < pi->nqsets; i++) {
132		qe.queue = i;
133		qe.class = tc;
134		ret = cxgb4_sched_class_bind(dev, &qe, SCHED_QUEUE);
135		if (ret)
136			goto out_free;
137	}
138
139	return 0;
140
141out_free:
142	while (i--) {
143		qe.queue = i;
144		qe.class = SCHED_CLS_NONE;
145		cxgb4_sched_class_unbind(dev, &qe, SCHED_QUEUE);
146	}
147
148	return ret;
149}
150
151static void cxgb4_matchall_tc_unbind_queues(struct net_device *dev)
152{
153	struct port_info *pi = netdev2pinfo(dev);
154	struct ch_sched_queue qe;
155	u32 i;
156
157	for (i = 0; i < pi->nqsets; i++) {
158		qe.queue = i;
159		qe.class = SCHED_CLS_NONE;
160		cxgb4_sched_class_unbind(dev, &qe, SCHED_QUEUE);
161	}
162}
163
164static int cxgb4_matchall_alloc_tc(struct net_device *dev,
165				   struct tc_cls_matchall_offload *cls)
166{
167	struct ch_sched_params p = {
168		.type = SCHED_CLASS_TYPE_PACKET,
169		.u.params.level = SCHED_CLASS_LEVEL_CH_RL,
170		.u.params.mode = SCHED_CLASS_MODE_CLASS,
171		.u.params.rateunit = SCHED_CLASS_RATEUNIT_BITS,
172		.u.params.ratemode = SCHED_CLASS_RATEMODE_ABS,
173		.u.params.class = SCHED_CLS_NONE,
174		.u.params.minrate = 0,
175		.u.params.weight = 0,
176		.u.params.pktsize = dev->mtu,
177	};
178	struct netlink_ext_ack *extack = cls->common.extack;
179	struct cxgb4_tc_port_matchall *tc_port_matchall;
180	struct port_info *pi = netdev2pinfo(dev);
181	struct adapter *adap = netdev2adap(dev);
182	struct flow_action_entry *entry;
183	struct sched_class *e;
184	int ret;
185	u32 i;
186
187	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
188
189	flow_action_for_each(i, entry, &cls->rule->action)
190		if (entry->id == FLOW_ACTION_POLICE)
191			break;
192
193	ret = cxgb4_policer_validate(&cls->rule->action, entry, extack);
194	if (ret)
195		return ret;
196
197	/* Convert from bytes per second to Kbps */
198	p.u.params.maxrate = div_u64(entry->police.rate_bytes_ps * 8, 1000);
199	p.u.params.channel = pi->tx_chan;
200	e = cxgb4_sched_class_alloc(dev, &p);
201	if (!e) {
202		NL_SET_ERR_MSG_MOD(extack,
203				   "No free traffic class available for policing action");
204		return -ENOMEM;
205	}
206
207	ret = cxgb4_matchall_tc_bind_queues(dev, e->idx);
208	if (ret) {
209		NL_SET_ERR_MSG_MOD(extack,
210				   "Could not bind queues to traffic class");
211		goto out_free;
212	}
213
214	tc_port_matchall->egress.hwtc = e->idx;
215	tc_port_matchall->egress.cookie = cls->cookie;
216	tc_port_matchall->egress.state = CXGB4_MATCHALL_STATE_ENABLED;
217	return 0;
218
219out_free:
220	cxgb4_sched_class_free(dev, e->idx);
221	return ret;
222}
223
224static void cxgb4_matchall_free_tc(struct net_device *dev)
225{
226	struct cxgb4_tc_port_matchall *tc_port_matchall;
227	struct port_info *pi = netdev2pinfo(dev);
228	struct adapter *adap = netdev2adap(dev);
229
230	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
231	cxgb4_matchall_tc_unbind_queues(dev);
232	cxgb4_sched_class_free(dev, tc_port_matchall->egress.hwtc);
233
234	tc_port_matchall->egress.hwtc = SCHED_CLS_NONE;
235	tc_port_matchall->egress.cookie = 0;
236	tc_port_matchall->egress.state = CXGB4_MATCHALL_STATE_DISABLED;
237}
238
239static int cxgb4_matchall_mirror_alloc(struct net_device *dev,
240				       struct tc_cls_matchall_offload *cls)
241{
242	struct netlink_ext_ack *extack = cls->common.extack;
243	struct cxgb4_tc_port_matchall *tc_port_matchall;
244	struct port_info *pi = netdev2pinfo(dev);
245	struct adapter *adap = netdev2adap(dev);
246	struct flow_action_entry *act;
247	int ret;
248	u32 i;
249
250	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
251	flow_action_for_each(i, act, &cls->rule->action) {
252		if (act->id == FLOW_ACTION_MIRRED) {
253			ret = cxgb4_port_mirror_alloc(dev);
254			if (ret) {
255				NL_SET_ERR_MSG_MOD(extack,
256						   "Couldn't allocate mirror");
257				return ret;
258			}
259
260			tc_port_matchall->ingress.viid_mirror = pi->viid_mirror;
261			break;
262		}
263	}
264
265	return 0;
266}
267
268static void cxgb4_matchall_mirror_free(struct net_device *dev)
269{
270	struct cxgb4_tc_port_matchall *tc_port_matchall;
271	struct port_info *pi = netdev2pinfo(dev);
272	struct adapter *adap = netdev2adap(dev);
273
274	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
275	if (!tc_port_matchall->ingress.viid_mirror)
276		return;
277
278	cxgb4_port_mirror_free(dev);
279	tc_port_matchall->ingress.viid_mirror = 0;
280}
281
282static int cxgb4_matchall_del_filter(struct net_device *dev, u8 filter_type)
283{
284	struct cxgb4_tc_port_matchall *tc_port_matchall;
285	struct port_info *pi = netdev2pinfo(dev);
286	struct adapter *adap = netdev2adap(dev);
287	int ret;
288
289	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
290	ret = cxgb4_del_filter(dev, tc_port_matchall->ingress.tid[filter_type],
291			       &tc_port_matchall->ingress.fs[filter_type]);
292	if (ret)
293		return ret;
294
295	tc_port_matchall->ingress.tid[filter_type] = 0;
296	return 0;
297}
298
299static int cxgb4_matchall_add_filter(struct net_device *dev,
300				     struct tc_cls_matchall_offload *cls,
301				     u8 filter_type)
302{
303	struct netlink_ext_ack *extack = cls->common.extack;
304	struct cxgb4_tc_port_matchall *tc_port_matchall;
305	struct port_info *pi = netdev2pinfo(dev);
306	struct adapter *adap = netdev2adap(dev);
307	struct ch_filter_specification *fs;
308	int ret, fidx;
309
310	/* Get a free filter entry TID, where we can insert this new
311	 * rule. Only insert rule if its prio doesn't conflict with
312	 * existing rules.
313	 */
314	fidx = cxgb4_get_free_ftid(dev, filter_type ? PF_INET6 : PF_INET,
315				   false, cls->common.prio);
316	if (fidx < 0) {
317		NL_SET_ERR_MSG_MOD(extack,
318				   "No free LETCAM index available");
319		return -ENOMEM;
320	}
321
322	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
323	fs = &tc_port_matchall->ingress.fs[filter_type];
324	memset(fs, 0, sizeof(*fs));
325
326	if (fidx < adap->tids.nhpftids)
327		fs->prio = 1;
328	fs->tc_prio = cls->common.prio;
329	fs->tc_cookie = cls->cookie;
330	fs->type = filter_type;
331	fs->hitcnts = 1;
332
333	fs->val.pfvf_vld = 1;
334	fs->val.pf = adap->pf;
335	fs->val.vf = pi->vin;
336
337	cxgb4_process_flow_actions(dev, &cls->rule->action, fs);
338
339	ret = cxgb4_set_filter(dev, fidx, fs);
340	if (ret)
341		return ret;
342
343	tc_port_matchall->ingress.tid[filter_type] = fidx;
344	return 0;
345}
346
347static int cxgb4_matchall_alloc_filter(struct net_device *dev,
348				       struct tc_cls_matchall_offload *cls)
349{
350	struct cxgb4_tc_port_matchall *tc_port_matchall;
351	struct port_info *pi = netdev2pinfo(dev);
352	struct adapter *adap = netdev2adap(dev);
353	int ret, i;
354
355	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
356
357	ret = cxgb4_matchall_mirror_alloc(dev, cls);
358	if (ret)
359		return ret;
360
361	for (i = 0; i < CXGB4_FILTER_TYPE_MAX; i++) {
362		ret = cxgb4_matchall_add_filter(dev, cls, i);
363		if (ret)
364			goto out_free;
365	}
366
367	tc_port_matchall->ingress.state = CXGB4_MATCHALL_STATE_ENABLED;
368	return 0;
369
370out_free:
371	while (i-- > 0)
372		cxgb4_matchall_del_filter(dev, i);
373
374	cxgb4_matchall_mirror_free(dev);
375	return ret;
376}
377
378static int cxgb4_matchall_free_filter(struct net_device *dev)
379{
380	struct cxgb4_tc_port_matchall *tc_port_matchall;
381	struct port_info *pi = netdev2pinfo(dev);
382	struct adapter *adap = netdev2adap(dev);
383	int ret;
384	u8 i;
385
386	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
387
388	for (i = 0; i < CXGB4_FILTER_TYPE_MAX; i++) {
389		ret = cxgb4_matchall_del_filter(dev, i);
390		if (ret)
391			return ret;
392	}
393
394	cxgb4_matchall_mirror_free(dev);
395
396	tc_port_matchall->ingress.packets = 0;
397	tc_port_matchall->ingress.bytes = 0;
398	tc_port_matchall->ingress.last_used = 0;
399	tc_port_matchall->ingress.state = CXGB4_MATCHALL_STATE_DISABLED;
400	return 0;
401}
402
403int cxgb4_tc_matchall_replace(struct net_device *dev,
404			      struct tc_cls_matchall_offload *cls_matchall,
405			      bool ingress)
406{
407	struct netlink_ext_ack *extack = cls_matchall->common.extack;
408	struct cxgb4_tc_port_matchall *tc_port_matchall;
409	struct port_info *pi = netdev2pinfo(dev);
410	struct adapter *adap = netdev2adap(dev);
411	int ret;
412
413	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
414	if (ingress) {
415		if (tc_port_matchall->ingress.state ==
416		    CXGB4_MATCHALL_STATE_ENABLED) {
417			NL_SET_ERR_MSG_MOD(extack,
418					   "Only 1 Ingress MATCHALL can be offloaded");
419			return -ENOMEM;
420		}
421
422		ret = cxgb4_validate_flow_actions(dev,
423						  &cls_matchall->rule->action,
424						  extack, 1);
425		if (ret)
426			return ret;
427
428		return cxgb4_matchall_alloc_filter(dev, cls_matchall);
429	}
430
431	if (tc_port_matchall->egress.state == CXGB4_MATCHALL_STATE_ENABLED) {
432		NL_SET_ERR_MSG_MOD(extack,
433				   "Only 1 Egress MATCHALL can be offloaded");
434		return -ENOMEM;
435	}
436
437	ret = cxgb4_matchall_egress_validate(dev, cls_matchall);
438	if (ret)
439		return ret;
440
441	return cxgb4_matchall_alloc_tc(dev, cls_matchall);
442}
443
444int cxgb4_tc_matchall_destroy(struct net_device *dev,
445			      struct tc_cls_matchall_offload *cls_matchall,
446			      bool ingress)
447{
448	struct cxgb4_tc_port_matchall *tc_port_matchall;
449	struct port_info *pi = netdev2pinfo(dev);
450	struct adapter *adap = netdev2adap(dev);
451
452	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
453	if (ingress) {
454		/* All the filter types of this matchall rule save the
455		 * same cookie. So, checking for the first one is
456		 * enough.
457		 */
458		if (cls_matchall->cookie !=
459		    tc_port_matchall->ingress.fs[0].tc_cookie)
460			return -ENOENT;
461
462		return cxgb4_matchall_free_filter(dev);
463	}
464
465	if (cls_matchall->cookie != tc_port_matchall->egress.cookie)
466		return -ENOENT;
467
468	cxgb4_matchall_free_tc(dev);
469	return 0;
470}
471
472int cxgb4_tc_matchall_stats(struct net_device *dev,
473			    struct tc_cls_matchall_offload *cls_matchall)
474{
475	u64 tmp_packets, tmp_bytes, packets = 0, bytes = 0;
476	struct cxgb4_tc_port_matchall *tc_port_matchall;
477	struct cxgb4_matchall_ingress_entry *ingress;
478	struct port_info *pi = netdev2pinfo(dev);
479	struct adapter *adap = netdev2adap(dev);
480	int ret;
481	u8 i;
482
483	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
484	if (tc_port_matchall->ingress.state == CXGB4_MATCHALL_STATE_DISABLED)
485		return -ENOENT;
486
487	ingress = &tc_port_matchall->ingress;
488	for (i = 0; i < CXGB4_FILTER_TYPE_MAX; i++) {
489		ret = cxgb4_get_filter_counters(dev, ingress->tid[i],
490						&tmp_packets, &tmp_bytes,
491						ingress->fs[i].hash);
492		if (ret)
493			return ret;
494
495		packets += tmp_packets;
496		bytes += tmp_bytes;
497	}
498
499	if (tc_port_matchall->ingress.packets != packets) {
500		flow_stats_update(&cls_matchall->stats,
501				  bytes - tc_port_matchall->ingress.bytes,
502				  packets - tc_port_matchall->ingress.packets,
503				  0, tc_port_matchall->ingress.last_used,
504				  FLOW_ACTION_HW_STATS_IMMEDIATE);
505
506		tc_port_matchall->ingress.packets = packets;
507		tc_port_matchall->ingress.bytes = bytes;
508		tc_port_matchall->ingress.last_used = jiffies;
509	}
510
511	return 0;
512}
513
514static void cxgb4_matchall_disable_offload(struct net_device *dev)
515{
516	struct cxgb4_tc_port_matchall *tc_port_matchall;
517	struct port_info *pi = netdev2pinfo(dev);
518	struct adapter *adap = netdev2adap(dev);
519
520	tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
521	if (tc_port_matchall->egress.state == CXGB4_MATCHALL_STATE_ENABLED)
522		cxgb4_matchall_free_tc(dev);
523
524	if (tc_port_matchall->ingress.state == CXGB4_MATCHALL_STATE_ENABLED)
525		cxgb4_matchall_free_filter(dev);
526}
527
528int cxgb4_init_tc_matchall(struct adapter *adap)
529{
530	struct cxgb4_tc_port_matchall *tc_port_matchall;
531	struct cxgb4_tc_matchall *tc_matchall;
532	int ret;
533
534	tc_matchall = kzalloc(sizeof(*tc_matchall), GFP_KERNEL);
535	if (!tc_matchall)
536		return -ENOMEM;
537
538	tc_port_matchall = kcalloc(adap->params.nports,
539				   sizeof(*tc_port_matchall),
540				   GFP_KERNEL);
541	if (!tc_port_matchall) {
542		ret = -ENOMEM;
543		goto out_free_matchall;
544	}
545
546	tc_matchall->port_matchall = tc_port_matchall;
547	adap->tc_matchall = tc_matchall;
548	return 0;
549
550out_free_matchall:
551	kfree(tc_matchall);
552	return ret;
553}
554
555void cxgb4_cleanup_tc_matchall(struct adapter *adap)
556{
557	u8 i;
558
559	if (adap->tc_matchall) {
560		if (adap->tc_matchall->port_matchall) {
561			for (i = 0; i < adap->params.nports; i++) {
562				struct net_device *dev = adap->port[i];
563
564				if (dev)
565					cxgb4_matchall_disable_offload(dev);
566			}
567			kfree(adap->tc_matchall->port_matchall);
568		}
569		kfree(adap->tc_matchall);
570	}
571}
572