net: mscc: ocelot: auto-detect packet buffer size and number of frame references
authorVladimir Oltean <vladimir.oltean@nxp.com>
Fri, 15 Jan 2021 02:11:11 +0000 (04:11 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 16 Jan 2021 04:02:33 +0000 (20:02 -0800)
Instead of reading these values from the reference manual and writing
them down into the driver, it appears that the hardware gives us the
option of detecting them dynamically.

The number of frame references corresponds to what the reference manual
notes, however it seems that the frame buffers are reported as slightly
less than the books would indicate. On VSC9959 (Felix), the books say it
should have 128KB of packet buffer, but the registers indicate only
129840 bytes (126.79 KB). Also, the unit of measurement for FREECNT from
the documentation of all these devices is incorrect (taken from an older
generation). This was confirmed by Younes Leroul from Microchip support.

Not having anything better to do with these values at the moment* (this
will change soon), let's just print them.

*The frame buffer size is, in fact, used to calculate the tail dropping
watermarks.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/dsa/ocelot/felix.c
drivers/net/dsa/ocelot/felix.h
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/dsa/ocelot/seville_vsc9953.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_vsc7514.c
include/soc/mscc/ocelot.h
include/soc/mscc/ocelot_qsys.h

index 8492151f8133416d6ab7d4f6c60ae145d61d611c..cf9317110591e77e7fa049fee71a726965d0a10c 100644 (file)
@@ -422,7 +422,6 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
        ocelot->map             = felix->info->map;
        ocelot->stats_layout    = felix->info->stats_layout;
        ocelot->num_stats       = felix->info->num_stats;
-       ocelot->shared_queue_sz = felix->info->shared_queue_sz;
        ocelot->num_mact_rows   = felix->info->num_mact_rows;
        ocelot->vcap            = felix->info->vcap;
        ocelot->ops             = felix->info->ops;
index 4c717324ac2f723e96be676c937cfc1f61ed2b41..5434fe278d2c366fe6fb5b7433f17c071e1ff0ef 100644 (file)
@@ -15,7 +15,6 @@ struct felix_info {
        const struct reg_field          *regfields;
        const u32 *const                *map;
        const struct ocelot_ops         *ops;
-       int                             shared_queue_sz;
        int                             num_mact_rows;
        const struct ocelot_stat_layout *stats_layout;
        unsigned int                    num_stats;
index a87597eef8cf397314d28f136591677cacab5cc6..b68df85e01a16a0551e0673d75abce30b8effff7 100644 (file)
@@ -1356,7 +1356,6 @@ static const struct felix_info felix_info_vsc9959 = {
        .stats_layout           = vsc9959_stats_layout,
        .num_stats              = ARRAY_SIZE(vsc9959_stats_layout),
        .vcap                   = vsc9959_vcap_props,
-       .shared_queue_sz        = 128 * 1024,
        .num_mact_rows          = 2048,
        .num_ports              = 6,
        .num_tx_queues          = FELIX_NUM_TC,
index ebbaf6817ec86898417a684f3530582b7c5c6216..b72813da6d9fcdda2401fa0ee3883513543e767e 100644 (file)
@@ -1181,7 +1181,6 @@ static const struct felix_info seville_info_vsc9953 = {
        .stats_layout           = vsc9953_stats_layout,
        .num_stats              = ARRAY_SIZE(vsc9953_stats_layout),
        .vcap                   = vsc9953_vcap_props,
-       .shared_queue_sz        = 256 * 1024,
        .num_mact_rows          = 2048,
        .num_ports              = 10,
        .mdio_bus_alloc         = vsc9953_mdio_bus_alloc,
index af620f7ce4690133e49eb516d0f19bd85b2ed7df..3af8e607c8a9f2ed82b35bdf4c90bff4550cb96f 100644 (file)
@@ -1354,7 +1354,7 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
                            pause_stop);
 
        /* Tail dropping watermarks */
-       atop_tot = (ocelot->shared_queue_sz - 9 * maxlen) /
+       atop_tot = (ocelot->packet_buffer_size - 9 * maxlen) /
                   OCELOT_BUFFER_CELL_SZ;
        atop = (9 * maxlen) / OCELOT_BUFFER_CELL_SZ;
        ocelot_write_rix(ocelot, ocelot->ops->wm_enc(atop), SYS_ATOP, port);
@@ -1467,6 +1467,25 @@ static void ocelot_cpu_port_init(struct ocelot *ocelot)
                         ANA_PORT_VLAN_CFG, cpu);
 }
 
+static void ocelot_detect_features(struct ocelot *ocelot)
+{
+       int mmgt, eq_ctrl;
+
+       /* For Ocelot, Felix, Seville, Serval etc, SYS:MMGT:MMGT:FREECNT holds
+        * the number of 240-byte free memory words (aka 4-cell chunks) and not
+        * 192 bytes as the documentation incorrectly says.
+        */
+       mmgt = ocelot_read(ocelot, SYS_MMGT);
+       ocelot->packet_buffer_size = 240 * SYS_MMGT_FREECNT(mmgt);
+
+       eq_ctrl = ocelot_read(ocelot, QSYS_EQ_CTRL);
+       ocelot->num_frame_refs = QSYS_MMGT_EQ_CTRL_FP_FREE_CNT(eq_ctrl);
+
+       dev_info(ocelot->dev,
+                "Detected %d bytes of packet buffer and %d frame references\n",
+                ocelot->packet_buffer_size, ocelot->num_frame_refs);
+}
+
 int ocelot_init(struct ocelot *ocelot)
 {
        char queue_name[32];
@@ -1509,6 +1528,7 @@ int ocelot_init(struct ocelot *ocelot)
 
        INIT_LIST_HEAD(&ocelot->multicast);
        INIT_LIST_HEAD(&ocelot->pgids);
+       ocelot_detect_features(ocelot);
        ocelot_mact_init(ocelot);
        ocelot_vlan_init(ocelot);
        ocelot_vcap_init(ocelot);
index 9cf2bc5f428927fe3f2877d2c8136746e05e9a79..7135ad18affe2aa00e1c5dae793d6818b28fbec3 100644 (file)
@@ -517,7 +517,6 @@ static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)
        ocelot->map = ocelot_regmap;
        ocelot->stats_layout = ocelot_stats_layout;
        ocelot->num_stats = ARRAY_SIZE(ocelot_stats_layout);
-       ocelot->shared_queue_sz = 224 * 1024;
        ocelot->num_mact_rows = 1024;
        ocelot->ops = ops;
 
index f3db75c0172be0bd75030c63914ec0ffc893e8d2..c17a372335cd4277d847be4f7b8c0e405fc24fea 100644 (file)
@@ -607,7 +607,8 @@ struct ocelot {
        const struct ocelot_stat_layout *stats_layout;
        unsigned int                    num_stats;
 
-       int                             shared_queue_sz;
+       int                             packet_buffer_size;
+       int                             num_frame_refs;
        int                             num_mact_rows;
 
        struct net_device               *hw_bridge_dev;
index a814bc2017d8d6f9880ee6e13fb6e652376fd5a5..b7b263a1906887c808aae104845d09eb669f5c96 100644 (file)
@@ -77,6 +77,9 @@
 #define QSYS_RES_STAT_MAXUSE(x)                           ((x) & GENMASK(11, 0))
 #define QSYS_RES_STAT_MAXUSE_M                            GENMASK(11, 0)
 
+#define QSYS_MMGT_EQ_CTRL_FP_FREE_CNT(x)                  ((x) & GENMASK(15, 0))
+#define QSYS_MMGT_EQ_CTRL_FP_FREE_CNT_M                   GENMASK(15, 0)
+
 #define QSYS_EVENTS_CORE_EV_FDC(x)                        (((x) << 2) & GENMASK(4, 2))
 #define QSYS_EVENTS_CORE_EV_FDC_M                         GENMASK(4, 2)
 #define QSYS_EVENTS_CORE_EV_FDC_X(x)                      (((x) & GENMASK(4, 2)) >> 2)