Skip to content

Commit 47c0b58

Browse files
committed
Merge branch 'Introduce-a-flow-gate-control-action-and-apply-IEEE'
Po Liu says: ==================== Introduce a flow gate control action and apply IEEE Changes from V4: ---------------- 0001: Fix and modify according to Vlid Buslov suggestions: - Change spin_lock_bh() to spin_lock() since tcf_gate_act() already in software irq. - Remove spin lock protect in the ops->cleanup function. - Enable the CONFIG_DEBUG_ATOMIC_SLEEP and CONFIG_PROVE_LOCKING checking, then fix as kzalloc flag type and lock deadlock. - Change kzalloc() flag type from GFP_KERNEL to GFP_ATOMIC since function in the spin_lock protect. - Change hrtimer type from HRTIMER_MODE_ABS to HRTIMER_MODE_ABS_SOFT to avoid deadlock. 0002: Fix and modify according to Vlid Buslov suggestions: - Remove all rcu_read_lock protection since no rcu parameters. - Enable the CONFIG_DEBUG_ATOMIC_SLEEP and CONFIG_PROVE_LOCKING checking, then check kzalloc sleeping flag. - Change kzalloc to kcalloc for array memory alloc and change GFP_KERNEL flag to GFP_ATOMIC since function holding spin_lock protect. 0003: - No changes. 0004: - Commit comments rephrase act by Claudiu Manoil. Changes from V3: ---------------- 0001: Fix and modify according to Vlid Buslov: - Remove the struct gate_action and move the parameters to the struct tcf_gate align with tc_action parameters. This would not need to alloc rcu type memory with pointer. - Remove the spin_lock type entry_lock which do not needed anymore, will use the tcf_lock system provided. - Provide lockep protect for the status parameters in the tcf_gate_act(). - Remove the cycletime 0 input warning, return error directly. And: - Remove Qci related description in the Kconfig for gate action. 0002: - Fix rcu_read_lock protect range suggested by Vlid Buslov. 0003: - No changes. 0004: - Fix bug of gate maxoct wildcard condition not included. - Fix the pass time basetime calculation report by Vladimir Otlean. Changes from V2: 0001: No changes. 0002: No changes. 0003: No changes. 0004: Fix the vlan id filter parameter and add reject src mac FF-FF-FF-FF-FF-FF filter in driver. Changes from V1: ---------------- 0000: Update description make it more clear 0001: Removed 'add update dropped stats' patch, will provide pull request as standalone patches. 0001: Update commit description make it more clear ack by Jiri Pirko. 0002: No changes 0003: Fix some code style ack by Jiri Pirko. 0004: Fix enetc_psfp_enable/disable parameter type ack by test robot iprout2 command patches: Not attach with these serial patches, will provide separate pull request after kernel accept these patches. Changes from RFC: ----------------- 0000: Reduce to 5 patches and remove the 4 max frame size offload and flow metering in the policing offload action, Only keep gate action offloading implementation. 0001: No changes. 0002: - fix kfree lead ack by Jakub Kicinski and Cong Wang - License fix from Jakub Kicinski and Stephen Hemminger - Update example in commit acked by Vinicius Costa Gomes - Fix the rcu protect in tcf_gate_act() acked by Vinicius 0003: No changes 0004: No changes 0005: Acked by Vinicius Costa Gomes - Use refcount kernel lib - Update stream gate check code position - Update reduce ref names more clear iprout2 command patches: 0000: Update license expression and add gate id 0001: Add tc action gate man page -------------------------------------------------------------------- These patches add stream gate action policing in IEEE802.1Qci (Per-Stream Filtering and Policing) software support and hardware offload support in tc flower, and implement the stream identify, stream filtering and stream gate filtering action in the NXP ENETC ethernet driver. Per-Stream Filtering and Policing (PSFP) specifies flow policing and filtering for ingress flows, and has three main parts: 1. The stream filter instance table consists of an ordered list of stream filters that determine the filtering and policing actions that are to be applied to frames received on a specific stream. The main elements are stream gate id, flow metering id and maximum SDU size. 2. The stream gate function setup a gate list to control ingress traffic class open/close state. When the gate is running at open state, the flow could pass but dropped when gate state is running to close. User setup a bastime to tell gate when start running the entry list, then the hardware would periodiclly. There is no compare qdisc action support. 3. Flow metering is two rates two buckets and three-color marker to policing the frames. Flow metering instance are as specified in the algorithm in MEF10.3. The most likely qdisc action is policing action. The first patch introduces an ingress frame flow control gate action, for the point 2. The tc gate action maintains the open/close state gate list, allowing flows to pass when the gate is open. Each gate action may policing one or more qdisc filters. When the start time arrived, The driver would repeat the gate list periodiclly. User can assign a passed time, the driver would calculate a new future time by the cycletime of the gate list. The 0002 patch introduces the gate flow hardware offloading. The 0003 patch adds support control the on/off for the tc flower offloading by ethtool. The 0004 patch implement the stream identify and stream filtering and stream gate filtering action in the NXP ENETC ethernet driver. Tc filter command provide filtering keys with MAC address and VLAN id. These keys would be set to stream identify instance entry. Stream gate instance entry would refer the gate action parameters. Stream filter instance entry would refer the stream gate index and assign a stream handle value matches to the stream identify instance. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents eb236c2 + 888ae5a commit 47c0b58

File tree

13 files changed

+2268
-1
lines changed

13 files changed

+2268
-1
lines changed

drivers/net/ethernet/freescale/enetc/enetc.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,9 @@ void enetc_get_si_caps(struct enetc_si *si)
756756

757757
if (val & ENETC_SIPCAPR0_QBV)
758758
si->hw_features |= ENETC_SI_F_QBV;
759+
760+
if (val & ENETC_SIPCAPR0_PSFP)
761+
si->hw_features |= ENETC_SI_F_PSFP;
759762
}
760763

761764
static int enetc_dma_alloc_bdr(struct enetc_bdr *r, size_t bd_size)
@@ -1518,6 +1521,8 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
15181521
return enetc_setup_tc_cbs(ndev, type_data);
15191522
case TC_SETUP_QDISC_ETF:
15201523
return enetc_setup_tc_txtime(ndev, type_data);
1524+
case TC_SETUP_BLOCK:
1525+
return enetc_setup_tc_psfp(ndev, type_data);
15211526
default:
15221527
return -EOPNOTSUPP;
15231528
}
@@ -1567,15 +1572,42 @@ static int enetc_set_rss(struct net_device *ndev, int en)
15671572
return 0;
15681573
}
15691574

1575+
static int enetc_set_psfp(struct net_device *ndev, int en)
1576+
{
1577+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
1578+
int err;
1579+
1580+
if (en) {
1581+
err = enetc_psfp_enable(priv);
1582+
if (err)
1583+
return err;
1584+
1585+
priv->active_offloads |= ENETC_F_QCI;
1586+
return 0;
1587+
}
1588+
1589+
err = enetc_psfp_disable(priv);
1590+
if (err)
1591+
return err;
1592+
1593+
priv->active_offloads &= ~ENETC_F_QCI;
1594+
1595+
return 0;
1596+
}
1597+
15701598
int enetc_set_features(struct net_device *ndev,
15711599
netdev_features_t features)
15721600
{
15731601
netdev_features_t changed = ndev->features ^ features;
1602+
int err = 0;
15741603

15751604
if (changed & NETIF_F_RXHASH)
15761605
enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH));
15771606

1578-
return 0;
1607+
if (changed & NETIF_F_HW_TC)
1608+
err = enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
1609+
1610+
return err;
15791611
}
15801612

15811613
#ifdef CONFIG_FSL_ENETC_PTP_CLOCK

drivers/net/ethernet/freescale/enetc/enetc.h

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ enum enetc_errata {
151151
};
152152

153153
#define ENETC_SI_F_QBV BIT(0)
154+
#define ENETC_SI_F_PSFP BIT(1)
154155

155156
/* PCI IEP device data */
156157
struct enetc_si {
@@ -203,12 +204,20 @@ struct enetc_cls_rule {
203204
};
204205

205206
#define ENETC_MAX_BDR_INT 2 /* fixed to max # of available cpus */
207+
struct psfp_cap {
208+
u32 max_streamid;
209+
u32 max_psfp_filter;
210+
u32 max_psfp_gate;
211+
u32 max_psfp_gatelist;
212+
u32 max_psfp_meter;
213+
};
206214

207215
/* TODO: more hardware offloads */
208216
enum enetc_active_offloads {
209217
ENETC_F_RX_TSTAMP = BIT(0),
210218
ENETC_F_TX_TSTAMP = BIT(1),
211219
ENETC_F_QBV = BIT(2),
220+
ENETC_F_QCI = BIT(3),
212221
};
213222

214223
struct enetc_ndev_priv {
@@ -231,6 +240,8 @@ struct enetc_ndev_priv {
231240

232241
struct enetc_cls_rule *cls_rules;
233242

243+
struct psfp_cap psfp_cap;
244+
234245
struct device_node *phy_node;
235246
phy_interface_t if_mode;
236247
};
@@ -289,9 +300,84 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
289300
void enetc_sched_speed_set(struct net_device *ndev);
290301
int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data);
291302
int enetc_setup_tc_txtime(struct net_device *ndev, void *type_data);
303+
int enetc_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
304+
void *cb_priv);
305+
int enetc_setup_tc_psfp(struct net_device *ndev, void *type_data);
306+
int enetc_psfp_init(struct enetc_ndev_priv *priv);
307+
int enetc_psfp_clean(struct enetc_ndev_priv *priv);
308+
309+
static inline void enetc_get_max_cap(struct enetc_ndev_priv *priv)
310+
{
311+
u32 reg;
312+
313+
reg = enetc_port_rd(&priv->si->hw, ENETC_PSIDCAPR);
314+
priv->psfp_cap.max_streamid = reg & ENETC_PSIDCAPR_MSK;
315+
/* Port stream filter capability */
316+
reg = enetc_port_rd(&priv->si->hw, ENETC_PSFCAPR);
317+
priv->psfp_cap.max_psfp_filter = reg & ENETC_PSFCAPR_MSK;
318+
/* Port stream gate capability */
319+
reg = enetc_port_rd(&priv->si->hw, ENETC_PSGCAPR);
320+
priv->psfp_cap.max_psfp_gate = (reg & ENETC_PSGCAPR_SGIT_MSK);
321+
priv->psfp_cap.max_psfp_gatelist = (reg & ENETC_PSGCAPR_GCL_MSK) >> 16;
322+
/* Port flow meter capability */
323+
reg = enetc_port_rd(&priv->si->hw, ENETC_PFMCAPR);
324+
priv->psfp_cap.max_psfp_meter = reg & ENETC_PFMCAPR_MSK;
325+
}
326+
327+
static inline int enetc_psfp_enable(struct enetc_ndev_priv *priv)
328+
{
329+
struct enetc_hw *hw = &priv->si->hw;
330+
int err;
331+
332+
enetc_get_max_cap(priv);
333+
334+
err = enetc_psfp_init(priv);
335+
if (err)
336+
return err;
337+
338+
enetc_wr(hw, ENETC_PPSFPMR, enetc_rd(hw, ENETC_PPSFPMR) |
339+
ENETC_PPSFPMR_PSFPEN | ENETC_PPSFPMR_VS |
340+
ENETC_PPSFPMR_PVC | ENETC_PPSFPMR_PVZC);
341+
342+
return 0;
343+
}
344+
345+
static inline int enetc_psfp_disable(struct enetc_ndev_priv *priv)
346+
{
347+
struct enetc_hw *hw = &priv->si->hw;
348+
int err;
349+
350+
err = enetc_psfp_clean(priv);
351+
if (err)
352+
return err;
353+
354+
enetc_wr(hw, ENETC_PPSFPMR, enetc_rd(hw, ENETC_PPSFPMR) &
355+
~ENETC_PPSFPMR_PSFPEN & ~ENETC_PPSFPMR_VS &
356+
~ENETC_PPSFPMR_PVC & ~ENETC_PPSFPMR_PVZC);
357+
358+
memset(&priv->psfp_cap, 0, sizeof(struct psfp_cap));
359+
360+
return 0;
361+
}
362+
292363
#else
293364
#define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP
294365
#define enetc_sched_speed_set(ndev) (void)0
295366
#define enetc_setup_tc_cbs(ndev, type_data) -EOPNOTSUPP
296367
#define enetc_setup_tc_txtime(ndev, type_data) -EOPNOTSUPP
368+
#define enetc_setup_tc_psfp(ndev, type_data) -EOPNOTSUPP
369+
#define enetc_setup_tc_block_cb NULL
370+
371+
#define enetc_get_max_cap(p) \
372+
memset(&((p)->psfp_cap), 0, sizeof(struct psfp_cap))
373+
374+
static inline int enetc_psfp_enable(struct enetc_ndev_priv *priv)
375+
{
376+
return 0;
377+
}
378+
379+
static inline int enetc_psfp_disable(struct enetc_ndev_priv *priv)
380+
{
381+
return 0;
382+
}
297383
#endif

drivers/net/ethernet/freescale/enetc/enetc_hw.h

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define ENETC_SICTR1 0x1c
2020
#define ENETC_SIPCAPR0 0x20
2121
#define ENETC_SIPCAPR0_QBV BIT(4)
22+
#define ENETC_SIPCAPR0_PSFP BIT(9)
2223
#define ENETC_SIPCAPR0_RSS BIT(8)
2324
#define ENETC_SIPCAPR1 0x24
2425
#define ENETC_SITGTGR 0x30
@@ -228,6 +229,15 @@ enum enetc_bdr_type {TX, RX};
228229
#define ENETC_PM0_IFM_RLP (BIT(5) | BIT(11))
229230
#define ENETC_PM0_IFM_RGAUTO (BIT(15) | ENETC_PMO_IFM_RG | BIT(1))
230231
#define ENETC_PM0_IFM_XGMII BIT(12)
232+
#define ENETC_PSIDCAPR 0x1b08
233+
#define ENETC_PSIDCAPR_MSK GENMASK(15, 0)
234+
#define ENETC_PSFCAPR 0x1b18
235+
#define ENETC_PSFCAPR_MSK GENMASK(15, 0)
236+
#define ENETC_PSGCAPR 0x1b28
237+
#define ENETC_PSGCAPR_GCL_MSK GENMASK(18, 16)
238+
#define ENETC_PSGCAPR_SGIT_MSK GENMASK(15, 0)
239+
#define ENETC_PFMCAPR 0x1b38
240+
#define ENETC_PFMCAPR_MSK GENMASK(15, 0)
231241

232242
/* MAC counters */
233243
#define ENETC_PM0_REOCT 0x8100
@@ -557,6 +567,9 @@ enum bdcr_cmd_class {
557567
BDCR_CMD_RFS,
558568
BDCR_CMD_PORT_GCL,
559569
BDCR_CMD_RECV_CLASSIFIER,
570+
BDCR_CMD_STREAM_IDENTIFY,
571+
BDCR_CMD_STREAM_FILTER,
572+
BDCR_CMD_STREAM_GCL,
560573
__BDCR_CMD_MAX_LEN,
561574
BDCR_CMD_MAX_LEN = __BDCR_CMD_MAX_LEN - 1,
562575
};
@@ -588,13 +601,152 @@ struct tgs_gcl_data {
588601
struct gce entry[];
589602
};
590603

604+
/* class 7, command 0, Stream Identity Entry Configuration */
605+
struct streamid_conf {
606+
__le32 stream_handle; /* init gate value */
607+
__le32 iports;
608+
u8 id_type;
609+
u8 oui[3];
610+
u8 res[3];
611+
u8 en;
612+
};
613+
614+
#define ENETC_CBDR_SID_VID_MASK 0xfff
615+
#define ENETC_CBDR_SID_VIDM BIT(12)
616+
#define ENETC_CBDR_SID_TG_MASK 0xc000
617+
/* streamid_conf address point to this data space */
618+
struct streamid_data {
619+
union {
620+
u8 dmac[6];
621+
u8 smac[6];
622+
};
623+
u16 vid_vidm_tg;
624+
};
625+
626+
#define ENETC_CBDR_SFI_PRI_MASK 0x7
627+
#define ENETC_CBDR_SFI_PRIM BIT(3)
628+
#define ENETC_CBDR_SFI_BLOV BIT(4)
629+
#define ENETC_CBDR_SFI_BLEN BIT(5)
630+
#define ENETC_CBDR_SFI_MSDUEN BIT(6)
631+
#define ENETC_CBDR_SFI_FMITEN BIT(7)
632+
#define ENETC_CBDR_SFI_ENABLE BIT(7)
633+
/* class 8, command 0, Stream Filter Instance, Short Format */
634+
struct sfi_conf {
635+
__le32 stream_handle;
636+
u8 multi;
637+
u8 res[2];
638+
u8 sthm;
639+
/* Max Service Data Unit or Flow Meter Instance Table index.
640+
* Depending on the value of FLT this represents either Max
641+
* Service Data Unit (max frame size) allowed by the filter
642+
* entry or is an index into the Flow Meter Instance table
643+
* index identifying the policer which will be used to police
644+
* it.
645+
*/
646+
__le16 fm_inst_table_index;
647+
__le16 msdu;
648+
__le16 sg_inst_table_index;
649+
u8 res1[2];
650+
__le32 input_ports;
651+
u8 res2[3];
652+
u8 en;
653+
};
654+
655+
/* class 8, command 2 stream Filter Instance status query short format
656+
* command no need structure define
657+
* Stream Filter Instance Query Statistics Response data
658+
*/
659+
struct sfi_counter_data {
660+
u32 matchl;
661+
u32 matchh;
662+
u32 msdu_dropl;
663+
u32 msdu_droph;
664+
u32 stream_gate_dropl;
665+
u32 stream_gate_droph;
666+
u32 flow_meter_dropl;
667+
u32 flow_meter_droph;
668+
};
669+
670+
#define ENETC_CBDR_SGI_OIPV_MASK 0x7
671+
#define ENETC_CBDR_SGI_OIPV_EN BIT(3)
672+
#define ENETC_CBDR_SGI_CGTST BIT(6)
673+
#define ENETC_CBDR_SGI_OGTST BIT(7)
674+
#define ENETC_CBDR_SGI_CFG_CHG BIT(1)
675+
#define ENETC_CBDR_SGI_CFG_PND BIT(2)
676+
#define ENETC_CBDR_SGI_OEX BIT(4)
677+
#define ENETC_CBDR_SGI_OEXEN BIT(5)
678+
#define ENETC_CBDR_SGI_IRX BIT(6)
679+
#define ENETC_CBDR_SGI_IRXEN BIT(7)
680+
#define ENETC_CBDR_SGI_ACLLEN_MASK 0x3
681+
#define ENETC_CBDR_SGI_OCLLEN_MASK 0xc
682+
#define ENETC_CBDR_SGI_EN BIT(7)
683+
/* class 9, command 0, Stream Gate Instance Table, Short Format
684+
* class 9, command 2, Stream Gate Instance Table entry query write back
685+
* Short Format
686+
*/
687+
struct sgi_table {
688+
u8 res[8];
689+
u8 oipv;
690+
u8 res0[2];
691+
u8 ocgtst;
692+
u8 res1[7];
693+
u8 gset;
694+
u8 oacl_len;
695+
u8 res2[2];
696+
u8 en;
697+
};
698+
699+
#define ENETC_CBDR_SGI_AIPV_MASK 0x7
700+
#define ENETC_CBDR_SGI_AIPV_EN BIT(3)
701+
#define ENETC_CBDR_SGI_AGTST BIT(7)
702+
703+
/* class 9, command 1, Stream Gate Control List, Long Format */
704+
struct sgcl_conf {
705+
u8 aipv;
706+
u8 res[2];
707+
u8 agtst;
708+
u8 res1[4];
709+
union {
710+
struct {
711+
u8 res2[4];
712+
u8 acl_len;
713+
u8 res3[3];
714+
};
715+
u8 cct[8]; /* Config change time */
716+
};
717+
};
718+
719+
#define ENETC_CBDR_SGL_IOMEN BIT(0)
720+
#define ENETC_CBDR_SGL_IPVEN BIT(3)
721+
#define ENETC_CBDR_SGL_GTST BIT(4)
722+
#define ENETC_CBDR_SGL_IPV_MASK 0xe
723+
/* Stream Gate Control List Entry */
724+
struct sgce {
725+
u32 interval;
726+
u8 msdu[3];
727+
u8 multi;
728+
};
729+
730+
/* stream control list class 9 , cmd 1 data buffer */
731+
struct sgcl_data {
732+
u32 btl;
733+
u32 bth;
734+
u32 ct;
735+
u32 cte;
736+
struct sgce sgcl[0];
737+
};
738+
591739
struct enetc_cbd {
592740
union{
741+
struct sfi_conf sfi_conf;
742+
struct sgi_table sgi_table;
593743
struct {
594744
__le32 addr[2];
595745
union {
596746
__le32 opt[4];
597747
struct tgs_gcl_conf gcl_conf;
748+
struct streamid_conf sid_set;
749+
struct sgcl_conf sgcl_conf;
598750
};
599751
}; /* Long format */
600752
__le32 data[6];
@@ -621,3 +773,10 @@ struct enetc_cbd {
621773
/* Port time specific departure */
622774
#define ENETC_PTCTSDR(n) (0x1210 + 4 * (n))
623775
#define ENETC_TSDE BIT(31)
776+
777+
/* PSFP setting */
778+
#define ENETC_PPSFPMR 0x11b00
779+
#define ENETC_PPSFPMR_PSFPEN BIT(0)
780+
#define ENETC_PPSFPMR_VS BIT(1)
781+
#define ENETC_PPSFPMR_PVC BIT(2)
782+
#define ENETC_PPSFPMR_PVZC BIT(3)

drivers/net/ethernet/freescale/enetc/enetc_pf.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,12 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
727727
if (si->hw_features & ENETC_SI_F_QBV)
728728
priv->active_offloads |= ENETC_F_QBV;
729729

730+
if (si->hw_features & ENETC_SI_F_PSFP && !enetc_psfp_enable(priv)) {
731+
priv->active_offloads |= ENETC_F_QCI;
732+
ndev->features |= NETIF_F_HW_TC;
733+
ndev->hw_features |= NETIF_F_HW_TC;
734+
}
735+
730736
/* pick up primary MAC address from SI */
731737
enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr);
732738
}

0 commit comments

Comments
 (0)