root/drivers/net/ethernet/mscc/ocelot_police.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qos_policer_conf_set
  2. ocelot_port_policer_add
  3. ocelot_port_policer_del

   1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
   2 /* Microsemi Ocelot Switch driver
   3  *
   4  * Copyright (c) 2019 Microsemi Corporation
   5  */
   6 
   7 #include "ocelot_police.h"
   8 
   9 enum mscc_qos_rate_mode {
  10         MSCC_QOS_RATE_MODE_DISABLED, /* Policer/shaper disabled */
  11         MSCC_QOS_RATE_MODE_LINE, /* Measure line rate in kbps incl. IPG */
  12         MSCC_QOS_RATE_MODE_DATA, /* Measures data rate in kbps excl. IPG */
  13         MSCC_QOS_RATE_MODE_FRAME, /* Measures frame rate in fps */
  14         __MSCC_QOS_RATE_MODE_END,
  15         NUM_MSCC_QOS_RATE_MODE = __MSCC_QOS_RATE_MODE_END,
  16         MSCC_QOS_RATE_MODE_MAX = __MSCC_QOS_RATE_MODE_END - 1,
  17 };
  18 
  19 /* Types for ANA:POL[0-192]:POL_MODE_CFG.FRM_MODE */
  20 #define POL_MODE_LINERATE   0 /* Incl IPG. Unit: 33 1/3 kbps, 4096 bytes */
  21 #define POL_MODE_DATARATE   1 /* Excl IPG. Unit: 33 1/3 kbps, 4096 bytes  */
  22 #define POL_MODE_FRMRATE_HI 2 /* Unit: 33 1/3 fps, 32.8 frames */
  23 #define POL_MODE_FRMRATE_LO 3 /* Unit: 1/3 fps, 0.3 frames */
  24 
  25 /* Policer indexes */
  26 #define POL_IX_PORT    0    /* 0-11    : Port policers */
  27 #define POL_IX_QUEUE   32   /* 32-127  : Queue policers  */
  28 
  29 /* Default policer order */
  30 #define POL_ORDER 0x1d3 /* Ocelot policer order: Serial (QoS -> Port -> VCAP) */
  31 
  32 struct qos_policer_conf {
  33         enum mscc_qos_rate_mode mode;
  34         bool dlb; /* Enable DLB (dual leaky bucket mode */
  35         bool cf;  /* Coupling flag (ignored in SLB mode) */
  36         u32  cir; /* CIR in kbps/fps (ignored in SLB mode) */
  37         u32  cbs; /* CBS in bytes/frames (ignored in SLB mode) */
  38         u32  pir; /* PIR in kbps/fps */
  39         u32  pbs; /* PBS in bytes/frames */
  40         u8   ipg; /* Size of IPG when MSCC_QOS_RATE_MODE_LINE is chosen */
  41 };
  42 
  43 static int qos_policer_conf_set(struct ocelot_port *port, u32 pol_ix,
  44                                 struct qos_policer_conf *conf)
  45 {
  46         u32 cf = 0, cir_ena = 0, frm_mode = POL_MODE_LINERATE;
  47         u32 cir = 0, cbs = 0, pir = 0, pbs = 0;
  48         bool cir_discard = 0, pir_discard = 0;
  49         struct ocelot *ocelot = port->ocelot;
  50         u32 pbs_max = 0, cbs_max = 0;
  51         u8 ipg = 20;
  52         u32 value;
  53 
  54         pir = conf->pir;
  55         pbs = conf->pbs;
  56 
  57         switch (conf->mode) {
  58         case MSCC_QOS_RATE_MODE_LINE:
  59         case MSCC_QOS_RATE_MODE_DATA:
  60                 if (conf->mode == MSCC_QOS_RATE_MODE_LINE) {
  61                         frm_mode = POL_MODE_LINERATE;
  62                         ipg = min_t(u8, GENMASK(4, 0), conf->ipg);
  63                 } else {
  64                         frm_mode = POL_MODE_DATARATE;
  65                 }
  66                 if (conf->dlb) {
  67                         cir_ena = 1;
  68                         cir = conf->cir;
  69                         cbs = conf->cbs;
  70                         if (cir == 0 && cbs == 0) {
  71                                 /* Discard cir frames */
  72                                 cir_discard = 1;
  73                         } else {
  74                                 cir = DIV_ROUND_UP(cir, 100);
  75                                 cir *= 3; /* 33 1/3 kbps */
  76                                 cbs = DIV_ROUND_UP(cbs, 4096);
  77                                 cbs = (cbs ? cbs : 1); /* No zero burst size */
  78                                 cbs_max = 60; /* Limit burst size */
  79                                 cf = conf->cf;
  80                                 if (cf)
  81                                         pir += conf->cir;
  82                         }
  83                 }
  84                 if (pir == 0 && pbs == 0) {
  85                         /* Discard PIR frames */
  86                         pir_discard = 1;
  87                 } else {
  88                         pir = DIV_ROUND_UP(pir, 100);
  89                         pir *= 3;  /* 33 1/3 kbps */
  90                         pbs = DIV_ROUND_UP(pbs, 4096);
  91                         pbs = (pbs ? pbs : 1); /* No zero burst size */
  92                         pbs_max = 60; /* Limit burst size */
  93                 }
  94                 break;
  95         case MSCC_QOS_RATE_MODE_FRAME:
  96                 if (pir >= 100) {
  97                         frm_mode = POL_MODE_FRMRATE_HI;
  98                         pir = DIV_ROUND_UP(pir, 100);
  99                         pir *= 3;  /* 33 1/3 fps */
 100                         pbs = (pbs * 10) / 328; /* 32.8 frames */
 101                         pbs = (pbs ? pbs : 1); /* No zero burst size */
 102                         pbs_max = GENMASK(6, 0); /* Limit burst size */
 103                 } else {
 104                         frm_mode = POL_MODE_FRMRATE_LO;
 105                         if (pir == 0 && pbs == 0) {
 106                                 /* Discard all frames */
 107                                 pir_discard = 1;
 108                                 cir_discard = 1;
 109                         } else {
 110                                 pir *= 3; /* 1/3 fps */
 111                                 pbs = (pbs * 10) / 3; /* 0.3 frames */
 112                                 pbs = (pbs ? pbs : 1); /* No zero burst size */
 113                                 pbs_max = 61; /* Limit burst size */
 114                         }
 115                 }
 116                 break;
 117         default: /* MSCC_QOS_RATE_MODE_DISABLED */
 118                 /* Disable policer using maximum rate and zero burst */
 119                 pir = GENMASK(15, 0);
 120                 pbs = 0;
 121                 break;
 122         }
 123 
 124         /* Check limits */
 125         if (pir > GENMASK(15, 0)) {
 126                 netdev_err(port->dev, "Invalid pir\n");
 127                 return -EINVAL;
 128         }
 129 
 130         if (cir > GENMASK(15, 0)) {
 131                 netdev_err(port->dev, "Invalid cir\n");
 132                 return -EINVAL;
 133         }
 134 
 135         if (pbs > pbs_max) {
 136                 netdev_err(port->dev, "Invalid pbs\n");
 137                 return -EINVAL;
 138         }
 139 
 140         if (cbs > cbs_max) {
 141                 netdev_err(port->dev, "Invalid cbs\n");
 142                 return -EINVAL;
 143         }
 144 
 145         value = (ANA_POL_MODE_CFG_IPG_SIZE(ipg) |
 146                  ANA_POL_MODE_CFG_FRM_MODE(frm_mode) |
 147                  (cf ? ANA_POL_MODE_CFG_DLB_COUPLED : 0) |
 148                  (cir_ena ? ANA_POL_MODE_CFG_CIR_ENA : 0) |
 149                  ANA_POL_MODE_CFG_OVERSHOOT_ENA);
 150 
 151         ocelot_write_gix(ocelot, value, ANA_POL_MODE_CFG, pol_ix);
 152 
 153         ocelot_write_gix(ocelot,
 154                          ANA_POL_PIR_CFG_PIR_RATE(pir) |
 155                          ANA_POL_PIR_CFG_PIR_BURST(pbs),
 156                          ANA_POL_PIR_CFG, pol_ix);
 157 
 158         ocelot_write_gix(ocelot,
 159                          (pir_discard ? GENMASK(22, 0) : 0),
 160                          ANA_POL_PIR_STATE, pol_ix);
 161 
 162         ocelot_write_gix(ocelot,
 163                          ANA_POL_CIR_CFG_CIR_RATE(cir) |
 164                          ANA_POL_CIR_CFG_CIR_BURST(cbs),
 165                          ANA_POL_CIR_CFG, pol_ix);
 166 
 167         ocelot_write_gix(ocelot,
 168                          (cir_discard ? GENMASK(22, 0) : 0),
 169                          ANA_POL_CIR_STATE, pol_ix);
 170 
 171         return 0;
 172 }
 173 
 174 int ocelot_port_policer_add(struct ocelot_port *port,
 175                             struct ocelot_policer *pol)
 176 {
 177         struct ocelot *ocelot = port->ocelot;
 178         struct qos_policer_conf pp = { 0 };
 179         int err;
 180 
 181         if (!pol)
 182                 return -EINVAL;
 183 
 184         pp.mode = MSCC_QOS_RATE_MODE_DATA;
 185         pp.pir = pol->rate;
 186         pp.pbs = pol->burst;
 187 
 188         netdev_dbg(port->dev,
 189                    "%s: port %u pir %u kbps, pbs %u bytes\n",
 190                    __func__, port->chip_port, pp.pir, pp.pbs);
 191 
 192         err = qos_policer_conf_set(port, POL_IX_PORT + port->chip_port, &pp);
 193         if (err)
 194                 return err;
 195 
 196         ocelot_rmw_gix(ocelot,
 197                        ANA_PORT_POL_CFG_PORT_POL_ENA |
 198                        ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
 199                        ANA_PORT_POL_CFG_PORT_POL_ENA |
 200                        ANA_PORT_POL_CFG_POL_ORDER_M,
 201                        ANA_PORT_POL_CFG, port->chip_port);
 202 
 203         return 0;
 204 }
 205 
 206 int ocelot_port_policer_del(struct ocelot_port *port)
 207 {
 208         struct ocelot *ocelot = port->ocelot;
 209         struct qos_policer_conf pp = { 0 };
 210         int err;
 211 
 212         netdev_dbg(port->dev, "%s: port %u\n", __func__, port->chip_port);
 213 
 214         pp.mode = MSCC_QOS_RATE_MODE_DISABLED;
 215 
 216         err = qos_policer_conf_set(port, POL_IX_PORT + port->chip_port, &pp);
 217         if (err)
 218                 return err;
 219 
 220         ocelot_rmw_gix(ocelot,
 221                        ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
 222                        ANA_PORT_POL_CFG_PORT_POL_ENA |
 223                        ANA_PORT_POL_CFG_POL_ORDER_M,
 224                        ANA_PORT_POL_CFG, port->chip_port);
 225 
 226         return 0;
 227 }

/* [<][>][^][v][top][bottom][index][help] */