arm64: Switch to 4.9 kernel
[openwrt/openwrt.git] / target / linux / mvebu / patches-4.4 / 045-net-mvneta-bm-add-support-for-hardware-buffer-manage.patch
1 From: Marcin Wojtas <mw@semihalf.com>
2 Date: Mon, 14 Mar 2016 09:39:03 +0100
3 Subject: [PATCH] net: mvneta: bm: add support for hardware buffer management
4
5 Buffer manager (BM) is a dedicated hardware unit that can be used by all
6 ethernet ports of Armada XP and 38x SoC's. It allows to offload CPU on RX
7 path by sparing DRAM access on refilling buffer pool, hardware-based
8 filling of descriptor ring data and better memory utilization due to HW
9 arbitration for using 'short' pools for small packets.
10
11 Tests performed with A388 SoC working as a network bridge between two
12 packet generators showed increase of maximum processed 64B packets by
13 ~20k (~555k packets with BM enabled vs ~535 packets without BM). Also
14 when pushing 1500B-packets with a line rate achieved, CPU load decreased
15 from around 25% without BM to 20% with BM.
16
17 BM comprise up to 4 buffer pointers' (BP) rings kept in DRAM, which
18 are called external BP pools - BPPE. Allocating and releasing buffer
19 pointers (BP) to/from BPPE is performed indirectly by write/read access
20 to a dedicated internal SRAM, where internal BP pools (BPPI) are placed.
21 BM hardware controls status of BPPE automatically, as well as assigning
22 proper buffers to RX descriptors. For more details please refer to
23 Functional Specification of Armada XP or 38x SoC.
24
25 In order to enable support for a separate hardware block, common for all
26 ports, a new driver has to be implemented ('mvneta_bm'). It provides
27 initialization sequence of address space, clocks, registers, SRAM,
28 empty pools' structures and also obtaining optional configuration
29 from DT (please refer to device tree binding documentation). mvneta_bm
30 exposes also a necessary API to mvneta driver, as well as a dedicated
31 structure with BM information (bm_priv), whose presence is used as a
32 flag notifying of BM usage by port. It has to be ensured that mvneta_bm
33 probe is executed prior to the ones in ports' driver. In case BM is not
34 used or its probe fails, mvneta falls back to use software buffer
35 management.
36
37 A sequence executed in mvneta_probe function is modified in order to have
38 an access to needed resources before possible port's BM initialization is
39 done. According to port-pools mapping provided by DT appropriate registers
40 are configured and the buffer pools are filled. RX path is modified
41 accordingly. Becaues the hardware allows a wide variety of configuration
42 options, following assumptions are made:
43 * using BM mechanisms can be selectively disabled/enabled basing
44 on DT configuration among the ports
45 * 'long' pool's single buffer size is tied to port's MTU
46 * using 'long' pool by port is obligatory and it cannot be shared
47 * using 'short' pool for smaller packets is optional
48 * one 'short' pool can be shared among all ports
49
50 This commit enables hardware buffer management operation cooperating with
51 existing mvneta driver. New device tree binding documentation is added and
52 the one of mvneta is updated accordingly.
53
54 [gregory.clement@free-electrons.com: removed the suspend/resume part]
55
56 Signed-off-by: Marcin Wojtas <mw@semihalf.com>
57 Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
58 Signed-off-by: David S. Miller <davem@davemloft.net>
59 ---
60 create mode 100644 Documentation/devicetree/bindings/net/marvell-neta-bm.txt
61 create mode 100644 drivers/net/ethernet/marvell/mvneta_bm.c
62 create mode 100644 drivers/net/ethernet/marvell/mvneta_bm.h
63
64 --- a/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
65 +++ b/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
66 @@ -13,15 +13,30 @@ Optional properties:
67 Value is presented in bytes. If not used, by default 1600B is set for
68 "marvell,armada-370-neta" and 9800B for others.
69
70 +Optional properties (valid only for Armada XP/38x):
71 +
72 +- buffer-manager: a phandle to a buffer manager node. Please refer to
73 + Documentation/devicetree/bindings/net/marvell-neta-bm.txt
74 +- bm,pool-long: ID of a pool, that will accept all packets of a size
75 + higher than 'short' pool's threshold (if set) and up to MTU value.
76 + Obligatory, when the port is supposed to use hardware
77 + buffer management.
78 +- bm,pool-short: ID of a pool, that will be used for accepting
79 + packets of a size lower than given threshold. If not set, the port
80 + will use a single 'long' pool for all packets, as defined above.
81 +
82 Example:
83
84 -ethernet@d0070000 {
85 +ethernet@70000 {
86 compatible = "marvell,armada-370-neta";
87 - reg = <0xd0070000 0x2500>;
88 + reg = <0x70000 0x2500>;
89 interrupts = <8>;
90 clocks = <&gate_clk 4>;
91 tx-csum-limit = <9800>
92 status = "okay";
93 phy = <&phy0>;
94 phy-mode = "rgmii-id";
95 + buffer-manager = <&bm>;
96 + bm,pool-long = <0>;
97 + bm,pool-short = <1>;
98 };
99 --- /dev/null
100 +++ b/Documentation/devicetree/bindings/net/marvell-neta-bm.txt
101 @@ -0,0 +1,49 @@
102 +* Marvell Armada 380/XP Buffer Manager driver (BM)
103 +
104 +Required properties:
105 +
106 +- compatible: should be "marvell,armada-380-neta-bm".
107 +- reg: address and length of the register set for the device.
108 +- clocks: a pointer to the reference clock for this device.
109 +- internal-mem: a phandle to BM internal SRAM definition.
110 +
111 +Optional properties (port):
112 +
113 +- pool<0 : 3>,capacity: size of external buffer pointers' ring maintained
114 + in DRAM. Can be set for each pool (id 0 : 3) separately. The value has
115 + to be chosen between 128 and 16352 and it also has to be aligned to 32.
116 + Otherwise the driver would adjust a given number or choose default if
117 + not set.
118 +- pool<0 : 3>,pkt-size: maximum size of a packet accepted by a given buffer
119 + pointers' pool (id 0 : 3). It will be taken into consideration only when pool
120 + type is 'short'. For 'long' ones it would be overridden by port's MTU.
121 + If not set a driver will choose a default value.
122 +
123 +In order to see how to hook the BM to a given ethernet port, please
124 +refer to Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt.
125 +
126 +Example:
127 +
128 +- main node:
129 +
130 +bm: bm@c8000 {
131 + compatible = "marvell,armada-380-neta-bm";
132 + reg = <0xc8000 0xac>;
133 + clocks = <&gateclk 13>;
134 + internal-mem = <&bm_bppi>;
135 + status = "okay";
136 + pool2,capacity = <4096>;
137 + pool1,pkt-size = <512>;
138 +};
139 +
140 +- internal SRAM node:
141 +
142 +bm_bppi: bm-bppi {
143 + compatible = "mmio-sram";
144 + reg = <MBUS_ID(0x0c, 0x04) 0 0x100000>;
145 + ranges = <0 MBUS_ID(0x0c, 0x04) 0 0x100000>;
146 + #address-cells = <1>;
147 + #size-cells = <1>;
148 + clocks = <&gateclk 13>;
149 + status = "okay";
150 +};
151 --- a/drivers/net/ethernet/marvell/Kconfig
152 +++ b/drivers/net/ethernet/marvell/Kconfig
153 @@ -40,6 +40,19 @@ config MVMDIO
154
155 This driver is used by the MV643XX_ETH and MVNETA drivers.
156
157 +config MVNETA_BM
158 + tristate "Marvell Armada 38x/XP network interface BM support"
159 + depends on MVNETA
160 + ---help---
161 + This driver supports auxiliary block of the network
162 + interface units in the Marvell ARMADA XP and ARMADA 38x SoC
163 + family, which is called buffer manager.
164 +
165 + This driver, when enabled, strictly cooperates with mvneta
166 + driver and is common for all network ports of the devices,
167 + even for Armada 370 SoC, which doesn't support hardware
168 + buffer management.
169 +
170 config MVNETA
171 tristate "Marvell Armada 370/38x/XP network interface support"
172 depends on PLAT_ORION
173 --- a/drivers/net/ethernet/marvell/Makefile
174 +++ b/drivers/net/ethernet/marvell/Makefile
175 @@ -4,6 +4,7 @@
176
177 obj-$(CONFIG_MVMDIO) += mvmdio.o
178 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
179 +obj-$(CONFIG_MVNETA_BM) += mvneta_bm.o
180 obj-$(CONFIG_MVNETA) += mvneta.o
181 obj-$(CONFIG_MVPP2) += mvpp2.o
182 obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o
183 --- a/drivers/net/ethernet/marvell/mvneta.c
184 +++ b/drivers/net/ethernet/marvell/mvneta.c
185 @@ -30,6 +30,7 @@
186 #include <linux/phy.h>
187 #include <linux/platform_device.h>
188 #include <linux/skbuff.h>
189 +#include "mvneta_bm.h"
190 #include <net/ip.h>
191 #include <net/ipv6.h>
192 #include <net/tso.h>
193 @@ -37,6 +38,10 @@
194 /* Registers */
195 #define MVNETA_RXQ_CONFIG_REG(q) (0x1400 + ((q) << 2))
196 #define MVNETA_RXQ_HW_BUF_ALLOC BIT(0)
197 +#define MVNETA_RXQ_SHORT_POOL_ID_SHIFT 4
198 +#define MVNETA_RXQ_SHORT_POOL_ID_MASK 0x30
199 +#define MVNETA_RXQ_LONG_POOL_ID_SHIFT 6
200 +#define MVNETA_RXQ_LONG_POOL_ID_MASK 0xc0
201 #define MVNETA_RXQ_PKT_OFFSET_ALL_MASK (0xf << 8)
202 #define MVNETA_RXQ_PKT_OFFSET_MASK(offs) ((offs) << 8)
203 #define MVNETA_RXQ_THRESHOLD_REG(q) (0x14c0 + ((q) << 2))
204 @@ -50,6 +55,9 @@
205 #define MVNETA_RXQ_STATUS_UPDATE_REG(q) (0x1500 + ((q) << 2))
206 #define MVNETA_RXQ_ADD_NON_OCCUPIED_SHIFT 16
207 #define MVNETA_RXQ_ADD_NON_OCCUPIED_MAX 255
208 +#define MVNETA_PORT_POOL_BUFFER_SZ_REG(pool) (0x1700 + ((pool) << 2))
209 +#define MVNETA_PORT_POOL_BUFFER_SZ_SHIFT 3
210 +#define MVNETA_PORT_POOL_BUFFER_SZ_MASK 0xfff8
211 #define MVNETA_PORT_RX_RESET 0x1cc0
212 #define MVNETA_PORT_RX_DMA_RESET BIT(0)
213 #define MVNETA_PHY_ADDR 0x2000
214 @@ -107,6 +115,7 @@
215 #define MVNETA_GMAC_CLOCK_DIVIDER 0x24f4
216 #define MVNETA_GMAC_1MS_CLOCK_ENABLE BIT(31)
217 #define MVNETA_ACC_MODE 0x2500
218 +#define MVNETA_BM_ADDRESS 0x2504
219 #define MVNETA_CPU_MAP(cpu) (0x2540 + ((cpu) << 2))
220 #define MVNETA_CPU_RXQ_ACCESS_ALL_MASK 0x000000ff
221 #define MVNETA_CPU_TXQ_ACCESS_ALL_MASK 0x0000ff00
222 @@ -253,7 +262,10 @@
223 #define MVNETA_CPU_D_CACHE_LINE_SIZE 32
224 #define MVNETA_TX_CSUM_DEF_SIZE 1600
225 #define MVNETA_TX_CSUM_MAX_SIZE 9800
226 -#define MVNETA_ACC_MODE_EXT 1
227 +#define MVNETA_ACC_MODE_EXT1 1
228 +#define MVNETA_ACC_MODE_EXT2 2
229 +
230 +#define MVNETA_MAX_DECODE_WIN 6
231
232 /* Timeout constants */
233 #define MVNETA_TX_DISABLE_TIMEOUT_MSEC 1000
234 @@ -293,7 +305,8 @@
235 ((addr >= txq->tso_hdrs_phys) && \
236 (addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE))
237
238 -#define MVNETA_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD)
239 +#define MVNETA_RX_GET_BM_POOL_ID(rxd) \
240 + (((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
241
242 struct mvneta_statistic {
243 unsigned short offset;
244 @@ -359,6 +372,7 @@ struct mvneta_pcpu_port {
245 };
246
247 struct mvneta_port {
248 + u8 id;
249 struct mvneta_pcpu_port __percpu *ports;
250 struct mvneta_pcpu_stats __percpu *stats;
251
252 @@ -392,6 +406,11 @@ struct mvneta_port {
253 unsigned int tx_csum_limit;
254 unsigned int use_inband_status:1;
255
256 + struct mvneta_bm *bm_priv;
257 + struct mvneta_bm_pool *pool_long;
258 + struct mvneta_bm_pool *pool_short;
259 + int bm_win_id;
260 +
261 u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
262
263 u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
264 @@ -417,6 +436,8 @@ struct mvneta_port {
265 #define MVNETA_TX_L4_CSUM_NOT BIT(31)
266
267 #define MVNETA_RXD_ERR_CRC 0x0
268 +#define MVNETA_RXD_BM_POOL_SHIFT 13
269 +#define MVNETA_RXD_BM_POOL_MASK (BIT(13) | BIT(14))
270 #define MVNETA_RXD_ERR_SUMMARY BIT(16)
271 #define MVNETA_RXD_ERR_OVERRUN BIT(17)
272 #define MVNETA_RXD_ERR_LEN BIT(18)
273 @@ -561,6 +582,9 @@ static int rxq_def;
274
275 static int rx_copybreak __read_mostly = 256;
276
277 +/* HW BM need that each port be identify by a unique ID */
278 +static int global_port_id;
279 +
280 #define MVNETA_DRIVER_NAME "mvneta"
281 #define MVNETA_DRIVER_VERSION "1.0"
282
283 @@ -827,6 +851,214 @@ static void mvneta_rxq_bm_disable(struct
284 mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
285 }
286
287 +/* Enable buffer management (BM) */
288 +static void mvneta_rxq_bm_enable(struct mvneta_port *pp,
289 + struct mvneta_rx_queue *rxq)
290 +{
291 + u32 val;
292 +
293 + val = mvreg_read(pp, MVNETA_RXQ_CONFIG_REG(rxq->id));
294 + val |= MVNETA_RXQ_HW_BUF_ALLOC;
295 + mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
296 +}
297 +
298 +/* Notify HW about port's assignment of pool for bigger packets */
299 +static void mvneta_rxq_long_pool_set(struct mvneta_port *pp,
300 + struct mvneta_rx_queue *rxq)
301 +{
302 + u32 val;
303 +
304 + val = mvreg_read(pp, MVNETA_RXQ_CONFIG_REG(rxq->id));
305 + val &= ~MVNETA_RXQ_LONG_POOL_ID_MASK;
306 + val |= (pp->pool_long->id << MVNETA_RXQ_LONG_POOL_ID_SHIFT);
307 +
308 + mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
309 +}
310 +
311 +/* Notify HW about port's assignment of pool for smaller packets */
312 +static void mvneta_rxq_short_pool_set(struct mvneta_port *pp,
313 + struct mvneta_rx_queue *rxq)
314 +{
315 + u32 val;
316 +
317 + val = mvreg_read(pp, MVNETA_RXQ_CONFIG_REG(rxq->id));
318 + val &= ~MVNETA_RXQ_SHORT_POOL_ID_MASK;
319 + val |= (pp->pool_short->id << MVNETA_RXQ_SHORT_POOL_ID_SHIFT);
320 +
321 + mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
322 +}
323 +
324 +/* Set port's receive buffer size for assigned BM pool */
325 +static inline void mvneta_bm_pool_bufsize_set(struct mvneta_port *pp,
326 + int buf_size,
327 + u8 pool_id)
328 +{
329 + u32 val;
330 +
331 + if (!IS_ALIGNED(buf_size, 8)) {
332 + dev_warn(pp->dev->dev.parent,
333 + "illegal buf_size value %d, round to %d\n",
334 + buf_size, ALIGN(buf_size, 8));
335 + buf_size = ALIGN(buf_size, 8);
336 + }
337 +
338 + val = mvreg_read(pp, MVNETA_PORT_POOL_BUFFER_SZ_REG(pool_id));
339 + val |= buf_size & MVNETA_PORT_POOL_BUFFER_SZ_MASK;
340 + mvreg_write(pp, MVNETA_PORT_POOL_BUFFER_SZ_REG(pool_id), val);
341 +}
342 +
343 +/* Configure MBUS window in order to enable access BM internal SRAM */
344 +static int mvneta_mbus_io_win_set(struct mvneta_port *pp, u32 base, u32 wsize,
345 + u8 target, u8 attr)
346 +{
347 + u32 win_enable, win_protect;
348 + int i;
349 +
350 + win_enable = mvreg_read(pp, MVNETA_BASE_ADDR_ENABLE);
351 +
352 + if (pp->bm_win_id < 0) {
353 + /* Find first not occupied window */
354 + for (i = 0; i < MVNETA_MAX_DECODE_WIN; i++) {
355 + if (win_enable & (1 << i)) {
356 + pp->bm_win_id = i;
357 + break;
358 + }
359 + }
360 + if (i == MVNETA_MAX_DECODE_WIN)
361 + return -ENOMEM;
362 + } else {
363 + i = pp->bm_win_id;
364 + }
365 +
366 + mvreg_write(pp, MVNETA_WIN_BASE(i), 0);
367 + mvreg_write(pp, MVNETA_WIN_SIZE(i), 0);
368 +
369 + if (i < 4)
370 + mvreg_write(pp, MVNETA_WIN_REMAP(i), 0);
371 +
372 + mvreg_write(pp, MVNETA_WIN_BASE(i), (base & 0xffff0000) |
373 + (attr << 8) | target);
374 +
375 + mvreg_write(pp, MVNETA_WIN_SIZE(i), (wsize - 1) & 0xffff0000);
376 +
377 + win_protect = mvreg_read(pp, MVNETA_ACCESS_PROTECT_ENABLE);
378 + win_protect |= 3 << (2 * i);
379 + mvreg_write(pp, MVNETA_ACCESS_PROTECT_ENABLE, win_protect);
380 +
381 + win_enable &= ~(1 << i);
382 + mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, win_enable);
383 +
384 + return 0;
385 +}
386 +
387 +/* Assign and initialize pools for port. In case of fail
388 + * buffer manager will remain disabled for current port.
389 + */
390 +static int mvneta_bm_port_init(struct platform_device *pdev,
391 + struct mvneta_port *pp)
392 +{
393 + struct device_node *dn = pdev->dev.of_node;
394 + u32 long_pool_id, short_pool_id, wsize;
395 + u8 target, attr;
396 + int err;
397 +
398 + /* Get BM window information */
399 + err = mvebu_mbus_get_io_win_info(pp->bm_priv->bppi_phys_addr, &wsize,
400 + &target, &attr);
401 + if (err < 0)
402 + return err;
403 +
404 + pp->bm_win_id = -1;
405 +
406 + /* Open NETA -> BM window */
407 + err = mvneta_mbus_io_win_set(pp, pp->bm_priv->bppi_phys_addr, wsize,
408 + target, attr);
409 + if (err < 0) {
410 + netdev_info(pp->dev, "fail to configure mbus window to BM\n");
411 + return err;
412 + }
413 +
414 + if (of_property_read_u32(dn, "bm,pool-long", &long_pool_id)) {
415 + netdev_info(pp->dev, "missing long pool id\n");
416 + return -EINVAL;
417 + }
418 +
419 + /* Create port's long pool depending on mtu */
420 + pp->pool_long = mvneta_bm_pool_use(pp->bm_priv, long_pool_id,
421 + MVNETA_BM_LONG, pp->id,
422 + MVNETA_RX_PKT_SIZE(pp->dev->mtu));
423 + if (!pp->pool_long) {
424 + netdev_info(pp->dev, "fail to obtain long pool for port\n");
425 + return -ENOMEM;
426 + }
427 +
428 + pp->pool_long->port_map |= 1 << pp->id;
429 +
430 + mvneta_bm_pool_bufsize_set(pp, pp->pool_long->buf_size,
431 + pp->pool_long->id);
432 +
433 + /* If short pool id is not defined, assume using single pool */
434 + if (of_property_read_u32(dn, "bm,pool-short", &short_pool_id))
435 + short_pool_id = long_pool_id;
436 +
437 + /* Create port's short pool */
438 + pp->pool_short = mvneta_bm_pool_use(pp->bm_priv, short_pool_id,
439 + MVNETA_BM_SHORT, pp->id,
440 + MVNETA_BM_SHORT_PKT_SIZE);
441 + if (!pp->pool_short) {
442 + netdev_info(pp->dev, "fail to obtain short pool for port\n");
443 + mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << pp->id);
444 + return -ENOMEM;
445 + }
446 +
447 + if (short_pool_id != long_pool_id) {
448 + pp->pool_short->port_map |= 1 << pp->id;
449 + mvneta_bm_pool_bufsize_set(pp, pp->pool_short->buf_size,
450 + pp->pool_short->id);
451 + }
452 +
453 + return 0;
454 +}
455 +
456 +/* Update settings of a pool for bigger packets */
457 +static void mvneta_bm_update_mtu(struct mvneta_port *pp, int mtu)
458 +{
459 + struct mvneta_bm_pool *bm_pool = pp->pool_long;
460 + int num;
461 +
462 + /* Release all buffers from long pool */
463 + mvneta_bm_bufs_free(pp->bm_priv, bm_pool, 1 << pp->id);
464 + if (bm_pool->buf_num) {
465 + WARN(1, "cannot free all buffers in pool %d\n",
466 + bm_pool->id);
467 + goto bm_mtu_err;
468 + }
469 +
470 + bm_pool->pkt_size = MVNETA_RX_PKT_SIZE(mtu);
471 + bm_pool->buf_size = MVNETA_RX_BUF_SIZE(bm_pool->pkt_size);
472 + bm_pool->frag_size = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
473 + SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(bm_pool->pkt_size));
474 +
475 + /* Fill entire long pool */
476 + num = mvneta_bm_bufs_add(pp->bm_priv, bm_pool, bm_pool->size);
477 + if (num != bm_pool->size) {
478 + WARN(1, "pool %d: %d of %d allocated\n",
479 + bm_pool->id, num, bm_pool->size);
480 + goto bm_mtu_err;
481 + }
482 + mvneta_bm_pool_bufsize_set(pp, bm_pool->buf_size, bm_pool->id);
483 +
484 + return;
485 +
486 +bm_mtu_err:
487 + mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << pp->id);
488 + mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short, 1 << pp->id);
489 +
490 + pp->bm_priv = NULL;
491 + mvreg_write(pp, MVNETA_ACC_MODE, MVNETA_ACC_MODE_EXT1);
492 + netdev_info(pp->dev, "fail to update MTU, fall back to software BM\n");
493 +}
494 +
495 /* Start the Ethernet port RX and TX activity */
496 static void mvneta_port_up(struct mvneta_port *pp)
497 {
498 @@ -1147,9 +1379,17 @@ static void mvneta_defaults_set(struct m
499 mvreg_write(pp, MVNETA_PORT_RX_RESET, 0);
500
501 /* Set Port Acceleration Mode */
502 - val = MVNETA_ACC_MODE_EXT;
503 + if (pp->bm_priv)
504 + /* HW buffer management + legacy parser */
505 + val = MVNETA_ACC_MODE_EXT2;
506 + else
507 + /* SW buffer management + legacy parser */
508 + val = MVNETA_ACC_MODE_EXT1;
509 mvreg_write(pp, MVNETA_ACC_MODE, val);
510
511 + if (pp->bm_priv)
512 + mvreg_write(pp, MVNETA_BM_ADDRESS, pp->bm_priv->bppi_phys_addr);
513 +
514 /* Update val of portCfg register accordingly with all RxQueue types */
515 val = MVNETA_PORT_CONFIG_DEFL_VALUE(pp->rxq_def);
516 mvreg_write(pp, MVNETA_PORT_CONFIG, val);
517 @@ -1516,23 +1756,25 @@ static void mvneta_txq_done(struct mvnet
518 }
519 }
520
521 -static void *mvneta_frag_alloc(const struct mvneta_port *pp)
522 +void *mvneta_frag_alloc(unsigned int frag_size)
523 {
524 - if (likely(pp->frag_size <= PAGE_SIZE))
525 - return netdev_alloc_frag(pp->frag_size);
526 + if (likely(frag_size <= PAGE_SIZE))
527 + return netdev_alloc_frag(frag_size);
528 else
529 - return kmalloc(pp->frag_size, GFP_ATOMIC);
530 + return kmalloc(frag_size, GFP_ATOMIC);
531 }
532 +EXPORT_SYMBOL_GPL(mvneta_frag_alloc);
533
534 -static void mvneta_frag_free(const struct mvneta_port *pp, void *data)
535 +void mvneta_frag_free(unsigned int frag_size, void *data)
536 {
537 - if (likely(pp->frag_size <= PAGE_SIZE))
538 + if (likely(frag_size <= PAGE_SIZE))
539 skb_free_frag(data);
540 else
541 kfree(data);
542 }
543 +EXPORT_SYMBOL_GPL(mvneta_frag_free);
544
545 -/* Refill processing */
546 +/* Refill processing for SW buffer management */
547 static int mvneta_rx_refill(struct mvneta_port *pp,
548 struct mvneta_rx_desc *rx_desc)
549
550 @@ -1540,7 +1782,7 @@ static int mvneta_rx_refill(struct mvnet
551 dma_addr_t phys_addr;
552 void *data;
553
554 - data = mvneta_frag_alloc(pp);
555 + data = mvneta_frag_alloc(pp->frag_size);
556 if (!data)
557 return -ENOMEM;
558
559 @@ -1548,7 +1790,7 @@ static int mvneta_rx_refill(struct mvnet
560 MVNETA_RX_BUF_SIZE(pp->pkt_size),
561 DMA_FROM_DEVICE);
562 if (unlikely(dma_mapping_error(pp->dev->dev.parent, phys_addr))) {
563 - mvneta_frag_free(pp, data);
564 + mvneta_frag_free(pp->frag_size, data);
565 return -ENOMEM;
566 }
567
568 @@ -1594,22 +1836,156 @@ static void mvneta_rxq_drop_pkts(struct
569 int rx_done, i;
570
571 rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
572 + if (rx_done)
573 + mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
574 +
575 + if (pp->bm_priv) {
576 + for (i = 0; i < rx_done; i++) {
577 + struct mvneta_rx_desc *rx_desc =
578 + mvneta_rxq_next_desc_get(rxq);
579 + u8 pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
580 + struct mvneta_bm_pool *bm_pool;
581 +
582 + bm_pool = &pp->bm_priv->bm_pools[pool_id];
583 + /* Return dropped buffer to the pool */
584 + mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
585 + rx_desc->buf_phys_addr);
586 + }
587 + return;
588 + }
589 +
590 for (i = 0; i < rxq->size; i++) {
591 struct mvneta_rx_desc *rx_desc = rxq->descs + i;
592 void *data = (void *)rx_desc->buf_cookie;
593
594 dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
595 MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
596 - mvneta_frag_free(pp, data);
597 + mvneta_frag_free(pp->frag_size, data);
598 }
599 +}
600
601 - if (rx_done)
602 - mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
603 +/* Main rx processing when using software buffer management */
604 +static int mvneta_rx_swbm(struct mvneta_port *pp, int rx_todo,
605 + struct mvneta_rx_queue *rxq)
606 +{
607 + struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
608 + struct net_device *dev = pp->dev;
609 + int rx_done;
610 + u32 rcvd_pkts = 0;
611 + u32 rcvd_bytes = 0;
612 +
613 + /* Get number of received packets */
614 + rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
615 +
616 + if (rx_todo > rx_done)
617 + rx_todo = rx_done;
618 +
619 + rx_done = 0;
620 +
621 + /* Fairness NAPI loop */
622 + while (rx_done < rx_todo) {
623 + struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq);
624 + struct sk_buff *skb;
625 + unsigned char *data;
626 + dma_addr_t phys_addr;
627 + u32 rx_status, frag_size;
628 + int rx_bytes, err;
629 +
630 + rx_done++;
631 + rx_status = rx_desc->status;
632 + rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
633 + data = (unsigned char *)rx_desc->buf_cookie;
634 + phys_addr = rx_desc->buf_phys_addr;
635 +
636 + if (!mvneta_rxq_desc_is_first_last(rx_status) ||
637 + (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
638 +err_drop_frame:
639 + dev->stats.rx_errors++;
640 + mvneta_rx_error(pp, rx_desc);
641 + /* leave the descriptor untouched */
642 + continue;
643 + }
644 +
645 + if (rx_bytes <= rx_copybreak) {
646 + /* better copy a small frame and not unmap the DMA region */
647 + skb = netdev_alloc_skb_ip_align(dev, rx_bytes);
648 + if (unlikely(!skb))
649 + goto err_drop_frame;
650 +
651 + dma_sync_single_range_for_cpu(dev->dev.parent,
652 + rx_desc->buf_phys_addr,
653 + MVNETA_MH_SIZE + NET_SKB_PAD,
654 + rx_bytes,
655 + DMA_FROM_DEVICE);
656 + memcpy(skb_put(skb, rx_bytes),
657 + data + MVNETA_MH_SIZE + NET_SKB_PAD,
658 + rx_bytes);
659 +
660 + skb->protocol = eth_type_trans(skb, dev);
661 + mvneta_rx_csum(pp, rx_status, skb);
662 + napi_gro_receive(&port->napi, skb);
663 +
664 + rcvd_pkts++;
665 + rcvd_bytes += rx_bytes;
666 +
667 + /* leave the descriptor and buffer untouched */
668 + continue;
669 + }
670 +
671 + /* Refill processing */
672 + err = mvneta_rx_refill(pp, rx_desc);
673 + if (err) {
674 + netdev_err(dev, "Linux processing - Can't refill\n");
675 + rxq->missed++;
676 + goto err_drop_frame;
677 + }
678 +
679 + frag_size = pp->frag_size;
680 +
681 + skb = build_skb(data, frag_size > PAGE_SIZE ? 0 : frag_size);
682 +
683 + /* After refill old buffer has to be unmapped regardless
684 + * the skb is successfully built or not.
685 + */
686 + dma_unmap_single(dev->dev.parent, phys_addr,
687 + MVNETA_RX_BUF_SIZE(pp->pkt_size),
688 + DMA_FROM_DEVICE);
689 +
690 + if (!skb)
691 + goto err_drop_frame;
692 +
693 + rcvd_pkts++;
694 + rcvd_bytes += rx_bytes;
695 +
696 + /* Linux processing */
697 + skb_reserve(skb, MVNETA_MH_SIZE + NET_SKB_PAD);
698 + skb_put(skb, rx_bytes);
699 +
700 + skb->protocol = eth_type_trans(skb, dev);
701 +
702 + mvneta_rx_csum(pp, rx_status, skb);
703 +
704 + napi_gro_receive(&port->napi, skb);
705 + }
706 +
707 + if (rcvd_pkts) {
708 + struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
709 +
710 + u64_stats_update_begin(&stats->syncp);
711 + stats->rx_packets += rcvd_pkts;
712 + stats->rx_bytes += rcvd_bytes;
713 + u64_stats_update_end(&stats->syncp);
714 + }
715 +
716 + /* Update rxq management counters */
717 + mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
718 +
719 + return rx_done;
720 }
721
722 -/* Main rx processing */
723 -static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
724 - struct mvneta_rx_queue *rxq)
725 +/* Main rx processing when using hardware buffer management */
726 +static int mvneta_rx_hwbm(struct mvneta_port *pp, int rx_todo,
727 + struct mvneta_rx_queue *rxq)
728 {
729 struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
730 struct net_device *dev = pp->dev;
731 @@ -1628,21 +2004,29 @@ static int mvneta_rx(struct mvneta_port
732 /* Fairness NAPI loop */
733 while (rx_done < rx_todo) {
734 struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq);
735 + struct mvneta_bm_pool *bm_pool = NULL;
736 struct sk_buff *skb;
737 unsigned char *data;
738 dma_addr_t phys_addr;
739 - u32 rx_status;
740 + u32 rx_status, frag_size;
741 int rx_bytes, err;
742 + u8 pool_id;
743
744 rx_done++;
745 rx_status = rx_desc->status;
746 rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
747 data = (unsigned char *)rx_desc->buf_cookie;
748 phys_addr = rx_desc->buf_phys_addr;
749 + pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
750 + bm_pool = &pp->bm_priv->bm_pools[pool_id];
751
752 if (!mvneta_rxq_desc_is_first_last(rx_status) ||
753 (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
754 - err_drop_frame:
755 +err_drop_frame_ret_pool:
756 + /* Return the buffer to the pool */
757 + mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
758 + rx_desc->buf_phys_addr);
759 +err_drop_frame:
760 dev->stats.rx_errors++;
761 mvneta_rx_error(pp, rx_desc);
762 /* leave the descriptor untouched */
763 @@ -1653,7 +2037,7 @@ static int mvneta_rx(struct mvneta_port
764 /* better copy a small frame and not unmap the DMA region */
765 skb = netdev_alloc_skb_ip_align(dev, rx_bytes);
766 if (unlikely(!skb))
767 - goto err_drop_frame;
768 + goto err_drop_frame_ret_pool;
769
770 dma_sync_single_range_for_cpu(dev->dev.parent,
771 rx_desc->buf_phys_addr,
772 @@ -1671,26 +2055,31 @@ static int mvneta_rx(struct mvneta_port
773 rcvd_pkts++;
774 rcvd_bytes += rx_bytes;
775
776 + /* Return the buffer to the pool */
777 + mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
778 + rx_desc->buf_phys_addr);
779 +
780 /* leave the descriptor and buffer untouched */
781 continue;
782 }
783
784 /* Refill processing */
785 - err = mvneta_rx_refill(pp, rx_desc);
786 + err = mvneta_bm_pool_refill(pp->bm_priv, bm_pool);
787 if (err) {
788 netdev_err(dev, "Linux processing - Can't refill\n");
789 rxq->missed++;
790 - goto err_drop_frame;
791 + goto err_drop_frame_ret_pool;
792 }
793
794 - skb = build_skb(data, pp->frag_size > PAGE_SIZE ? 0 : pp->frag_size);
795 + frag_size = bm_pool->frag_size;
796 +
797 + skb = build_skb(data, frag_size > PAGE_SIZE ? 0 : frag_size);
798
799 /* After refill old buffer has to be unmapped regardless
800 * the skb is successfully built or not.
801 */
802 - dma_unmap_single(dev->dev.parent, phys_addr,
803 - MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
804 -
805 + dma_unmap_single(&pp->bm_priv->pdev->dev, phys_addr,
806 + bm_pool->buf_size, DMA_FROM_DEVICE);
807 if (!skb)
808 goto err_drop_frame;
809
810 @@ -2295,7 +2684,10 @@ static int mvneta_poll(struct napi_struc
811
812 if (rx_queue) {
813 rx_queue = rx_queue - 1;
814 - rx_done = mvneta_rx(pp, budget, &pp->rxqs[rx_queue]);
815 + if (pp->bm_priv)
816 + rx_done = mvneta_rx_hwbm(pp, budget, &pp->rxqs[rx_queue]);
817 + else
818 + rx_done = mvneta_rx_swbm(pp, budget, &pp->rxqs[rx_queue]);
819 }
820
821 budget -= rx_done;
822 @@ -2384,9 +2776,17 @@ static int mvneta_rxq_init(struct mvneta
823 mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal);
824 mvneta_rx_time_coal_set(pp, rxq, rxq->time_coal);
825
826 - /* Fill RXQ with buffers from RX pool */
827 - mvneta_rxq_buf_size_set(pp, rxq, MVNETA_RX_BUF_SIZE(pp->pkt_size));
828 - mvneta_rxq_bm_disable(pp, rxq);
829 + if (!pp->bm_priv) {
830 + /* Fill RXQ with buffers from RX pool */
831 + mvneta_rxq_buf_size_set(pp, rxq,
832 + MVNETA_RX_BUF_SIZE(pp->pkt_size));
833 + mvneta_rxq_bm_disable(pp, rxq);
834 + } else {
835 + mvneta_rxq_bm_enable(pp, rxq);
836 + mvneta_rxq_long_pool_set(pp, rxq);
837 + mvneta_rxq_short_pool_set(pp, rxq);
838 + }
839 +
840 mvneta_rxq_fill(pp, rxq, rxq->size);
841
842 return 0;
843 @@ -2659,6 +3059,9 @@ static int mvneta_change_mtu(struct net_
844 dev->mtu = mtu;
845
846 if (!netif_running(dev)) {
847 + if (pp->bm_priv)
848 + mvneta_bm_update_mtu(pp, mtu);
849 +
850 netdev_update_features(dev);
851 return 0;
852 }
853 @@ -2671,6 +3074,9 @@ static int mvneta_change_mtu(struct net_
854 mvneta_cleanup_txqs(pp);
855 mvneta_cleanup_rxqs(pp);
856
857 + if (pp->bm_priv)
858 + mvneta_bm_update_mtu(pp, mtu);
859 +
860 pp->pkt_size = MVNETA_RX_PKT_SIZE(dev->mtu);
861 pp->frag_size = SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(pp->pkt_size)) +
862 SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
863 @@ -3563,6 +3969,7 @@ static int mvneta_probe(struct platform_
864 struct resource *res;
865 struct device_node *dn = pdev->dev.of_node;
866 struct device_node *phy_node;
867 + struct device_node *bm_node;
868 struct mvneta_port *pp;
869 struct net_device *dev;
870 const char *dt_mac_addr;
871 @@ -3690,26 +4097,39 @@ static int mvneta_probe(struct platform_
872
873 pp->tx_csum_limit = tx_csum_limit;
874
875 + dram_target_info = mv_mbus_dram_info();
876 + if (dram_target_info)
877 + mvneta_conf_mbus_windows(pp, dram_target_info);
878 +
879 pp->tx_ring_size = MVNETA_MAX_TXD;
880 pp->rx_ring_size = MVNETA_MAX_RXD;
881
882 pp->dev = dev;
883 SET_NETDEV_DEV(dev, &pdev->dev);
884
885 + pp->id = global_port_id++;
886 +
887 + /* Obtain access to BM resources if enabled and already initialized */
888 + bm_node = of_parse_phandle(dn, "buffer-manager", 0);
889 + if (bm_node && bm_node->data) {
890 + pp->bm_priv = bm_node->data;
891 + err = mvneta_bm_port_init(pdev, pp);
892 + if (err < 0) {
893 + dev_info(&pdev->dev, "use SW buffer management\n");
894 + pp->bm_priv = NULL;
895 + }
896 + }
897 +
898 err = mvneta_init(&pdev->dev, pp);
899 if (err < 0)
900 - goto err_free_stats;
901 + goto err_netdev;
902
903 err = mvneta_port_power_up(pp, phy_mode);
904 if (err < 0) {
905 dev_err(&pdev->dev, "can't power up port\n");
906 - goto err_free_stats;
907 + goto err_netdev;
908 }
909
910 - dram_target_info = mv_mbus_dram_info();
911 - if (dram_target_info)
912 - mvneta_conf_mbus_windows(pp, dram_target_info);
913 -
914 for_each_present_cpu(cpu) {
915 struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
916
917 @@ -3744,6 +4164,13 @@ static int mvneta_probe(struct platform_
918
919 return 0;
920
921 +err_netdev:
922 + unregister_netdev(dev);
923 + if (pp->bm_priv) {
924 + mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << pp->id);
925 + mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short,
926 + 1 << pp->id);
927 + }
928 err_free_stats:
929 free_percpu(pp->stats);
930 err_free_ports:
931 @@ -3773,6 +4200,12 @@ static int mvneta_remove(struct platform
932 of_node_put(pp->phy_node);
933 free_netdev(dev);
934
935 + if (pp->bm_priv) {
936 + mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << pp->id);
937 + mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short,
938 + 1 << pp->id);
939 + }
940 +
941 return 0;
942 }
943
944 --- /dev/null
945 +++ b/drivers/net/ethernet/marvell/mvneta_bm.c
946 @@ -0,0 +1,546 @@
947 +/*
948 + * Driver for Marvell NETA network controller Buffer Manager.
949 + *
950 + * Copyright (C) 2015 Marvell
951 + *
952 + * Marcin Wojtas <mw@semihalf.com>
953 + *
954 + * This file is licensed under the terms of the GNU General Public
955 + * License version 2. This program is licensed "as is" without any
956 + * warranty of any kind, whether express or implied.
957 + */
958 +
959 +#include <linux/kernel.h>
960 +#include <linux/genalloc.h>
961 +#include <linux/platform_device.h>
962 +#include <linux/netdevice.h>
963 +#include <linux/skbuff.h>
964 +#include <linux/mbus.h>
965 +#include <linux/module.h>
966 +#include <linux/io.h>
967 +#include <linux/of.h>
968 +#include <linux/clk.h>
969 +#include "mvneta_bm.h"
970 +
971 +#define MVNETA_BM_DRIVER_NAME "mvneta_bm"
972 +#define MVNETA_BM_DRIVER_VERSION "1.0"
973 +
974 +static void mvneta_bm_write(struct mvneta_bm *priv, u32 offset, u32 data)
975 +{
976 + writel(data, priv->reg_base + offset);
977 +}
978 +
979 +static u32 mvneta_bm_read(struct mvneta_bm *priv, u32 offset)
980 +{
981 + return readl(priv->reg_base + offset);
982 +}
983 +
984 +static void mvneta_bm_pool_enable(struct mvneta_bm *priv, int pool_id)
985 +{
986 + u32 val;
987 +
988 + val = mvneta_bm_read(priv, MVNETA_BM_POOL_BASE_REG(pool_id));
989 + val |= MVNETA_BM_POOL_ENABLE_MASK;
990 + mvneta_bm_write(priv, MVNETA_BM_POOL_BASE_REG(pool_id), val);
991 +
992 + /* Clear BM cause register */
993 + mvneta_bm_write(priv, MVNETA_BM_INTR_CAUSE_REG, 0);
994 +}
995 +
996 +static void mvneta_bm_pool_disable(struct mvneta_bm *priv, int pool_id)
997 +{
998 + u32 val;
999 +
1000 + val = mvneta_bm_read(priv, MVNETA_BM_POOL_BASE_REG(pool_id));
1001 + val &= ~MVNETA_BM_POOL_ENABLE_MASK;
1002 + mvneta_bm_write(priv, MVNETA_BM_POOL_BASE_REG(pool_id), val);
1003 +}
1004 +
1005 +static inline void mvneta_bm_config_set(struct mvneta_bm *priv, u32 mask)
1006 +{
1007 + u32 val;
1008 +
1009 + val = mvneta_bm_read(priv, MVNETA_BM_CONFIG_REG);
1010 + val |= mask;
1011 + mvneta_bm_write(priv, MVNETA_BM_CONFIG_REG, val);
1012 +}
1013 +
1014 +static inline void mvneta_bm_config_clear(struct mvneta_bm *priv, u32 mask)
1015 +{
1016 + u32 val;
1017 +
1018 + val = mvneta_bm_read(priv, MVNETA_BM_CONFIG_REG);
1019 + val &= ~mask;
1020 + mvneta_bm_write(priv, MVNETA_BM_CONFIG_REG, val);
1021 +}
1022 +
1023 +static void mvneta_bm_pool_target_set(struct mvneta_bm *priv, int pool_id,
1024 + u8 target_id, u8 attr)
1025 +{
1026 + u32 val;
1027 +
1028 + val = mvneta_bm_read(priv, MVNETA_BM_XBAR_POOL_REG(pool_id));
1029 + val &= ~MVNETA_BM_TARGET_ID_MASK(pool_id);
1030 + val &= ~MVNETA_BM_XBAR_ATTR_MASK(pool_id);
1031 + val |= MVNETA_BM_TARGET_ID_VAL(pool_id, target_id);
1032 + val |= MVNETA_BM_XBAR_ATTR_VAL(pool_id, attr);
1033 +
1034 + mvneta_bm_write(priv, MVNETA_BM_XBAR_POOL_REG(pool_id), val);
1035 +}
1036 +
1037 +/* Allocate skb for BM pool */
1038 +void *mvneta_buf_alloc(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
1039 + dma_addr_t *buf_phys_addr)
1040 +{
1041 + void *buf;
1042 + dma_addr_t phys_addr;
1043 +
1044 + buf = mvneta_frag_alloc(bm_pool->frag_size);
1045 + if (!buf)
1046 + return NULL;
1047 +
1048 + /* In order to update buf_cookie field of RX descriptor properly,
1049 + * BM hardware expects buf virtual address to be placed in the
1050 + * first four bytes of mapped buffer.
1051 + */
1052 + *(u32 *)buf = (u32)buf;
1053 + phys_addr = dma_map_single(&priv->pdev->dev, buf, bm_pool->buf_size,
1054 + DMA_FROM_DEVICE);
1055 + if (unlikely(dma_mapping_error(&priv->pdev->dev, phys_addr))) {
1056 + mvneta_frag_free(bm_pool->frag_size, buf);
1057 + return NULL;
1058 + }
1059 + *buf_phys_addr = phys_addr;
1060 +
1061 + return buf;
1062 +}
1063 +
1064 +/* Refill processing for HW buffer management */
1065 +int mvneta_bm_pool_refill(struct mvneta_bm *priv,
1066 + struct mvneta_bm_pool *bm_pool)
1067 +{
1068 + dma_addr_t buf_phys_addr;
1069 + void *buf;
1070 +
1071 + buf = mvneta_buf_alloc(priv, bm_pool, &buf_phys_addr);
1072 + if (!buf)
1073 + return -ENOMEM;
1074 +
1075 + mvneta_bm_pool_put_bp(priv, bm_pool, buf_phys_addr);
1076 +
1077 + return 0;
1078 +}
1079 +EXPORT_SYMBOL_GPL(mvneta_bm_pool_refill);
1080 +
1081 +/* Allocate buffers for the pool */
1082 +int mvneta_bm_bufs_add(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
1083 + int buf_num)
1084 +{
1085 + int err, i;
1086 +
1087 + if (bm_pool->buf_num == bm_pool->size) {
1088 + dev_dbg(&priv->pdev->dev, "pool %d already filled\n",
1089 + bm_pool->id);
1090 + return bm_pool->buf_num;
1091 + }
1092 +
1093 + if (buf_num < 0 ||
1094 + (buf_num + bm_pool->buf_num > bm_pool->size)) {
1095 + dev_err(&priv->pdev->dev,
1096 + "cannot allocate %d buffers for pool %d\n",
1097 + buf_num, bm_pool->id);
1098 + return 0;
1099 + }
1100 +
1101 + for (i = 0; i < buf_num; i++) {
1102 + err = mvneta_bm_pool_refill(priv, bm_pool);
1103 + if (err < 0)
1104 + break;
1105 + }
1106 +
1107 + /* Update BM driver with number of buffers added to pool */
1108 + bm_pool->buf_num += i;
1109 +
1110 + dev_dbg(&priv->pdev->dev,
1111 + "%s pool %d: pkt_size=%4d, buf_size=%4d, frag_size=%4d\n",
1112 + bm_pool->type == MVNETA_BM_SHORT ? "short" : "long",
1113 + bm_pool->id, bm_pool->pkt_size, bm_pool->buf_size,
1114 + bm_pool->frag_size);
1115 +
1116 + dev_dbg(&priv->pdev->dev,
1117 + "%s pool %d: %d of %d buffers added\n",
1118 + bm_pool->type == MVNETA_BM_SHORT ? "short" : "long",
1119 + bm_pool->id, i, buf_num);
1120 +
1121 + return i;
1122 +}
1123 +EXPORT_SYMBOL_GPL(mvneta_bm_bufs_add);
1124 +
1125 +/* Create pool */
1126 +static int mvneta_bm_pool_create(struct mvneta_bm *priv,
1127 + struct mvneta_bm_pool *bm_pool)
1128 +{
1129 + struct platform_device *pdev = priv->pdev;
1130 + u8 target_id, attr;
1131 + int size_bytes, err;
1132 +
1133 + size_bytes = sizeof(u32) * bm_pool->size;
1134 + bm_pool->virt_addr = dma_alloc_coherent(&pdev->dev, size_bytes,
1135 + &bm_pool->phys_addr,
1136 + GFP_KERNEL);
1137 + if (!bm_pool->virt_addr)
1138 + return -ENOMEM;
1139 +
1140 + if (!IS_ALIGNED((u32)bm_pool->virt_addr, MVNETA_BM_POOL_PTR_ALIGN)) {
1141 + dma_free_coherent(&pdev->dev, size_bytes, bm_pool->virt_addr,
1142 + bm_pool->phys_addr);
1143 + dev_err(&pdev->dev, "BM pool %d is not %d bytes aligned\n",
1144 + bm_pool->id, MVNETA_BM_POOL_PTR_ALIGN);
1145 + return -ENOMEM;
1146 + }
1147 +
1148 + err = mvebu_mbus_get_dram_win_info(bm_pool->phys_addr, &target_id,
1149 + &attr);
1150 + if (err < 0) {
1151 + dma_free_coherent(&pdev->dev, size_bytes, bm_pool->virt_addr,
1152 + bm_pool->phys_addr);
1153 + return err;
1154 + }
1155 +
1156 + /* Set pool address */
1157 + mvneta_bm_write(priv, MVNETA_BM_POOL_BASE_REG(bm_pool->id),
1158 + bm_pool->phys_addr);
1159 +
1160 + mvneta_bm_pool_target_set(priv, bm_pool->id, target_id, attr);
1161 + mvneta_bm_pool_enable(priv, bm_pool->id);
1162 +
1163 + return 0;
1164 +}
1165 +
1166 +/* Notify the driver that BM pool is being used as specific type and return the
1167 + * pool pointer on success
1168 + */
1169 +struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
1170 + enum mvneta_bm_type type, u8 port_id,
1171 + int pkt_size)
1172 +{
1173 + struct mvneta_bm_pool *new_pool = &priv->bm_pools[pool_id];
1174 + int num, err;
1175 +
1176 + if (new_pool->type == MVNETA_BM_LONG &&
1177 + new_pool->port_map != 1 << port_id) {
1178 + dev_err(&priv->pdev->dev,
1179 + "long pool cannot be shared by the ports\n");
1180 + return NULL;
1181 + }
1182 +
1183 + if (new_pool->type == MVNETA_BM_SHORT && new_pool->type != type) {
1184 + dev_err(&priv->pdev->dev,
1185 + "mixing pools' types between the ports is forbidden\n");
1186 + return NULL;
1187 + }
1188 +
1189 + if (new_pool->pkt_size == 0 || type != MVNETA_BM_SHORT)
1190 + new_pool->pkt_size = pkt_size;
1191 +
1192 + /* Allocate buffers in case BM pool hasn't been used yet */
1193 + if (new_pool->type == MVNETA_BM_FREE) {
1194 + new_pool->type = type;
1195 + new_pool->buf_size = MVNETA_RX_BUF_SIZE(new_pool->pkt_size);
1196 + new_pool->frag_size =
1197 + SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(new_pool->pkt_size)) +
1198 + SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
1199 +
1200 + /* Create new pool */
1201 + err = mvneta_bm_pool_create(priv, new_pool);
1202 + if (err) {
1203 + dev_err(&priv->pdev->dev, "fail to create pool %d\n",
1204 + new_pool->id);
1205 + return NULL;
1206 + }
1207 +
1208 + /* Allocate buffers for this pool */
1209 + num = mvneta_bm_bufs_add(priv, new_pool, new_pool->size);
1210 + if (num != new_pool->size) {
1211 + WARN(1, "pool %d: %d of %d allocated\n",
1212 + new_pool->id, num, new_pool->size);
1213 + return NULL;
1214 + }
1215 + }
1216 +
1217 + return new_pool;
1218 +}
1219 +EXPORT_SYMBOL_GPL(mvneta_bm_pool_use);
1220 +
1221 +/* Free all buffers from the pool */
1222 +void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
1223 + u8 port_map)
1224 +{
1225 + int i;
1226 +
1227 + bm_pool->port_map &= ~port_map;
1228 + if (bm_pool->port_map)
1229 + return;
1230 +
1231 + mvneta_bm_config_set(priv, MVNETA_BM_EMPTY_LIMIT_MASK);
1232 +
1233 + for (i = 0; i < bm_pool->buf_num; i++) {
1234 + dma_addr_t buf_phys_addr;
1235 + u32 *vaddr;
1236 +
1237 + /* Get buffer physical address (indirect access) */
1238 + buf_phys_addr = mvneta_bm_pool_get_bp(priv, bm_pool);
1239 +
1240 + /* Work-around to the problems when destroying the pool,
1241 + * when it occurs that a read access to BPPI returns 0.
1242 + */
1243 + if (buf_phys_addr == 0)
1244 + continue;
1245 +
1246 + vaddr = phys_to_virt(buf_phys_addr);
1247 + if (!vaddr)
1248 + break;
1249 +
1250 + dma_unmap_single(&priv->pdev->dev, buf_phys_addr,
1251 + bm_pool->buf_size, DMA_FROM_DEVICE);
1252 + mvneta_frag_free(bm_pool->frag_size, vaddr);
1253 + }
1254 +
1255 + mvneta_bm_config_clear(priv, MVNETA_BM_EMPTY_LIMIT_MASK);
1256 +
1257 + /* Update BM driver with number of buffers removed from pool */
1258 + bm_pool->buf_num -= i;
1259 +}
1260 +EXPORT_SYMBOL_GPL(mvneta_bm_bufs_free);
1261 +
1262 +/* Cleanup pool */
1263 +void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
1264 + struct mvneta_bm_pool *bm_pool, u8 port_map)
1265 +{
1266 + bm_pool->port_map &= ~port_map;
1267 + if (bm_pool->port_map)
1268 + return;
1269 +
1270 + bm_pool->type = MVNETA_BM_FREE;
1271 +
1272 + mvneta_bm_bufs_free(priv, bm_pool, port_map);
1273 + if (bm_pool->buf_num)
1274 + WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id);
1275 +
1276 + if (bm_pool->virt_addr) {
1277 + dma_free_coherent(&priv->pdev->dev, sizeof(u32) * bm_pool->size,
1278 + bm_pool->virt_addr, bm_pool->phys_addr);
1279 + bm_pool->virt_addr = NULL;
1280 + }
1281 +
1282 + mvneta_bm_pool_disable(priv, bm_pool->id);
1283 +}
1284 +EXPORT_SYMBOL_GPL(mvneta_bm_pool_destroy);
1285 +
1286 +static void mvneta_bm_pools_init(struct mvneta_bm *priv)
1287 +{
1288 + struct device_node *dn = priv->pdev->dev.of_node;
1289 + struct mvneta_bm_pool *bm_pool;
1290 + char prop[15];
1291 + u32 size;
1292 + int i;
1293 +
1294 + /* Activate BM unit */
1295 + mvneta_bm_write(priv, MVNETA_BM_COMMAND_REG, MVNETA_BM_START_MASK);
1296 +
1297 + /* Create all pools with maximum size */
1298 + for (i = 0; i < MVNETA_BM_POOLS_NUM; i++) {
1299 + bm_pool = &priv->bm_pools[i];
1300 + bm_pool->id = i;
1301 + bm_pool->type = MVNETA_BM_FREE;
1302 +
1303 + /* Reset read pointer */
1304 + mvneta_bm_write(priv, MVNETA_BM_POOL_READ_PTR_REG(i), 0);
1305 +
1306 + /* Reset write pointer */
1307 + mvneta_bm_write(priv, MVNETA_BM_POOL_WRITE_PTR_REG(i), 0);
1308 +
1309 + /* Configure pool size according to DT or use default value */
1310 + sprintf(prop, "pool%d,capacity", i);
1311 + if (of_property_read_u32(dn, prop, &size)) {
1312 + size = MVNETA_BM_POOL_CAP_DEF;
1313 + } else if (size > MVNETA_BM_POOL_CAP_MAX) {
1314 + dev_warn(&priv->pdev->dev,
1315 + "Illegal pool %d capacity %d, set to %d\n",
1316 + i, size, MVNETA_BM_POOL_CAP_MAX);
1317 + size = MVNETA_BM_POOL_CAP_MAX;
1318 + } else if (size < MVNETA_BM_POOL_CAP_MIN) {
1319 + dev_warn(&priv->pdev->dev,
1320 + "Illegal pool %d capacity %d, set to %d\n",
1321 + i, size, MVNETA_BM_POOL_CAP_MIN);
1322 + size = MVNETA_BM_POOL_CAP_MIN;
1323 + } else if (!IS_ALIGNED(size, MVNETA_BM_POOL_CAP_ALIGN)) {
1324 + dev_warn(&priv->pdev->dev,
1325 + "Illegal pool %d capacity %d, round to %d\n",
1326 + i, size, ALIGN(size,
1327 + MVNETA_BM_POOL_CAP_ALIGN));
1328 + size = ALIGN(size, MVNETA_BM_POOL_CAP_ALIGN);
1329 + }
1330 + bm_pool->size = size;
1331 +
1332 + mvneta_bm_write(priv, MVNETA_BM_POOL_SIZE_REG(i),
1333 + bm_pool->size);
1334 +
1335 + /* Obtain custom pkt_size from DT */
1336 + sprintf(prop, "pool%d,pkt-size", i);
1337 + if (of_property_read_u32(dn, prop, &bm_pool->pkt_size))
1338 + bm_pool->pkt_size = 0;
1339 + }
1340 +}
1341 +
1342 +static void mvneta_bm_default_set(struct mvneta_bm *priv)
1343 +{
1344 + u32 val;
1345 +
1346 + /* Mask BM all interrupts */
1347 + mvneta_bm_write(priv, MVNETA_BM_INTR_MASK_REG, 0);
1348 +
1349 + /* Clear BM cause register */
1350 + mvneta_bm_write(priv, MVNETA_BM_INTR_CAUSE_REG, 0);
1351 +
1352 + /* Set BM configuration register */
1353 + val = mvneta_bm_read(priv, MVNETA_BM_CONFIG_REG);
1354 +
1355 + /* Reduce MaxInBurstSize from 32 BPs to 16 BPs */
1356 + val &= ~MVNETA_BM_MAX_IN_BURST_SIZE_MASK;
1357 + val |= MVNETA_BM_MAX_IN_BURST_SIZE_16BP;
1358 + mvneta_bm_write(priv, MVNETA_BM_CONFIG_REG, val);
1359 +}
1360 +
1361 +static int mvneta_bm_init(struct mvneta_bm *priv)
1362 +{
1363 + mvneta_bm_default_set(priv);
1364 +
1365 + /* Allocate and initialize BM pools structures */
1366 + priv->bm_pools = devm_kcalloc(&priv->pdev->dev, MVNETA_BM_POOLS_NUM,
1367 + sizeof(struct mvneta_bm_pool),
1368 + GFP_KERNEL);
1369 + if (!priv->bm_pools)
1370 + return -ENOMEM;
1371 +
1372 + mvneta_bm_pools_init(priv);
1373 +
1374 + return 0;
1375 +}
1376 +
1377 +static int mvneta_bm_get_sram(struct device_node *dn,
1378 + struct mvneta_bm *priv)
1379 +{
1380 + priv->bppi_pool = of_gen_pool_get(dn, "internal-mem", 0);
1381 + if (!priv->bppi_pool)
1382 + return -ENOMEM;
1383 +
1384 + priv->bppi_virt_addr = gen_pool_dma_alloc(priv->bppi_pool,
1385 + MVNETA_BM_BPPI_SIZE,
1386 + &priv->bppi_phys_addr);
1387 + if (!priv->bppi_virt_addr)
1388 + return -ENOMEM;
1389 +
1390 + return 0;
1391 +}
1392 +
1393 +static void mvneta_bm_put_sram(struct mvneta_bm *priv)
1394 +{
1395 + gen_pool_free(priv->bppi_pool, priv->bppi_phys_addr,
1396 + MVNETA_BM_BPPI_SIZE);
1397 +}
1398 +
1399 +static int mvneta_bm_probe(struct platform_device *pdev)
1400 +{
1401 + struct device_node *dn = pdev->dev.of_node;
1402 + struct mvneta_bm *priv;
1403 + struct resource *res;
1404 + int err;
1405 +
1406 + priv = devm_kzalloc(&pdev->dev, sizeof(struct mvneta_bm), GFP_KERNEL);
1407 + if (!priv)
1408 + return -ENOMEM;
1409 +
1410 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1411 + priv->reg_base = devm_ioremap_resource(&pdev->dev, res);
1412 + if (IS_ERR(priv->reg_base))
1413 + return PTR_ERR(priv->reg_base);
1414 +
1415 + priv->clk = devm_clk_get(&pdev->dev, NULL);
1416 + if (IS_ERR(priv->clk))
1417 + return PTR_ERR(priv->clk);
1418 + err = clk_prepare_enable(priv->clk);
1419 + if (err < 0)
1420 + return err;
1421 +
1422 + err = mvneta_bm_get_sram(dn, priv);
1423 + if (err < 0) {
1424 + dev_err(&pdev->dev, "failed to allocate internal memory\n");
1425 + goto err_clk;
1426 + }
1427 +
1428 + priv->pdev = pdev;
1429 +
1430 + /* Initialize buffer manager internals */
1431 + err = mvneta_bm_init(priv);
1432 + if (err < 0) {
1433 + dev_err(&pdev->dev, "failed to initialize controller\n");
1434 + goto err_sram;
1435 + }
1436 +
1437 + dn->data = priv;
1438 + platform_set_drvdata(pdev, priv);
1439 +
1440 + dev_info(&pdev->dev, "Buffer Manager for network controller enabled\n");
1441 +
1442 + return 0;
1443 +
1444 +err_sram:
1445 + mvneta_bm_put_sram(priv);
1446 +err_clk:
1447 + clk_disable_unprepare(priv->clk);
1448 + return err;
1449 +}
1450 +
1451 +static int mvneta_bm_remove(struct platform_device *pdev)
1452 +{
1453 + struct mvneta_bm *priv = platform_get_drvdata(pdev);
1454 + u8 all_ports_map = 0xff;
1455 + int i = 0;
1456 +
1457 + for (i = 0; i < MVNETA_BM_POOLS_NUM; i++) {
1458 + struct mvneta_bm_pool *bm_pool = &priv->bm_pools[i];
1459 +
1460 + mvneta_bm_pool_destroy(priv, bm_pool, all_ports_map);
1461 + }
1462 +
1463 + mvneta_bm_put_sram(priv);
1464 +
1465 + /* Dectivate BM unit */
1466 + mvneta_bm_write(priv, MVNETA_BM_COMMAND_REG, MVNETA_BM_STOP_MASK);
1467 +
1468 + clk_disable_unprepare(priv->clk);
1469 +
1470 + return 0;
1471 +}
1472 +
1473 +static const struct of_device_id mvneta_bm_match[] = {
1474 + { .compatible = "marvell,armada-380-neta-bm" },
1475 + { }
1476 +};
1477 +MODULE_DEVICE_TABLE(of, mvneta_bm_match);
1478 +
1479 +static struct platform_driver mvneta_bm_driver = {
1480 + .probe = mvneta_bm_probe,
1481 + .remove = mvneta_bm_remove,
1482 + .driver = {
1483 + .name = MVNETA_BM_DRIVER_NAME,
1484 + .of_match_table = mvneta_bm_match,
1485 + },
1486 +};
1487 +
1488 +module_platform_driver(mvneta_bm_driver);
1489 +
1490 +MODULE_DESCRIPTION("Marvell NETA Buffer Manager Driver - www.marvell.com");
1491 +MODULE_AUTHOR("Marcin Wojtas <mw@semihalf.com>");
1492 +MODULE_LICENSE("GPL v2");
1493 --- /dev/null
1494 +++ b/drivers/net/ethernet/marvell/mvneta_bm.h
1495 @@ -0,0 +1,189 @@
1496 +/*
1497 + * Driver for Marvell NETA network controller Buffer Manager.
1498 + *
1499 + * Copyright (C) 2015 Marvell
1500 + *
1501 + * Marcin Wojtas <mw@semihalf.com>
1502 + *
1503 + * This file is licensed under the terms of the GNU General Public
1504 + * License version 2. This program is licensed "as is" without any
1505 + * warranty of any kind, whether express or implied.
1506 + */
1507 +
1508 +#ifndef _MVNETA_BM_H_
1509 +#define _MVNETA_BM_H_
1510 +
1511 +/* BM Configuration Register */
1512 +#define MVNETA_BM_CONFIG_REG 0x0
1513 +#define MVNETA_BM_STATUS_MASK 0x30
1514 +#define MVNETA_BM_ACTIVE_MASK BIT(4)
1515 +#define MVNETA_BM_MAX_IN_BURST_SIZE_MASK 0x60000
1516 +#define MVNETA_BM_MAX_IN_BURST_SIZE_16BP BIT(18)
1517 +#define MVNETA_BM_EMPTY_LIMIT_MASK BIT(19)
1518 +
1519 +/* BM Activation Register */
1520 +#define MVNETA_BM_COMMAND_REG 0x4
1521 +#define MVNETA_BM_START_MASK BIT(0)
1522 +#define MVNETA_BM_STOP_MASK BIT(1)
1523 +#define MVNETA_BM_PAUSE_MASK BIT(2)
1524 +
1525 +/* BM Xbar interface Register */
1526 +#define MVNETA_BM_XBAR_01_REG 0x8
1527 +#define MVNETA_BM_XBAR_23_REG 0xc
1528 +#define MVNETA_BM_XBAR_POOL_REG(pool) \
1529 + (((pool) < 2) ? MVNETA_BM_XBAR_01_REG : MVNETA_BM_XBAR_23_REG)
1530 +#define MVNETA_BM_TARGET_ID_OFFS(pool) (((pool) & 1) ? 16 : 0)
1531 +#define MVNETA_BM_TARGET_ID_MASK(pool) \
1532 + (0xf << MVNETA_BM_TARGET_ID_OFFS(pool))
1533 +#define MVNETA_BM_TARGET_ID_VAL(pool, id) \
1534 + ((id) << MVNETA_BM_TARGET_ID_OFFS(pool))
1535 +#define MVNETA_BM_XBAR_ATTR_OFFS(pool) (((pool) & 1) ? 20 : 4)
1536 +#define MVNETA_BM_XBAR_ATTR_MASK(pool) \
1537 + (0xff << MVNETA_BM_XBAR_ATTR_OFFS(pool))
1538 +#define MVNETA_BM_XBAR_ATTR_VAL(pool, attr) \
1539 + ((attr) << MVNETA_BM_XBAR_ATTR_OFFS(pool))
1540 +
1541 +/* Address of External Buffer Pointers Pool Register */
1542 +#define MVNETA_BM_POOL_BASE_REG(pool) (0x10 + ((pool) << 4))
1543 +#define MVNETA_BM_POOL_ENABLE_MASK BIT(0)
1544 +
1545 +/* External Buffer Pointers Pool RD pointer Register */
1546 +#define MVNETA_BM_POOL_READ_PTR_REG(pool) (0x14 + ((pool) << 4))
1547 +#define MVNETA_BM_POOL_SET_READ_PTR_MASK 0xfffc
1548 +#define MVNETA_BM_POOL_GET_READ_PTR_OFFS 16
1549 +#define MVNETA_BM_POOL_GET_READ_PTR_MASK 0xfffc0000
1550 +
1551 +/* External Buffer Pointers Pool WR pointer */
1552 +#define MVNETA_BM_POOL_WRITE_PTR_REG(pool) (0x18 + ((pool) << 4))
1553 +#define MVNETA_BM_POOL_SET_WRITE_PTR_OFFS 0
1554 +#define MVNETA_BM_POOL_SET_WRITE_PTR_MASK 0xfffc
1555 +#define MVNETA_BM_POOL_GET_WRITE_PTR_OFFS 16
1556 +#define MVNETA_BM_POOL_GET_WRITE_PTR_MASK 0xfffc0000
1557 +
1558 +/* External Buffer Pointers Pool Size Register */
1559 +#define MVNETA_BM_POOL_SIZE_REG(pool) (0x1c + ((pool) << 4))
1560 +#define MVNETA_BM_POOL_SIZE_MASK 0x3fff
1561 +
1562 +/* BM Interrupt Cause Register */
1563 +#define MVNETA_BM_INTR_CAUSE_REG (0x50)
1564 +
1565 +/* BM interrupt Mask Register */
1566 +#define MVNETA_BM_INTR_MASK_REG (0x54)
1567 +
1568 +/* Other definitions */
1569 +#define MVNETA_BM_SHORT_PKT_SIZE 256
1570 +#define MVNETA_BM_POOLS_NUM 4
1571 +#define MVNETA_BM_POOL_CAP_MIN 128
1572 +#define MVNETA_BM_POOL_CAP_DEF 2048
1573 +#define MVNETA_BM_POOL_CAP_MAX \
1574 + (16 * 1024 - MVNETA_BM_POOL_CAP_ALIGN)
1575 +#define MVNETA_BM_POOL_CAP_ALIGN 32
1576 +#define MVNETA_BM_POOL_PTR_ALIGN 32
1577 +
1578 +#define MVNETA_BM_POOL_ACCESS_OFFS 8
1579 +
1580 +#define MVNETA_BM_BPPI_SIZE 0x100000
1581 +
1582 +#define MVNETA_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD)
1583 +
1584 +enum mvneta_bm_type {
1585 + MVNETA_BM_FREE,
1586 + MVNETA_BM_LONG,
1587 + MVNETA_BM_SHORT
1588 +};
1589 +
1590 +struct mvneta_bm {
1591 + void __iomem *reg_base;
1592 + struct clk *clk;
1593 + struct platform_device *pdev;
1594 +
1595 + struct gen_pool *bppi_pool;
1596 + /* BPPI virtual base address */
1597 + void __iomem *bppi_virt_addr;
1598 + /* BPPI physical base address */
1599 + dma_addr_t bppi_phys_addr;
1600 +
1601 + /* BM pools */
1602 + struct mvneta_bm_pool *bm_pools;
1603 +};
1604 +
1605 +struct mvneta_bm_pool {
1606 + /* Pool number in the range 0-3 */
1607 + u8 id;
1608 + enum mvneta_bm_type type;
1609 +
1610 + /* Buffer Pointers Pool External (BPPE) size in number of bytes */
1611 + int size;
1612 + /* Number of buffers used by this pool */
1613 + int buf_num;
1614 + /* Pool buffer size */
1615 + int buf_size;
1616 + /* Packet size */
1617 + int pkt_size;
1618 + /* Single frag size */
1619 + u32 frag_size;
1620 +
1621 + /* BPPE virtual base address */
1622 + u32 *virt_addr;
1623 + /* BPPE physical base address */
1624 + dma_addr_t phys_addr;
1625 +
1626 + /* Ports using BM pool */
1627 + u8 port_map;
1628 +
1629 + struct mvneta_bm *priv;
1630 +};
1631 +
1632 +/* Declarations and definitions */
1633 +void *mvneta_frag_alloc(unsigned int frag_size);
1634 +void mvneta_frag_free(unsigned int frag_size, void *data);
1635 +
1636 +#if defined(CONFIG_MVNETA_BM) || defined(CONFIG_MVNETA_BM_MODULE)
1637 +void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
1638 + struct mvneta_bm_pool *bm_pool, u8 port_map);
1639 +void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
1640 + u8 port_map);
1641 +int mvneta_bm_bufs_add(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
1642 + int buf_num);
1643 +int mvneta_bm_pool_refill(struct mvneta_bm *priv,
1644 + struct mvneta_bm_pool *bm_pool);
1645 +struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
1646 + enum mvneta_bm_type type, u8 port_id,
1647 + int pkt_size);
1648 +
1649 +static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv,
1650 + struct mvneta_bm_pool *bm_pool,
1651 + dma_addr_t buf_phys_addr)
1652 +{
1653 + writel_relaxed(buf_phys_addr, priv->bppi_virt_addr +
1654 + (bm_pool->id << MVNETA_BM_POOL_ACCESS_OFFS));
1655 +}
1656 +
1657 +static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv,
1658 + struct mvneta_bm_pool *bm_pool)
1659 +{
1660 + return readl_relaxed(priv->bppi_virt_addr +
1661 + (bm_pool->id << MVNETA_BM_POOL_ACCESS_OFFS));
1662 +}
1663 +#else
1664 +void mvneta_bm_pool_destroy(struct mvneta_bm *priv,
1665 + struct mvneta_bm_pool *bm_pool, u8 port_map) {}
1666 +void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
1667 + u8 port_map) {}
1668 +int mvneta_bm_bufs_add(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool,
1669 + int buf_num) { return 0; }
1670 +int mvneta_bm_pool_refill(struct mvneta_bm *priv,
1671 + struct mvneta_bm_pool *bm_pool) {return 0; }
1672 +struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
1673 + enum mvneta_bm_type type, u8 port_id,
1674 + int pkt_size) { return NULL; }
1675 +
1676 +static inline void mvneta_bm_pool_put_bp(struct mvneta_bm *priv,
1677 + struct mvneta_bm_pool *bm_pool,
1678 + dma_addr_t buf_phys_addr) {}
1679 +
1680 +static inline u32 mvneta_bm_pool_get_bp(struct mvneta_bm *priv,
1681 + struct mvneta_bm_pool *bm_pool)
1682 +{ return 0; }
1683 +#endif /* CONFIG_MVNETA_BM */
1684 +#endif