045-net-mvneta-bm-add-support-for-hardware-buffer-manage.patch 50 KB

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