* [PATCH v2 1/8] dt-bindings: net: Add support for AM65x SR1.0 in ICSSG
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
@ 2024-01-17 16:14 ` Diogo Ivo
2024-01-17 17:35 ` Rob Herring
2024-01-17 16:14 ` [PATCH v2 3/8] net: ti: icssg-prueth: add SR1.0-specific configuration bits Diogo Ivo
` (7 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Diogo Ivo @ 2024-01-17 16:14 UTC (permalink / raw)
To: danishanwar, rogerq, davem, edumazet, kuba, pabeni, robh+dt,
krzysztof.kozlowski+dt, conor+dt, linux-arm-kernel, netdev,
devicetree
Cc: Diogo Ivo, Jan Kiszka
Silicon Revision 1.0 of the AM65x came with a slightly different ICSSG
support: Only 2 PRUs per slice are available and instead 2 additional
DMA channels are used for management purposes. We have no restrictions
on specified PRUs, but the DMA channels need to be adjusted.
Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
---
Changes in v2:
- Removed explicit reference to SR2.0
- Moved sr1 to the SoC name
- Expand dma-names list and adjust min/maxItems depending on SR1.0/2.0
.../bindings/net/ti,icssg-prueth.yaml | 29 ++++++++++++++++---
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
index 229c8f32019f..59a3292191d9 100644
--- a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
+++ b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
@@ -19,8 +19,9 @@ allOf:
properties:
compatible:
enum:
- - ti,am642-icssg-prueth # for AM64x SoC family
- - ti,am654-icssg-prueth # for AM65x SoC family
+ - ti,am642-icssg-prueth # for AM64x SoC family
+ - ti,am654-icssg-prueth # for AM65x SoC family
+ - ti,am654-sr1-icssg-prueth # for AM65x SoC family, SR1.0
sram:
$ref: /schemas/types.yaml#/definitions/phandle
@@ -28,8 +29,7 @@ properties:
phandle to MSMC SRAM node
dmas:
- maxItems: 10
-
+ minItems: 10
dma-names:
items:
- const: tx0-0
@@ -42,6 +42,8 @@ properties:
- const: tx1-3
- const: rx0
- const: rx1
+ - const: rxmgm0
+ - const: rxmgm1
ti,mii-g-rt:
$ref: /schemas/types.yaml#/definitions/phandle
@@ -132,6 +134,25 @@ required:
- interrupts
- interrupt-names
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: ti,am654-sr1-icssg-prueth
+ then:
+ properties:
+ dmas:
+ minItems: 12
+ dma-names:
+ minItems: 12
+ else:
+ properties:
+ dmas:
+ maxItems: 10
+ dma-names:
+ maxItems: 10
+
unevaluatedProperties: false
examples:
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2 1/8] dt-bindings: net: Add support for AM65x SR1.0 in ICSSG
2024-01-17 16:14 ` [PATCH v2 1/8] dt-bindings: net: Add support for AM65x SR1.0 in ICSSG Diogo Ivo
@ 2024-01-17 17:35 ` Rob Herring
0 siblings, 0 replies; 15+ messages in thread
From: Rob Herring @ 2024-01-17 17:35 UTC (permalink / raw)
To: Diogo Ivo
Cc: conor+dt, danishanwar, rogerq, devicetree, davem, kuba, robh+dt,
netdev, Jan Kiszka, pabeni, krzysztof.kozlowski+dt,
linux-arm-kernel, edumazet
On Wed, 17 Jan 2024 16:14:55 +0000, Diogo Ivo wrote:
> Silicon Revision 1.0 of the AM65x came with a slightly different ICSSG
> support: Only 2 PRUs per slice are available and instead 2 additional
> DMA channels are used for management purposes. We have no restrictions
> on specified PRUs, but the DMA channels need to be adjusted.
>
> Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
> ---
> Changes in v2:
> - Removed explicit reference to SR2.0
> - Moved sr1 to the SoC name
> - Expand dma-names list and adjust min/maxItems depending on SR1.0/2.0
>
> .../bindings/net/ti,icssg-prueth.yaml | 29 ++++++++++++++++---
> 1 file changed, 25 insertions(+), 4 deletions(-)
>
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
./Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml:137:1: [error] duplication of key "allOf" in mapping (key-duplicates)
dtschema/dtc warnings/errors:
make[2]: *** Deleting file 'Documentation/devicetree/bindings/net/ti,icssg-prueth.example.dts'
Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml:137:1: found duplicate key "allOf" with value "[]" (original value: "[]")
make[2]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/net/ti,icssg-prueth.example.dts] Error 1
make[2]: *** Waiting for unfinished jobs....
./Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml:137:1: found duplicate key "allOf" with value "[]" (original value: "[]")
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml: ignoring, error parsing file
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1424: dt_binding_check] Error 2
make: *** [Makefile:234: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240117161602.153233-2-diogo.ivo@siemens.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 3/8] net: ti: icssg-prueth: add SR1.0-specific configuration bits
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
2024-01-17 16:14 ` [PATCH v2 1/8] dt-bindings: net: Add support for AM65x SR1.0 in ICSSG Diogo Ivo
@ 2024-01-17 16:14 ` Diogo Ivo
2024-01-17 16:14 ` [PATCH v2 4/8] net: ti: icssg-classifier: Add support for SR1.0 Diogo Ivo
` (6 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-01-17 16:14 UTC (permalink / raw)
To: danishanwar, rogerq, davem, edumazet, kuba, pabeni, andrew,
grygorii.strashko, linux-arm-kernel, netdev
Cc: Diogo Ivo, Jan Kiszka
Add fields to differentiate between SR1.0 and SR2.0 in the driver
as well as the structures necessary to program SR1.0.
Based on the work of Roger Quadros in TI's 5.10 SDK [1].
[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
---
drivers/net/ethernet/ti/icssg/icssg_prueth.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 8b6d6b497010..1bdd3d301fde 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -127,6 +127,7 @@ struct prueth_rx_chn {
/* data for each emac port */
struct prueth_emac {
+ bool is_sr1;
bool fw_running;
struct prueth *prueth;
struct net_device *ndev;
@@ -155,6 +156,10 @@ struct prueth_emac {
int rx_flow_id_base;
int tx_ch_num;
+ /* SR1.0 Management channel */
+ struct prueth_rx_chn rx_mgm_chn;
+ int rx_mgm_flow_id_base;
+
spinlock_t lock; /* serialize access */
/* TX HW Timestamping */
@@ -182,10 +187,12 @@ struct prueth_emac {
* struct prueth_pdata - PRUeth platform data
* @fdqring_mode: Free desc queue mode
* @quirk_10m_link_issue: 10M link detect errata
+ * @is_sr1: device is SR1.0
*/
struct prueth_pdata {
enum k3_ring_mode fdqring_mode;
u32 quirk_10m_link_issue:1;
+ u32 is_sr1:1;
};
/**
@@ -224,6 +231,7 @@ struct prueth {
struct device_node *eth_node[PRUETH_NUM_MACS];
struct prueth_emac *emac[PRUETH_NUM_MACS];
struct net_device *registered_netdevs[PRUETH_NUM_MACS];
+ struct icssg_config_sr1 config[PRUSS_NUM_PRUS];
struct regmap *miig_rt;
struct regmap *mii_rt;
@@ -236,6 +244,13 @@ struct prueth {
struct icss_iep *iep1;
};
+struct emac_tx_ts_response_sr1 {
+ u32 lo_ts;
+ u32 hi_ts;
+ u32 reserved;
+ u32 cookie;
+};
+
struct emac_tx_ts_response {
u32 reserved[2];
u32 cookie;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 4/8] net: ti: icssg-classifier: Add support for SR1.0
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
2024-01-17 16:14 ` [PATCH v2 1/8] dt-bindings: net: Add support for AM65x SR1.0 in ICSSG Diogo Ivo
2024-01-17 16:14 ` [PATCH v2 3/8] net: ti: icssg-prueth: add SR1.0-specific configuration bits Diogo Ivo
@ 2024-01-17 16:14 ` Diogo Ivo
2024-01-17 20:48 ` Andrew Lunn
2024-01-17 16:14 ` [PATCH v2 5/8] net: ti: icssg-config: Add SR1.0 configuration functions Diogo Ivo
` (5 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Diogo Ivo @ 2024-01-17 16:14 UTC (permalink / raw)
To: danishanwar, rogerq, davem, edumazet, kuba, pabeni, andrew,
dan.carpenter, robh, grygorii.strashko, linux-arm-kernel, netdev
Cc: Diogo Ivo, Jan Kiszka
Add the functions to program the SR1.0 packet classifier.
Based on the work of Roger Quadros in TI's 5.10 SDK [1].
[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
---
.../net/ethernet/ti/icssg/icssg_classifier.c | 113 ++++++++++++++++--
drivers/net/ethernet/ti/icssg/icssg_prueth.c | 2 +-
drivers/net/ethernet/ti/icssg/icssg_prueth.h | 6 +-
3 files changed, 110 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_classifier.c b/drivers/net/ethernet/ti/icssg/icssg_classifier.c
index 6df53ab17fbc..d7288eb6c0fd 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_classifier.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_classifier.c
@@ -274,6 +274,16 @@ static void rx_class_set_or(struct regmap *miig_rt, int slice, int n,
regmap_write(miig_rt, offset, data);
}
+static u32 rx_class_get_or(struct regmap *miig_rt, int slice, int n)
+{
+ u32 offset, val;
+
+ offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN);
+ regmap_read(miig_rt, offset, &val);
+
+ return val;
+}
+
void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac)
{
regmap_write(miig_rt, MAC_INTERFACE_0, (u32)(mac[0] | mac[1] << 8 |
@@ -288,6 +298,26 @@ void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
regmap_write(miig_rt, offs[slice].mac1, (u32)(mac[4] | mac[5] << 8));
}
+static void icssg_class_ft1_add_mcast(struct regmap *miig_rt, int slice,
+ int slot, const u8 *addr, const u8 *mask)
+{
+ int i;
+ u32 val;
+
+ WARN(slot >= FT1_NUM_SLOTS, "invalid slot: %d\n", slot);
+
+ rx_class_ft1_set_da(miig_rt, slice, slot, addr);
+ rx_class_ft1_set_da_mask(miig_rt, slice, slot, mask);
+ rx_class_ft1_cfg_set_type(miig_rt, slice, slot, FT1_CFG_TYPE_EQ);
+
+ /* Enable the FT1 slot in OR enable for all classifiers */
+ for (i = 0; i < ICSSG_NUM_CLASSIFIERS_IN_USE; i++) {
+ val = rx_class_get_or(miig_rt, slice, i);
+ val |= RX_CLASS_FT_FT1_MATCH(slot);
+ rx_class_set_or(miig_rt, slice, i, val);
+ }
+}
+
/* disable all RX traffic */
void icssg_class_disable(struct regmap *miig_rt, int slice)
{
@@ -331,30 +361,95 @@ void icssg_class_disable(struct regmap *miig_rt, int slice)
regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
}
-void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti)
+void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti,
+ bool is_sr1)
{
+ int classifiers_in_use = is_sr1 ? ICSSG_NUM_CLASSIFIERS_IN_USE : 1;
u32 data;
+ int n;
/* defaults */
icssg_class_disable(miig_rt, slice);
/* Setup Classifier */
- /* match on Broadcast or MAC_PRU address */
- data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;
+ for (n = 0; n < classifiers_in_use; n++) {
+ /* match on Broadcast or MAC_PRU address */
+ data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;
- /* multicast */
- if (allmulti)
- data |= RX_CLASS_FT_MC;
+ /* multicast */
+ if (allmulti)
+ data |= RX_CLASS_FT_MC;
- rx_class_set_or(miig_rt, slice, 0, data);
+ rx_class_set_or(miig_rt, slice, n, data);
- /* set CFG1 for OR_OR_AND for classifier */
- rx_class_sel_set_type(miig_rt, slice, 0, RX_CLASS_SEL_TYPE_OR_OR_AND);
+ /* set CFG1 for OR_OR_AND for classifier */
+ rx_class_sel_set_type(miig_rt, slice, n,
+ RX_CLASS_SEL_TYPE_OR_OR_AND);
+ }
/* clear CFG2 */
regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
}
+void icssg_class_promiscuous_sr1(struct regmap *miig_rt, int slice)
+{
+ u32 data, offset;
+ int n;
+
+ /* defaults */
+ icssg_class_disable(miig_rt, slice);
+
+ /* Setup Classifier */
+ for (n = 0; n < ICSSG_NUM_CLASSIFIERS_IN_USE; n++) {
+ /* set RAW_MASK to bypass filters */
+ offset = RX_CLASS_GATES_N_REG(slice, n);
+ regmap_read(miig_rt, offset, &data);
+ data |= RX_CLASS_GATES_RAW_MASK;
+ regmap_write(miig_rt, offset, data);
+ }
+}
+
+void icssg_class_add_mcast_sr1(struct regmap *miig_rt, int slice,
+ struct net_device *ndev)
+{
+ u8 sr_addr[6] = { 0x01, 0x80, 0xc2, 0, 0, 0 };
+ u8 cb_addr[6] = { 0x01, 0x00, 0x5e, 0, 0, 0 };
+ u8 mask_addr[6] = { 0, 0, 0, 0, 0, 0xff };
+ struct netdev_hw_addr *ha;
+ int slot = 2;
+
+ rx_class_ft1_set_start_len(miig_rt, slice, 0, 6);
+ /* reserve first 2 slots for
+ * 1) 01-80-C2-00-00-XX Known Service Ethernet Multicast addresses
+ * 2) 01-00-5e-00-00-XX Local Network Control Block
+ * (224.0.0.0 - 224.0.0.255 (224.0.0/24))
+ */
+ icssg_class_ft1_add_mcast(miig_rt, slice, 0, sr_addr, mask_addr);
+ icssg_class_ft1_add_mcast(miig_rt, slice, 1, cb_addr, mask_addr);
+ mask_addr[5] = 0;
+ netdev_for_each_mc_addr(ha, ndev) {
+ /* skip addresses matching reserved slots */
+ if (!memcmp(sr_addr, ha->addr, 5) ||
+ !memcmp(cb_addr, ha->addr, 5)) {
+ netdev_dbg(ndev, "mcast skip %pM\n", ha->addr);
+ continue;
+ }
+
+ if (slot >= FT1_NUM_SLOTS) {
+ netdev_dbg(ndev,
+ "can't add more than %d MC addresses, enabling allmulti\n",
+ FT1_NUM_SLOTS);
+ icssg_class_default(miig_rt, slice, 1, true);
+ break;
+ }
+
+ netdev_dbg(ndev, "mcast add %pM\n", ha->addr);
+ icssg_class_ft1_add_mcast(miig_rt, slice, slot,
+ ha->addr, mask_addr);
+ slot++;
+ }
+}
+
/* required for SAV check */
void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr)
{
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index 411898a4f38c..5ec2cdc16c51 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -1329,7 +1329,7 @@ static int emac_ndo_open(struct net_device *ndev)
icssg_class_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
icssg_ft1_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
- icssg_class_default(prueth->miig_rt, slice, 0);
+ icssg_class_default(prueth->miig_rt, slice, 0, emac->is_sr1);
/* Notify the stack of the actual queue counts. */
ret = netif_set_real_num_tx_queues(ndev, num_data_chn);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index 1bdd3d301fde..c2221db25950 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -277,7 +277,11 @@ extern const struct ethtool_ops icssg_ethtool_ops;
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac);
void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac);
void icssg_class_disable(struct regmap *miig_rt, int slice);
-void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti);
+void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti,
+ bool is_sr1);
+void icssg_class_promiscuous_sr1(struct regmap *miig_rt, int slice);
+void icssg_class_add_mcast_sr1(struct regmap *miig_rt, int slice,
+ struct net_device *ndev);
void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr);
/* config helpers */
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2 4/8] net: ti: icssg-classifier: Add support for SR1.0
2024-01-17 16:14 ` [PATCH v2 4/8] net: ti: icssg-classifier: Add support for SR1.0 Diogo Ivo
@ 2024-01-17 20:48 ` Andrew Lunn
0 siblings, 0 replies; 15+ messages in thread
From: Andrew Lunn @ 2024-01-17 20:48 UTC (permalink / raw)
To: Diogo Ivo
Cc: danishanwar, rogerq, davem, edumazet, kuba, pabeni,
dan.carpenter, robh, grygorii.strashko, linux-arm-kernel, netdev,
Jan Kiszka
> +void icssg_class_add_mcast_sr1(struct regmap *miig_rt, int slice,
> + struct net_device *ndev)
> +{
> + u8 sr_addr[6] = { 0x01, 0x80, 0xc2, 0, 0, 0 };
eth_reserved_addr_base in linux/etherdevice.h
> + u8 cb_addr[6] = { 0x01, 0x00, 0x5e, 0, 0, 0 };
This also appears in etherdevice.h, but will need a little bit of
refactoring to make it usable.
Andrew
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 5/8] net: ti: icssg-config: Add SR1.0 configuration functions
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
` (2 preceding siblings ...)
2024-01-17 16:14 ` [PATCH v2 4/8] net: ti: icssg-classifier: Add support for SR1.0 Diogo Ivo
@ 2024-01-17 16:14 ` Diogo Ivo
2024-01-17 16:15 ` [PATCH v2 6/8] net: ti: icssg-ethtool: Adjust channel count for SR1.0 Diogo Ivo
` (4 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-01-17 16:14 UTC (permalink / raw)
To: danishanwar, rogerq, davem, edumazet, kuba, pabeni, andrew,
jacob.e.keller, grygorii.strashko, linux-arm-kernel, netdev
Cc: Diogo Ivo, Jan Kiszka
The SR1.0 firmware needs to configured differently from the
current SR2.0 firmware. Add the necessary functions.
Based on the work of Roger Quadros, Vignesh Raghavendra
and Grygorii Strashko in TI's 5.10 SDK [1].
[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
---
Changes in v2:
- Removed explicit references to SR2.0
- Added static keyword to icssg_config_sr1()
drivers/net/ethernet/ti/icssg/icssg_config.c | 86 ++++++++++++++++++--
1 file changed, 81 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c
index 99de8a40ed60..34bc16599a2d 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_config.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_config.c
@@ -18,6 +18,8 @@
*/
/* IPG is in core_clk cycles */
+#define MII_RT_TX_IPG_100M_SR1 0x166
+#define MII_RT_TX_IPG_1G_SR1 0x1a
#define MII_RT_TX_IPG_100M 0x17
#define MII_RT_TX_IPG_1G 0xb
@@ -205,14 +207,20 @@ void icssg_config_ipg(struct prueth_emac *emac)
switch (emac->speed) {
case SPEED_1000:
- icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_1G);
+ icssg_mii_update_ipg(prueth->mii_rt, slice,
+ prueth->pdata.is_sr1 ?
+ MII_RT_TX_IPG_1G_SR1 : MII_RT_TX_IPG_1G);
break;
case SPEED_100:
- icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
+ icssg_mii_update_ipg(prueth->mii_rt, slice,
+ prueth->pdata.is_sr1 ?
+ MII_RT_TX_IPG_100M_SR1 : MII_RT_TX_IPG_100M);
break;
case SPEED_10:
- /* IPG for 10M is same as 100M */
- icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
+ /* Firmware hardcodes IPG for SR1. SR2 same as 100M */
+ if (!prueth->pdata.is_sr1)
+ icssg_mii_update_ipg(prueth->mii_rt, slice,
+ MII_RT_TX_IPG_100M);
break;
default:
/* Other links speeds not supported */
@@ -221,6 +229,56 @@ void icssg_config_ipg(struct prueth_emac *emac)
}
}
+/* SR1: Set buffer sizes for the pools. There are 8 internal queues
+ * implemented in firmware, but only 4 tx channels/threads in the Egress
+ * direction to firmware. Need a high priority queue for management
+ * messages since they shouldn't be blocked even during high traffic
+ * situation. So use Q0-Q2 as data queues and Q3 as management queue
+ * in the max case. However for ease of configuration, use the max
+ * data queue + 1 for management message if we are not using max
+ * case.
+ *
+ * Allocate 4 MTU buffers per data queue. Firmware requires
+ * pool sizes to be set for internal queues. Set the upper 5 queue
+ * pool size to min size of 128 bytes since there are only 3 tx
+ * data channels and management queue requires only minimum buffer.
+ * i.e lower queues are used by driver and highest priority queue
+ * from that is used for management message.
+ */
+
+static int emac_egress_buf_pool_size[] = {
+ PRUETH_EMAC_BUF_POOL_SIZE_SR1, PRUETH_EMAC_BUF_POOL_SIZE_SR1,
+ PRUETH_EMAC_BUF_POOL_SIZE_SR1, PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1,
+ PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1, PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1,
+ PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1, PRUETH_EMAC_BUF_POOL_MIN_SIZE_SR1};
+
+static void icssg_config_sr1(struct prueth *prueth, struct prueth_emac *emac,
+ int slice)
+{
+ struct icssg_config_sr1 *config;
+ void __iomem *va;
+ int i, index;
+
+ va = prueth->shram.va + slice * ICSSG_CONFIG_OFFSET_SLICE1;
+ config = &prueth->config[slice];
+ memset(config, 0, sizeof(*config));
+ config->addr_lo = cpu_to_le32(lower_32_bits(prueth->msmcram.pa));
+ config->addr_hi = cpu_to_le32(upper_32_bits(prueth->msmcram.pa));
+ config->num_tx_threads = 0;
+ config->rx_flow_id = emac->rx_flow_id_base; /* flow id for host port */
+ config->rx_mgr_flow_id = emac->rx_mgm_flow_id_base; /* for mgm ch */
+ config->rand_seed = get_random_u32();
+
+ for (i = PRUETH_EMAC_BUF_POOL_START_SR1; i < PRUETH_NUM_BUF_POOLS_SR1; i++) {
+ index = i - PRUETH_EMAC_BUF_POOL_START_SR1;
+ config->tx_buf_sz[i] = cpu_to_le32(emac_egress_buf_pool_size[index]);
+ }
+
+ memcpy_toio(va, &prueth->config[slice], sizeof(prueth->config[slice]));
+
+ emac->speed = SPEED_1000;
+}
+
static void emac_r30_cmd_init(struct prueth_emac *emac)
{
struct icssg_r30_cmd __iomem *p;
@@ -331,6 +389,11 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
struct icssg_flow_cfg __iomem *flow_cfg;
int ret;
+ if (prueth->pdata.is_sr1) {
+ icssg_config_sr1(prueth, emac, slice);
+ return 0;
+ }
+
icssg_init_emac_mode(prueth);
memset_io(config, 0, TAS_GATE_MASK_LIST0);
@@ -435,19 +498,32 @@ int emac_set_port_state(struct prueth_emac *emac,
void icssg_config_half_duplex(struct prueth_emac *emac)
{
+ struct icssg_config_sr1 *config;
+ void __iomem *va;
+ int slice;
u32 val;
if (!emac->half_duplex)
return;
val = get_random_u32();
- writel(val, emac->dram.va + HD_RAND_SEED_OFFSET);
+ if (emac->is_sr1) {
+ slice = prueth_emac_slice(emac);
+ va = emac->prueth->shram.va + slice * ICSSG_CONFIG_OFFSET_SLICE1;
+ config = (struct icssg_config_sr1 *)va;
+ writel(val, &config->rand_seed);
+ } else {
+ writel(val, emac->dram.va + HD_RAND_SEED_OFFSET);
+ }
}
void icssg_config_set_speed(struct prueth_emac *emac)
{
u8 fw_speed;
+ if (emac->is_sr1)
+ return;
+
switch (emac->speed) {
case SPEED_1000:
fw_speed = FW_LINK_SPEED_1G;
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 6/8] net: ti: icssg-ethtool: Adjust channel count for SR1.0
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
` (3 preceding siblings ...)
2024-01-17 16:14 ` [PATCH v2 5/8] net: ti: icssg-config: Add SR1.0 configuration functions Diogo Ivo
@ 2024-01-17 16:15 ` Diogo Ivo
2024-01-22 13:42 ` Roger Quadros
2024-01-17 16:15 ` [PATCH v2 7/8] net: ti: iccsg-prueth: Add necessary functions for SR1.0 support Diogo Ivo
` (3 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Diogo Ivo @ 2024-01-17 16:15 UTC (permalink / raw)
To: danishanwar, rogerq, davem, edumazet, kuba, pabeni,
grygorii.strashko, andrew, linux-arm-kernel, netdev
Cc: Diogo Ivo, Jan Kiszka
SR1.0 uses the highest priority channel to transmit control
messages to the firmware. Take this into account when computing
channels.
Based on the work of Roger Quadros in TI's 5.10 SDK [1].
[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
---
drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
index a27ec1dcc8d5..29e67526fa22 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
@@ -141,6 +141,9 @@ static int emac_set_channels(struct net_device *ndev,
return -EBUSY;
emac->tx_ch_num = ch->tx_count;
+ /* highest channel number for management messaging on SR1 */
+ if (emac->is_sr1)
+ emac->tx_ch_num++;
return 0;
}
@@ -151,9 +154,12 @@ static void emac_get_channels(struct net_device *ndev,
struct prueth_emac *emac = netdev_priv(ndev);
ch->max_rx = 1;
- ch->max_tx = PRUETH_MAX_TX_QUEUES;
+ /* SR1 use high priority channel for management messages */
+ ch->max_tx = emac->is_sr1 ? PRUETH_MAX_TX_QUEUES - 1 :
+ PRUETH_MAX_TX_QUEUES;
ch->rx_count = 1;
- ch->tx_count = emac->tx_ch_num;
+ ch->tx_count = emac->is_sr1 ? emac->tx_ch_num - 1 :
+ emac->tx_ch_num;
}
static const struct ethtool_rmon_hist_range emac_rmon_ranges[] = {
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2 6/8] net: ti: icssg-ethtool: Adjust channel count for SR1.0
2024-01-17 16:15 ` [PATCH v2 6/8] net: ti: icssg-ethtool: Adjust channel count for SR1.0 Diogo Ivo
@ 2024-01-22 13:42 ` Roger Quadros
0 siblings, 0 replies; 15+ messages in thread
From: Roger Quadros @ 2024-01-22 13:42 UTC (permalink / raw)
To: Diogo Ivo, danishanwar, davem, edumazet, kuba, pabeni,
grygorii.strashko, andrew, linux-arm-kernel, netdev
Cc: Jan Kiszka
On 17/01/2024 18:15, Diogo Ivo wrote:
> SR1.0 uses the highest priority channel to transmit control
> messages to the firmware. Take this into account when computing
> channels.
>
> Based on the work of Roger Quadros in TI's 5.10 SDK [1].
>
> [1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
>
> Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
> ---
> drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
> index a27ec1dcc8d5..29e67526fa22 100644
> --- a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
> +++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
> @@ -141,6 +141,9 @@ static int emac_set_channels(struct net_device *ndev,
> return -EBUSY;
>
> emac->tx_ch_num = ch->tx_count;
> + /* highest channel number for management messaging on SR1 */
> + if (emac->is_sr1)
> + emac->tx_ch_num++;
I don't recollect now but is management channel always pinned to the highest priority
channel?
Wouldn't it be better if we don't mix up management channel details here
in emac_get/set_channels(). So this patch is not required and we only need
to set ch->max_tx to PRUETH_MAX_TX_QUEUES-1 for sr1?
>
> return 0;
> }
> @@ -151,9 +154,12 @@ static void emac_get_channels(struct net_device *ndev,
> struct prueth_emac *emac = netdev_priv(ndev);
>
> ch->max_rx = 1;
> - ch->max_tx = PRUETH_MAX_TX_QUEUES;
Leave the above intact and add
if (emac->is_sr1)
ch->max_tx--;
> + /* SR1 use high priority channel for management messages */
> + ch->max_tx = emac->is_sr1 ? PRUETH_MAX_TX_QUEUES - 1 :
> + PRUETH_MAX_TX_QUEUES;
> ch->rx_count = 1;
> - ch->tx_count = emac->tx_ch_num;
> + ch->tx_count = emac->is_sr1 ? emac->tx_ch_num - 1 :
> + emac->tx_ch_num;
> }
>
> static const struct ethtool_rmon_hist_range emac_rmon_ranges[] = {
--
cheers,
-roger
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 7/8] net: ti: iccsg-prueth: Add necessary functions for SR1.0 support
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
` (4 preceding siblings ...)
2024-01-17 16:15 ` [PATCH v2 6/8] net: ti: icssg-ethtool: Adjust channel count for SR1.0 Diogo Ivo
@ 2024-01-17 16:15 ` Diogo Ivo
2024-01-17 20:56 ` Andrew Lunn
2024-01-17 16:15 ` [PATCH v2 8/8] net: ti: icssg-prueth: Wire up support for SR1.0 Diogo Ivo
` (2 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: Diogo Ivo @ 2024-01-17 16:15 UTC (permalink / raw)
To: danishanwar, rogerq, davem, edumazet, kuba, pabeni, andrew,
dan.carpenter, robh, linux-arm-kernel, netdev
Cc: Diogo Ivo, Jan Kiszka
Add functions required to correctly program the SR1.0 firmware for
network operation.
Based on the work of Roger Quadros, Vignesh Raghavendra and
Grygorii Strashko in TI's 5.10 SDK [1].
[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
---
drivers/net/ethernet/ti/icssg/icssg_prueth.c | 255 +++++++++++++++++++
1 file changed, 255 insertions(+)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index 5ec2cdc16c51..db15c8680741 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -616,6 +616,101 @@ static int emac_get_tx_ts(struct prueth_emac *emac,
return 0;
}
+static int emac_send_command_sr1(struct prueth_emac *emac, u32 cmd)
+{
+ dma_addr_t desc_dma, buf_dma;
+ struct prueth_tx_chn *tx_chn;
+ struct cppi5_host_desc_t *first_desc;
+ u32 *data = emac->cmd_data;
+ u32 pkt_len = sizeof(emac->cmd_data);
+ void **swdata;
+ int ret = 0;
+ u32 *epib;
+
+ netdev_dbg(emac->ndev, "Sending cmd %x\n", cmd);
+
+ /* only one command at a time allowed to firmware */
+ mutex_lock(&emac->cmd_lock);
+ data[0] = cpu_to_le32(cmd);
+
+ /* highest priority channel for management messages */
+ tx_chn = &emac->tx_chns[emac->tx_ch_num - 1];
+
+ /* Map the linear buffer */
+ buf_dma = dma_map_single(tx_chn->dma_dev, data, pkt_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) {
+ netdev_err(emac->ndev, "cmd %x: failed to map cmd buffer\n", cmd);
+ ret = -EINVAL;
+ goto err_unlock;
+ }
+
+ first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+ if (!first_desc) {
+ netdev_err(emac->ndev, "cmd %x: failed to allocate descriptor\n", cmd);
+ dma_unmap_single(tx_chn->dma_dev, buf_dma, pkt_len, DMA_TO_DEVICE);
+ ret = -ENOMEM;
+ goto err_unlock;
+ }
+
+ cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+ PRUETH_NAV_PS_DATA_SIZE);
+ cppi5_hdesc_set_pkttype(first_desc, PRUETH_PKT_TYPE_CMD);
+ epib = first_desc->epib;
+ epib[0] = 0;
+ epib[1] = 0;
+
+ cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
+ swdata = cppi5_hdesc_get_swdata(first_desc);
+ *swdata = data;
+
+ cppi5_hdesc_set_pktlen(first_desc, pkt_len);
+ desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
+
+ /* send command */
+ reinit_completion(&emac->cmd_complete);
+ ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
+ if (ret) {
+ netdev_err(emac->ndev, "cmd %x: push failed: %d\n", cmd, ret);
+ goto free_desc;
+ }
+ ret = wait_for_completion_timeout(&emac->cmd_complete, msecs_to_jiffies(100));
+ if (!ret)
+ netdev_err(emac->ndev, "cmd %x: completion timeout\n", cmd);
+
+ mutex_unlock(&emac->cmd_lock);
+
+ return ret;
+free_desc:
+ prueth_xmit_free(tx_chn, first_desc);
+err_unlock:
+ mutex_unlock(&emac->cmd_lock);
+
+ return ret;
+}
+
+static void emac_change_port_speed_duplex_sr1(struct prueth_emac *emac)
+{
+ u32 cmd = ICSSG_PSTATE_SPEED_DUPLEX_CMD, val;
+ struct prueth *prueth = emac->prueth;
+ int slice = prueth_emac_slice(emac);
+
+ /* only full duplex supported for now */
+ if (emac->duplex != DUPLEX_FULL)
+ return;
+
+ val = icssg_rgmii_get_speed(prueth->miig_rt, slice);
+ /* firmware expects full duplex settings in bit 2-1 */
+ val <<= 1;
+ cmd |= val;
+
+ val = icssg_rgmii_get_fullduplex(prueth->miig_rt, slice);
+ /* firmware expects full duplex settings in bit 3 */
+ val <<= 3;
+ cmd |= val;
+
+ emac_send_command_sr1(emac, cmd);
+}
+
static void tx_ts_work(struct prueth_emac *emac)
{
struct skb_shared_hwtstamps ssh;
@@ -873,6 +968,141 @@ static irqreturn_t prueth_tx_ts_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+/* get one packet from requested flow_id
+ *
+ * Returns skb pointer if packet found else NULL
+ * Caller must free the returned skb.
+ */
+static struct sk_buff *prueth_process_rx_mgm(struct prueth_emac *emac,
+ u32 flow_id)
+{
+ struct prueth_rx_chn *rx_chn = &emac->rx_mgm_chn;
+ struct net_device *ndev = emac->ndev;
+ struct cppi5_host_desc_t *desc_rx;
+ struct sk_buff *skb, *new_skb;
+ dma_addr_t desc_dma, buf_dma;
+ u32 buf_dma_len, pkt_len;
+ void **swdata;
+ int ret;
+
+ ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
+ if (ret) {
+ if (ret != -ENODATA)
+ netdev_err(ndev, "rx mgm pop: failed: %d\n", ret);
+ return NULL;
+ }
+
+ if (cppi5_desc_is_tdcm(desc_dma)) /* Teardown */
+ return NULL;
+
+ desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
+
+ /* Fix FW bug about incorrect PSDATA size */
+ if (cppi5_hdesc_get_psdata_size(desc_rx) != PRUETH_NAV_PS_DATA_SIZE) {
+ cppi5_hdesc_update_psdata_size(desc_rx,
+ PRUETH_NAV_PS_DATA_SIZE);
+ }
+
+ swdata = cppi5_hdesc_get_swdata(desc_rx);
+ skb = *swdata;
+ cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
+ pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
+
+ dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
+ k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+
+ new_skb = netdev_alloc_skb_ip_align(ndev, PRUETH_MAX_PKT_SIZE);
+ /* if allocation fails we drop the packet but push the
+ * descriptor back to the ring with old skb to prevent a stall
+ */
+ if (!new_skb) {
+ netdev_err(ndev,
+ "skb alloc failed, dropped mgm pkt from flow %d\n",
+ flow_id);
+ new_skb = skb;
+ skb = NULL; /* return NULL */
+ } else {
+ /* return the filled skb */
+ skb_put(skb, pkt_len);
+ }
+
+ /* queue another DMA */
+ ret = prueth_dma_rx_push(emac, new_skb, &emac->rx_mgm_chn);
+ if (WARN_ON(ret < 0))
+ dev_kfree_skb_any(new_skb);
+
+ return skb;
+}
+
+static void prueth_tx_ts_sr1(struct prueth_emac *emac,
+ struct emac_tx_ts_response_sr1 *tsr)
+{
+ u64 ns;
+ struct skb_shared_hwtstamps ssh;
+ struct sk_buff *skb;
+
+ ns = (u64)tsr->hi_ts << 32 | tsr->lo_ts;
+
+ if (tsr->cookie >= PRUETH_MAX_TX_TS_REQUESTS) {
+ netdev_dbg(emac->ndev, "Invalid TX TS cookie 0x%x\n",
+ tsr->cookie);
+ return;
+ }
+
+ skb = emac->tx_ts_skb[tsr->cookie];
+ emac->tx_ts_skb[tsr->cookie] = NULL; /* free slot */
+
+ memset(&ssh, 0, sizeof(ssh));
+ ssh.hwtstamp = ns_to_ktime(ns);
+
+ skb_tstamp_tx(skb, &ssh);
+ dev_consume_skb_any(skb);
+}
+
+static irqreturn_t prueth_rx_mgm_ts_thread_sr1(int irq, void *dev_id)
+{
+ struct prueth_emac *emac = dev_id;
+ struct sk_buff *skb;
+
+ skb = prueth_process_rx_mgm(emac, PRUETH_RX_MGM_FLOW_TIMESTAMP);
+ if (!skb)
+ return IRQ_NONE;
+
+ prueth_tx_ts_sr1(emac, (void *)skb->data);
+ dev_kfree_skb_any(skb);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t prueth_rx_mgm_rsp_thread(int irq, void *dev_id)
+{
+ struct prueth_emac *emac = dev_id;
+ struct sk_buff *skb;
+ u32 rsp;
+
+ skb = prueth_process_rx_mgm(emac, PRUETH_RX_MGM_FLOW_RESPONSE);
+ if (!skb)
+ return IRQ_NONE;
+
+ /* Process command response */
+ rsp = le32_to_cpu(*(u32 *)skb->data);
+ if ((rsp & 0xffff0000) == ICSSG_SHUTDOWN_CMD) {
+ netdev_dbg(emac->ndev,
+ "f/w Shutdown cmd resp %x\n", rsp);
+ complete(&emac->cmd_complete);
+ } else if ((rsp & 0xffff0000) ==
+ ICSSG_PSTATE_SPEED_DUPLEX_CMD) {
+ netdev_dbg(emac->ndev,
+ "f/w Speed/Duplex cmd rsp %x\n",
+ rsp);
+ complete(&emac->cmd_complete);
+ }
+
+ dev_kfree_skb_any(skb);
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t prueth_rx_irq(int irq, void *dev_id)
{
struct prueth_emac *emac = dev_id;
@@ -1517,6 +1747,31 @@ static void emac_ndo_tx_timeout(struct net_device *ndev, unsigned int txqueue)
ndev->stats.tx_errors++;
}
+static void emac_ndo_set_rx_mode_sr1(struct net_device *ndev)
+{
+ struct prueth_emac *emac = netdev_priv(ndev);
+ struct prueth *prueth = emac->prueth;
+ int slice = prueth_emac_slice(emac);
+ bool promisc = ndev->flags & IFF_PROMISC;
+ bool allmulti = ndev->flags & IFF_ALLMULTI;
+
+ if (promisc) {
+ icssg_class_promiscuous_sr1(prueth->miig_rt, slice);
+ return;
+ }
+
+ if (allmulti) {
+ icssg_class_default(prueth->miig_rt, slice, 1, true);
+ return;
+ }
+
+ icssg_class_default(prueth->miig_rt, slice, 0, true);
+ if (!netdev_mc_empty(ndev)) {
+ /* program multicast address list into Classifier */
+ icssg_class_add_mcast_sr1(prueth->miig_rt, slice, ndev);
+ }
+}
+
static void emac_ndo_set_rx_mode_work(struct work_struct *work)
{
struct prueth_emac *emac = container_of(work, struct prueth_emac, rx_mode_work);
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2 7/8] net: ti: iccsg-prueth: Add necessary functions for SR1.0 support
2024-01-17 16:15 ` [PATCH v2 7/8] net: ti: iccsg-prueth: Add necessary functions for SR1.0 support Diogo Ivo
@ 2024-01-17 20:56 ` Andrew Lunn
0 siblings, 0 replies; 15+ messages in thread
From: Andrew Lunn @ 2024-01-17 20:56 UTC (permalink / raw)
To: Diogo Ivo
Cc: danishanwar, rogerq, davem, edumazet, kuba, pabeni,
dan.carpenter, robh, linux-arm-kernel, netdev, Jan Kiszka
> +static void emac_change_port_speed_duplex_sr1(struct prueth_emac *emac)
> +{
> + u32 cmd = ICSSG_PSTATE_SPEED_DUPLEX_CMD, val;
> + struct prueth *prueth = emac->prueth;
> + int slice = prueth_emac_slice(emac);
> +
> + /* only full duplex supported for now */
> + if (emac->duplex != DUPLEX_FULL)
> + return;
You should tell phylib this, after connecting to the PHY. If you look
around you will find code like:
engleder/tsnep_main.c: phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
engleder/tsnep_main.c: phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
engleder/tsnep_main.c: phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
The PHY will then not advertise the half duplex modes, and probably
ethtool will be disallowed to force a half duplex mode.
Andrwe
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 8/8] net: ti: icssg-prueth: Wire up support for SR1.0
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
` (5 preceding siblings ...)
2024-01-17 16:15 ` [PATCH v2 7/8] net: ti: iccsg-prueth: Add necessary functions for SR1.0 support Diogo Ivo
@ 2024-01-17 16:15 ` Diogo Ivo
2024-01-18 1:16 ` [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Jakub Kicinski
2024-01-23 12:15 ` Roger Quadros
8 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-01-17 16:15 UTC (permalink / raw)
To: danishanwar, rogerq, davem, edumazet, kuba, pabeni, andrew,
dan.carpenter, robh, linux-arm-kernel, netdev
Cc: Diogo Ivo, Jan Kiszka
Add the function calls to enable operation for SR1.0.
Based on the work of Roger Quadros, Vignesh Raghavendra and
Grygorii Strashko in TI's 5.10 SDK [1].
[1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
Co-developed-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Diogo Ivo <diogo.ivo@siemens.com>
---
Changes in v2:
- Removed explicit references to SR2.0
drivers/net/ethernet/ti/icssg/icssg_prueth.c | 299 +++++++++++++++----
1 file changed, 239 insertions(+), 60 deletions(-)
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index db15c8680741..352fb1cb3aba 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -169,6 +169,13 @@ static int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
desc_dma);
swdata = cppi5_hdesc_get_swdata(desc_tx);
+ /* was this command's TX complete? */
+ if (emac->is_sr1 && *(swdata) == emac->cmd_data) {
+ prueth_xmit_free(tx_chn, desc_tx);
+ budget++; /* not a data packet */
+ continue;
+ }
+
skb = *(swdata);
prueth_xmit_free(tx_chn, desc_tx);
@@ -344,6 +351,7 @@ static int prueth_init_rx_chns(struct prueth_emac *emac,
struct net_device *ndev = emac->ndev;
u32 fdqring_id, hdesc_size;
int i, ret = 0, slice;
+ int flow_id_base;
slice = prueth_emac_slice(emac);
if (slice < 0)
@@ -384,8 +392,14 @@ static int prueth_init_rx_chns(struct prueth_emac *emac,
goto fail;
}
- emac->rx_flow_id_base = k3_udma_glue_rx_get_flow_id_base(rx_chn->rx_chn);
- netdev_dbg(ndev, "flow id base = %d\n", emac->rx_flow_id_base);
+ flow_id_base = k3_udma_glue_rx_get_flow_id_base(rx_chn->rx_chn);
+ if (!strcmp(name, "rxmgm")) {
+ emac->rx_mgm_flow_id_base = flow_id_base;
+ netdev_dbg(ndev, "mgm flow id base = %d\n", flow_id_base);
+ } else {
+ emac->rx_flow_id_base = flow_id_base;
+ netdev_dbg(ndev, "flow id base = %d\n", flow_id_base);
+ }
fdqring_id = K3_RINGACC_RING_ID_ANY;
for (i = 0; i < rx_cfg.flow_id_num; i++) {
@@ -494,10 +508,14 @@ static void emac_rx_timestamp(struct prueth_emac *emac,
struct skb_shared_hwtstamps *ssh;
u64 ns;
- u32 hi_sw = readl(emac->prueth->shram.va +
- TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET);
- ns = icssg_ts_to_ns(hi_sw, psdata[1], psdata[0],
- IEP_DEFAULT_CYCLE_TIME_NS);
+ if (emac->is_sr1) {
+ ns = (u64)psdata[1] << 32 | psdata[0];
+ } else {
+ u32 hi_sw = readl(emac->prueth->shram.va +
+ TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET);
+ ns = icssg_ts_to_ns(hi_sw, psdata[1], psdata[0],
+ IEP_DEFAULT_CYCLE_TIME_NS);
+ }
ssh = skb_hwtstamps(skb);
memset(ssh, 0, sizeof(*ssh));
@@ -1119,6 +1137,17 @@ struct icssg_firmwares {
char *txpru;
};
+static struct icssg_firmwares icssg_emac_firmwares_sr1[] = {
+ {
+ .pru = "ti-pruss/am65x-pru0-prueth-fw.elf",
+ .rtu = "ti-pruss/am65x-rtu0-prueth-fw.elf",
+ },
+ {
+ .pru = "ti-pruss/am65x-pru1-prueth-fw.elf",
+ .rtu = "ti-pruss/am65x-rtu1-prueth-fw.elf",
+ }
+};
+
static struct icssg_firmwares icssg_emac_firmwares[] = {
{
.pru = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
@@ -1138,7 +1167,8 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
struct device *dev = prueth->dev;
int slice, ret;
- firmwares = icssg_emac_firmwares;
+ firmwares = prueth->pdata.is_sr1 ? icssg_emac_firmwares_sr1
+ : icssg_emac_firmwares;
slice = prueth_emac_slice(emac);
if (slice < 0) {
@@ -1164,11 +1194,15 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
goto halt_pru;
}
- ret = rproc_set_firmware(prueth->txpru[slice], firmwares[slice].txpru);
- ret = rproc_boot(prueth->txpru[slice]);
- if (ret) {
- dev_err(dev, "failed to boot TX_PRU%d: %d\n", slice, ret);
- goto halt_rtu;
+ if (!emac->is_sr1) {
+ ret = rproc_set_firmware(prueth->txpru[slice],
+ firmwares[slice].txpru);
+ ret = rproc_boot(prueth->txpru[slice]);
+ if (ret) {
+ dev_err(dev, "failed to boot TX_PRU%d: %d\n",
+ slice, ret);
+ goto halt_rtu;
+ }
}
emac->fw_running = 1;
@@ -1201,7 +1235,8 @@ static void prueth_emac_stop(struct prueth_emac *emac)
}
emac->fw_running = 0;
- rproc_shutdown(prueth->txpru[slice]);
+ if (!emac->is_sr1)
+ rproc_shutdown(prueth->txpru[slice]);
rproc_shutdown(prueth->rtu[slice]);
rproc_shutdown(prueth->pru[slice]);
}
@@ -1269,11 +1304,15 @@ static void emac_adjust_link(struct net_device *ndev)
icssg_config_ipg(emac);
spin_unlock_irqrestore(&emac->lock, flags);
icssg_config_set_speed(emac);
- emac_set_port_state(emac, ICSSG_EMAC_PORT_FORWARD);
+ if (!emac->is_sr1)
+ emac_set_port_state(emac, ICSSG_EMAC_PORT_FORWARD);
- } else {
+ } else if (!emac->is_sr1) {
emac_set_port_state(emac, ICSSG_EMAC_PORT_DISABLE);
}
+
+ if (emac->is_sr1 && emac->link)
+ emac_change_port_speed_duplex_sr1(emac);
}
if (emac->link) {
@@ -1288,8 +1327,10 @@ static void emac_adjust_link(struct net_device *ndev)
static int emac_napi_rx_poll(struct napi_struct *napi_rx, int budget)
{
struct prueth_emac *emac = prueth_napi_to_emac(napi_rx);
- int rx_flow = PRUETH_RX_FLOW_DATA;
- int flow = PRUETH_MAX_RX_FLOWS;
+ int rx_flow = emac->is_sr1 ?
+ PRUETH_RX_FLOW_DATA_SR1 : PRUETH_RX_FLOW_DATA;
+ int flow = emac->is_sr1 ?
+ PRUETH_MAX_RX_FLOWS_SR1 : PRUETH_MAX_RX_FLOWS;
int num_rx = 0;
int cur_budget;
int ret;
@@ -1553,11 +1594,19 @@ static int emac_ndo_open(struct net_device *ndev)
memset_io(prueth->shram.va, 0, ICSSG_CONFIG_OFFSET_SLICE1 * PRUETH_NUM_MACS);
}
+ if (emac->is_sr1) {
+ /* For SR1, high priority channel is used exclusively for
+ * management messages. Do reduce number of data channels.
+ */
+ num_data_chn--;
+ }
+
/* set h/w MAC as user might have re-configured */
ether_addr_copy(emac->mac_addr, ndev->dev_addr);
icssg_class_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
- icssg_ft1_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
+ if (!emac->is_sr1)
+ icssg_ft1_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
icssg_class_default(prueth->miig_rt, slice, 0, emac->is_sr1);
@@ -1575,7 +1624,8 @@ static int emac_ndo_open(struct net_device *ndev)
return ret;
}
- max_rx_flows = PRUETH_MAX_RX_FLOWS;
+ max_rx_flows = emac->is_sr1 ?
+ PRUETH_MAX_RX_FLOWS_SR1 : PRUETH_MAX_RX_FLOWS;
ret = prueth_init_rx_chns(emac, &emac->rx_chns, "rx",
max_rx_flows, PRUETH_MAX_RX_DESC);
if (ret) {
@@ -1583,12 +1633,24 @@ static int emac_ndo_open(struct net_device *ndev)
goto cleanup_tx;
}
+ if (emac->is_sr1) {
+ ret = prueth_init_rx_chns(emac, &emac->rx_mgm_chn, "rxmgm",
+ PRUETH_MAX_RX_MGM_FLOWS,
+ PRUETH_MAX_RX_MGM_DESC);
+ if (ret) {
+ dev_err(dev, "failed to init rx mgmt channel: %d\n",
+ ret);
+ goto cleanup_rx;
+ }
+ }
+
ret = prueth_ndev_add_tx_napi(emac);
if (ret)
- goto cleanup_rx;
+ goto cleanup_rx_mgm;
/* we use only the highest priority flow for now i.e. @irq[3] */
- rx_flow = PRUETH_RX_FLOW_DATA;
+ rx_flow = emac->is_sr1 ?
+ PRUETH_RX_FLOW_DATA_SR1 : PRUETH_RX_FLOW_DATA;
ret = request_irq(emac->rx_chns.irq[rx_flow], prueth_rx_irq,
IRQF_TRIGGER_HIGH, dev_name(dev), emac);
if (ret) {
@@ -1596,31 +1658,66 @@ static int emac_ndo_open(struct net_device *ndev)
goto cleanup_napi;
}
+ if (!emac->is_sr1)
+ goto skip_mgm_irq;
+
+ ret = request_threaded_irq(emac->rx_mgm_chn.irq[PRUETH_RX_MGM_FLOW_RESPONSE],
+ NULL, prueth_rx_mgm_rsp_thread,
+ IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+ dev_name(dev), emac);
+ if (ret) {
+ dev_err(dev, "unable to request RX Management RSP IRQ\n");
+ goto free_rx_irq;
+ }
+
+ ret = request_threaded_irq(emac->rx_mgm_chn.irq[PRUETH_RX_MGM_FLOW_TIMESTAMP],
+ NULL, prueth_rx_mgm_ts_thread_sr1,
+ IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+ dev_name(dev), emac);
+ if (ret) {
+ dev_err(dev, "unable to request RX Management TS IRQ\n");
+ goto free_rx_mgm_rsp_irq;
+ }
+
+skip_mgm_irq:
/* reset and start PRU firmware */
ret = prueth_emac_start(prueth, emac);
if (ret)
- goto free_rx_irq;
+ goto free_rx_mgmt_ts_irq;
icssg_mii_update_mtu(prueth->mii_rt, slice, ndev->max_mtu);
- if (!prueth->emacs_initialized) {
+ if (!emac->is_sr1 && !prueth->emacs_initialized) {
ret = icss_iep_init(emac->iep, &prueth_iep_clockops,
emac, IEP_DEFAULT_CYCLE_TIME_NS);
}
- ret = request_threaded_irq(emac->tx_ts_irq, NULL, prueth_tx_ts_irq,
- IRQF_ONESHOT, dev_name(dev), emac);
- if (ret)
- goto stop;
+ if (!emac->is_sr1) {
+ ret = request_threaded_irq(emac->tx_ts_irq, NULL,
+ prueth_tx_ts_irq, IRQF_ONESHOT,
+ dev_name(dev), emac);
+ if (ret)
+ goto stop;
+ }
/* Prepare RX */
ret = prueth_prepare_rx_chan(emac, &emac->rx_chns, PRUETH_MAX_PKT_SIZE);
if (ret)
goto free_tx_ts_irq;
+ if (emac->is_sr1) {
+ ret = prueth_prepare_rx_chan(emac, &emac->rx_mgm_chn, 64);
+ if (ret)
+ goto reset_rx_chn;
+
+ ret = k3_udma_glue_enable_rx_chn(emac->rx_mgm_chn.rx_chn);
+ if (ret)
+ goto reset_rx_chn;
+ }
+
ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn);
if (ret)
- goto reset_rx_chn;
+ goto reset_rx_mgm_chn;
for (i = 0; i < emac->tx_ch_num; i++) {
ret = k3_udma_glue_enable_tx_chn(emac->tx_chns[i].tx_chn);
@@ -1647,16 +1744,33 @@ static int emac_ndo_open(struct net_device *ndev)
* any SKB for completion. So set false to free_skb
*/
prueth_reset_tx_chan(emac, i, false);
+reset_rx_mgm_chn:
+ if (emac->is_sr1)
+ prueth_reset_rx_chan(&emac->rx_mgm_chn,
+ PRUETH_MAX_RX_MGM_FLOWS, true);
reset_rx_chn:
prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, false);
free_tx_ts_irq:
- free_irq(emac->tx_ts_irq, emac);
+ if (!emac->is_sr1)
+ free_irq(emac->tx_ts_irq, emac);
stop:
prueth_emac_stop(emac);
+free_rx_mgmt_ts_irq:
+ if (emac->is_sr1)
+ free_irq(emac->rx_mgm_chn.irq[PRUETH_RX_MGM_FLOW_TIMESTAMP],
+ emac);
+free_rx_mgm_rsp_irq:
+ if (emac->is_sr1)
+ free_irq(emac->rx_mgm_chn.irq[PRUETH_RX_MGM_FLOW_RESPONSE],
+ emac);
free_rx_irq:
free_irq(emac->rx_chns.irq[rx_flow], emac);
cleanup_napi:
prueth_ndev_del_tx_napi(emac, emac->tx_ch_num);
+cleanup_rx_mgm:
+ if (emac->is_sr1)
+ prueth_cleanup_rx_chns(emac, &emac->rx_mgm_chn,
+ PRUETH_MAX_RX_MGM_FLOWS);
cleanup_rx:
prueth_cleanup_rx_chns(emac, &emac->rx_chns, max_rx_flows);
cleanup_tx:
@@ -1677,7 +1791,8 @@ static int emac_ndo_stop(struct net_device *ndev)
{
struct prueth_emac *emac = netdev_priv(ndev);
struct prueth *prueth = emac->prueth;
- int rx_flow = PRUETH_RX_FLOW_DATA;
+ int rx_flow = emac->is_sr1 ? PRUETH_RX_FLOW_DATA_SR1 :
+ PRUETH_RX_FLOW_DATA;
int max_rx_flows;
int ret, i;
@@ -1690,6 +1805,9 @@ static int emac_ndo_stop(struct net_device *ndev)
icssg_class_disable(prueth->miig_rt, prueth_emac_slice(emac));
+ if (emac->is_sr1)
+ emac_send_command_sr1(emac, ICSSG_SHUTDOWN_CMD);
+
atomic_set(&emac->tdown_cnt, emac->tx_ch_num);
/* ensure new tdown_cnt value is visible */
smp_mb__after_atomic();
@@ -1707,10 +1825,17 @@ static int emac_ndo_stop(struct net_device *ndev)
for (i = 0; i < emac->tx_ch_num; i++)
napi_disable(&emac->tx_chns[i].napi_tx);
- max_rx_flows = PRUETH_MAX_RX_FLOWS;
+ max_rx_flows = emac->is_sr1 ?
+ PRUETH_MAX_RX_FLOWS_SR1 : PRUETH_MAX_RX_FLOWS;
k3_udma_glue_tdown_rx_chn(emac->rx_chns.rx_chn, true);
prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, true);
+ if (emac->is_sr1) {
+ /* Teardown RX MGM channel */
+ k3_udma_glue_tdown_rx_chn(emac->rx_mgm_chn.rx_chn, true);
+ prueth_reset_rx_chan(&emac->rx_mgm_chn,
+ PRUETH_MAX_RX_MGM_FLOWS, true);
+ }
napi_disable(&emac->napi_rx);
@@ -1722,18 +1847,28 @@ static int emac_ndo_stop(struct net_device *ndev)
/* stop PRUs */
prueth_emac_stop(emac);
- if (prueth->emacs_initialized == 1)
+ if (!emac->is_sr1 && prueth->emacs_initialized == 1)
icss_iep_exit(emac->iep);
/* stop PRUs */
prueth_emac_stop(emac);
- free_irq(emac->tx_ts_irq, emac);
+ if (!emac->is_sr1)
+ free_irq(emac->tx_ts_irq, emac);
+ if (emac->is_sr1) {
+ free_irq(emac->rx_mgm_chn.irq[PRUETH_RX_MGM_FLOW_TIMESTAMP],
+ emac);
+ free_irq(emac->rx_mgm_chn.irq[PRUETH_RX_MGM_FLOW_RESPONSE],
+ emac);
+ }
free_irq(emac->rx_chns.irq[rx_flow], emac);
prueth_ndev_del_tx_napi(emac, emac->tx_ch_num);
prueth_cleanup_tx_chns(emac);
+ if (emac->is_sr1)
+ prueth_cleanup_rx_chns(emac, &emac->rx_mgm_chn,
+ PRUETH_MAX_RX_MGM_FLOWS);
prueth_cleanup_rx_chns(emac, &emac->rx_chns, max_rx_flows);
prueth_cleanup_tx_chns(emac);
@@ -1814,7 +1949,10 @@ static void emac_ndo_set_rx_mode(struct net_device *ndev)
{
struct prueth_emac *emac = netdev_priv(ndev);
- queue_work(emac->cmd_wq, &emac->rx_mode_work);
+ if (emac->is_sr1)
+ emac_ndo_set_rx_mode_sr1(ndev);
+ else
+ queue_work(emac->cmd_wq, &emac->rx_mode_work);
}
static int emac_set_ts_config(struct net_device *ndev, struct ifreq *ifr)
@@ -1994,6 +2132,10 @@ static int prueth_netdev_init(struct prueth *prueth,
if (mac == PRUETH_MAC_INVALID)
return -EINVAL;
+ /* Use 1 channel for management messages on SR1 */
+ if (prueth->pdata.is_sr1)
+ num_tx_chn--;
+
ndev = alloc_etherdev_mq(sizeof(*emac), num_tx_chn);
if (!ndev)
return -ENOMEM;
@@ -2021,7 +2163,15 @@ static int prueth_netdev_init(struct prueth *prueth,
goto free_wq;
}
+ emac->is_sr1 = prueth->pdata.is_sr1;
emac->tx_ch_num = 1;
+ if (emac->is_sr1) {
+ /* use a dedicated high priority channel for management
+ * messages which is +1 of highest priority data channel.
+ */
+ emac->tx_ch_num++;
+ goto skip_irq;
+ }
irq_name = "tx_ts0";
if (emac->port_id == PRUETH_PORT_MII1)
@@ -2032,6 +2182,7 @@ static int prueth_netdev_init(struct prueth *prueth,
goto free;
}
+skip_irq:
SET_NETDEV_DEV(ndev, prueth->dev);
spin_lock_init(&emac->lock);
mutex_init(&emac->cmd_lock);
@@ -2158,7 +2309,7 @@ static int prueth_get_cores(struct prueth *prueth, int slice)
idx = 0;
break;
case ICSS_SLICE1:
- idx = 3;
+ idx = prueth->pdata.is_sr1 ? 2 : 3;
break;
default:
return -EINVAL;
@@ -2180,6 +2331,9 @@ static int prueth_get_cores(struct prueth *prueth, int slice)
return dev_err_probe(dev, ret, "unable to get RTU%d\n", slice);
}
+ if (prueth->pdata.is_sr1)
+ return 0;
+
idx++;
prueth->txpru[slice] = pru_rproc_get(np, idx, NULL);
if (IS_ERR(prueth->txpru[slice])) {
@@ -2329,14 +2483,20 @@ static int prueth_probe(struct platform_device *pdev)
goto put_mem;
}
- msmc_ram_size = MSMC_RAM_SIZE;
+ msmc_ram_size = prueth->pdata.is_sr1 ? MSMC_RAM_SIZE_SR1 : MSMC_RAM_SIZE;
- /* NOTE: FW bug needs buffer base to be 64KB aligned */
- prueth->msmcram.va =
- (void __iomem *)gen_pool_alloc_algo(prueth->sram_pool,
- msmc_ram_size,
- gen_pool_first_fit_align,
- &gp_data);
+ if (prueth->pdata.is_sr1) {
+ prueth->msmcram.va =
+ (void __iomem *)gen_pool_alloc(prueth->sram_pool,
+ msmc_ram_size);
+ } else {
+ /* NOTE: FW bug needs buffer base to be 64KB aligned */
+ prueth->msmcram.va =
+ (void __iomem *)gen_pool_alloc_algo(prueth->sram_pool,
+ msmc_ram_size,
+ gen_pool_first_fit_align,
+ &gp_data);
+ }
if (!prueth->msmcram.va) {
ret = -ENOMEM;
@@ -2350,17 +2510,19 @@ static int prueth_probe(struct platform_device *pdev)
dev_dbg(dev, "sram: pa %llx va %p size %zx\n", prueth->msmcram.pa,
prueth->msmcram.va, prueth->msmcram.size);
- prueth->iep0 = icss_iep_get_idx(np, 0);
- if (IS_ERR(prueth->iep0)) {
- ret = dev_err_probe(dev, PTR_ERR(prueth->iep0), "iep0 get failed\n");
- prueth->iep0 = NULL;
- goto free_pool;
- }
+ if (!prueth->pdata.is_sr1) {
+ prueth->iep0 = icss_iep_get_idx(np, 0);
+ if (IS_ERR(prueth->iep0)) {
+ ret = dev_err_probe(dev, PTR_ERR(prueth->iep0), "iep0 get failed\n");
+ prueth->iep0 = NULL;
+ goto free_pool;
+ }
- prueth->iep1 = icss_iep_get_idx(np, 1);
- if (IS_ERR(prueth->iep1)) {
- ret = dev_err_probe(dev, PTR_ERR(prueth->iep1), "iep1 get failed\n");
- goto put_iep0;
+ prueth->iep1 = icss_iep_get_idx(np, 1);
+ if (IS_ERR(prueth->iep1)) {
+ ret = dev_err_probe(dev, PTR_ERR(prueth->iep1), "iep1 get failed\n");
+ goto put_iep0;
+ }
}
if (prueth->pdata.quirk_10m_link_issue) {
@@ -2382,7 +2544,8 @@ static int prueth_probe(struct platform_device *pdev)
if (of_find_property(eth0_node, "ti,half-duplex-capable", NULL))
prueth->emac[PRUETH_MAC0]->half_duplex = 1;
- prueth->emac[PRUETH_MAC0]->iep = prueth->iep0;
+ if (!prueth->pdata.is_sr1)
+ prueth->emac[PRUETH_MAC0]->iep = prueth->iep0;
}
if (eth1_node) {
@@ -2396,7 +2559,8 @@ static int prueth_probe(struct platform_device *pdev)
if (of_find_property(eth1_node, "ti,half-duplex-capable", NULL))
prueth->emac[PRUETH_MAC1]->half_duplex = 1;
- prueth->emac[PRUETH_MAC1]->iep = prueth->iep0;
+ if (!prueth->pdata.is_sr1)
+ prueth->emac[PRUETH_MAC1]->iep = prueth->iep0;
}
/* register the network devices */
@@ -2457,10 +2621,13 @@ static int prueth_probe(struct platform_device *pdev)
exit_iep:
if (prueth->pdata.quirk_10m_link_issue)
icss_iep_exit_fw(prueth->iep1);
- icss_iep_put(prueth->iep1);
+
+ if (!prueth->pdata.is_sr1)
+ icss_iep_put(prueth->iep1);
put_iep0:
- icss_iep_put(prueth->iep0);
+ if (!prueth->pdata.is_sr1)
+ icss_iep_put(prueth->iep0);
prueth->iep0 = NULL;
prueth->iep1 = NULL;
@@ -2511,15 +2678,21 @@ static void prueth_remove(struct platform_device *pdev)
prueth_netdev_exit(prueth, eth_node);
}
- if (prueth->pdata.quirk_10m_link_issue)
+ if (prueth->pdata.is_sr1) {
+ icss_iep_exit(prueth->iep1);
+ icss_iep_exit(prueth->iep0);
+ } else if (prueth->pdata.quirk_10m_link_issue) {
icss_iep_exit_fw(prueth->iep1);
+ }
- icss_iep_put(prueth->iep1);
- icss_iep_put(prueth->iep0);
+ if (!prueth->pdata.is_sr1) {
+ icss_iep_put(prueth->iep1);
+ icss_iep_put(prueth->iep0);
+ }
gen_pool_free(prueth->sram_pool,
(unsigned long)prueth->msmcram.va,
- MSMC_RAM_SIZE);
+ prueth->pdata.is_sr1 ? MSMC_RAM_SIZE_SR1 : MSMC_RAM_SIZE);
pruss_release_mem_region(prueth->pruss, &prueth->shram);
@@ -2588,6 +2761,11 @@ static const struct dev_pm_ops prueth_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(prueth_suspend, prueth_resume)
};
+static const struct prueth_pdata am654_icssg_pdata_sr1 = {
+ .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
+ .is_sr1 = 1,
+};
+
static const struct prueth_pdata am654_icssg_pdata = {
.fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
.quirk_10m_link_issue = 1,
@@ -2598,6 +2776,7 @@ static const struct prueth_pdata am64x_icssg_pdata = {
};
static const struct of_device_id prueth_dt_match[] = {
+ { .compatible = "ti,am654-sr1-icssg-prueth", .data = &am654_icssg_pdata_sr1 },
{ .compatible = "ti,am654-icssg-prueth", .data = &am654_icssg_pdata },
{ .compatible = "ti,am642-icssg-prueth", .data = &am64x_icssg_pdata },
{ /* sentinel */ }
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
` (6 preceding siblings ...)
2024-01-17 16:15 ` [PATCH v2 8/8] net: ti: icssg-prueth: Wire up support for SR1.0 Diogo Ivo
@ 2024-01-18 1:16 ` Jakub Kicinski
2024-01-23 12:15 ` Roger Quadros
8 siblings, 0 replies; 15+ messages in thread
From: Jakub Kicinski @ 2024-01-18 1:16 UTC (permalink / raw)
To: Diogo Ivo
Cc: danishanwar, rogerq, davem, edumazet, pabeni, andrew,
dan.carpenter, grygorii.strashko, jacob.e.keller, robh, robh+dt,
krzysztof.kozlowski+dt, conor+dt, linux-arm-kernel, netdev,
devicetree, jan.kiszka
On Wed, 17 Jan 2024 16:14:54 +0000 Diogo Ivo wrote:
> net: ti: icssg-config: add SR1.0-specific configuration bits
FWIW looks like this patch didn't make it to the list.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices
2024-01-17 16:14 [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Diogo Ivo
` (7 preceding siblings ...)
2024-01-18 1:16 ` [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices Jakub Kicinski
@ 2024-01-23 12:15 ` Roger Quadros
2024-01-24 9:24 ` Diogo Ivo
8 siblings, 1 reply; 15+ messages in thread
From: Roger Quadros @ 2024-01-23 12:15 UTC (permalink / raw)
To: Diogo Ivo, danishanwar, davem, edumazet, kuba, pabeni, andrew,
dan.carpenter, grygorii.strashko, jacob.e.keller, robh, robh+dt,
krzysztof.kozlowski+dt, conor+dt, linux-arm-kernel, netdev,
devicetree
Cc: jan.kiszka
Hello Diogo,
On 17/01/2024 18:14, Diogo Ivo wrote:
> Hello,
>
> This series extends the current ICSSG-based Ethernet driver to support
> Silicon Revision 1.0 devices.
>
> Notable differences between the Silicon Revisions are that there is
> no TX core in SR1.0 with this being handled by the firmware, requiring
> extra DMA channels to communicate commands to the firmware (with the
> firmware being different as well) and in the packet classifier.
>
> The motivation behind it is that a significant number of Siemens
> devices containing SR1.0 silicon have been deployed in the field
> and need to be supported and updated to newer kernel versions
> without losing functionality.
Adding SR1.0 support with all its ifdefs makes the driver more complicated
than it should be.
I think we need to treat SR1.0 and SR2.0 as different devices with their
own independent drivers. While the data path is pretty much the same,
also like in am65-cpsw-nuss.c, the initialization, firmware and other
runtime logic is significantly different.
How about introducing a new icssg_prueth_sr1.c and putting all the SR1 stuff
there? You could still re-use the other helper files in net/ti/icssg/.
It also warrants for it's own Kconfig symbol so it can be built only
if required.
Any common logic could still be moved to icssg_common.c and re-used in both drivers.
>
> This series is based on TI's 5.10 SDK [1].
>
> The first version of this patch series can be found in [2].
>
> [1]: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/?h=ti-linux-5.10.y
> [2]: https://lore.kernel.org/all/20231219174548.3481-1-diogo.ivo@siemens.com/
>
> Changes in v2:
> - Addressed Krzysztof's comments on the dt-binding
> - Removed explicit references to SR2.0
> - Added static keyword as indicated by the kernel test robot
>
> Diogo Ivo (8):
> dt-bindings: net: Add support for AM65x SR1.0 in ICSSG
> net: ti: icssg-config: add SR1.0-specific configuration bits
> net: ti: icssg-prueth: add SR1.0-specific configuration bits
> net: ti: icssg-classifier: Add support for SR1.0
> net: ti: icssg-config: Add SR1.0 configuration functions
> net: ti: icssg-ethtool: Adjust channel count for SR1.0
> net: ti: iccsg-prueth: Add necessary functions for SR1.0 support
> net: ti: icssg-prueth: Wire up support for SR1.0
>
> .../bindings/net/ti,icssg-prueth.yaml | 29 +-
> .../net/ethernet/ti/icssg/icssg_classifier.c | 113 +++-
> drivers/net/ethernet/ti/icssg/icssg_config.c | 86 ++-
> drivers/net/ethernet/ti/icssg/icssg_config.h | 55 ++
> drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 10 +-
> drivers/net/ethernet/ti/icssg/icssg_prueth.c | 556 ++++++++++++++++--
> drivers/net/ethernet/ti/icssg/icssg_prueth.h | 21 +-
> 7 files changed, 788 insertions(+), 82 deletions(-)
>
--
cheers,
-roger
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/8] Add support for ICSSG-based Ethernet on SR1.0 devices
2024-01-23 12:15 ` Roger Quadros
@ 2024-01-24 9:24 ` Diogo Ivo
0 siblings, 0 replies; 15+ messages in thread
From: Diogo Ivo @ 2024-01-24 9:24 UTC (permalink / raw)
To: Roger Quadros, danishanwar, davem, edumazet, kuba, pabeni,
andrew, dan.carpenter, grygorii.strashko, jacob.e.keller, robh,
robh+dt, krzysztof.kozlowski+dt, conor+dt, linux-arm-kernel,
netdev, devicetree
Cc: jan.kiszka, diogo.ivo
Hi all, thank you for your input so far.
On 1/23/24 12:15, Roger Quadros wrote:
> Hello Diogo,
>
> On 17/01/2024 18:14, Diogo Ivo wrote:
>> Hello,
>>
>> This series extends the current ICSSG-based Ethernet driver to support
>> Silicon Revision 1.0 devices.
>>
>> Notable differences between the Silicon Revisions are that there is
>> no TX core in SR1.0 with this being handled by the firmware, requiring
>> extra DMA channels to communicate commands to the firmware (with the
>> firmware being different as well) and in the packet classifier.
>>
>> The motivation behind it is that a significant number of Siemens
>> devices containing SR1.0 silicon have been deployed in the field
>> and need to be supported and updated to newer kernel versions
>> without losing functionality.
> Adding SR1.0 support with all its ifdefs makes the driver more complicated
> than it should be.
>
> I think we need to treat SR1.0 and SR2.0 as different devices with their
> own independent drivers. While the data path is pretty much the same,
> also like in am65-cpsw-nuss.c, the initialization, firmware and other
> runtime logic is significantly different.
>
> How about introducing a new icssg_prueth_sr1.c and putting all the SR1 stuff
> there? You could still re-use the other helper files in net/ti/icssg/.
> It also warrants for it's own Kconfig symbol so it can be built only
> if required.
> Any common logic could still be moved to icssg_common.c and re-used in both drivers.
Yes, that sounds like a more reasonable approach. I will refactor the code
and come back with a v3, hopefully with all patches getting sent out :)
Best regards,
Diogo
^ permalink raw reply [flat|nested] 15+ messages in thread