forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
....@@ -6,6 +6,7 @@
66 #include <linux/dcbnl.h>
77 #include <linux/if_ether.h>
88 #include <linux/list.h>
9
+#include <linux/netlink.h>
910
1011 #include "spectrum.h"
1112 #include "core.h"
....@@ -15,6 +16,8 @@
1516 struct mlxsw_sp_sb_pr {
1617 enum mlxsw_reg_sbpr_mode mode;
1718 u32 size;
19
+ u8 freeze_mode:1,
20
+ freeze_size:1;
1821 };
1922
2023 struct mlxsw_cp_sb_occ {
....@@ -25,9 +28,14 @@
2528 struct mlxsw_sp_sb_cm {
2629 u32 min_buff;
2730 u32 max_buff;
28
- u8 pool;
31
+ u16 pool_index;
2932 struct mlxsw_cp_sb_occ occ;
33
+ u8 freeze_pool:1,
34
+ freeze_thresh:1;
3035 };
36
+
37
+#define MLXSW_SP_SB_INFI -1U
38
+#define MLXSW_SP_SB_REST -2U
3139
3240 struct mlxsw_sp_sb_pm {
3341 u32 min_buff;
....@@ -35,18 +43,86 @@
3543 struct mlxsw_cp_sb_occ occ;
3644 };
3745
38
-#define MLXSW_SP_SB_POOL_COUNT 4
39
-#define MLXSW_SP_SB_TC_COUNT 8
46
+struct mlxsw_sp_sb_mm {
47
+ u32 min_buff;
48
+ u32 max_buff;
49
+ u16 pool_index;
50
+};
51
+
52
+struct mlxsw_sp_sb_pool_des {
53
+ enum mlxsw_reg_sbxx_dir dir;
54
+ u8 pool;
55
+};
56
+
57
+#define MLXSW_SP_SB_POOL_ING 0
58
+#define MLXSW_SP_SB_POOL_EGR 4
59
+#define MLXSW_SP_SB_POOL_EGR_MC 8
60
+#define MLXSW_SP_SB_POOL_ING_CPU 9
61
+#define MLXSW_SP_SB_POOL_EGR_CPU 10
62
+
63
+static const struct mlxsw_sp_sb_pool_des mlxsw_sp1_sb_pool_dess[] = {
64
+ {MLXSW_REG_SBXX_DIR_INGRESS, 0},
65
+ {MLXSW_REG_SBXX_DIR_INGRESS, 1},
66
+ {MLXSW_REG_SBXX_DIR_INGRESS, 2},
67
+ {MLXSW_REG_SBXX_DIR_INGRESS, 3},
68
+ {MLXSW_REG_SBXX_DIR_EGRESS, 0},
69
+ {MLXSW_REG_SBXX_DIR_EGRESS, 1},
70
+ {MLXSW_REG_SBXX_DIR_EGRESS, 2},
71
+ {MLXSW_REG_SBXX_DIR_EGRESS, 3},
72
+ {MLXSW_REG_SBXX_DIR_EGRESS, 15},
73
+ {MLXSW_REG_SBXX_DIR_INGRESS, 4},
74
+ {MLXSW_REG_SBXX_DIR_EGRESS, 4},
75
+};
76
+
77
+static const struct mlxsw_sp_sb_pool_des mlxsw_sp2_sb_pool_dess[] = {
78
+ {MLXSW_REG_SBXX_DIR_INGRESS, 0},
79
+ {MLXSW_REG_SBXX_DIR_INGRESS, 1},
80
+ {MLXSW_REG_SBXX_DIR_INGRESS, 2},
81
+ {MLXSW_REG_SBXX_DIR_INGRESS, 3},
82
+ {MLXSW_REG_SBXX_DIR_EGRESS, 0},
83
+ {MLXSW_REG_SBXX_DIR_EGRESS, 1},
84
+ {MLXSW_REG_SBXX_DIR_EGRESS, 2},
85
+ {MLXSW_REG_SBXX_DIR_EGRESS, 3},
86
+ {MLXSW_REG_SBXX_DIR_EGRESS, 15},
87
+ {MLXSW_REG_SBXX_DIR_INGRESS, 4},
88
+ {MLXSW_REG_SBXX_DIR_EGRESS, 4},
89
+};
90
+
91
+#define MLXSW_SP_SB_ING_TC_COUNT 8
92
+#define MLXSW_SP_SB_EG_TC_COUNT 16
4093
4194 struct mlxsw_sp_sb_port {
42
- struct mlxsw_sp_sb_cm cms[2][MLXSW_SP_SB_TC_COUNT];
43
- struct mlxsw_sp_sb_pm pms[2][MLXSW_SP_SB_POOL_COUNT];
95
+ struct mlxsw_sp_sb_cm ing_cms[MLXSW_SP_SB_ING_TC_COUNT];
96
+ struct mlxsw_sp_sb_cm eg_cms[MLXSW_SP_SB_EG_TC_COUNT];
97
+ struct mlxsw_sp_sb_pm *pms;
4498 };
4599
46100 struct mlxsw_sp_sb {
47
- struct mlxsw_sp_sb_pr prs[2][MLXSW_SP_SB_POOL_COUNT];
101
+ struct mlxsw_sp_sb_pr *prs;
48102 struct mlxsw_sp_sb_port *ports;
49103 u32 cell_size;
104
+ u32 max_headroom_cells;
105
+ u64 sb_size;
106
+};
107
+
108
+struct mlxsw_sp_sb_vals {
109
+ unsigned int pool_count;
110
+ const struct mlxsw_sp_sb_pool_des *pool_dess;
111
+ const struct mlxsw_sp_sb_pm *pms;
112
+ const struct mlxsw_sp_sb_pm *pms_cpu;
113
+ const struct mlxsw_sp_sb_pr *prs;
114
+ const struct mlxsw_sp_sb_mm *mms;
115
+ const struct mlxsw_sp_sb_cm *cms_ingress;
116
+ const struct mlxsw_sp_sb_cm *cms_egress;
117
+ const struct mlxsw_sp_sb_cm *cms_cpu;
118
+ unsigned int mms_count;
119
+ unsigned int cms_ingress_count;
120
+ unsigned int cms_egress_count;
121
+ unsigned int cms_cpu_count;
122
+};
123
+
124
+struct mlxsw_sp_sb_ops {
125
+ u32 (*int_buf_size_get)(int mtu, u32 speed);
50126 };
51127
52128 u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells)
....@@ -59,96 +135,137 @@
59135 return DIV_ROUND_UP(bytes, mlxsw_sp->sb->cell_size);
60136 }
61137
62
-static struct mlxsw_sp_sb_pr *mlxsw_sp_sb_pr_get(struct mlxsw_sp *mlxsw_sp,
63
- u8 pool,
64
- enum mlxsw_reg_sbxx_dir dir)
138
+static u32 mlxsw_sp_port_headroom_8x_adjust(const struct mlxsw_sp_port *mlxsw_sp_port,
139
+ u32 size_cells)
65140 {
66
- return &mlxsw_sp->sb->prs[dir][pool];
141
+ /* Ports with eight lanes use two headroom buffers between which the
142
+ * configured headroom size is split. Therefore, multiply the calculated
143
+ * headroom size by two.
144
+ */
145
+ return mlxsw_sp_port->mapping.width == 8 ? 2 * size_cells : size_cells;
146
+}
147
+
148
+static struct mlxsw_sp_sb_pr *mlxsw_sp_sb_pr_get(struct mlxsw_sp *mlxsw_sp,
149
+ u16 pool_index)
150
+{
151
+ return &mlxsw_sp->sb->prs[pool_index];
152
+}
153
+
154
+static bool mlxsw_sp_sb_cm_exists(u8 pg_buff, enum mlxsw_reg_sbxx_dir dir)
155
+{
156
+ if (dir == MLXSW_REG_SBXX_DIR_INGRESS)
157
+ return pg_buff < MLXSW_SP_SB_ING_TC_COUNT;
158
+ else
159
+ return pg_buff < MLXSW_SP_SB_EG_TC_COUNT;
67160 }
68161
69162 static struct mlxsw_sp_sb_cm *mlxsw_sp_sb_cm_get(struct mlxsw_sp *mlxsw_sp,
70163 u8 local_port, u8 pg_buff,
71164 enum mlxsw_reg_sbxx_dir dir)
72165 {
73
- return &mlxsw_sp->sb->ports[local_port].cms[dir][pg_buff];
166
+ struct mlxsw_sp_sb_port *sb_port = &mlxsw_sp->sb->ports[local_port];
167
+
168
+ WARN_ON(!mlxsw_sp_sb_cm_exists(pg_buff, dir));
169
+ if (dir == MLXSW_REG_SBXX_DIR_INGRESS)
170
+ return &sb_port->ing_cms[pg_buff];
171
+ else
172
+ return &sb_port->eg_cms[pg_buff];
74173 }
75174
76175 static struct mlxsw_sp_sb_pm *mlxsw_sp_sb_pm_get(struct mlxsw_sp *mlxsw_sp,
77
- u8 local_port, u8 pool,
78
- enum mlxsw_reg_sbxx_dir dir)
176
+ u8 local_port, u16 pool_index)
79177 {
80
- return &mlxsw_sp->sb->ports[local_port].pms[dir][pool];
178
+ return &mlxsw_sp->sb->ports[local_port].pms[pool_index];
81179 }
82180
83
-static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u8 pool,
84
- enum mlxsw_reg_sbxx_dir dir,
85
- enum mlxsw_reg_sbpr_mode mode, u32 size)
181
+static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u16 pool_index,
182
+ enum mlxsw_reg_sbpr_mode mode,
183
+ u32 size, bool infi_size)
86184 {
185
+ const struct mlxsw_sp_sb_pool_des *des =
186
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
87187 char sbpr_pl[MLXSW_REG_SBPR_LEN];
88188 struct mlxsw_sp_sb_pr *pr;
89189 int err;
90190
91
- mlxsw_reg_sbpr_pack(sbpr_pl, pool, dir, mode, size);
191
+ mlxsw_reg_sbpr_pack(sbpr_pl, des->pool, des->dir, mode,
192
+ size, infi_size);
92193 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl);
93194 if (err)
94195 return err;
95196
96
- pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir);
197
+ if (infi_size)
198
+ size = mlxsw_sp_bytes_cells(mlxsw_sp, mlxsw_sp->sb->sb_size);
199
+ pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool_index);
97200 pr->mode = mode;
98201 pr->size = size;
99202 return 0;
100203 }
101204
102205 static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
103
- u8 pg_buff, enum mlxsw_reg_sbxx_dir dir,
104
- u32 min_buff, u32 max_buff, u8 pool)
206
+ u8 pg_buff, u32 min_buff, u32 max_buff,
207
+ bool infi_max, u16 pool_index)
105208 {
209
+ const struct mlxsw_sp_sb_pool_des *des =
210
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
106211 char sbcm_pl[MLXSW_REG_SBCM_LEN];
212
+ struct mlxsw_sp_sb_cm *cm;
107213 int err;
108214
109
- mlxsw_reg_sbcm_pack(sbcm_pl, local_port, pg_buff, dir,
110
- min_buff, max_buff, pool);
215
+ mlxsw_reg_sbcm_pack(sbcm_pl, local_port, pg_buff, des->dir,
216
+ min_buff, max_buff, infi_max, des->pool);
111217 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl);
112218 if (err)
113219 return err;
114
- if (pg_buff < MLXSW_SP_SB_TC_COUNT) {
115
- struct mlxsw_sp_sb_cm *cm;
116220
117
- cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, pg_buff, dir);
221
+ if (mlxsw_sp_sb_cm_exists(pg_buff, des->dir)) {
222
+ if (infi_max)
223
+ max_buff = mlxsw_sp_bytes_cells(mlxsw_sp,
224
+ mlxsw_sp->sb->sb_size);
225
+
226
+ cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, pg_buff,
227
+ des->dir);
118228 cm->min_buff = min_buff;
119229 cm->max_buff = max_buff;
120
- cm->pool = pool;
230
+ cm->pool_index = pool_index;
121231 }
122232 return 0;
123233 }
124234
125235 static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port,
126
- u8 pool, enum mlxsw_reg_sbxx_dir dir,
127
- u32 min_buff, u32 max_buff)
236
+ u16 pool_index, u32 min_buff, u32 max_buff)
128237 {
238
+ const struct mlxsw_sp_sb_pool_des *des =
239
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
129240 char sbpm_pl[MLXSW_REG_SBPM_LEN];
130241 struct mlxsw_sp_sb_pm *pm;
131242 int err;
132243
133
- mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, false,
244
+ mlxsw_reg_sbpm_pack(sbpm_pl, local_port, des->pool, des->dir, false,
134245 min_buff, max_buff);
135246 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl);
136247 if (err)
137248 return err;
138249
139
- pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool, dir);
250
+ pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool_index);
140251 pm->min_buff = min_buff;
141252 pm->max_buff = max_buff;
142253 return 0;
143254 }
144255
145256 static int mlxsw_sp_sb_pm_occ_clear(struct mlxsw_sp *mlxsw_sp, u8 local_port,
146
- u8 pool, enum mlxsw_reg_sbxx_dir dir,
147
- struct list_head *bulk_list)
257
+ u16 pool_index, struct list_head *bulk_list)
148258 {
259
+ const struct mlxsw_sp_sb_pool_des *des =
260
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
149261 char sbpm_pl[MLXSW_REG_SBPM_LEN];
150262
151
- mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, true, 0, 0);
263
+ if (local_port == MLXSW_PORT_CPU_PORT &&
264
+ des->dir == MLXSW_REG_SBXX_DIR_INGRESS)
265
+ return 0;
266
+
267
+ mlxsw_reg_sbpm_pack(sbpm_pl, local_port, des->pool, des->dir,
268
+ true, 0, 0);
152269 return mlxsw_reg_trans_query(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl,
153270 bulk_list, NULL, 0);
154271 }
....@@ -163,90 +280,396 @@
163280 }
164281
165282 static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port,
166
- u8 pool, enum mlxsw_reg_sbxx_dir dir,
167
- struct list_head *bulk_list)
283
+ u16 pool_index, struct list_head *bulk_list)
168284 {
285
+ const struct mlxsw_sp_sb_pool_des *des =
286
+ &mlxsw_sp->sb_vals->pool_dess[pool_index];
169287 char sbpm_pl[MLXSW_REG_SBPM_LEN];
170288 struct mlxsw_sp_sb_pm *pm;
171289
172
- pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool, dir);
173
- mlxsw_reg_sbpm_pack(sbpm_pl, local_port, pool, dir, false, 0, 0);
290
+ if (local_port == MLXSW_PORT_CPU_PORT &&
291
+ des->dir == MLXSW_REG_SBXX_DIR_INGRESS)
292
+ return 0;
293
+
294
+ pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port, pool_index);
295
+ mlxsw_reg_sbpm_pack(sbpm_pl, local_port, des->pool, des->dir,
296
+ false, 0, 0);
174297 return mlxsw_reg_trans_query(mlxsw_sp->core, MLXSW_REG(sbpm), sbpm_pl,
175298 bulk_list,
176299 mlxsw_sp_sb_pm_occ_query_cb,
177300 (unsigned long) pm);
178301 }
179302
180
-static const u16 mlxsw_sp_pbs[] = {
181
- [0] = 2 * ETH_FRAME_LEN,
182
- [9] = 2 * MLXSW_PORT_MAX_MTU,
183
-};
303
+void mlxsw_sp_hdroom_prios_reset_buf_idx(struct mlxsw_sp_hdroom *hdroom)
304
+{
305
+ int prio;
184306
185
-#define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs)
307
+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
308
+ switch (hdroom->mode) {
309
+ case MLXSW_SP_HDROOM_MODE_DCB:
310
+ hdroom->prios.prio[prio].buf_idx = hdroom->prios.prio[prio].ets_buf_idx;
311
+ break;
312
+ case MLXSW_SP_HDROOM_MODE_TC:
313
+ hdroom->prios.prio[prio].buf_idx = hdroom->prios.prio[prio].set_buf_idx;
314
+ break;
315
+ }
316
+ }
317
+}
318
+
319
+void mlxsw_sp_hdroom_bufs_reset_lossiness(struct mlxsw_sp_hdroom *hdroom)
320
+{
321
+ int prio;
322
+ int i;
323
+
324
+ for (i = 0; i < DCBX_MAX_BUFFERS; i++)
325
+ hdroom->bufs.buf[i].lossy = true;
326
+
327
+ for (prio = 0; prio < IEEE_8021Q_MAX_PRIORITIES; prio++) {
328
+ if (!hdroom->prios.prio[prio].lossy)
329
+ hdroom->bufs.buf[hdroom->prios.prio[prio].buf_idx].lossy = false;
330
+ }
331
+}
332
+
333
+static u16 mlxsw_sp_hdroom_buf_threshold_get(const struct mlxsw_sp *mlxsw_sp, int mtu)
334
+{
335
+ return 2 * mlxsw_sp_bytes_cells(mlxsw_sp, mtu);
336
+}
337
+
338
+static void mlxsw_sp_hdroom_buf_pack(char *pbmc_pl, int index, u16 size, u16 thres, bool lossy)
339
+{
340
+ if (lossy)
341
+ mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, index, size);
342
+ else
343
+ mlxsw_reg_pbmc_lossless_buffer_pack(pbmc_pl, index, size,
344
+ thres);
345
+}
346
+
347
+static u16 mlxsw_sp_hdroom_buf_delay_get(const struct mlxsw_sp *mlxsw_sp,
348
+ const struct mlxsw_sp_hdroom *hdroom)
349
+{
350
+ u16 delay_cells;
351
+
352
+ delay_cells = mlxsw_sp_bytes_cells(mlxsw_sp, hdroom->delay_bytes);
353
+
354
+ /* In the worst case scenario the delay will be made up of packets that
355
+ * are all of size CELL_SIZE + 1, which means each packet will require
356
+ * almost twice its true size when buffered in the switch. We therefore
357
+ * multiply this value by the "cell factor", which is close to 2.
358
+ *
359
+ * Another MTU is added in case the transmitting host already started
360
+ * transmitting a maximum length frame when the PFC packet was received.
361
+ */
362
+ return 2 * delay_cells + mlxsw_sp_bytes_cells(mlxsw_sp, hdroom->mtu);
363
+}
364
+
365
+static u32 mlxsw_sp_hdroom_int_buf_size_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed)
366
+{
367
+ u32 buffsize = mlxsw_sp->sb_ops->int_buf_size_get(speed, mtu);
368
+
369
+ return mlxsw_sp_bytes_cells(mlxsw_sp, buffsize) + 1;
370
+}
371
+
372
+static bool mlxsw_sp_hdroom_buf_is_used(const struct mlxsw_sp_hdroom *hdroom, int buf)
373
+{
374
+ int prio;
375
+
376
+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
377
+ if (hdroom->prios.prio[prio].buf_idx == buf)
378
+ return true;
379
+ }
380
+ return false;
381
+}
382
+
383
+void mlxsw_sp_hdroom_bufs_reset_sizes(struct mlxsw_sp_port *mlxsw_sp_port,
384
+ struct mlxsw_sp_hdroom *hdroom)
385
+{
386
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
387
+ u16 reserve_cells;
388
+ int i;
389
+
390
+ /* Internal buffer. */
391
+ reserve_cells = mlxsw_sp_hdroom_int_buf_size_get(mlxsw_sp, mlxsw_sp_port->max_speed,
392
+ mlxsw_sp_port->max_mtu);
393
+ reserve_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, reserve_cells);
394
+ hdroom->int_buf.reserve_cells = reserve_cells;
395
+
396
+ if (hdroom->int_buf.enable)
397
+ hdroom->int_buf.size_cells = reserve_cells;
398
+ else
399
+ hdroom->int_buf.size_cells = 0;
400
+
401
+ /* PG buffers. */
402
+ for (i = 0; i < DCBX_MAX_BUFFERS; i++) {
403
+ struct mlxsw_sp_hdroom_buf *buf = &hdroom->bufs.buf[i];
404
+ u16 thres_cells;
405
+ u16 delay_cells;
406
+
407
+ if (!mlxsw_sp_hdroom_buf_is_used(hdroom, i)) {
408
+ thres_cells = 0;
409
+ delay_cells = 0;
410
+ } else if (buf->lossy) {
411
+ thres_cells = mlxsw_sp_hdroom_buf_threshold_get(mlxsw_sp, hdroom->mtu);
412
+ delay_cells = 0;
413
+ } else {
414
+ thres_cells = mlxsw_sp_hdroom_buf_threshold_get(mlxsw_sp, hdroom->mtu);
415
+ delay_cells = mlxsw_sp_hdroom_buf_delay_get(mlxsw_sp, hdroom);
416
+ }
417
+
418
+ thres_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, thres_cells);
419
+ delay_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, delay_cells);
420
+
421
+ buf->thres_cells = thres_cells;
422
+ if (hdroom->mode == MLXSW_SP_HDROOM_MODE_DCB) {
423
+ buf->size_cells = thres_cells + delay_cells;
424
+ } else {
425
+ /* Do not allow going below the minimum size, even if
426
+ * the user requested it.
427
+ */
428
+ buf->size_cells = max(buf->set_size_cells, buf->thres_cells);
429
+ }
430
+ }
431
+}
432
+
186433 #define MLXSW_SP_PB_UNUSED 8
187434
188
-static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port)
435
+static int mlxsw_sp_hdroom_configure_buffers(struct mlxsw_sp_port *mlxsw_sp_port,
436
+ const struct mlxsw_sp_hdroom *hdroom, bool force)
189437 {
190438 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
191439 char pbmc_pl[MLXSW_REG_PBMC_LEN];
440
+ bool dirty;
441
+ int err;
192442 int i;
193443
194
- mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port,
195
- 0xffff, 0xffff / 2);
196
- for (i = 0; i < MLXSW_SP_PBS_LEN; i++) {
197
- u16 size = mlxsw_sp_bytes_cells(mlxsw_sp, mlxsw_sp_pbs[i]);
444
+ dirty = memcmp(&mlxsw_sp_port->hdroom->bufs, &hdroom->bufs, sizeof(hdroom->bufs));
445
+ if (!dirty && !force)
446
+ return 0;
447
+
448
+ mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0xffff, 0xffff / 2);
449
+ for (i = 0; i < MLXSW_SP_PB_COUNT; i++) {
450
+ const struct mlxsw_sp_hdroom_buf *buf = &hdroom->bufs.buf[i];
198451
199452 if (i == MLXSW_SP_PB_UNUSED)
200453 continue;
201
- mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, i, size);
454
+
455
+ mlxsw_sp_hdroom_buf_pack(pbmc_pl, i, buf->size_cells, buf->thres_cells, buf->lossy);
202456 }
203
- mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl,
204
- MLXSW_REG_PBMC_PORT_SHARED_BUF_IDX, 0);
205
- return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
457
+
458
+ mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, MLXSW_REG_PBMC_PORT_SHARED_BUF_IDX, 0);
459
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
460
+ if (err)
461
+ return err;
462
+
463
+ mlxsw_sp_port->hdroom->bufs = hdroom->bufs;
464
+ return 0;
206465 }
207466
208
-static int mlxsw_sp_port_pb_prio_init(struct mlxsw_sp_port *mlxsw_sp_port)
467
+static int mlxsw_sp_hdroom_configure_priomap(struct mlxsw_sp_port *mlxsw_sp_port,
468
+ const struct mlxsw_sp_hdroom *hdroom, bool force)
209469 {
210470 char pptb_pl[MLXSW_REG_PPTB_LEN];
211
- int i;
471
+ bool dirty;
472
+ int prio;
473
+ int err;
474
+
475
+ dirty = memcmp(&mlxsw_sp_port->hdroom->prios, &hdroom->prios, sizeof(hdroom->prios));
476
+ if (!dirty && !force)
477
+ return 0;
212478
213479 mlxsw_reg_pptb_pack(pptb_pl, mlxsw_sp_port->local_port);
214
- for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
215
- mlxsw_reg_pptb_prio_to_buff_pack(pptb_pl, i, 0);
216
- return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pptb),
217
- pptb_pl);
480
+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
481
+ mlxsw_reg_pptb_prio_to_buff_pack(pptb_pl, prio, hdroom->prios.prio[prio].buf_idx);
482
+
483
+ err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pptb), pptb_pl);
484
+ if (err)
485
+ return err;
486
+
487
+ mlxsw_sp_port->hdroom->prios = hdroom->prios;
488
+ return 0;
489
+}
490
+
491
+static int mlxsw_sp_hdroom_configure_int_buf(struct mlxsw_sp_port *mlxsw_sp_port,
492
+ const struct mlxsw_sp_hdroom *hdroom, bool force)
493
+{
494
+ char sbib_pl[MLXSW_REG_SBIB_LEN];
495
+ bool dirty;
496
+ int err;
497
+
498
+ dirty = memcmp(&mlxsw_sp_port->hdroom->int_buf, &hdroom->int_buf, sizeof(hdroom->int_buf));
499
+ if (!dirty && !force)
500
+ return 0;
501
+
502
+ mlxsw_reg_sbib_pack(sbib_pl, mlxsw_sp_port->local_port, hdroom->int_buf.size_cells);
503
+ err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(sbib), sbib_pl);
504
+ if (err)
505
+ return err;
506
+
507
+ mlxsw_sp_port->hdroom->int_buf = hdroom->int_buf;
508
+ return 0;
509
+}
510
+
511
+static bool mlxsw_sp_hdroom_bufs_fit(struct mlxsw_sp *mlxsw_sp,
512
+ const struct mlxsw_sp_hdroom *hdroom)
513
+{
514
+ u32 taken_headroom_cells = 0;
515
+ int i;
516
+
517
+ for (i = 0; i < MLXSW_SP_PB_COUNT; i++)
518
+ taken_headroom_cells += hdroom->bufs.buf[i].size_cells;
519
+
520
+ taken_headroom_cells += hdroom->int_buf.reserve_cells;
521
+ return taken_headroom_cells <= mlxsw_sp->sb->max_headroom_cells;
522
+}
523
+
524
+static int __mlxsw_sp_hdroom_configure(struct mlxsw_sp_port *mlxsw_sp_port,
525
+ const struct mlxsw_sp_hdroom *hdroom, bool force)
526
+{
527
+ struct mlxsw_sp_hdroom orig_hdroom;
528
+ struct mlxsw_sp_hdroom tmp_hdroom;
529
+ int err;
530
+ int i;
531
+
532
+ /* Port buffers need to be configured in three steps. First, all buffers
533
+ * with non-zero size are configured. Then, prio-to-buffer map is
534
+ * updated, allowing traffic to flow to the now non-zero buffers.
535
+ * Finally, zero-sized buffers are configured, because now no traffic
536
+ * should be directed to them anymore. This way, in a non-congested
537
+ * system, no packet drops are introduced by the reconfiguration.
538
+ */
539
+
540
+ orig_hdroom = *mlxsw_sp_port->hdroom;
541
+ tmp_hdroom = orig_hdroom;
542
+ for (i = 0; i < MLXSW_SP_PB_COUNT; i++) {
543
+ if (hdroom->bufs.buf[i].size_cells)
544
+ tmp_hdroom.bufs.buf[i] = hdroom->bufs.buf[i];
545
+ }
546
+
547
+ if (!mlxsw_sp_hdroom_bufs_fit(mlxsw_sp_port->mlxsw_sp, &tmp_hdroom) ||
548
+ !mlxsw_sp_hdroom_bufs_fit(mlxsw_sp_port->mlxsw_sp, hdroom))
549
+ return -ENOBUFS;
550
+
551
+ err = mlxsw_sp_hdroom_configure_buffers(mlxsw_sp_port, &tmp_hdroom, force);
552
+ if (err)
553
+ return err;
554
+
555
+ err = mlxsw_sp_hdroom_configure_priomap(mlxsw_sp_port, hdroom, force);
556
+ if (err)
557
+ goto err_configure_priomap;
558
+
559
+ err = mlxsw_sp_hdroom_configure_buffers(mlxsw_sp_port, hdroom, false);
560
+ if (err)
561
+ goto err_configure_buffers;
562
+
563
+ err = mlxsw_sp_hdroom_configure_int_buf(mlxsw_sp_port, hdroom, false);
564
+ if (err)
565
+ goto err_configure_int_buf;
566
+
567
+ *mlxsw_sp_port->hdroom = *hdroom;
568
+ return 0;
569
+
570
+err_configure_int_buf:
571
+ mlxsw_sp_hdroom_configure_buffers(mlxsw_sp_port, &tmp_hdroom, false);
572
+err_configure_buffers:
573
+ mlxsw_sp_hdroom_configure_priomap(mlxsw_sp_port, &tmp_hdroom, false);
574
+err_configure_priomap:
575
+ mlxsw_sp_hdroom_configure_buffers(mlxsw_sp_port, &orig_hdroom, false);
576
+ return err;
577
+}
578
+
579
+int mlxsw_sp_hdroom_configure(struct mlxsw_sp_port *mlxsw_sp_port,
580
+ const struct mlxsw_sp_hdroom *hdroom)
581
+{
582
+ return __mlxsw_sp_hdroom_configure(mlxsw_sp_port, hdroom, false);
218583 }
219584
220585 static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port)
221586 {
222
- int err;
587
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
588
+ struct mlxsw_sp_hdroom hdroom = {};
589
+ u32 size9;
590
+ int prio;
223591
224
- err = mlxsw_sp_port_pb_init(mlxsw_sp_port);
225
- if (err)
226
- return err;
227
- return mlxsw_sp_port_pb_prio_init(mlxsw_sp_port);
592
+ hdroom.mtu = mlxsw_sp_port->dev->mtu;
593
+ hdroom.mode = MLXSW_SP_HDROOM_MODE_DCB;
594
+ for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
595
+ hdroom.prios.prio[prio].lossy = true;
596
+
597
+ mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom);
598
+ mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom);
599
+
600
+ /* Buffer 9 is used for control traffic. */
601
+ size9 = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, mlxsw_sp_port->max_mtu);
602
+ hdroom.bufs.buf[9].size_cells = mlxsw_sp_bytes_cells(mlxsw_sp, size9);
603
+
604
+ return __mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom, true);
605
+}
606
+
607
+static int mlxsw_sp_sb_port_init(struct mlxsw_sp *mlxsw_sp,
608
+ struct mlxsw_sp_sb_port *sb_port)
609
+{
610
+ struct mlxsw_sp_sb_pm *pms;
611
+
612
+ pms = kcalloc(mlxsw_sp->sb_vals->pool_count, sizeof(*pms),
613
+ GFP_KERNEL);
614
+ if (!pms)
615
+ return -ENOMEM;
616
+ sb_port->pms = pms;
617
+ return 0;
618
+}
619
+
620
+static void mlxsw_sp_sb_port_fini(struct mlxsw_sp_sb_port *sb_port)
621
+{
622
+ kfree(sb_port->pms);
228623 }
229624
230625 static int mlxsw_sp_sb_ports_init(struct mlxsw_sp *mlxsw_sp)
231626 {
232627 unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
628
+ struct mlxsw_sp_sb_pr *prs;
629
+ int i;
630
+ int err;
233631
234632 mlxsw_sp->sb->ports = kcalloc(max_ports,
235633 sizeof(struct mlxsw_sp_sb_port),
236634 GFP_KERNEL);
237635 if (!mlxsw_sp->sb->ports)
238636 return -ENOMEM;
637
+
638
+ prs = kcalloc(mlxsw_sp->sb_vals->pool_count, sizeof(*prs),
639
+ GFP_KERNEL);
640
+ if (!prs) {
641
+ err = -ENOMEM;
642
+ goto err_alloc_prs;
643
+ }
644
+ mlxsw_sp->sb->prs = prs;
645
+
646
+ for (i = 0; i < max_ports; i++) {
647
+ err = mlxsw_sp_sb_port_init(mlxsw_sp, &mlxsw_sp->sb->ports[i]);
648
+ if (err)
649
+ goto err_sb_port_init;
650
+ }
651
+
239652 return 0;
653
+
654
+err_sb_port_init:
655
+ for (i--; i >= 0; i--)
656
+ mlxsw_sp_sb_port_fini(&mlxsw_sp->sb->ports[i]);
657
+ kfree(mlxsw_sp->sb->prs);
658
+err_alloc_prs:
659
+ kfree(mlxsw_sp->sb->ports);
660
+ return err;
240661 }
241662
242663 static void mlxsw_sp_sb_ports_fini(struct mlxsw_sp *mlxsw_sp)
243664 {
665
+ int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
666
+ int i;
667
+
668
+ for (i = max_ports - 1; i >= 0; i--)
669
+ mlxsw_sp_sb_port_fini(&mlxsw_sp->sb->ports[i]);
670
+ kfree(mlxsw_sp->sb->prs);
244671 kfree(mlxsw_sp->sb->ports);
245672 }
246
-
247
-#define MLXSW_SP_SB_PR_INGRESS_SIZE 12440000
248
-#define MLXSW_SP_SB_PR_INGRESS_MNG_SIZE (200 * 1000)
249
-#define MLXSW_SP_SB_PR_EGRESS_SIZE 13232000
250673
251674 #define MLXSW_SP_SB_PR(_mode, _size) \
252675 { \
....@@ -254,113 +677,214 @@
254677 .size = _size, \
255678 }
256679
257
-static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs_ingress[] = {
258
- MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
259
- MLXSW_SP_SB_PR_INGRESS_SIZE),
680
+#define MLXSW_SP_SB_PR_EXT(_mode, _size, _freeze_mode, _freeze_size) \
681
+ { \
682
+ .mode = _mode, \
683
+ .size = _size, \
684
+ .freeze_mode = _freeze_mode, \
685
+ .freeze_size = _freeze_size, \
686
+ }
687
+
688
+#define MLXSW_SP1_SB_PR_CPU_SIZE (256 * 1000)
689
+
690
+/* Order according to mlxsw_sp1_sb_pool_dess */
691
+static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = {
692
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, MLXSW_SP_SB_REST),
260693 MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
261694 MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
262
- MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC,
263
- MLXSW_SP_SB_PR_INGRESS_MNG_SIZE),
695
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
696
+ MLXSW_SP_SB_PR_EXT(MLXSW_REG_SBPR_MODE_DYNAMIC, MLXSW_SP_SB_REST,
697
+ true, false),
698
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
699
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
700
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
701
+ MLXSW_SP_SB_PR_EXT(MLXSW_REG_SBPR_MODE_STATIC, MLXSW_SP_SB_INFI,
702
+ true, true),
703
+ MLXSW_SP_SB_PR_EXT(MLXSW_REG_SBPR_MODE_DYNAMIC,
704
+ MLXSW_SP1_SB_PR_CPU_SIZE, true, false),
705
+ MLXSW_SP_SB_PR_EXT(MLXSW_REG_SBPR_MODE_DYNAMIC,
706
+ MLXSW_SP1_SB_PR_CPU_SIZE, true, false),
264707 };
265708
266
-#define MLXSW_SP_SB_PRS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs_ingress)
709
+#define MLXSW_SP2_SB_PR_CPU_SIZE (256 * 1000)
267710
268
-static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs_egress[] = {
269
- MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, MLXSW_SP_SB_PR_EGRESS_SIZE),
270
- MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
271
- MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
272
- MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0),
711
+/* Order according to mlxsw_sp2_sb_pool_dess */
712
+static const struct mlxsw_sp_sb_pr mlxsw_sp2_sb_prs[] = {
713
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, MLXSW_SP_SB_REST),
714
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
715
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
716
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
717
+ MLXSW_SP_SB_PR_EXT(MLXSW_REG_SBPR_MODE_DYNAMIC, MLXSW_SP_SB_REST,
718
+ true, false),
719
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
720
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
721
+ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0),
722
+ MLXSW_SP_SB_PR_EXT(MLXSW_REG_SBPR_MODE_STATIC, MLXSW_SP_SB_INFI,
723
+ true, true),
724
+ MLXSW_SP_SB_PR_EXT(MLXSW_REG_SBPR_MODE_DYNAMIC,
725
+ MLXSW_SP2_SB_PR_CPU_SIZE, true, false),
726
+ MLXSW_SP_SB_PR_EXT(MLXSW_REG_SBPR_MODE_DYNAMIC,
727
+ MLXSW_SP2_SB_PR_CPU_SIZE, true, false),
273728 };
274729
275
-#define MLXSW_SP_SB_PRS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs_egress)
276
-
277
-static int __mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp,
278
- enum mlxsw_reg_sbxx_dir dir,
279
- const struct mlxsw_sp_sb_pr *prs,
280
- size_t prs_len)
730
+static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp,
731
+ const struct mlxsw_sp_sb_pr *prs,
732
+ const struct mlxsw_sp_sb_pool_des *pool_dess,
733
+ size_t prs_len)
281734 {
735
+ /* Round down, unlike mlxsw_sp_bytes_cells(). */
736
+ u32 sb_cells = div_u64(mlxsw_sp->sb->sb_size, mlxsw_sp->sb->cell_size);
737
+ u32 rest_cells[2] = {sb_cells, sb_cells};
282738 int i;
283739 int err;
284740
741
+ /* Calculate how much space to give to the "REST" pools in either
742
+ * direction.
743
+ */
285744 for (i = 0; i < prs_len; i++) {
286
- u32 size = mlxsw_sp_bytes_cells(mlxsw_sp, prs[i].size);
745
+ enum mlxsw_reg_sbxx_dir dir = pool_dess[i].dir;
746
+ u32 size = prs[i].size;
747
+ u32 size_cells;
287748
288
- err = mlxsw_sp_sb_pr_write(mlxsw_sp, i, dir, prs[i].mode, size);
749
+ if (size == MLXSW_SP_SB_INFI || size == MLXSW_SP_SB_REST)
750
+ continue;
751
+
752
+ size_cells = mlxsw_sp_bytes_cells(mlxsw_sp, size);
753
+ if (WARN_ON_ONCE(size_cells > rest_cells[dir]))
754
+ continue;
755
+
756
+ rest_cells[dir] -= size_cells;
757
+ }
758
+
759
+ for (i = 0; i < prs_len; i++) {
760
+ u32 size = prs[i].size;
761
+ u32 size_cells;
762
+
763
+ if (size == MLXSW_SP_SB_INFI) {
764
+ err = mlxsw_sp_sb_pr_write(mlxsw_sp, i, prs[i].mode,
765
+ 0, true);
766
+ } else if (size == MLXSW_SP_SB_REST) {
767
+ size_cells = rest_cells[pool_dess[i].dir];
768
+ err = mlxsw_sp_sb_pr_write(mlxsw_sp, i, prs[i].mode,
769
+ size_cells, false);
770
+ } else {
771
+ size_cells = mlxsw_sp_bytes_cells(mlxsw_sp, size);
772
+ err = mlxsw_sp_sb_pr_write(mlxsw_sp, i, prs[i].mode,
773
+ size_cells, false);
774
+ }
289775 if (err)
290776 return err;
291777 }
292778 return 0;
293779 }
294780
295
-static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp)
296
-{
297
- int err;
298
-
299
- err = __mlxsw_sp_sb_prs_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_INGRESS,
300
- mlxsw_sp_sb_prs_ingress,
301
- MLXSW_SP_SB_PRS_INGRESS_LEN);
302
- if (err)
303
- return err;
304
- return __mlxsw_sp_sb_prs_init(mlxsw_sp, MLXSW_REG_SBXX_DIR_EGRESS,
305
- mlxsw_sp_sb_prs_egress,
306
- MLXSW_SP_SB_PRS_EGRESS_LEN);
307
-}
308
-
309781 #define MLXSW_SP_SB_CM(_min_buff, _max_buff, _pool) \
310782 { \
311783 .min_buff = _min_buff, \
312784 .max_buff = _max_buff, \
313
- .pool = _pool, \
785
+ .pool_index = _pool, \
314786 }
315787
316
-static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = {
317
- MLXSW_SP_SB_CM(10000, 8, 0),
318
- MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
319
- MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
320
- MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
321
- MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
322
- MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
323
- MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
324
- MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0),
325
- MLXSW_SP_SB_CM(0, 0, 0), /* dummy, this PG does not exist */
326
- MLXSW_SP_SB_CM(20000, 1, 3),
788
+#define MLXSW_SP_SB_CM_ING(_min_buff, _max_buff) \
789
+ { \
790
+ .min_buff = _min_buff, \
791
+ .max_buff = _max_buff, \
792
+ .pool_index = MLXSW_SP_SB_POOL_ING, \
793
+ }
794
+
795
+#define MLXSW_SP_SB_CM_EGR(_min_buff, _max_buff) \
796
+ { \
797
+ .min_buff = _min_buff, \
798
+ .max_buff = _max_buff, \
799
+ .pool_index = MLXSW_SP_SB_POOL_EGR, \
800
+ }
801
+
802
+#define MLXSW_SP_SB_CM_EGR_MC(_min_buff, _max_buff) \
803
+ { \
804
+ .min_buff = _min_buff, \
805
+ .max_buff = _max_buff, \
806
+ .pool_index = MLXSW_SP_SB_POOL_EGR_MC, \
807
+ .freeze_pool = true, \
808
+ .freeze_thresh = true, \
809
+ }
810
+
811
+static const struct mlxsw_sp_sb_cm mlxsw_sp1_sb_cms_ingress[] = {
812
+ MLXSW_SP_SB_CM_ING(10000, 8),
813
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
814
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
815
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
816
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
817
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
818
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
819
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
820
+ MLXSW_SP_SB_CM_ING(0, 0), /* dummy, this PG does not exist */
821
+ MLXSW_SP_SB_CM(10000, 8, MLXSW_SP_SB_POOL_ING_CPU),
327822 };
328823
329
-#define MLXSW_SP_SB_CMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_ingress)
330
-
331
-static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = {
332
- MLXSW_SP_SB_CM(1500, 9, 0),
333
- MLXSW_SP_SB_CM(1500, 9, 0),
334
- MLXSW_SP_SB_CM(1500, 9, 0),
335
- MLXSW_SP_SB_CM(1500, 9, 0),
336
- MLXSW_SP_SB_CM(1500, 9, 0),
337
- MLXSW_SP_SB_CM(1500, 9, 0),
338
- MLXSW_SP_SB_CM(1500, 9, 0),
339
- MLXSW_SP_SB_CM(1500, 9, 0),
340
- MLXSW_SP_SB_CM(0, 140000, 15),
341
- MLXSW_SP_SB_CM(0, 140000, 15),
342
- MLXSW_SP_SB_CM(0, 140000, 15),
343
- MLXSW_SP_SB_CM(0, 140000, 15),
344
- MLXSW_SP_SB_CM(0, 140000, 15),
345
- MLXSW_SP_SB_CM(0, 140000, 15),
346
- MLXSW_SP_SB_CM(0, 140000, 15),
347
- MLXSW_SP_SB_CM(0, 140000, 15),
348
- MLXSW_SP_SB_CM(1, 0xff, 0),
824
+static const struct mlxsw_sp_sb_cm mlxsw_sp2_sb_cms_ingress[] = {
825
+ MLXSW_SP_SB_CM_ING(0, 7),
826
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
827
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
828
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
829
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
830
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
831
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
832
+ MLXSW_SP_SB_CM_ING(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
833
+ MLXSW_SP_SB_CM_ING(0, 0), /* dummy, this PG does not exist */
834
+ MLXSW_SP_SB_CM(10000, 8, MLXSW_SP_SB_POOL_ING_CPU),
349835 };
350836
351
-#define MLXSW_SP_SB_CMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_egress)
837
+static const struct mlxsw_sp_sb_cm mlxsw_sp1_sb_cms_egress[] = {
838
+ MLXSW_SP_SB_CM_EGR(1500, 9),
839
+ MLXSW_SP_SB_CM_EGR(1500, 9),
840
+ MLXSW_SP_SB_CM_EGR(1500, 9),
841
+ MLXSW_SP_SB_CM_EGR(1500, 9),
842
+ MLXSW_SP_SB_CM_EGR(1500, 9),
843
+ MLXSW_SP_SB_CM_EGR(1500, 9),
844
+ MLXSW_SP_SB_CM_EGR(1500, 9),
845
+ MLXSW_SP_SB_CM_EGR(1500, 9),
846
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
847
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
848
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
849
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
850
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
851
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
852
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
853
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
854
+ MLXSW_SP_SB_CM_EGR(1, 0xff),
855
+};
352856
353
-#define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(0, 0, 0)
857
+static const struct mlxsw_sp_sb_cm mlxsw_sp2_sb_cms_egress[] = {
858
+ MLXSW_SP_SB_CM_EGR(0, 7),
859
+ MLXSW_SP_SB_CM_EGR(0, 7),
860
+ MLXSW_SP_SB_CM_EGR(0, 7),
861
+ MLXSW_SP_SB_CM_EGR(0, 7),
862
+ MLXSW_SP_SB_CM_EGR(0, 7),
863
+ MLXSW_SP_SB_CM_EGR(0, 7),
864
+ MLXSW_SP_SB_CM_EGR(0, 7),
865
+ MLXSW_SP_SB_CM_EGR(0, 7),
866
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
867
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
868
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
869
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
870
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
871
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
872
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
873
+ MLXSW_SP_SB_CM_EGR_MC(0, MLXSW_SP_SB_INFI),
874
+ MLXSW_SP_SB_CM_EGR(1, 0xff),
875
+};
876
+
877
+#define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(0, 0, MLXSW_SP_SB_POOL_EGR_CPU)
354878
355879 static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = {
880
+ MLXSW_SP_SB_CM(1000, 8, MLXSW_SP_SB_POOL_EGR_CPU),
881
+ MLXSW_SP_SB_CM(1000, 8, MLXSW_SP_SB_POOL_EGR_CPU),
882
+ MLXSW_SP_SB_CM(1000, 8, MLXSW_SP_SB_POOL_EGR_CPU),
883
+ MLXSW_SP_SB_CM(1000, 8, MLXSW_SP_SB_POOL_EGR_CPU),
884
+ MLXSW_SP_SB_CM(1000, 8, MLXSW_SP_SB_POOL_EGR_CPU),
885
+ MLXSW_SP_SB_CM(1000, 8, MLXSW_SP_SB_POOL_EGR_CPU),
356886 MLXSW_SP_CPU_PORT_SB_CM,
357
- MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0),
358
- MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0),
359
- MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0),
360
- MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0),
361
- MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0),
362
- MLXSW_SP_CPU_PORT_SB_CM,
363
- MLXSW_SP_SB_CM(MLXSW_PORT_MAX_MTU, 0, 0),
887
+ MLXSW_SP_SB_CM(1000, 8, MLXSW_SP_SB_POOL_EGR_CPU),
364888 MLXSW_SP_CPU_PORT_SB_CM,
365889 MLXSW_SP_CPU_PORT_SB_CM,
366890 MLXSW_SP_CPU_PORT_SB_CM,
....@@ -387,30 +911,49 @@
387911 MLXSW_SP_CPU_PORT_SB_CM,
388912 };
389913
390
-#define MLXSW_SP_CPU_PORT_SB_MCS_LEN \
391
- ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms)
914
+static bool
915
+mlxsw_sp_sb_pool_is_static(struct mlxsw_sp *mlxsw_sp, u16 pool_index)
916
+{
917
+ struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool_index);
918
+
919
+ return pr->mode == MLXSW_REG_SBPR_MODE_STATIC;
920
+}
392921
393922 static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
394923 enum mlxsw_reg_sbxx_dir dir,
395924 const struct mlxsw_sp_sb_cm *cms,
396925 size_t cms_len)
397926 {
927
+ const struct mlxsw_sp_sb_vals *sb_vals = mlxsw_sp->sb_vals;
398928 int i;
399929 int err;
400930
401931 for (i = 0; i < cms_len; i++) {
402932 const struct mlxsw_sp_sb_cm *cm;
403933 u32 min_buff;
934
+ u32 max_buff;
404935
405936 if (i == 8 && dir == MLXSW_REG_SBXX_DIR_INGRESS)
406937 continue; /* PG number 8 does not exist, skip it */
407938 cm = &cms[i];
408
- /* All pools are initialized using dynamic thresholds,
409
- * therefore 'max_buff' isn't specified in cells.
410
- */
939
+ if (WARN_ON(sb_vals->pool_dess[cm->pool_index].dir != dir))
940
+ continue;
941
+
411942 min_buff = mlxsw_sp_bytes_cells(mlxsw_sp, cm->min_buff);
412
- err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, i, dir,
413
- min_buff, cm->max_buff, cm->pool);
943
+ max_buff = cm->max_buff;
944
+ if (max_buff == MLXSW_SP_SB_INFI) {
945
+ err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, i,
946
+ min_buff, 0,
947
+ true, cm->pool_index);
948
+ } else {
949
+ if (mlxsw_sp_sb_pool_is_static(mlxsw_sp,
950
+ cm->pool_index))
951
+ max_buff = mlxsw_sp_bytes_cells(mlxsw_sp,
952
+ max_buff);
953
+ err = mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, i,
954
+ min_buff, max_buff,
955
+ false, cm->pool_index);
956
+ }
414957 if (err)
415958 return err;
416959 }
....@@ -419,27 +962,28 @@
419962
420963 static int mlxsw_sp_port_sb_cms_init(struct mlxsw_sp_port *mlxsw_sp_port)
421964 {
965
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
422966 int err;
423967
424
- err = __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
968
+ err = __mlxsw_sp_sb_cms_init(mlxsw_sp,
425969 mlxsw_sp_port->local_port,
426970 MLXSW_REG_SBXX_DIR_INGRESS,
427
- mlxsw_sp_sb_cms_ingress,
428
- MLXSW_SP_SB_CMS_INGRESS_LEN);
971
+ mlxsw_sp->sb_vals->cms_ingress,
972
+ mlxsw_sp->sb_vals->cms_ingress_count);
429973 if (err)
430974 return err;
431975 return __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp,
432976 mlxsw_sp_port->local_port,
433977 MLXSW_REG_SBXX_DIR_EGRESS,
434
- mlxsw_sp_sb_cms_egress,
435
- MLXSW_SP_SB_CMS_EGRESS_LEN);
978
+ mlxsw_sp->sb_vals->cms_egress,
979
+ mlxsw_sp->sb_vals->cms_egress_count);
436980 }
437981
438982 static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp)
439983 {
440984 return __mlxsw_sp_sb_cms_init(mlxsw_sp, 0, MLXSW_REG_SBXX_DIR_EGRESS,
441
- mlxsw_sp_cpu_port_sb_cms,
442
- MLXSW_SP_CPU_PORT_SB_MCS_LEN);
985
+ mlxsw_sp->sb_vals->cms_cpu,
986
+ mlxsw_sp->sb_vals->cms_cpu_count);
443987 }
444988
445989 #define MLXSW_SP_SB_PM(_min_buff, _max_buff) \
....@@ -448,38 +992,73 @@
448992 .max_buff = _max_buff, \
449993 }
450994
451
-static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_ingress[] = {
995
+/* Order according to mlxsw_sp1_sb_pool_dess */
996
+static const struct mlxsw_sp_sb_pm mlxsw_sp1_sb_pms[] = {
452997 MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX),
453998 MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
454999 MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
455
- MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX),
456
-};
457
-
458
-#define MLXSW_SP_SB_PMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_ingress)
459
-
460
-static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms_egress[] = {
1000
+ MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
4611001 MLXSW_SP_SB_PM(0, 7),
4621002 MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
4631003 MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
4641004 MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
1005
+ MLXSW_SP_SB_PM(10000, 90000),
1006
+ MLXSW_SP_SB_PM(0, 8), /* 50% occupancy */
1007
+ MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
4651008 };
4661009
467
-#define MLXSW_SP_SB_PMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms_egress)
1010
+/* Order according to mlxsw_sp2_sb_pool_dess */
1011
+static const struct mlxsw_sp_sb_pm mlxsw_sp2_sb_pms[] = {
1012
+ MLXSW_SP_SB_PM(0, 7),
1013
+ MLXSW_SP_SB_PM(0, 0),
1014
+ MLXSW_SP_SB_PM(0, 0),
1015
+ MLXSW_SP_SB_PM(0, 0),
1016
+ MLXSW_SP_SB_PM(0, 7),
1017
+ MLXSW_SP_SB_PM(0, 0),
1018
+ MLXSW_SP_SB_PM(0, 0),
1019
+ MLXSW_SP_SB_PM(0, 0),
1020
+ MLXSW_SP_SB_PM(10000, 90000),
1021
+ MLXSW_SP_SB_PM(0, 8), /* 50% occupancy */
1022
+ MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN),
1023
+};
4681024
469
-static int __mlxsw_sp_port_sb_pms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
470
- enum mlxsw_reg_sbxx_dir dir,
471
- const struct mlxsw_sp_sb_pm *pms,
472
- size_t pms_len)
1025
+/* Order according to mlxsw_sp*_sb_pool_dess */
1026
+static const struct mlxsw_sp_sb_pm mlxsw_sp_cpu_port_sb_pms[] = {
1027
+ MLXSW_SP_SB_PM(0, 0),
1028
+ MLXSW_SP_SB_PM(0, 0),
1029
+ MLXSW_SP_SB_PM(0, 0),
1030
+ MLXSW_SP_SB_PM(0, 0),
1031
+ MLXSW_SP_SB_PM(0, 0),
1032
+ MLXSW_SP_SB_PM(0, 0),
1033
+ MLXSW_SP_SB_PM(0, 0),
1034
+ MLXSW_SP_SB_PM(0, 0),
1035
+ MLXSW_SP_SB_PM(0, 90000),
1036
+ MLXSW_SP_SB_PM(0, 0),
1037
+ MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX),
1038
+};
1039
+
1040
+static int mlxsw_sp_sb_pms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port,
1041
+ const struct mlxsw_sp_sb_pm *pms,
1042
+ bool skip_ingress)
4731043 {
474
- int i;
475
- int err;
1044
+ int i, err;
4761045
477
- for (i = 0; i < pms_len; i++) {
478
- const struct mlxsw_sp_sb_pm *pm;
1046
+ for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) {
1047
+ const struct mlxsw_sp_sb_pm *pm = &pms[i];
1048
+ const struct mlxsw_sp_sb_pool_des *des;
1049
+ u32 max_buff;
1050
+ u32 min_buff;
4791051
480
- pm = &pms[i];
481
- err = mlxsw_sp_sb_pm_write(mlxsw_sp, local_port, i, dir,
482
- pm->min_buff, pm->max_buff);
1052
+ des = &mlxsw_sp->sb_vals->pool_dess[i];
1053
+ if (skip_ingress && des->dir == MLXSW_REG_SBXX_DIR_INGRESS)
1054
+ continue;
1055
+
1056
+ min_buff = mlxsw_sp_bytes_cells(mlxsw_sp, pm->min_buff);
1057
+ max_buff = pm->max_buff;
1058
+ if (mlxsw_sp_sb_pool_is_static(mlxsw_sp, i))
1059
+ max_buff = mlxsw_sp_bytes_cells(mlxsw_sp, max_buff);
1060
+ err = mlxsw_sp_sb_pm_write(mlxsw_sp, local_port, i, min_buff,
1061
+ max_buff);
4831062 if (err)
4841063 return err;
4851064 }
....@@ -488,54 +1067,42 @@
4881067
4891068 static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port)
4901069 {
491
- int err;
1070
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
4921071
493
- err = __mlxsw_sp_port_sb_pms_init(mlxsw_sp_port->mlxsw_sp,
494
- mlxsw_sp_port->local_port,
495
- MLXSW_REG_SBXX_DIR_INGRESS,
496
- mlxsw_sp_sb_pms_ingress,
497
- MLXSW_SP_SB_PMS_INGRESS_LEN);
498
- if (err)
499
- return err;
500
- return __mlxsw_sp_port_sb_pms_init(mlxsw_sp_port->mlxsw_sp,
501
- mlxsw_sp_port->local_port,
502
- MLXSW_REG_SBXX_DIR_EGRESS,
503
- mlxsw_sp_sb_pms_egress,
504
- MLXSW_SP_SB_PMS_EGRESS_LEN);
1072
+ return mlxsw_sp_sb_pms_init(mlxsw_sp, mlxsw_sp_port->local_port,
1073
+ mlxsw_sp->sb_vals->pms, false);
5051074 }
5061075
507
-struct mlxsw_sp_sb_mm {
508
- u32 min_buff;
509
- u32 max_buff;
510
- u8 pool;
511
-};
1076
+static int mlxsw_sp_cpu_port_sb_pms_init(struct mlxsw_sp *mlxsw_sp)
1077
+{
1078
+ return mlxsw_sp_sb_pms_init(mlxsw_sp, 0, mlxsw_sp->sb_vals->pms_cpu,
1079
+ true);
1080
+}
5121081
513
-#define MLXSW_SP_SB_MM(_min_buff, _max_buff, _pool) \
1082
+#define MLXSW_SP_SB_MM(_min_buff, _max_buff) \
5141083 { \
5151084 .min_buff = _min_buff, \
5161085 .max_buff = _max_buff, \
517
- .pool = _pool, \
1086
+ .pool_index = MLXSW_SP_SB_POOL_EGR, \
5181087 }
5191088
5201089 static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = {
521
- MLXSW_SP_SB_MM(20000, 0xff, 0),
522
- MLXSW_SP_SB_MM(20000, 0xff, 0),
523
- MLXSW_SP_SB_MM(20000, 0xff, 0),
524
- MLXSW_SP_SB_MM(20000, 0xff, 0),
525
- MLXSW_SP_SB_MM(20000, 0xff, 0),
526
- MLXSW_SP_SB_MM(20000, 0xff, 0),
527
- MLXSW_SP_SB_MM(20000, 0xff, 0),
528
- MLXSW_SP_SB_MM(20000, 0xff, 0),
529
- MLXSW_SP_SB_MM(20000, 0xff, 0),
530
- MLXSW_SP_SB_MM(20000, 0xff, 0),
531
- MLXSW_SP_SB_MM(20000, 0xff, 0),
532
- MLXSW_SP_SB_MM(20000, 0xff, 0),
533
- MLXSW_SP_SB_MM(20000, 0xff, 0),
534
- MLXSW_SP_SB_MM(20000, 0xff, 0),
535
- MLXSW_SP_SB_MM(20000, 0xff, 0),
1090
+ MLXSW_SP_SB_MM(0, 6),
1091
+ MLXSW_SP_SB_MM(0, 6),
1092
+ MLXSW_SP_SB_MM(0, 6),
1093
+ MLXSW_SP_SB_MM(0, 6),
1094
+ MLXSW_SP_SB_MM(0, 6),
1095
+ MLXSW_SP_SB_MM(0, 6),
1096
+ MLXSW_SP_SB_MM(0, 6),
1097
+ MLXSW_SP_SB_MM(0, 6),
1098
+ MLXSW_SP_SB_MM(0, 6),
1099
+ MLXSW_SP_SB_MM(0, 6),
1100
+ MLXSW_SP_SB_MM(0, 6),
1101
+ MLXSW_SP_SB_MM(0, 6),
1102
+ MLXSW_SP_SB_MM(0, 6),
1103
+ MLXSW_SP_SB_MM(0, 6),
1104
+ MLXSW_SP_SB_MM(0, 6),
5361105 };
537
-
538
-#define MLXSW_SP_SB_MMS_LEN ARRAY_SIZE(mlxsw_sp_sb_mms)
5391106
5401107 static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp)
5411108 {
....@@ -543,17 +1110,19 @@
5431110 int i;
5441111 int err;
5451112
546
- for (i = 0; i < MLXSW_SP_SB_MMS_LEN; i++) {
1113
+ for (i = 0; i < mlxsw_sp->sb_vals->mms_count; i++) {
1114
+ const struct mlxsw_sp_sb_pool_des *des;
5471115 const struct mlxsw_sp_sb_mm *mc;
5481116 u32 min_buff;
5491117
550
- mc = &mlxsw_sp_sb_mms[i];
551
- /* All pools are initialized using dynamic thresholds,
552
- * therefore 'max_buff' isn't specified in cells.
1118
+ mc = &mlxsw_sp->sb_vals->mms[i];
1119
+ des = &mlxsw_sp->sb_vals->pool_dess[mc->pool_index];
1120
+ /* All pools used by sb_mm's are initialized using dynamic
1121
+ * thresholds, therefore 'max_buff' isn't specified in cells.
5531122 */
5541123 min_buff = mlxsw_sp_bytes_cells(mlxsw_sp, mc->min_buff);
5551124 mlxsw_reg_sbmm_pack(sbmm_pl, i, min_buff, mc->max_buff,
556
- mc->pool);
1125
+ des->pool);
5571126 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbmm), sbmm_pl);
5581127 if (err)
5591128 return err;
....@@ -561,40 +1130,146 @@
5611130 return 0;
5621131 }
5631132
1133
+static void mlxsw_sp_pool_count(struct mlxsw_sp *mlxsw_sp,
1134
+ u16 *p_ingress_len, u16 *p_egress_len)
1135
+{
1136
+ int i;
1137
+
1138
+ for (i = 0; i < mlxsw_sp->sb_vals->pool_count; ++i) {
1139
+ if (mlxsw_sp->sb_vals->pool_dess[i].dir ==
1140
+ MLXSW_REG_SBXX_DIR_INGRESS)
1141
+ (*p_ingress_len)++;
1142
+ else
1143
+ (*p_egress_len)++;
1144
+ }
1145
+
1146
+ WARN(*p_egress_len == 0, "No egress pools\n");
1147
+}
1148
+
1149
+const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = {
1150
+ .pool_count = ARRAY_SIZE(mlxsw_sp1_sb_pool_dess),
1151
+ .pool_dess = mlxsw_sp1_sb_pool_dess,
1152
+ .pms = mlxsw_sp1_sb_pms,
1153
+ .pms_cpu = mlxsw_sp_cpu_port_sb_pms,
1154
+ .prs = mlxsw_sp1_sb_prs,
1155
+ .mms = mlxsw_sp_sb_mms,
1156
+ .cms_ingress = mlxsw_sp1_sb_cms_ingress,
1157
+ .cms_egress = mlxsw_sp1_sb_cms_egress,
1158
+ .cms_cpu = mlxsw_sp_cpu_port_sb_cms,
1159
+ .mms_count = ARRAY_SIZE(mlxsw_sp_sb_mms),
1160
+ .cms_ingress_count = ARRAY_SIZE(mlxsw_sp1_sb_cms_ingress),
1161
+ .cms_egress_count = ARRAY_SIZE(mlxsw_sp1_sb_cms_egress),
1162
+ .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms),
1163
+};
1164
+
1165
+const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = {
1166
+ .pool_count = ARRAY_SIZE(mlxsw_sp2_sb_pool_dess),
1167
+ .pool_dess = mlxsw_sp2_sb_pool_dess,
1168
+ .pms = mlxsw_sp2_sb_pms,
1169
+ .pms_cpu = mlxsw_sp_cpu_port_sb_pms,
1170
+ .prs = mlxsw_sp2_sb_prs,
1171
+ .mms = mlxsw_sp_sb_mms,
1172
+ .cms_ingress = mlxsw_sp2_sb_cms_ingress,
1173
+ .cms_egress = mlxsw_sp2_sb_cms_egress,
1174
+ .cms_cpu = mlxsw_sp_cpu_port_sb_cms,
1175
+ .mms_count = ARRAY_SIZE(mlxsw_sp_sb_mms),
1176
+ .cms_ingress_count = ARRAY_SIZE(mlxsw_sp2_sb_cms_ingress),
1177
+ .cms_egress_count = ARRAY_SIZE(mlxsw_sp2_sb_cms_egress),
1178
+ .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms),
1179
+};
1180
+
1181
+static u32 mlxsw_sp1_pb_int_buf_size_get(int mtu, u32 speed)
1182
+{
1183
+ return mtu * 5 / 2;
1184
+}
1185
+
1186
+static u32 __mlxsw_sp_pb_int_buf_size_get(int mtu, u32 speed, u32 buffer_factor)
1187
+{
1188
+ return 3 * mtu + buffer_factor * speed / 1000;
1189
+}
1190
+
1191
+#define MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR 38
1192
+
1193
+static u32 mlxsw_sp2_pb_int_buf_size_get(int mtu, u32 speed)
1194
+{
1195
+ int factor = MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR;
1196
+
1197
+ return __mlxsw_sp_pb_int_buf_size_get(mtu, speed, factor);
1198
+}
1199
+
1200
+#define MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR 50
1201
+
1202
+static u32 mlxsw_sp3_pb_int_buf_size_get(int mtu, u32 speed)
1203
+{
1204
+ int factor = MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR;
1205
+
1206
+ return __mlxsw_sp_pb_int_buf_size_get(mtu, speed, factor);
1207
+}
1208
+
1209
+const struct mlxsw_sp_sb_ops mlxsw_sp1_sb_ops = {
1210
+ .int_buf_size_get = mlxsw_sp1_pb_int_buf_size_get,
1211
+};
1212
+
1213
+const struct mlxsw_sp_sb_ops mlxsw_sp2_sb_ops = {
1214
+ .int_buf_size_get = mlxsw_sp2_pb_int_buf_size_get,
1215
+};
1216
+
1217
+const struct mlxsw_sp_sb_ops mlxsw_sp3_sb_ops = {
1218
+ .int_buf_size_get = mlxsw_sp3_pb_int_buf_size_get,
1219
+};
1220
+
5641221 int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp)
5651222 {
566
- u64 sb_size;
1223
+ u32 max_headroom_size;
1224
+ u16 ing_pool_count = 0;
1225
+ u16 eg_pool_count = 0;
5671226 int err;
5681227
5691228 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, CELL_SIZE))
5701229 return -EIO;
5711230
572
- if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_BUFFER_SIZE))
1231
+ if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, GUARANTEED_SHARED_BUFFER))
5731232 return -EIO;
574
- sb_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_BUFFER_SIZE);
1233
+
1234
+ if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_HEADROOM_SIZE))
1235
+ return -EIO;
5751236
5761237 mlxsw_sp->sb = kzalloc(sizeof(*mlxsw_sp->sb), GFP_KERNEL);
5771238 if (!mlxsw_sp->sb)
5781239 return -ENOMEM;
5791240 mlxsw_sp->sb->cell_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, CELL_SIZE);
1241
+ mlxsw_sp->sb->sb_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
1242
+ GUARANTEED_SHARED_BUFFER);
1243
+ max_headroom_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
1244
+ MAX_HEADROOM_SIZE);
1245
+ /* Round down, because this limit must not be overstepped. */
1246
+ mlxsw_sp->sb->max_headroom_cells = max_headroom_size /
1247
+ mlxsw_sp->sb->cell_size;
5801248
5811249 err = mlxsw_sp_sb_ports_init(mlxsw_sp);
5821250 if (err)
5831251 goto err_sb_ports_init;
584
- err = mlxsw_sp_sb_prs_init(mlxsw_sp);
1252
+ err = mlxsw_sp_sb_prs_init(mlxsw_sp, mlxsw_sp->sb_vals->prs,
1253
+ mlxsw_sp->sb_vals->pool_dess,
1254
+ mlxsw_sp->sb_vals->pool_count);
5851255 if (err)
5861256 goto err_sb_prs_init;
5871257 err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp);
5881258 if (err)
5891259 goto err_sb_cpu_port_sb_cms_init;
1260
+ err = mlxsw_sp_cpu_port_sb_pms_init(mlxsw_sp);
1261
+ if (err)
1262
+ goto err_sb_cpu_port_pms_init;
5901263 err = mlxsw_sp_sb_mms_init(mlxsw_sp);
5911264 if (err)
5921265 goto err_sb_mms_init;
593
- err = devlink_sb_register(priv_to_devlink(mlxsw_sp->core), 0, sb_size,
594
- MLXSW_SP_SB_POOL_COUNT,
595
- MLXSW_SP_SB_POOL_COUNT,
596
- MLXSW_SP_SB_TC_COUNT,
597
- MLXSW_SP_SB_TC_COUNT);
1266
+ mlxsw_sp_pool_count(mlxsw_sp, &ing_pool_count, &eg_pool_count);
1267
+ err = devlink_sb_register(priv_to_devlink(mlxsw_sp->core), 0,
1268
+ mlxsw_sp->sb->sb_size,
1269
+ ing_pool_count,
1270
+ eg_pool_count,
1271
+ MLXSW_SP_SB_ING_TC_COUNT,
1272
+ MLXSW_SP_SB_EG_TC_COUNT);
5981273 if (err)
5991274 goto err_devlink_sb_register;
6001275
....@@ -602,6 +1277,7 @@
6021277
6031278 err_devlink_sb_register:
6041279 err_sb_mms_init:
1280
+err_sb_cpu_port_pms_init:
6051281 err_sb_cpu_port_sb_cms_init:
6061282 err_sb_prs_init:
6071283 mlxsw_sp_sb_ports_fini(mlxsw_sp);
....@@ -621,36 +1297,32 @@
6211297 {
6221298 int err;
6231299
1300
+ mlxsw_sp_port->hdroom = kzalloc(sizeof(*mlxsw_sp_port->hdroom), GFP_KERNEL);
1301
+ if (!mlxsw_sp_port->hdroom)
1302
+ return -ENOMEM;
1303
+ mlxsw_sp_port->hdroom->mtu = mlxsw_sp_port->dev->mtu;
1304
+
6241305 err = mlxsw_sp_port_headroom_init(mlxsw_sp_port);
6251306 if (err)
626
- return err;
1307
+ goto err_headroom_init;
6271308 err = mlxsw_sp_port_sb_cms_init(mlxsw_sp_port);
6281309 if (err)
629
- return err;
1310
+ goto err_port_sb_cms_init;
6301311 err = mlxsw_sp_port_sb_pms_init(mlxsw_sp_port);
1312
+ if (err)
1313
+ goto err_port_sb_pms_init;
1314
+ return 0;
6311315
1316
+err_port_sb_pms_init:
1317
+err_port_sb_cms_init:
1318
+err_headroom_init:
1319
+ kfree(mlxsw_sp_port->hdroom);
6321320 return err;
6331321 }
6341322
635
-static u8 pool_get(u16 pool_index)
1323
+void mlxsw_sp_port_buffers_fini(struct mlxsw_sp_port *mlxsw_sp_port)
6361324 {
637
- return pool_index % MLXSW_SP_SB_POOL_COUNT;
638
-}
639
-
640
-static u16 pool_index_get(u8 pool, enum mlxsw_reg_sbxx_dir dir)
641
-{
642
- u16 pool_index;
643
-
644
- pool_index = pool;
645
- if (dir == MLXSW_REG_SBXX_DIR_EGRESS)
646
- pool_index += MLXSW_SP_SB_POOL_COUNT;
647
- return pool_index;
648
-}
649
-
650
-static enum mlxsw_reg_sbxx_dir dir_get(u16 pool_index)
651
-{
652
- return pool_index < MLXSW_SP_SB_POOL_COUNT ?
653
- MLXSW_REG_SBXX_DIR_INGRESS : MLXSW_REG_SBXX_DIR_EGRESS;
1325
+ kfree(mlxsw_sp_port->hdroom);
6541326 }
6551327
6561328 int mlxsw_sp_sb_pool_get(struct mlxsw_core *mlxsw_core,
....@@ -658,58 +1330,78 @@
6581330 struct devlink_sb_pool_info *pool_info)
6591331 {
6601332 struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
661
- u8 pool = pool_get(pool_index);
662
- enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
663
- struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir);
1333
+ enum mlxsw_reg_sbxx_dir dir;
1334
+ struct mlxsw_sp_sb_pr *pr;
6641335
1336
+ dir = mlxsw_sp->sb_vals->pool_dess[pool_index].dir;
1337
+ pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool_index);
6651338 pool_info->pool_type = (enum devlink_sb_pool_type) dir;
6661339 pool_info->size = mlxsw_sp_cells_bytes(mlxsw_sp, pr->size);
6671340 pool_info->threshold_type = (enum devlink_sb_threshold_type) pr->mode;
1341
+ pool_info->cell_size = mlxsw_sp->sb->cell_size;
6681342 return 0;
6691343 }
6701344
6711345 int mlxsw_sp_sb_pool_set(struct mlxsw_core *mlxsw_core,
6721346 unsigned int sb_index, u16 pool_index, u32 size,
673
- enum devlink_sb_threshold_type threshold_type)
1347
+ enum devlink_sb_threshold_type threshold_type,
1348
+ struct netlink_ext_ack *extack)
6741349 {
6751350 struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
6761351 u32 pool_size = mlxsw_sp_bytes_cells(mlxsw_sp, size);
677
- u8 pool = pool_get(pool_index);
678
- enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
1352
+ const struct mlxsw_sp_sb_pr *pr;
6791353 enum mlxsw_reg_sbpr_mode mode;
6801354
681
- if (size > MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_BUFFER_SIZE))
682
- return -EINVAL;
683
-
6841355 mode = (enum mlxsw_reg_sbpr_mode) threshold_type;
685
- return mlxsw_sp_sb_pr_write(mlxsw_sp, pool, dir, mode, pool_size);
1356
+ pr = &mlxsw_sp->sb_vals->prs[pool_index];
1357
+
1358
+ if (size > MLXSW_CORE_RES_GET(mlxsw_sp->core,
1359
+ GUARANTEED_SHARED_BUFFER)) {
1360
+ NL_SET_ERR_MSG_MOD(extack, "Exceeded shared buffer size");
1361
+ return -EINVAL;
1362
+ }
1363
+
1364
+ if (pr->freeze_mode && pr->mode != mode) {
1365
+ NL_SET_ERR_MSG_MOD(extack, "Changing this pool's threshold type is forbidden");
1366
+ return -EINVAL;
1367
+ }
1368
+
1369
+ if (pr->freeze_size && pr->size != size) {
1370
+ NL_SET_ERR_MSG_MOD(extack, "Changing this pool's size is forbidden");
1371
+ return -EINVAL;
1372
+ }
1373
+
1374
+ return mlxsw_sp_sb_pr_write(mlxsw_sp, pool_index, mode,
1375
+ pool_size, false);
6861376 }
6871377
6881378 #define MLXSW_SP_SB_THRESHOLD_TO_ALPHA_OFFSET (-2) /* 3->1, 16->14 */
6891379
690
-static u32 mlxsw_sp_sb_threshold_out(struct mlxsw_sp *mlxsw_sp, u8 pool,
691
- enum mlxsw_reg_sbxx_dir dir, u32 max_buff)
1380
+static u32 mlxsw_sp_sb_threshold_out(struct mlxsw_sp *mlxsw_sp, u16 pool_index,
1381
+ u32 max_buff)
6921382 {
693
- struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir);
1383
+ struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool_index);
6941384
6951385 if (pr->mode == MLXSW_REG_SBPR_MODE_DYNAMIC)
6961386 return max_buff - MLXSW_SP_SB_THRESHOLD_TO_ALPHA_OFFSET;
6971387 return mlxsw_sp_cells_bytes(mlxsw_sp, max_buff);
6981388 }
6991389
700
-static int mlxsw_sp_sb_threshold_in(struct mlxsw_sp *mlxsw_sp, u8 pool,
701
- enum mlxsw_reg_sbxx_dir dir, u32 threshold,
702
- u32 *p_max_buff)
1390
+static int mlxsw_sp_sb_threshold_in(struct mlxsw_sp *mlxsw_sp, u16 pool_index,
1391
+ u32 threshold, u32 *p_max_buff,
1392
+ struct netlink_ext_ack *extack)
7031393 {
704
- struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool, dir);
1394
+ struct mlxsw_sp_sb_pr *pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool_index);
7051395
7061396 if (pr->mode == MLXSW_REG_SBPR_MODE_DYNAMIC) {
7071397 int val;
7081398
7091399 val = threshold + MLXSW_SP_SB_THRESHOLD_TO_ALPHA_OFFSET;
7101400 if (val < MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN ||
711
- val > MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX)
1401
+ val > MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX) {
1402
+ NL_SET_ERR_MSG_MOD(extack, "Invalid dynamic threshold value");
7121403 return -EINVAL;
1404
+ }
7131405 *p_max_buff = val;
7141406 } else {
7151407 *p_max_buff = mlxsw_sp_bytes_cells(mlxsw_sp, threshold);
....@@ -725,35 +1417,36 @@
7251417 mlxsw_core_port_driver_priv(mlxsw_core_port);
7261418 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
7271419 u8 local_port = mlxsw_sp_port->local_port;
728
- u8 pool = pool_get(pool_index);
729
- enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
7301420 struct mlxsw_sp_sb_pm *pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port,
731
- pool, dir);
1421
+ pool_index);
7321422
733
- *p_threshold = mlxsw_sp_sb_threshold_out(mlxsw_sp, pool, dir,
1423
+ *p_threshold = mlxsw_sp_sb_threshold_out(mlxsw_sp, pool_index,
7341424 pm->max_buff);
7351425 return 0;
7361426 }
7371427
7381428 int mlxsw_sp_sb_port_pool_set(struct mlxsw_core_port *mlxsw_core_port,
7391429 unsigned int sb_index, u16 pool_index,
740
- u32 threshold)
1430
+ u32 threshold, struct netlink_ext_ack *extack)
7411431 {
7421432 struct mlxsw_sp_port *mlxsw_sp_port =
7431433 mlxsw_core_port_driver_priv(mlxsw_core_port);
7441434 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
7451435 u8 local_port = mlxsw_sp_port->local_port;
746
- u8 pool = pool_get(pool_index);
747
- enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
7481436 u32 max_buff;
7491437 int err;
7501438
751
- err = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool, dir,
752
- threshold, &max_buff);
1439
+ if (local_port == MLXSW_PORT_CPU_PORT) {
1440
+ NL_SET_ERR_MSG_MOD(extack, "Changing CPU port's threshold is forbidden");
1441
+ return -EINVAL;
1442
+ }
1443
+
1444
+ err = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool_index,
1445
+ threshold, &max_buff, extack);
7531446 if (err)
7541447 return err;
7551448
756
- return mlxsw_sp_sb_pm_write(mlxsw_sp, local_port, pool, dir,
1449
+ return mlxsw_sp_sb_pm_write(mlxsw_sp, local_port, pool_index,
7571450 0, max_buff);
7581451 }
7591452
....@@ -771,41 +1464,65 @@
7711464 struct mlxsw_sp_sb_cm *cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port,
7721465 pg_buff, dir);
7731466
774
- *p_threshold = mlxsw_sp_sb_threshold_out(mlxsw_sp, cm->pool, dir,
1467
+ *p_threshold = mlxsw_sp_sb_threshold_out(mlxsw_sp, cm->pool_index,
7751468 cm->max_buff);
776
- *p_pool_index = pool_index_get(cm->pool, dir);
1469
+ *p_pool_index = cm->pool_index;
7771470 return 0;
7781471 }
7791472
7801473 int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port,
7811474 unsigned int sb_index, u16 tc_index,
7821475 enum devlink_sb_pool_type pool_type,
783
- u16 pool_index, u32 threshold)
1476
+ u16 pool_index, u32 threshold,
1477
+ struct netlink_ext_ack *extack)
7841478 {
7851479 struct mlxsw_sp_port *mlxsw_sp_port =
7861480 mlxsw_core_port_driver_priv(mlxsw_core_port);
7871481 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
7881482 u8 local_port = mlxsw_sp_port->local_port;
1483
+ const struct mlxsw_sp_sb_cm *cm;
7891484 u8 pg_buff = tc_index;
7901485 enum mlxsw_reg_sbxx_dir dir = (enum mlxsw_reg_sbxx_dir) pool_type;
791
- u8 pool = pool_get(pool_index);
7921486 u32 max_buff;
7931487 int err;
7941488
795
- if (dir != dir_get(pool_index))
1489
+ if (local_port == MLXSW_PORT_CPU_PORT) {
1490
+ NL_SET_ERR_MSG_MOD(extack, "Changing CPU port's binding is forbidden");
7961491 return -EINVAL;
1492
+ }
7971493
798
- err = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool, dir,
799
- threshold, &max_buff);
1494
+ if (dir != mlxsw_sp->sb_vals->pool_dess[pool_index].dir) {
1495
+ NL_SET_ERR_MSG_MOD(extack, "Binding egress TC to ingress pool and vice versa is forbidden");
1496
+ return -EINVAL;
1497
+ }
1498
+
1499
+ if (dir == MLXSW_REG_SBXX_DIR_INGRESS)
1500
+ cm = &mlxsw_sp->sb_vals->cms_ingress[tc_index];
1501
+ else
1502
+ cm = &mlxsw_sp->sb_vals->cms_egress[tc_index];
1503
+
1504
+ if (cm->freeze_pool && cm->pool_index != pool_index) {
1505
+ NL_SET_ERR_MSG_MOD(extack, "Binding this TC to a different pool is forbidden");
1506
+ return -EINVAL;
1507
+ }
1508
+
1509
+ if (cm->freeze_thresh && cm->max_buff != threshold) {
1510
+ NL_SET_ERR_MSG_MOD(extack, "Changing this TC's threshold is forbidden");
1511
+ return -EINVAL;
1512
+ }
1513
+
1514
+ err = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool_index,
1515
+ threshold, &max_buff, extack);
8001516 if (err)
8011517 return err;
8021518
803
- return mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, pg_buff, dir,
804
- 0, max_buff, pool);
1519
+ return mlxsw_sp_sb_cm_write(mlxsw_sp, local_port, pg_buff,
1520
+ 0, max_buff, false, pool_index);
8051521 }
8061522
8071523 #define MASKED_COUNT_MAX \
808
- (MLXSW_REG_SBSR_REC_MAX_COUNT / (MLXSW_SP_SB_TC_COUNT * 2))
1524
+ (MLXSW_REG_SBSR_REC_MAX_COUNT / \
1525
+ (MLXSW_SP_SB_ING_TC_COUNT + MLXSW_SP_SB_EG_TC_COUNT))
8091526
8101527 struct mlxsw_sp_sb_sr_occ_query_cb_ctx {
8111528 u8 masked_count;
....@@ -831,7 +1548,12 @@
8311548 local_port < mlxsw_core_max_ports(mlxsw_core); local_port++) {
8321549 if (!mlxsw_sp->ports[local_port])
8331550 continue;
834
- for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) {
1551
+ if (local_port == MLXSW_PORT_CPU_PORT) {
1552
+ /* Ingress quotas are not supported for the CPU port */
1553
+ masked_count++;
1554
+ continue;
1555
+ }
1556
+ for (i = 0; i < MLXSW_SP_SB_ING_TC_COUNT; i++) {
8351557 cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, i,
8361558 MLXSW_REG_SBXX_DIR_INGRESS);
8371559 mlxsw_reg_sbsr_rec_unpack(sbsr_pl, rec_index++,
....@@ -845,7 +1567,7 @@
8451567 local_port < mlxsw_core_max_ports(mlxsw_core); local_port++) {
8461568 if (!mlxsw_sp->ports[local_port])
8471569 continue;
848
- for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) {
1570
+ for (i = 0; i < MLXSW_SP_SB_EG_TC_COUNT; i++) {
8491571 cm = mlxsw_sp_sb_cm_get(mlxsw_sp, local_port, i,
8501572 MLXSW_REG_SBXX_DIR_EGRESS);
8511573 mlxsw_reg_sbsr_rec_unpack(sbsr_pl, rec_index++,
....@@ -866,7 +1588,7 @@
8661588 char *sbsr_pl;
8671589 u8 masked_count;
8681590 u8 local_port_1;
869
- u8 local_port = 0;
1591
+ u8 local_port;
8701592 int i;
8711593 int err;
8721594 int err2;
....@@ -875,28 +1597,26 @@
8751597 if (!sbsr_pl)
8761598 return -ENOMEM;
8771599
1600
+ local_port = MLXSW_PORT_CPU_PORT;
8781601 next_batch:
879
- local_port++;
8801602 local_port_1 = local_port;
8811603 masked_count = 0;
8821604 mlxsw_reg_sbsr_pack(sbsr_pl, false);
883
- for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) {
1605
+ for (i = 0; i < MLXSW_SP_SB_ING_TC_COUNT; i++)
8841606 mlxsw_reg_sbsr_pg_buff_mask_set(sbsr_pl, i, 1);
1607
+ for (i = 0; i < MLXSW_SP_SB_EG_TC_COUNT; i++)
8851608 mlxsw_reg_sbsr_tclass_mask_set(sbsr_pl, i, 1);
886
- }
8871609 for (; local_port < mlxsw_core_max_ports(mlxsw_core); local_port++) {
8881610 if (!mlxsw_sp->ports[local_port])
8891611 continue;
890
- mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1);
1612
+ if (local_port != MLXSW_PORT_CPU_PORT) {
1613
+ /* Ingress quotas are not supported for the CPU port */
1614
+ mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl,
1615
+ local_port, 1);
1616
+ }
8911617 mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1);
892
- for (i = 0; i < MLXSW_SP_SB_POOL_COUNT; i++) {
1618
+ for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) {
8931619 err = mlxsw_sp_sb_pm_occ_query(mlxsw_sp, local_port, i,
894
- MLXSW_REG_SBXX_DIR_INGRESS,
895
- &bulk_list);
896
- if (err)
897
- goto out;
898
- err = mlxsw_sp_sb_pm_occ_query(mlxsw_sp, local_port, i,
899
- MLXSW_REG_SBXX_DIR_EGRESS,
9001620 &bulk_list);
9011621 if (err)
9021622 goto out;
....@@ -914,8 +1634,10 @@
9141634 cb_priv);
9151635 if (err)
9161636 goto out;
917
- if (local_port < mlxsw_core_max_ports(mlxsw_core))
1637
+ if (local_port < mlxsw_core_max_ports(mlxsw_core)) {
1638
+ local_port++;
9181639 goto next_batch;
1640
+ }
9191641
9201642 out:
9211643 err2 = mlxsw_reg_trans_bulk_wait(&bulk_list);
....@@ -932,7 +1654,7 @@
9321654 LIST_HEAD(bulk_list);
9331655 char *sbsr_pl;
9341656 unsigned int masked_count;
935
- u8 local_port = 0;
1657
+ u8 local_port;
9361658 int i;
9371659 int err;
9381660 int err2;
....@@ -941,27 +1663,25 @@
9411663 if (!sbsr_pl)
9421664 return -ENOMEM;
9431665
1666
+ local_port = MLXSW_PORT_CPU_PORT;
9441667 next_batch:
945
- local_port++;
9461668 masked_count = 0;
9471669 mlxsw_reg_sbsr_pack(sbsr_pl, true);
948
- for (i = 0; i < MLXSW_SP_SB_TC_COUNT; i++) {
1670
+ for (i = 0; i < MLXSW_SP_SB_ING_TC_COUNT; i++)
9491671 mlxsw_reg_sbsr_pg_buff_mask_set(sbsr_pl, i, 1);
1672
+ for (i = 0; i < MLXSW_SP_SB_EG_TC_COUNT; i++)
9501673 mlxsw_reg_sbsr_tclass_mask_set(sbsr_pl, i, 1);
951
- }
9521674 for (; local_port < mlxsw_core_max_ports(mlxsw_core); local_port++) {
9531675 if (!mlxsw_sp->ports[local_port])
9541676 continue;
955
- mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1);
1677
+ if (local_port != MLXSW_PORT_CPU_PORT) {
1678
+ /* Ingress quotas are not supported for the CPU port */
1679
+ mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl,
1680
+ local_port, 1);
1681
+ }
9561682 mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1);
957
- for (i = 0; i < MLXSW_SP_SB_POOL_COUNT; i++) {
1683
+ for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) {
9581684 err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i,
959
- MLXSW_REG_SBXX_DIR_INGRESS,
960
- &bulk_list);
961
- if (err)
962
- goto out;
963
- err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i,
964
- MLXSW_REG_SBXX_DIR_EGRESS,
9651685 &bulk_list);
9661686 if (err)
9671687 goto out;
....@@ -975,8 +1695,10 @@
9751695 &bulk_list, NULL, 0);
9761696 if (err)
9771697 goto out;
978
- if (local_port < mlxsw_core_max_ports(mlxsw_core))
1698
+ if (local_port < mlxsw_core_max_ports(mlxsw_core)) {
1699
+ local_port++;
9791700 goto next_batch;
1701
+ }
9801702
9811703 out:
9821704 err2 = mlxsw_reg_trans_bulk_wait(&bulk_list);
....@@ -994,10 +1716,8 @@
9941716 mlxsw_core_port_driver_priv(mlxsw_core_port);
9951717 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
9961718 u8 local_port = mlxsw_sp_port->local_port;
997
- u8 pool = pool_get(pool_index);
998
- enum mlxsw_reg_sbxx_dir dir = dir_get(pool_index);
9991719 struct mlxsw_sp_sb_pm *pm = mlxsw_sp_sb_pm_get(mlxsw_sp, local_port,
1000
- pool, dir);
1720
+ pool_index);
10011721
10021722 *p_cur = mlxsw_sp_cells_bytes(mlxsw_sp, pm->occ.cur);
10031723 *p_max = mlxsw_sp_cells_bytes(mlxsw_sp, pm->occ.max);