Skip to content

Commit 888ae5a

Browse files
liupoerdavem330
authored andcommitted
net: enetc: add tc flower psfp offload driver
This patch is to add tc flower offload for the enetc IEEE 802.1Qci(PSFP) function. There are four main feature parts to implement the flow policing and filtering for ingress flow with IEEE 802.1Qci features. They are stream identify(this is defined in the P802.1cb exactly but needed for 802.1Qci), stream filtering, stream gate and flow metering. Each function block includes many entries by index to assign parameters. So for one frame would be filtered by stream identify first, then flow into stream filter block by the same handle between stream identify and stream filtering. Then flow into stream gate control which assigned by the stream filtering entry. And then policing by the gate and limited by the max sdu in the filter block(optional). At last, policing by the flow metering block, index choosing at the fitering block. So you can see that each entry of block may link to many upper entries since they can be assigned same index means more streams want to share the same feature in the stream filtering or stream gate or flow metering. To implement such features, each stream filtered by source/destination mac address, some stream maybe also plus the vlan id value would be treated as one flow chain. This would be identified by the chain_index which already in the tc filter concept. Driver would maintain this chain and also with gate modules. The stream filter entry create by the gate index and flow meter(optional) entry id and also one priority value. Offloading only transfer the gate action and flow filtering parameters. Driver would create (or search same gate id and flow meter id and priority) one stream filter entry to set to the hardware. So stream filtering do not need transfer by the action offloading. This architecture is same with tc filter and actions relationship. tc filter maintain the list for each flow feature by keys. And actions maintain by the action list. Below showing a example commands by tc: > tc qdisc add dev eth0 ingress > ip link set eth0 address 10:00:80:00:00:00 > tc filter add dev eth0 parent ffff: protocol ip chain 11 \ flower skip_sw dst_mac 10:00:80:00:00:00 \ action gate index 10 \ sched-entry open 200000000 1 8000000 \ sched-entry close 100000000 -1 -1 Command means to set the dst_mac 10:00:80:00:00:00 to index 11 of stream identify module. Then setting the gate index 10 of stream gate module. Keep the gate open for 200ms and limit the traffic volume to 8MB in this sched-entry. Then direct the frames to the ingress queue 1. Signed-off-by: Po Liu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 79e4998 commit 888ae5a

File tree

5 files changed

+1300
-15
lines changed

5 files changed

+1300
-15
lines changed

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,8 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
15211521
return enetc_setup_tc_cbs(ndev, type_data);
15221522
case TC_SETUP_QDISC_ETF:
15231523
return enetc_setup_tc_txtime(ndev, type_data);
1524+
case TC_SETUP_BLOCK:
1525+
return enetc_setup_tc_psfp(ndev, type_data);
15241526
default:
15251527
return -EOPNOTSUPP;
15261528
}
@@ -1573,32 +1575,39 @@ static int enetc_set_rss(struct net_device *ndev, int en)
15731575
static int enetc_set_psfp(struct net_device *ndev, int en)
15741576
{
15751577
struct enetc_ndev_priv *priv = netdev_priv(ndev);
1578+
int err;
15761579

15771580
if (en) {
1581+
err = enetc_psfp_enable(priv);
1582+
if (err)
1583+
return err;
1584+
15781585
priv->active_offloads |= ENETC_F_QCI;
1579-
enetc_get_max_cap(priv);
1580-
enetc_psfp_enable(&priv->si->hw);
1581-
} else {
1582-
priv->active_offloads &= ~ENETC_F_QCI;
1583-
memset(&priv->psfp_cap, 0, sizeof(struct psfp_cap));
1584-
enetc_psfp_disable(&priv->si->hw);
1586+
return 0;
15851587
}
15861588

1589+
err = enetc_psfp_disable(priv);
1590+
if (err)
1591+
return err;
1592+
1593+
priv->active_offloads &= ~ENETC_F_QCI;
1594+
15871595
return 0;
15881596
}
15891597

15901598
int enetc_set_features(struct net_device *ndev,
15911599
netdev_features_t features)
15921600
{
15931601
netdev_features_t changed = ndev->features ^ features;
1602+
int err = 0;
15941603

15951604
if (changed & NETIF_F_RXHASH)
15961605
enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH));
15971606

15981607
if (changed & NETIF_F_HW_TC)
1599-
enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
1608+
err = enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
16001609

1601-
return 0;
1610+
return err;
16021611
}
16031612

16041613
#ifdef CONFIG_FSL_ENETC_PTP_CLOCK

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

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data);
300300
void enetc_sched_speed_set(struct net_device *ndev);
301301
int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data);
302302
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);
303308

304309
static inline void enetc_get_max_cap(struct enetc_ndev_priv *priv)
305310
{
@@ -319,27 +324,60 @@ static inline void enetc_get_max_cap(struct enetc_ndev_priv *priv)
319324
priv->psfp_cap.max_psfp_meter = reg & ENETC_PFMCAPR_MSK;
320325
}
321326

322-
static inline void enetc_psfp_enable(struct enetc_hw *hw)
327+
static inline int enetc_psfp_enable(struct enetc_ndev_priv *priv)
323328
{
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+
324338
enetc_wr(hw, ENETC_PPSFPMR, enetc_rd(hw, ENETC_PPSFPMR) |
325339
ENETC_PPSFPMR_PSFPEN | ENETC_PPSFPMR_VS |
326340
ENETC_PPSFPMR_PVC | ENETC_PPSFPMR_PVZC);
341+
342+
return 0;
327343
}
328344

329-
static inline void enetc_psfp_disable(struct enetc_hw *hw)
345+
static inline int enetc_psfp_disable(struct enetc_ndev_priv *priv)
330346
{
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+
331354
enetc_wr(hw, ENETC_PPSFPMR, enetc_rd(hw, ENETC_PPSFPMR) &
332355
~ENETC_PPSFPMR_PSFPEN & ~ENETC_PPSFPMR_VS &
333356
~ENETC_PPSFPMR_PVC & ~ENETC_PPSFPMR_PVZC);
357+
358+
memset(&priv->psfp_cap, 0, sizeof(struct psfp_cap));
359+
360+
return 0;
334361
}
362+
335363
#else
336364
#define enetc_setup_tc_taprio(ndev, type_data) -EOPNOTSUPP
337365
#define enetc_sched_speed_set(ndev) (void)0
338366
#define enetc_setup_tc_cbs(ndev, type_data) -EOPNOTSUPP
339367
#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+
340371
#define enetc_get_max_cap(p) \
341372
memset(&((p)->psfp_cap), 0, sizeof(struct psfp_cap))
342373

343-
#define enetc_psfp_enable(hw) (void)0
344-
#define enetc_psfp_disable(hw) (void)0
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+
}
345383
#endif

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

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,9 @@ enum bdcr_cmd_class {
567567
BDCR_CMD_RFS,
568568
BDCR_CMD_PORT_GCL,
569569
BDCR_CMD_RECV_CLASSIFIER,
570+
BDCR_CMD_STREAM_IDENTIFY,
571+
BDCR_CMD_STREAM_FILTER,
572+
BDCR_CMD_STREAM_GCL,
570573
__BDCR_CMD_MAX_LEN,
571574
BDCR_CMD_MAX_LEN = __BDCR_CMD_MAX_LEN - 1,
572575
};
@@ -598,13 +601,152 @@ struct tgs_gcl_data {
598601
struct gce entry[];
599602
};
600603

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+
601739
struct enetc_cbd {
602740
union{
741+
struct sfi_conf sfi_conf;
742+
struct sgi_table sgi_table;
603743
struct {
604744
__le32 addr[2];
605745
union {
606746
__le32 opt[4];
607747
struct tgs_gcl_conf gcl_conf;
748+
struct streamid_conf sid_set;
749+
struct sgcl_conf sgcl_conf;
608750
};
609751
}; /* Long format */
610752
__le32 data[6];

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,12 +727,10 @@ 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) {
730+
if (si->hw_features & ENETC_SI_F_PSFP && !enetc_psfp_enable(priv)) {
731731
priv->active_offloads |= ENETC_F_QCI;
732732
ndev->features |= NETIF_F_HW_TC;
733733
ndev->hw_features |= NETIF_F_HW_TC;
734-
enetc_get_max_cap(priv);
735-
enetc_psfp_enable(&si->hw);
736734
}
737735

738736
/* pick up primary MAC address from SI */

0 commit comments

Comments
 (0)