Skip to content

Commit 4d75250

Browse files
vladimirolteandavem330
authored andcommitted
net: dsa: sja1105: offload the Credit-Based Shaper qdisc
SJA1105, being AVB/TSN switches, provide hardware assist for the Credit-Based Shaper as described in the IEEE 8021Q-2018 document. First generation has 10 shapers, freely assignable to any of the 4 external ports and 8 traffic classes, and second generation has 16 shapers. The Credit-Based Shaper tables are accessed through the dynamic reconfiguration interface, so we have to restore them manually after a switch reset. The tables are backed up by the static config only on P/Q/R/S, and we don't want to add custom code only for that family, since the procedure that is in place now works for both. Tested with the following commands: data_rate_kbps=67000 port_transmit_rate_kbps=1000000 idleslope=$data_rate_kbps sendslope=$(($idleslope - $port_transmit_rate_kbps)) locredit=$((-0x80000000)) hicredit=$((0x7fffffff)) tc qdisc add dev swp2 root handle 1: mqprio hw 0 num_tc 8 \ map 0 1 2 3 4 5 6 7 \ queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 tc qdisc replace dev swp2 parent 1:1 cbs \ idleslope $idleslope \ sendslope $sendslope \ hicredit $hicredit \ locredit $locredit \ offload 1 Signed-off-by: Vladimir Oltean <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7c74186 commit 4d75250

File tree

5 files changed

+199
-0
lines changed

5 files changed

+199
-0
lines changed

drivers/net/dsa/sja1105/sja1105.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct sja1105_info {
8484
* the egress timestamps.
8585
*/
8686
int ptpegr_ts_bytes;
87+
int num_cbs_shapers;
8788
const struct sja1105_dynamic_table_ops *dyn_ops;
8889
const struct sja1105_table_ops *static_ops;
8990
const struct sja1105_regs *regs;
@@ -218,6 +219,7 @@ struct sja1105_private {
218219
struct mutex mgmt_lock;
219220
bool expect_dsa_8021q;
220221
enum sja1105_vlan_state vlan_state;
222+
struct sja1105_cbs_entry *cbs;
221223
struct sja1105_tagger_data tagger_data;
222224
struct sja1105_ptp_data ptp_data;
223225
struct sja1105_tas_data tas_data;

drivers/net/dsa/sja1105/sja1105_dynamic_config.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@
136136
#define SJA1105_SIZE_RETAGGING_DYN_CMD \
137137
(SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY)
138138

139+
#define SJA1105ET_SIZE_CBS_DYN_CMD \
140+
(SJA1105_SIZE_DYN_CMD + SJA1105ET_SIZE_CBS_ENTRY)
141+
142+
#define SJA1105PQRS_SIZE_CBS_DYN_CMD \
143+
(SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_CBS_ENTRY)
144+
139145
#define SJA1105_MAX_DYN_CMD_SIZE \
140146
SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD
141147

@@ -542,6 +548,60 @@ sja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
542548
sja1105_packing(p, &cmd->index, 5, 0, size, op);
543549
}
544550

551+
static void sja1105et_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
552+
enum packing_op op)
553+
{
554+
u8 *p = buf + SJA1105ET_SIZE_CBS_ENTRY;
555+
const int size = SJA1105_SIZE_DYN_CMD;
556+
557+
sja1105_packing(p, &cmd->valid, 31, 31, size, op);
558+
sja1105_packing(p, &cmd->index, 19, 16, size, op);
559+
}
560+
561+
static size_t sja1105et_cbs_entry_packing(void *buf, void *entry_ptr,
562+
enum packing_op op)
563+
{
564+
const size_t size = SJA1105ET_SIZE_CBS_ENTRY;
565+
struct sja1105_cbs_entry *entry = entry_ptr;
566+
u8 *cmd = buf + size;
567+
u32 *p = buf;
568+
569+
sja1105_packing(cmd, &entry->port, 5, 3, SJA1105_SIZE_DYN_CMD, op);
570+
sja1105_packing(cmd, &entry->prio, 2, 0, SJA1105_SIZE_DYN_CMD, op);
571+
sja1105_packing(p + 3, &entry->credit_lo, 31, 0, size, op);
572+
sja1105_packing(p + 2, &entry->credit_hi, 31, 0, size, op);
573+
sja1105_packing(p + 1, &entry->send_slope, 31, 0, size, op);
574+
sja1105_packing(p + 0, &entry->idle_slope, 31, 0, size, op);
575+
return size;
576+
}
577+
578+
static void sja1105pqrs_cbs_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
579+
enum packing_op op)
580+
{
581+
u8 *p = buf + SJA1105PQRS_SIZE_CBS_ENTRY;
582+
const int size = SJA1105_SIZE_DYN_CMD;
583+
584+
sja1105_packing(p, &cmd->valid, 31, 31, size, op);
585+
sja1105_packing(p, &cmd->rdwrset, 30, 30, size, op);
586+
sja1105_packing(p, &cmd->errors, 29, 29, size, op);
587+
sja1105_packing(p, &cmd->index, 3, 0, size, op);
588+
}
589+
590+
static size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr,
591+
enum packing_op op)
592+
{
593+
const size_t size = SJA1105PQRS_SIZE_CBS_ENTRY;
594+
struct sja1105_cbs_entry *entry = entry_ptr;
595+
596+
sja1105_packing(buf, &entry->port, 159, 157, size, op);
597+
sja1105_packing(buf, &entry->prio, 156, 154, size, op);
598+
sja1105_packing(buf, &entry->credit_lo, 153, 122, size, op);
599+
sja1105_packing(buf, &entry->credit_hi, 121, 90, size, op);
600+
sja1105_packing(buf, &entry->send_slope, 89, 58, size, op);
601+
sja1105_packing(buf, &entry->idle_slope, 57, 26, size, op);
602+
return size;
603+
}
604+
545605
#define OP_READ BIT(0)
546606
#define OP_WRITE BIT(1)
547607
#define OP_DEL BIT(2)
@@ -631,6 +691,14 @@ struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
631691
.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
632692
.addr = 0x31,
633693
},
694+
[BLK_IDX_CBS] = {
695+
.entry_packing = sja1105et_cbs_entry_packing,
696+
.cmd_packing = sja1105et_cbs_cmd_packing,
697+
.max_entry_count = SJA1105ET_MAX_CBS_COUNT,
698+
.access = OP_WRITE,
699+
.packed_size = SJA1105ET_SIZE_CBS_DYN_CMD,
700+
.addr = 0x2c,
701+
},
634702
[BLK_IDX_XMII_PARAMS] = {0},
635703
};
636704

@@ -725,6 +793,14 @@ struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
725793
.packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD,
726794
.addr = 0x38,
727795
},
796+
[BLK_IDX_CBS] = {
797+
.entry_packing = sja1105pqrs_cbs_entry_packing,
798+
.cmd_packing = sja1105pqrs_cbs_cmd_packing,
799+
.max_entry_count = SJA1105PQRS_MAX_CBS_COUNT,
800+
.access = OP_WRITE,
801+
.packed_size = SJA1105PQRS_SIZE_CBS_DYN_CMD,
802+
.addr = 0x32,
803+
},
728804
[BLK_IDX_XMII_PARAMS] = {0},
729805
};
730806

drivers/net/dsa/sja1105/sja1105_main.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,92 @@ static void sja1105_bridge_leave(struct dsa_switch *ds, int port,
16401640
sja1105_bridge_member(ds, port, br, false);
16411641
}
16421642

1643+
#define BYTES_PER_KBIT (1000LL / 8)
1644+
1645+
static int sja1105_find_unused_cbs_shaper(struct sja1105_private *priv)
1646+
{
1647+
int i;
1648+
1649+
for (i = 0; i < priv->info->num_cbs_shapers; i++)
1650+
if (!priv->cbs[i].idle_slope && !priv->cbs[i].send_slope)
1651+
return i;
1652+
1653+
return -1;
1654+
}
1655+
1656+
static int sja1105_delete_cbs_shaper(struct sja1105_private *priv, int port,
1657+
int prio)
1658+
{
1659+
int i;
1660+
1661+
for (i = 0; i < priv->info->num_cbs_shapers; i++) {
1662+
struct sja1105_cbs_entry *cbs = &priv->cbs[i];
1663+
1664+
if (cbs->port == port && cbs->prio == prio) {
1665+
memset(cbs, 0, sizeof(*cbs));
1666+
return sja1105_dynamic_config_write(priv, BLK_IDX_CBS,
1667+
i, cbs, true);
1668+
}
1669+
}
1670+
1671+
return 0;
1672+
}
1673+
1674+
static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
1675+
struct tc_cbs_qopt_offload *offload)
1676+
{
1677+
struct sja1105_private *priv = ds->priv;
1678+
struct sja1105_cbs_entry *cbs;
1679+
int index;
1680+
1681+
if (!offload->enable)
1682+
return sja1105_delete_cbs_shaper(priv, port, offload->queue);
1683+
1684+
index = sja1105_find_unused_cbs_shaper(priv);
1685+
if (index < 0)
1686+
return -ENOSPC;
1687+
1688+
cbs = &priv->cbs[index];
1689+
cbs->port = port;
1690+
cbs->prio = offload->queue;
1691+
/* locredit and sendslope are negative by definition. In hardware,
1692+
* positive values must be provided, and the negative sign is implicit.
1693+
*/
1694+
cbs->credit_hi = offload->hicredit;
1695+
cbs->credit_lo = abs(offload->locredit);
1696+
/* User space is in kbits/sec, hardware in bytes/sec */
1697+
cbs->idle_slope = offload->idleslope * BYTES_PER_KBIT;
1698+
cbs->send_slope = abs(offload->sendslope * BYTES_PER_KBIT);
1699+
/* Convert the negative values from 64-bit 2's complement
1700+
* to 32-bit 2's complement (for the case of 0x80000000 whose
1701+
* negative is still negative).
1702+
*/
1703+
cbs->credit_lo &= GENMASK_ULL(31, 0);
1704+
cbs->send_slope &= GENMASK_ULL(31, 0);
1705+
1706+
return sja1105_dynamic_config_write(priv, BLK_IDX_CBS, index, cbs,
1707+
true);
1708+
}
1709+
1710+
static int sja1105_reload_cbs(struct sja1105_private *priv)
1711+
{
1712+
int rc = 0, i;
1713+
1714+
for (i = 0; i < priv->info->num_cbs_shapers; i++) {
1715+
struct sja1105_cbs_entry *cbs = &priv->cbs[i];
1716+
1717+
if (!cbs->idle_slope && !cbs->send_slope)
1718+
continue;
1719+
1720+
rc = sja1105_dynamic_config_write(priv, BLK_IDX_CBS, i, cbs,
1721+
true);
1722+
if (rc)
1723+
break;
1724+
}
1725+
1726+
return rc;
1727+
}
1728+
16431729
static const char * const sja1105_reset_reasons[] = {
16441730
[SJA1105_VLAN_FILTERING] = "VLAN filtering",
16451731
[SJA1105_RX_HWTSTAMPING] = "RX timestamping",
@@ -1754,6 +1840,10 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
17541840
sja1105_sgmii_pcs_force_speed(priv, speed);
17551841
}
17561842
}
1843+
1844+
rc = sja1105_reload_cbs(priv);
1845+
if (rc < 0)
1846+
goto out;
17571847
out:
17581848
mutex_unlock(&priv->mgmt_lock);
17591849

@@ -3131,6 +3221,8 @@ static int sja1105_port_setup_tc(struct dsa_switch *ds, int port,
31313221
switch (type) {
31323222
case TC_SETUP_QDISC_TAPRIO:
31333223
return sja1105_setup_tc_taprio(ds, port, type_data);
3224+
case TC_SETUP_QDISC_CBS:
3225+
return sja1105_setup_tc_cbs(ds, port, type_data);
31343226
default:
31353227
return -EOPNOTSUPP;
31363228
}
@@ -3408,6 +3500,14 @@ static int sja1105_probe(struct spi_device *spi)
34083500
if (rc)
34093501
return rc;
34103502

3503+
if (IS_ENABLED(CONFIG_NET_SCH_CBS)) {
3504+
priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers,
3505+
sizeof(struct sja1105_cbs_entry),
3506+
GFP_KERNEL);
3507+
if (!priv->cbs)
3508+
return -ENOMEM;
3509+
}
3510+
34113511
/* Connections between dsa_port and sja1105_port */
34123512
for (port = 0; port < SJA1105_NUM_PORTS; port++) {
34133513
struct sja1105_port *sp = &priv->ports[port];

drivers/net/dsa/sja1105/sja1105_spi.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ struct sja1105_info sja1105e_info = {
515515
.qinq_tpid = ETH_P_8021Q,
516516
.ptp_ts_bits = 24,
517517
.ptpegr_ts_bytes = 4,
518+
.num_cbs_shapers = SJA1105ET_MAX_CBS_COUNT,
518519
.reset_cmd = sja1105et_reset_cmd,
519520
.fdb_add_cmd = sja1105et_fdb_add,
520521
.fdb_del_cmd = sja1105et_fdb_del,
@@ -530,6 +531,7 @@ struct sja1105_info sja1105t_info = {
530531
.qinq_tpid = ETH_P_8021Q,
531532
.ptp_ts_bits = 24,
532533
.ptpegr_ts_bytes = 4,
534+
.num_cbs_shapers = SJA1105ET_MAX_CBS_COUNT,
533535
.reset_cmd = sja1105et_reset_cmd,
534536
.fdb_add_cmd = sja1105et_fdb_add,
535537
.fdb_del_cmd = sja1105et_fdb_del,
@@ -545,6 +547,7 @@ struct sja1105_info sja1105p_info = {
545547
.qinq_tpid = ETH_P_8021AD,
546548
.ptp_ts_bits = 32,
547549
.ptpegr_ts_bytes = 8,
550+
.num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT,
548551
.setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay,
549552
.reset_cmd = sja1105pqrs_reset_cmd,
550553
.fdb_add_cmd = sja1105pqrs_fdb_add,
@@ -561,6 +564,7 @@ struct sja1105_info sja1105q_info = {
561564
.qinq_tpid = ETH_P_8021AD,
562565
.ptp_ts_bits = 32,
563566
.ptpegr_ts_bytes = 8,
567+
.num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT,
564568
.setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay,
565569
.reset_cmd = sja1105pqrs_reset_cmd,
566570
.fdb_add_cmd = sja1105pqrs_fdb_add,
@@ -577,6 +581,7 @@ struct sja1105_info sja1105r_info = {
577581
.qinq_tpid = ETH_P_8021AD,
578582
.ptp_ts_bits = 32,
579583
.ptpegr_ts_bytes = 8,
584+
.num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT,
580585
.setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay,
581586
.reset_cmd = sja1105pqrs_reset_cmd,
582587
.fdb_add_cmd = sja1105pqrs_fdb_add,
@@ -594,6 +599,7 @@ struct sja1105_info sja1105s_info = {
594599
.qinq_tpid = ETH_P_8021AD,
595600
.ptp_ts_bits = 32,
596601
.ptpegr_ts_bytes = 8,
602+
.num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT,
597603
.setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay,
598604
.reset_cmd = sja1105pqrs_reset_cmd,
599605
.fdb_add_cmd = sja1105pqrs_fdb_add,

drivers/net/dsa/sja1105/sja1105_static_config.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@
3030
#define SJA1105ET_SIZE_L2_LOOKUP_PARAMS_ENTRY 4
3131
#define SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY 40
3232
#define SJA1105ET_SIZE_AVB_PARAMS_ENTRY 12
33+
#define SJA1105ET_SIZE_CBS_ENTRY 16
3334
#define SJA1105PQRS_SIZE_L2_LOOKUP_ENTRY 20
3435
#define SJA1105PQRS_SIZE_MAC_CONFIG_ENTRY 32
3536
#define SJA1105PQRS_SIZE_L2_LOOKUP_PARAMS_ENTRY 16
3637
#define SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY 44
3738
#define SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY 16
39+
#define SJA1105PQRS_SIZE_CBS_ENTRY 20
3840

3941
/* UM10944.pdf Page 11, Table 2. Configuration Blocks */
4042
enum {
@@ -56,6 +58,7 @@ enum {
5658
BLKID_AVB_PARAMS = 0x10,
5759
BLKID_GENERAL_PARAMS = 0x11,
5860
BLKID_RETAGGING = 0x12,
61+
BLKID_CBS = 0x13,
5962
BLKID_XMII_PARAMS = 0x4E,
6063
};
6164

@@ -78,6 +81,7 @@ enum sja1105_blk_idx {
7881
BLK_IDX_AVB_PARAMS,
7982
BLK_IDX_GENERAL_PARAMS,
8083
BLK_IDX_RETAGGING,
84+
BLK_IDX_CBS,
8185
BLK_IDX_XMII_PARAMS,
8286
BLK_IDX_MAX,
8387
/* Fake block indices that are only valid for dynamic access */
@@ -105,6 +109,8 @@ enum sja1105_blk_idx {
105109
#define SJA1105_MAX_RETAGGING_COUNT 32
106110
#define SJA1105_MAX_XMII_PARAMS_COUNT 1
107111
#define SJA1105_MAX_AVB_PARAMS_COUNT 1
112+
#define SJA1105ET_MAX_CBS_COUNT 10
113+
#define SJA1105PQRS_MAX_CBS_COUNT 16
108114

109115
#define SJA1105_MAX_FRAME_MEMORY 929
110116
#define SJA1105_MAX_FRAME_MEMORY_RETAGGING 910
@@ -289,6 +295,15 @@ struct sja1105_retagging_entry {
289295
u64 destports;
290296
};
291297

298+
struct sja1105_cbs_entry {
299+
u64 port;
300+
u64 prio;
301+
u64 credit_hi;
302+
u64 credit_lo;
303+
u64 send_slope;
304+
u64 idle_slope;
305+
};
306+
292307
struct sja1105_xmii_params_entry {
293308
u64 phy_mac[5];
294309
u64 xmii_mode[5];

0 commit comments

Comments
 (0)