7215-dpaa2-evb-Added-Edge-Virtual-Bridge-driver.patch 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918
  1. From 54bcaca10728c1a1c8adfa48124ea79cce4ef929 Mon Sep 17 00:00:00 2001
  2. From: Razvan Stefanescu <razvan.stefanescu@freescale.com>
  3. Date: Tue, 22 Sep 2015 08:43:08 +0300
  4. Subject: [PATCH 215/226] dpaa2-evb: Added Edge Virtual Bridge driver
  5. This is a commit of the cummulative, squashed dpaa2-evb patches.
  6. All the commit logs are preserved below.
  7. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
  8. ----------------------------------------------------------------
  9. dpaa2-evb: Added Edge Virtual Bridge driver
  10. This contains the following patches migrated from linux-v4.0:
  11. staging: fsl-dpaa2: evb: Added Edge Virtual Bridge driver
  12. staging: fsl-dpaa2: evb: Added ethtool port counters
  13. staging: fsl-dpaa2: evb: Include by default in configuration
  14. staging: fsl-dpaa2: evb: Rebasing onto kernel 4.0
  15. staging: fsl-dpaa2: evb: Port to MC-0.7 FLibs
  16. dpaa2-evb: Set carrier state on port open
  17. dpaa2-evb: Add support for link state update
  18. dpaa2-evb: Update flib to MC 8.0.1
  19. staging: fsl-mc: migrated remaining flibs for MC fw 8.0.0 (split)
  20. Inital patches have been signed-off by:
  21. Alex Marginean <alexandru.marginean@freescale.com>
  22. J. German Rivera <German.Rivera@freescale.com>
  23. Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
  24. Razvan Stefanescu <razvan.stefanescu@freescale.com>
  25. And reviewed by:
  26. Stuart Yoder <stuart.yoder@freescale.com>
  27. Porting to linux-v4.1 requires changes related to iflink usage and
  28. ndo_bridge_getlink() parameters list.
  29. Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
  30. dpaa2-evb: Port to linux-v4.1
  31. Update iflink usage.
  32. Update evb_getlink() parameter list to match ndo_bridge_getlink().
  33. Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
  34. dpaa2-evb: Add VLAN_8021Q dependency
  35. EVB traffic steering methods related to VLAN require VLAN support in kernel.
  36. Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
  37. dpaa2-evb: Update dpdmux binary interface to 5.0
  38. This corresponds to MC release 0.8.0.
  39. Signed-off-by: Razvan Stefanescu <razvan.stefanescu@freescale.com>
  40. dpaa2-evb: Add support to set max frame length.
  41. All the packets bigger than max_frame_length will be dropped.
  42. Signed-off-by: Mihaela Panescu <mihaela.panescu@freescale.com>
  43. dpaa2-evb: resolve compile issues on uprev to 4.5
  44. -irq_number field no longer exists in fsl-mc interrupt
  45. struct
  46. -netdev_master_upper_dev_link() has 2 new parameters, which
  47. are set to NULL for now
  48. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>
  49. ---
  50. MAINTAINERS | 6 +
  51. drivers/staging/fsl-dpaa2/Kconfig | 1 +
  52. drivers/staging/fsl-dpaa2/Makefile | 1 +
  53. drivers/staging/fsl-dpaa2/evb/Kconfig | 8 +
  54. drivers/staging/fsl-dpaa2/evb/Makefile | 10 +
  55. drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h | 256 ++++++
  56. drivers/staging/fsl-dpaa2/evb/dpdmux.c | 567 +++++++++++++
  57. drivers/staging/fsl-dpaa2/evb/dpdmux.h | 724 +++++++++++++++++
  58. drivers/staging/fsl-dpaa2/evb/evb.c | 1216 ++++++++++++++++++++++++++++
  59. 9 files changed, 2789 insertions(+)
  60. create mode 100644 drivers/staging/fsl-dpaa2/evb/Kconfig
  61. create mode 100644 drivers/staging/fsl-dpaa2/evb/Makefile
  62. create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h
  63. create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux.c
  64. create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux.h
  65. create mode 100644 drivers/staging/fsl-dpaa2/evb/evb.c
  66. --- a/MAINTAINERS
  67. +++ b/MAINTAINERS
  68. @@ -4560,6 +4560,12 @@ L: linux-kernel@vger.kernel.org
  69. S: Maintained
  70. F: drivers/staging/fsl-dpaa2/mac/
  71. ++FREESCALE DPAA2 EDGE VIRTUAL BRIDGE DRIVER
  72. +M: Alex Marginean <Alexandru.Marginean@freescale.com>
  73. +L: linux-kernel@vger.kernel.org
  74. +S: Maintained
  75. +F: drivers/staging/fsl-dpaa2/evb/
  76. +
  77. FREEVXFS FILESYSTEM
  78. M: Christoph Hellwig <hch@infradead.org>
  79. W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
  80. --- a/drivers/staging/fsl-dpaa2/Kconfig
  81. +++ b/drivers/staging/fsl-dpaa2/Kconfig
  82. @@ -10,3 +10,4 @@ config FSL_DPAA2
  83. # TODO move DPIO driver in-here?
  84. source "drivers/staging/fsl-dpaa2/ethernet/Kconfig"
  85. source "drivers/staging/fsl-dpaa2/mac/Kconfig"
  86. +source "drivers/staging/fsl-dpaa2/evb/Kconfig"
  87. --- a/drivers/staging/fsl-dpaa2/Makefile
  88. +++ b/drivers/staging/fsl-dpaa2/Makefile
  89. @@ -4,3 +4,4 @@
  90. obj-$(CONFIG_FSL_DPAA2_ETH) += ethernet/
  91. obj-$(CONFIG_FSL_DPAA2_MAC) += mac/
  92. +obj-$(CONFIG_FSL_DPAA2_EVB) += evb/
  93. --- /dev/null
  94. +++ b/drivers/staging/fsl-dpaa2/evb/Kconfig
  95. @@ -0,0 +1,8 @@
  96. +config FSL_DPAA2_EVB
  97. + tristate "DPAA2 Edge Virtual Bridge"
  98. + depends on FSL_MC_BUS && FSL_DPAA2 && FSL_DPAA2_ETH
  99. + select FSL_DPAA2_MAC
  100. + select VLAN_8021Q
  101. + default y
  102. + ---help---
  103. + Prototype driver for DPAA2 Edge Virtual Bridge.
  104. --- /dev/null
  105. +++ b/drivers/staging/fsl-dpaa2/evb/Makefile
  106. @@ -0,0 +1,10 @@
  107. +
  108. +obj-$(CONFIG_FSL_DPAA2_EVB) += dpaa2-evb.o
  109. +
  110. +dpaa2-evb-objs := evb.o dpdmux.o
  111. +
  112. +all:
  113. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  114. +
  115. +clean:
  116. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  117. --- /dev/null
  118. +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h
  119. @@ -0,0 +1,256 @@
  120. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  121. + *
  122. + * Redistribution and use in source and binary forms, with or without
  123. + * modification, are permitted provided that the following conditions are met:
  124. + * * Redistributions of source code must retain the above copyright
  125. + * notice, this list of conditions and the following disclaimer.
  126. + * * Redistributions in binary form must reproduce the above copyright
  127. + * notice, this list of conditions and the following disclaimer in the
  128. + * documentation and/or other materials provided with the distribution.
  129. + * * Neither the name of the above-listed copyright holders nor the
  130. + * names of any contributors may be used to endorse or promote products
  131. + * derived from this software without specific prior written permission.
  132. + *
  133. + *
  134. + * ALTERNATIVELY, this software may be distributed under the terms of the
  135. + * GNU General Public License ("GPL") as published by the Free Software
  136. + * Foundation, either version 2 of that License or (at your option) any
  137. + * later version.
  138. + *
  139. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  140. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  141. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  142. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  143. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  144. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  145. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  146. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  147. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  148. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  149. + * POSSIBILITY OF SUCH DAMAGE.
  150. + */
  151. +#ifndef _FSL_DPDMUX_CMD_H
  152. +#define _FSL_DPDMUX_CMD_H
  153. +
  154. +/* DPDMUX Version */
  155. +#define DPDMUX_VER_MAJOR 5
  156. +#define DPDMUX_VER_MINOR 0
  157. +
  158. +/* Command IDs */
  159. +#define DPDMUX_CMDID_CLOSE 0x800
  160. +#define DPDMUX_CMDID_OPEN 0x806
  161. +#define DPDMUX_CMDID_CREATE 0x906
  162. +#define DPDMUX_CMDID_DESTROY 0x900
  163. +
  164. +#define DPDMUX_CMDID_ENABLE 0x002
  165. +#define DPDMUX_CMDID_DISABLE 0x003
  166. +#define DPDMUX_CMDID_GET_ATTR 0x004
  167. +#define DPDMUX_CMDID_RESET 0x005
  168. +#define DPDMUX_CMDID_IS_ENABLED 0x006
  169. +
  170. +#define DPDMUX_CMDID_SET_IRQ 0x010
  171. +#define DPDMUX_CMDID_GET_IRQ 0x011
  172. +#define DPDMUX_CMDID_SET_IRQ_ENABLE 0x012
  173. +#define DPDMUX_CMDID_GET_IRQ_ENABLE 0x013
  174. +#define DPDMUX_CMDID_SET_IRQ_MASK 0x014
  175. +#define DPDMUX_CMDID_GET_IRQ_MASK 0x015
  176. +#define DPDMUX_CMDID_GET_IRQ_STATUS 0x016
  177. +#define DPDMUX_CMDID_CLEAR_IRQ_STATUS 0x017
  178. +
  179. +#define DPDMUX_CMDID_UL_SET_MAX_FRAME_LENGTH 0x0a1
  180. +
  181. +#define DPDMUX_CMDID_UL_RESET_COUNTERS 0x0a3
  182. +
  183. +#define DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES 0x0a7
  184. +#define DPDMUX_CMDID_IF_GET_ATTR 0x0a8
  185. +
  186. +#define DPDMUX_CMDID_IF_ADD_L2_RULE 0x0b0
  187. +#define DPDMUX_CMDID_IF_REMOVE_L2_RULE 0x0b1
  188. +#define DPDMUX_CMDID_IF_GET_COUNTER 0x0b2
  189. +#define DPDMUX_CMDID_IF_SET_LINK_CFG 0x0b3
  190. +#define DPDMUX_CMDID_IF_GET_LINK_STATE 0x0b4
  191. +
  192. +/* cmd, param, offset, width, type, arg_name */
  193. +#define DPDMUX_CMD_OPEN(cmd, dpdmux_id) \
  194. + MC_CMD_OP(cmd, 0, 0, 32, int, dpdmux_id)
  195. +
  196. +/* cmd, param, offset, width, type, arg_name */
  197. +#define DPDMUX_CMD_CREATE(cmd, cfg) \
  198. +do { \
  199. + MC_CMD_OP(cmd, 0, 0, 8, enum dpdmux_method, cfg->method);\
  200. + MC_CMD_OP(cmd, 0, 8, 8, enum dpdmux_manip, cfg->manip);\
  201. + MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\
  202. + MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->adv.max_dmat_entries);\
  203. + MC_CMD_OP(cmd, 1, 16, 16, uint16_t, cfg->adv.max_mc_groups);\
  204. + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->adv.max_vlan_ids);\
  205. + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->adv.options);\
  206. +} while (0)
  207. +
  208. +/* cmd, param, offset, width, type, arg_name */
  209. +#define DPDMUX_RSP_IS_ENABLED(cmd, en) \
  210. + MC_RSP_OP(cmd, 0, 0, 1, int, en)
  211. +
  212. +/* cmd, param, offset, width, type, arg_name */
  213. +#define DPDMUX_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \
  214. +do { \
  215. + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\
  216. + MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\
  217. + MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\
  218. + MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \
  219. +} while (0)
  220. +
  221. +/* cmd, param, offset, width, type, arg_name */
  222. +#define DPDMUX_CMD_GET_IRQ(cmd, irq_index) \
  223. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
  224. +
  225. +/* cmd, param, offset, width, type, arg_name */
  226. +#define DPDMUX_RSP_GET_IRQ(cmd, type, irq_cfg) \
  227. +do { \
  228. + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \
  229. + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \
  230. + MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \
  231. + MC_RSP_OP(cmd, 2, 32, 32, int, type); \
  232. +} while (0)
  233. +
  234. +/* cmd, param, offset, width, type, arg_name */
  235. +#define DPDMUX_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
  236. +do { \
  237. + MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en);\
  238. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
  239. +} while (0)
  240. +
  241. +/* cmd, param, offset, width, type, arg_name */
  242. +#define DPDMUX_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
  243. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
  244. +
  245. +/* cmd, param, offset, width, type, arg_name */
  246. +#define DPDMUX_RSP_GET_IRQ_ENABLE(cmd, en) \
  247. + MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en)
  248. +
  249. +/* cmd, param, offset, width, type, arg_name */
  250. +#define DPDMUX_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
  251. +do { \
  252. + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \
  253. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \
  254. +} while (0)
  255. +
  256. +/* cmd, param, offset, width, type, arg_name */
  257. +#define DPDMUX_CMD_GET_IRQ_MASK(cmd, irq_index) \
  258. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
  259. +
  260. +/* cmd, param, offset, width, type, arg_name */
  261. +#define DPDMUX_RSP_GET_IRQ_MASK(cmd, mask) \
  262. + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask)
  263. +
  264. +/* cmd, param, offset, width, type, arg_name */
  265. +#define DPDMUX_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \
  266. +do { \
  267. + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\
  268. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
  269. +} while (0)
  270. +
  271. +/* cmd, param, offset, width, type, arg_name */
  272. +#define DPDMUX_RSP_GET_IRQ_STATUS(cmd, status) \
  273. + MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) \
  274. +
  275. +/* cmd, param, offset, width, type, arg_name */
  276. +#define DPDMUX_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
  277. +do { \
  278. + MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \
  279. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \
  280. +} while (0)
  281. +
  282. +#define DPDMUX_RSP_GET_ATTR(cmd, attr) \
  283. +do { \
  284. + MC_RSP_OP(cmd, 0, 0, 8, enum dpdmux_method, attr->method);\
  285. + MC_RSP_OP(cmd, 0, 8, 8, enum dpdmux_manip, attr->manip);\
  286. + MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->num_ifs);\
  287. + MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->mem_size);\
  288. + MC_RSP_OP(cmd, 2, 0, 32, int, attr->id);\
  289. + MC_RSP_OP(cmd, 3, 0, 64, uint64_t, attr->options);\
  290. + MC_RSP_OP(cmd, 4, 0, 16, uint16_t, attr->version.major);\
  291. + MC_RSP_OP(cmd, 4, 16, 16, uint16_t, attr->version.minor);\
  292. +} while (0)
  293. +
  294. +/* cmd, param, offset, width, type, arg_name */
  295. +#define DPDMUX_CMD_UL_SET_MAX_FRAME_LENGTH(cmd, max_frame_length) \
  296. + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, max_frame_length)
  297. +
  298. +/* cmd, param, offset, width, type, arg_name */
  299. +#define DPDMUX_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg) \
  300. +do { \
  301. + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
  302. + MC_CMD_OP(cmd, 0, 16, 4, enum dpdmux_accepted_frames_type, cfg->type);\
  303. + MC_CMD_OP(cmd, 0, 20, 4, enum dpdmux_unaccepted_frames_action, \
  304. + cfg->unaccept_act);\
  305. +} while (0)
  306. +
  307. +/* cmd, param, offset, width, type, arg_name */
  308. +#define DPDMUX_CMD_IF_GET_ATTR(cmd, if_id) \
  309. + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
  310. +
  311. +/* cmd, param, offset, width, type, arg_name */
  312. +#define DPDMUX_RSP_IF_GET_ATTR(cmd, attr) \
  313. +do { \
  314. + MC_RSP_OP(cmd, 0, 56, 4, enum dpdmux_accepted_frames_type, \
  315. + attr->accept_frame_type);\
  316. + MC_RSP_OP(cmd, 0, 24, 1, int, attr->enabled);\
  317. + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->rate);\
  318. +} while (0)
  319. +
  320. +#define DPDMUX_CMD_IF_REMOVE_L2_RULE(cmd, if_id, l2_rule) \
  321. +do { \
  322. + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
  323. + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, l2_rule->mac_addr[5]);\
  324. + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, l2_rule->mac_addr[4]);\
  325. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, l2_rule->mac_addr[3]);\
  326. + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, l2_rule->mac_addr[2]);\
  327. + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, l2_rule->mac_addr[1]);\
  328. + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, l2_rule->mac_addr[0]);\
  329. + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, l2_rule->vlan_id);\
  330. +} while (0)
  331. +
  332. +#define DPDMUX_CMD_IF_ADD_L2_RULE(cmd, if_id, l2_rule) \
  333. +do { \
  334. + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
  335. + MC_CMD_OP(cmd, 0, 16, 8, uint8_t, l2_rule->mac_addr[5]);\
  336. + MC_CMD_OP(cmd, 0, 24, 8, uint8_t, l2_rule->mac_addr[4]);\
  337. + MC_CMD_OP(cmd, 0, 32, 8, uint8_t, l2_rule->mac_addr[3]);\
  338. + MC_CMD_OP(cmd, 0, 40, 8, uint8_t, l2_rule->mac_addr[2]);\
  339. + MC_CMD_OP(cmd, 0, 48, 8, uint8_t, l2_rule->mac_addr[1]);\
  340. + MC_CMD_OP(cmd, 0, 56, 8, uint8_t, l2_rule->mac_addr[0]);\
  341. + MC_CMD_OP(cmd, 1, 32, 16, uint16_t, l2_rule->vlan_id);\
  342. +} while (0)
  343. +
  344. +/* cmd, param, offset, width, type, arg_name */
  345. +#define DPDMUX_CMD_IF_GET_COUNTER(cmd, if_id, counter_type) \
  346. +do { \
  347. + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
  348. + MC_CMD_OP(cmd, 0, 16, 8, enum dpdmux_counter_type, counter_type);\
  349. +} while (0)
  350. +
  351. +/* cmd, param, offset, width, type, arg_name */
  352. +#define DPDMUX_RSP_IF_GET_COUNTER(cmd, counter) \
  353. + MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter)
  354. +
  355. +/* cmd, param, offset, width, type, arg_name */
  356. +#define DPDMUX_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg) \
  357. +do { \
  358. + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\
  359. + MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\
  360. + MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\
  361. +} while (0)
  362. +
  363. +/* cmd, param, offset, width, type, arg_name */
  364. +#define DPDMUX_CMD_IF_GET_LINK_STATE(cmd, if_id) \
  365. + MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id)
  366. +
  367. +/* cmd, param, offset, width, type, arg_name */
  368. +#define DPDMUX_RSP_IF_GET_LINK_STATE(cmd, state) \
  369. +do { \
  370. + MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\
  371. + MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\
  372. + MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\
  373. +} while (0)
  374. +
  375. +#endif /* _FSL_DPDMUX_CMD_H */
  376. --- /dev/null
  377. +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux.c
  378. @@ -0,0 +1,567 @@
  379. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  380. + *
  381. + * Redistribution and use in source and binary forms, with or without
  382. + * modification, are permitted provided that the following conditions are met:
  383. + * * Redistributions of source code must retain the above copyright
  384. + * notice, this list of conditions and the following disclaimer.
  385. + * * Redistributions in binary form must reproduce the above copyright
  386. + * notice, this list of conditions and the following disclaimer in the
  387. + * documentation and/or other materials provided with the distribution.
  388. + * * Neither the name of the above-listed copyright holders nor the
  389. + * names of any contributors may be used to endorse or promote products
  390. + * derived from this software without specific prior written permission.
  391. + *
  392. + *
  393. + * ALTERNATIVELY, this software may be distributed under the terms of the
  394. + * GNU General Public License ("GPL") as published by the Free Software
  395. + * Foundation, either version 2 of that License or (at your option) any
  396. + * later version.
  397. + *
  398. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  399. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  400. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  401. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  402. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  403. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  404. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  405. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  406. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  407. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  408. + * POSSIBILITY OF SUCH DAMAGE.
  409. + */
  410. +#include "../../fsl-mc/include/mc-sys.h"
  411. +#include "../../fsl-mc/include/mc-cmd.h"
  412. +#include "dpdmux.h"
  413. +#include "dpdmux-cmd.h"
  414. +
  415. +int dpdmux_open(struct fsl_mc_io *mc_io,
  416. + uint32_t cmd_flags,
  417. + int dpdmux_id,
  418. + uint16_t *token)
  419. +{
  420. + struct mc_command cmd = { 0 };
  421. + int err;
  422. +
  423. + /* prepare command */
  424. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_OPEN,
  425. + cmd_flags,
  426. + 0);
  427. + DPDMUX_CMD_OPEN(cmd, dpdmux_id);
  428. +
  429. + /* send command to mc*/
  430. + err = mc_send_command(mc_io, &cmd);
  431. + if (err)
  432. + return err;
  433. +
  434. + /* retrieve response parameters */
  435. + *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
  436. +
  437. + return 0;
  438. +}
  439. +
  440. +int dpdmux_close(struct fsl_mc_io *mc_io,
  441. + uint32_t cmd_flags,
  442. + uint16_t token)
  443. +{
  444. + struct mc_command cmd = { 0 };
  445. +
  446. + /* prepare command */
  447. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLOSE,
  448. + cmd_flags,
  449. + token);
  450. +
  451. + /* send command to mc*/
  452. + return mc_send_command(mc_io, &cmd);
  453. +}
  454. +
  455. +int dpdmux_create(struct fsl_mc_io *mc_io,
  456. + uint32_t cmd_flags,
  457. + const struct dpdmux_cfg *cfg,
  458. + uint16_t *token)
  459. +{
  460. + struct mc_command cmd = { 0 };
  461. + int err;
  462. +
  463. + /* prepare command */
  464. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CREATE,
  465. + cmd_flags,
  466. + 0);
  467. + DPDMUX_CMD_CREATE(cmd, cfg);
  468. +
  469. + /* send command to mc*/
  470. + err = mc_send_command(mc_io, &cmd);
  471. + if (err)
  472. + return err;
  473. +
  474. + /* retrieve response parameters */
  475. + *token = MC_CMD_HDR_READ_TOKEN(cmd.header);
  476. +
  477. + return 0;
  478. +}
  479. +
  480. +int dpdmux_destroy(struct fsl_mc_io *mc_io,
  481. + uint32_t cmd_flags,
  482. + uint16_t token)
  483. +{
  484. + struct mc_command cmd = { 0 };
  485. +
  486. + /* prepare command */
  487. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DESTROY,
  488. + cmd_flags,
  489. + token);
  490. +
  491. + /* send command to mc*/
  492. + return mc_send_command(mc_io, &cmd);
  493. +}
  494. +
  495. +int dpdmux_enable(struct fsl_mc_io *mc_io,
  496. + uint32_t cmd_flags,
  497. + uint16_t token)
  498. +{
  499. + struct mc_command cmd = { 0 };
  500. +
  501. + /* prepare command */
  502. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_ENABLE,
  503. + cmd_flags,
  504. + token);
  505. +
  506. + /* send command to mc*/
  507. + return mc_send_command(mc_io, &cmd);
  508. +}
  509. +
  510. +int dpdmux_disable(struct fsl_mc_io *mc_io,
  511. + uint32_t cmd_flags,
  512. + uint16_t token)
  513. +{
  514. + struct mc_command cmd = { 0 };
  515. +
  516. + /* prepare command */
  517. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DISABLE,
  518. + cmd_flags,
  519. + token);
  520. +
  521. + /* send command to mc*/
  522. + return mc_send_command(mc_io, &cmd);
  523. +}
  524. +
  525. +int dpdmux_is_enabled(struct fsl_mc_io *mc_io,
  526. + uint32_t cmd_flags,
  527. + uint16_t token,
  528. + int *en)
  529. +{
  530. + struct mc_command cmd = { 0 };
  531. + int err;
  532. + /* prepare command */
  533. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IS_ENABLED,
  534. + cmd_flags,
  535. + token);
  536. +
  537. + /* send command to mc*/
  538. + err = mc_send_command(mc_io, &cmd);
  539. + if (err)
  540. + return err;
  541. +
  542. + /* retrieve response parameters */
  543. + DPDMUX_RSP_IS_ENABLED(cmd, *en);
  544. +
  545. + return 0;
  546. +}
  547. +
  548. +int dpdmux_reset(struct fsl_mc_io *mc_io,
  549. + uint32_t cmd_flags,
  550. + uint16_t token)
  551. +{
  552. + struct mc_command cmd = { 0 };
  553. +
  554. + /* prepare command */
  555. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_RESET,
  556. + cmd_flags,
  557. + token);
  558. +
  559. + /* send command to mc*/
  560. + return mc_send_command(mc_io, &cmd);
  561. +}
  562. +
  563. +int dpdmux_set_irq(struct fsl_mc_io *mc_io,
  564. + uint32_t cmd_flags,
  565. + uint16_t token,
  566. + uint8_t irq_index,
  567. + struct dpdmux_irq_cfg *irq_cfg)
  568. +{
  569. + struct mc_command cmd = { 0 };
  570. +
  571. + /* prepare command */
  572. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ,
  573. + cmd_flags,
  574. + token);
  575. + DPDMUX_CMD_SET_IRQ(cmd, irq_index, irq_cfg);
  576. +
  577. + /* send command to mc*/
  578. + return mc_send_command(mc_io, &cmd);
  579. +}
  580. +
  581. +int dpdmux_get_irq(struct fsl_mc_io *mc_io,
  582. + uint32_t cmd_flags,
  583. + uint16_t token,
  584. + uint8_t irq_index,
  585. + int *type,
  586. + struct dpdmux_irq_cfg *irq_cfg)
  587. +{
  588. + struct mc_command cmd = { 0 };
  589. + int err;
  590. +
  591. + /* prepare command */
  592. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ,
  593. + cmd_flags,
  594. + token);
  595. + DPDMUX_CMD_GET_IRQ(cmd, irq_index);
  596. +
  597. + /* send command to mc*/
  598. + err = mc_send_command(mc_io, &cmd);
  599. + if (err)
  600. + return err;
  601. +
  602. + /* retrieve response parameters */
  603. + DPDMUX_RSP_GET_IRQ(cmd, *type, irq_cfg);
  604. +
  605. + return 0;
  606. +}
  607. +
  608. +int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io,
  609. + uint32_t cmd_flags,
  610. + uint16_t token,
  611. + uint8_t irq_index,
  612. + uint8_t en)
  613. +{
  614. + struct mc_command cmd = { 0 };
  615. +
  616. + /* prepare command */
  617. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_ENABLE,
  618. + cmd_flags,
  619. + token);
  620. + DPDMUX_CMD_SET_IRQ_ENABLE(cmd, irq_index, en);
  621. +
  622. + /* send command to mc*/
  623. + return mc_send_command(mc_io, &cmd);
  624. +}
  625. +
  626. +int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io,
  627. + uint32_t cmd_flags,
  628. + uint16_t token,
  629. + uint8_t irq_index,
  630. + uint8_t *en)
  631. +{
  632. + struct mc_command cmd = { 0 };
  633. + int err;
  634. +
  635. + /* prepare command */
  636. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_ENABLE,
  637. + cmd_flags,
  638. + token);
  639. + DPDMUX_CMD_GET_IRQ_ENABLE(cmd, irq_index);
  640. +
  641. + /* send command to mc*/
  642. + err = mc_send_command(mc_io, &cmd);
  643. + if (err)
  644. + return err;
  645. +
  646. + /* retrieve response parameters */
  647. + DPDMUX_RSP_GET_IRQ_ENABLE(cmd, *en);
  648. +
  649. + return 0;
  650. +}
  651. +
  652. +int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io,
  653. + uint32_t cmd_flags,
  654. + uint16_t token,
  655. + uint8_t irq_index,
  656. + uint32_t mask)
  657. +{
  658. + struct mc_command cmd = { 0 };
  659. +
  660. + /* prepare command */
  661. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_MASK,
  662. + cmd_flags,
  663. + token);
  664. + DPDMUX_CMD_SET_IRQ_MASK(cmd, irq_index, mask);
  665. +
  666. + /* send command to mc*/
  667. + return mc_send_command(mc_io, &cmd);
  668. +}
  669. +
  670. +int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io,
  671. + uint32_t cmd_flags,
  672. + uint16_t token,
  673. + uint8_t irq_index,
  674. + uint32_t *mask)
  675. +{
  676. + struct mc_command cmd = { 0 };
  677. + int err;
  678. +
  679. + /* prepare command */
  680. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_MASK,
  681. + cmd_flags,
  682. + token);
  683. + DPDMUX_CMD_GET_IRQ_MASK(cmd, irq_index);
  684. +
  685. + /* send command to mc*/
  686. + err = mc_send_command(mc_io, &cmd);
  687. + if (err)
  688. + return err;
  689. +
  690. + /* retrieve response parameters */
  691. + DPDMUX_RSP_GET_IRQ_MASK(cmd, *mask);
  692. +
  693. + return 0;
  694. +}
  695. +
  696. +int dpdmux_get_irq_status(struct fsl_mc_io *mc_io,
  697. + uint32_t cmd_flags,
  698. + uint16_t token,
  699. + uint8_t irq_index,
  700. + uint32_t *status)
  701. +{
  702. + struct mc_command cmd = { 0 };
  703. + int err;
  704. +
  705. + /* prepare command */
  706. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_STATUS,
  707. + cmd_flags,
  708. + token);
  709. + DPDMUX_CMD_GET_IRQ_STATUS(cmd, irq_index, *status);
  710. +
  711. + /* send command to mc*/
  712. + err = mc_send_command(mc_io, &cmd);
  713. + if (err)
  714. + return err;
  715. +
  716. + /* retrieve response parameters */
  717. + DPDMUX_RSP_GET_IRQ_STATUS(cmd, *status);
  718. +
  719. + return 0;
  720. +}
  721. +
  722. +int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io,
  723. + uint32_t cmd_flags,
  724. + uint16_t token,
  725. + uint8_t irq_index,
  726. + uint32_t status)
  727. +{
  728. + struct mc_command cmd = { 0 };
  729. +
  730. + /* prepare command */
  731. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLEAR_IRQ_STATUS,
  732. + cmd_flags,
  733. + token);
  734. + DPDMUX_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status);
  735. +
  736. + /* send command to mc*/
  737. + return mc_send_command(mc_io, &cmd);
  738. +}
  739. +
  740. +int dpdmux_get_attributes(struct fsl_mc_io *mc_io,
  741. + uint32_t cmd_flags,
  742. + uint16_t token,
  743. + struct dpdmux_attr *attr)
  744. +{
  745. + struct mc_command cmd = { 0 };
  746. + int err;
  747. +
  748. + /* prepare command */
  749. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_ATTR,
  750. + cmd_flags,
  751. + token);
  752. +
  753. + /* send command to mc*/
  754. + err = mc_send_command(mc_io, &cmd);
  755. + if (err)
  756. + return err;
  757. +
  758. + /* retrieve response parameters */
  759. + DPDMUX_RSP_GET_ATTR(cmd, attr);
  760. +
  761. + return 0;
  762. +}
  763. +
  764. +int dpdmux_ul_set_max_frame_length(struct fsl_mc_io *mc_io,
  765. + uint32_t cmd_flags,
  766. + uint16_t token,
  767. + uint16_t max_frame_length)
  768. +{
  769. + struct mc_command cmd = { 0 };
  770. +
  771. + /* prepare command */
  772. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_SET_MAX_FRAME_LENGTH,
  773. + cmd_flags,
  774. + token);
  775. + DPDMUX_CMD_UL_SET_MAX_FRAME_LENGTH(cmd, max_frame_length);
  776. +
  777. + /* send command to mc*/
  778. + return mc_send_command(mc_io, &cmd);
  779. +}
  780. +
  781. +int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io,
  782. + uint32_t cmd_flags,
  783. + uint16_t token)
  784. +{
  785. + struct mc_command cmd = { 0 };
  786. +
  787. + /* prepare command */
  788. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_RESET_COUNTERS,
  789. + cmd_flags,
  790. + token);
  791. +
  792. + /* send command to mc*/
  793. + return mc_send_command(mc_io, &cmd);
  794. +}
  795. +
  796. +int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io,
  797. + uint32_t cmd_flags,
  798. + uint16_t token,
  799. + uint16_t if_id,
  800. + const struct dpdmux_accepted_frames *cfg)
  801. +{
  802. + struct mc_command cmd = { 0 };
  803. +
  804. + /* prepare command */
  805. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES,
  806. + cmd_flags,
  807. + token);
  808. + DPDMUX_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg);
  809. +
  810. + /* send command to mc*/
  811. + return mc_send_command(mc_io, &cmd);
  812. +}
  813. +
  814. +int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io,
  815. + uint32_t cmd_flags,
  816. + uint16_t token,
  817. + uint16_t if_id,
  818. + struct dpdmux_if_attr *attr)
  819. +{
  820. + struct mc_command cmd = { 0 };
  821. + int err;
  822. +
  823. + /* prepare command */
  824. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_ATTR,
  825. + cmd_flags,
  826. + token);
  827. + DPDMUX_CMD_IF_GET_ATTR(cmd, if_id);
  828. +
  829. + /* send command to mc*/
  830. + err = mc_send_command(mc_io, &cmd);
  831. + if (err)
  832. + return err;
  833. +
  834. + /* retrieve response parameters */
  835. + DPDMUX_RSP_IF_GET_ATTR(cmd, attr);
  836. +
  837. + return 0;
  838. +}
  839. +
  840. +int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io,
  841. + uint32_t cmd_flags,
  842. + uint16_t token,
  843. + uint16_t if_id,
  844. + const struct dpdmux_l2_rule *rule)
  845. +{
  846. + struct mc_command cmd = { 0 };
  847. +
  848. + /* prepare command */
  849. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_REMOVE_L2_RULE,
  850. + cmd_flags,
  851. + token);
  852. + DPDMUX_CMD_IF_REMOVE_L2_RULE(cmd, if_id, rule);
  853. +
  854. + /* send command to mc*/
  855. + return mc_send_command(mc_io, &cmd);
  856. +}
  857. +
  858. +int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io,
  859. + uint32_t cmd_flags,
  860. + uint16_t token,
  861. + uint16_t if_id,
  862. + const struct dpdmux_l2_rule *rule)
  863. +{
  864. + struct mc_command cmd = { 0 };
  865. +
  866. + /* prepare command */
  867. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_ADD_L2_RULE,
  868. + cmd_flags,
  869. + token);
  870. + DPDMUX_CMD_IF_ADD_L2_RULE(cmd, if_id, rule);
  871. +
  872. + /* send command to mc*/
  873. + return mc_send_command(mc_io, &cmd);
  874. +}
  875. +
  876. +int dpdmux_if_get_counter(struct fsl_mc_io *mc_io,
  877. + uint32_t cmd_flags,
  878. + uint16_t token,
  879. + uint16_t if_id,
  880. + enum dpdmux_counter_type counter_type,
  881. + uint64_t *counter)
  882. +{
  883. + struct mc_command cmd = { 0 };
  884. + int err;
  885. +
  886. + /* prepare command */
  887. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_COUNTER,
  888. + cmd_flags,
  889. + token);
  890. + DPDMUX_CMD_IF_GET_COUNTER(cmd, if_id, counter_type);
  891. +
  892. + /* send command to mc*/
  893. + err = mc_send_command(mc_io, &cmd);
  894. + if (err)
  895. + return err;
  896. +
  897. + /* retrieve response parameters */
  898. + DPDMUX_RSP_IF_GET_COUNTER(cmd, *counter);
  899. +
  900. + return 0;
  901. +}
  902. +
  903. +int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io,
  904. + uint32_t cmd_flags,
  905. + uint16_t token,
  906. + uint16_t if_id,
  907. + struct dpdmux_link_cfg *cfg)
  908. +{
  909. + struct mc_command cmd = { 0 };
  910. +
  911. + /* prepare command */
  912. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_LINK_CFG,
  913. + cmd_flags,
  914. + token);
  915. + DPDMUX_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg);
  916. +
  917. + /* send command to mc*/
  918. + return mc_send_command(mc_io, &cmd);
  919. +}
  920. +
  921. +int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io,
  922. + uint32_t cmd_flags,
  923. + uint16_t token,
  924. + uint16_t if_id,
  925. + struct dpdmux_link_state *state)
  926. +{
  927. + struct mc_command cmd = { 0 };
  928. + int err;
  929. +
  930. + /* prepare command */
  931. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_LINK_STATE,
  932. + cmd_flags,
  933. + token);
  934. + DPDMUX_CMD_IF_GET_LINK_STATE(cmd, if_id);
  935. +
  936. + /* send command to mc*/
  937. + err = mc_send_command(mc_io, &cmd);
  938. + if (err)
  939. + return err;
  940. +
  941. + /* retrieve response parameters */
  942. + DPDMUX_RSP_IF_GET_LINK_STATE(cmd, state);
  943. +
  944. + return 0;
  945. +}
  946. --- /dev/null
  947. +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux.h
  948. @@ -0,0 +1,724 @@
  949. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  950. + *
  951. + * Redistribution and use in source and binary forms, with or without
  952. + * modification, are permitted provided that the following conditions are met:
  953. + * * Redistributions of source code must retain the above copyright
  954. + * notice, this list of conditions and the following disclaimer.
  955. + * * Redistributions in binary form must reproduce the above copyright
  956. + * notice, this list of conditions and the following disclaimer in the
  957. + * documentation and/or other materials provided with the distribution.
  958. + * * Neither the name of the above-listed copyright holders nor the
  959. + * names of any contributors may be used to endorse or promote products
  960. + * derived from this software without specific prior written permission.
  961. + *
  962. + *
  963. + * ALTERNATIVELY, this software may be distributed under the terms of the
  964. + * GNU General Public License ("GPL") as published by the Free Software
  965. + * Foundation, either version 2 of that License or (at your option) any
  966. + * later version.
  967. + *
  968. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  969. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  970. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  971. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  972. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  973. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  974. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  975. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  976. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  977. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  978. + * POSSIBILITY OF SUCH DAMAGE.
  979. + */
  980. +#ifndef __FSL_DPDMUX_H
  981. +#define __FSL_DPDMUX_H
  982. +
  983. +#include "../../fsl-mc/include/net.h"
  984. +
  985. +struct fsl_mc_io;
  986. +
  987. +/* Data Path Demux API
  988. + * Contains API for handling DPDMUX topology and functionality
  989. + */
  990. +
  991. +/**
  992. + * dpdmux_open() - Open a control session for the specified object
  993. + * @mc_io: Pointer to MC portal's I/O object
  994. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  995. + * @dpdmux_id: DPDMUX unique ID
  996. + * @token: Returned token; use in subsequent API calls
  997. + *
  998. + * This function can be used to open a control session for an
  999. + * already created object; an object may have been declared in
  1000. + * the DPL or by calling the dpdmux_create() function.
  1001. + * This function returns a unique authentication token,
  1002. + * associated with the specific object ID and the specific MC
  1003. + * portal; this token must be used in all subsequent commands for
  1004. + * this specific object.
  1005. + *
  1006. + * Return: '0' on Success; Error code otherwise.
  1007. + */
  1008. +int dpdmux_open(struct fsl_mc_io *mc_io,
  1009. + uint32_t cmd_flags,
  1010. + int dpdmux_id,
  1011. + uint16_t *token);
  1012. +
  1013. +/**
  1014. + * dpdmux_close() - Close the control session of the object
  1015. + * @mc_io: Pointer to MC portal's I/O object
  1016. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1017. + * @token: Token of DPDMUX object
  1018. + *
  1019. + * After this function is called, no further operations are
  1020. + * allowed on the object without opening a new control session.
  1021. + *
  1022. + * Return: '0' on Success; Error code otherwise.
  1023. + */
  1024. +int dpdmux_close(struct fsl_mc_io *mc_io,
  1025. + uint32_t cmd_flags,
  1026. + uint16_t token);
  1027. +
  1028. +/**
  1029. + * DPDMUX general options
  1030. + */
  1031. +
  1032. +/**
  1033. + * Enable bridging between internal interfaces
  1034. + */
  1035. +#define DPDMUX_OPT_BRIDGE_EN 0x0000000000000002ULL
  1036. +
  1037. +#define DPDMUX_IRQ_INDEX_IF 0x0000
  1038. +#define DPDMUX_IRQ_INDEX 0x0001
  1039. +
  1040. +/**
  1041. + * IRQ event - Indicates that the link state changed
  1042. + */
  1043. +#define DPDMUX_IRQ_EVENT_LINK_CHANGED 0x0001
  1044. +
  1045. +/**
  1046. + * enum dpdmux_manip - DPDMUX manipulation operations
  1047. + * @DPDMUX_MANIP_NONE: No manipulation on frames
  1048. + * @DPDMUX_MANIP_ADD_REMOVE_S_VLAN: Add S-VLAN on egress, remove it on ingress
  1049. + */
  1050. +enum dpdmux_manip {
  1051. + DPDMUX_MANIP_NONE = 0x0,
  1052. + DPDMUX_MANIP_ADD_REMOVE_S_VLAN = 0x1
  1053. +};
  1054. +
  1055. +/**
  1056. + * enum dpdmux_method - DPDMUX method options
  1057. + * @DPDMUX_METHOD_NONE: no DPDMUX method
  1058. + * @DPDMUX_METHOD_C_VLAN_MAC: DPDMUX based on C-VLAN and MAC address
  1059. + * @DPDMUX_METHOD_MAC: DPDMUX based on MAC address
  1060. + * @DPDMUX_METHOD_C_VLAN: DPDMUX based on C-VLAN
  1061. + * @DPDMUX_METHOD_S_VLAN: DPDMUX based on S-VLAN
  1062. + */
  1063. +enum dpdmux_method {
  1064. + DPDMUX_METHOD_NONE = 0x0,
  1065. + DPDMUX_METHOD_C_VLAN_MAC = 0x1,
  1066. + DPDMUX_METHOD_MAC = 0x2,
  1067. + DPDMUX_METHOD_C_VLAN = 0x3,
  1068. + DPDMUX_METHOD_S_VLAN = 0x4
  1069. +};
  1070. +
  1071. +/**
  1072. + * struct dpdmux_cfg - DPDMUX configuration parameters
  1073. + * @method: Defines the operation method for the DPDMUX address table
  1074. + * @manip: Required manipulation operation
  1075. + * @num_ifs: Number of interfaces (excluding the uplink interface)
  1076. + * @adv: Advanced parameters; default is all zeros;
  1077. + * use this structure to change default settings
  1078. + */
  1079. +struct dpdmux_cfg {
  1080. + enum dpdmux_method method;
  1081. + enum dpdmux_manip manip;
  1082. + uint16_t num_ifs;
  1083. + /**
  1084. + * struct adv - Advanced parameters
  1085. + * @options: DPDMUX options - combination of 'DPDMUX_OPT_<X>' flags
  1086. + * @max_dmat_entries: Maximum entries in DPDMUX address table
  1087. + * 0 - indicates default: 64 entries per interface.
  1088. + * @max_mc_groups: Number of multicast groups in DPDMUX table
  1089. + * 0 - indicates default: 32 multicast groups
  1090. + * @max_vlan_ids: max vlan ids allowed in the system -
  1091. + * relevant only case of working in mac+vlan method.
  1092. + * 0 - indicates default 16 vlan ids.
  1093. + */
  1094. + struct {
  1095. + uint64_t options;
  1096. + uint16_t max_dmat_entries;
  1097. + uint16_t max_mc_groups;
  1098. + uint16_t max_vlan_ids;
  1099. + } adv;
  1100. +};
  1101. +
  1102. +/**
  1103. + * dpdmux_create() - Create the DPDMUX object
  1104. + * @mc_io: Pointer to MC portal's I/O object
  1105. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1106. + * @cfg: Configuration structure
  1107. + * @token: Returned token; use in subsequent API calls
  1108. + *
  1109. + * Create the DPDMUX object, allocate required resources and
  1110. + * perform required initialization.
  1111. + *
  1112. + * The object can be created either by declaring it in the
  1113. + * DPL file, or by calling this function.
  1114. + *
  1115. + * This function returns a unique authentication token,
  1116. + * associated with the specific object ID and the specific MC
  1117. + * portal; this token must be used in all subsequent calls to
  1118. + * this specific object. For objects that are created using the
  1119. + * DPL file, call dpdmux_open() function to get an authentication
  1120. + * token first.
  1121. + *
  1122. + * Return: '0' on Success; Error code otherwise.
  1123. + */
  1124. +int dpdmux_create(struct fsl_mc_io *mc_io,
  1125. + uint32_t cmd_flags,
  1126. + const struct dpdmux_cfg *cfg,
  1127. + uint16_t *token);
  1128. +
  1129. +/**
  1130. + * dpdmux_destroy() - Destroy the DPDMUX object and release all its resources.
  1131. + * @mc_io: Pointer to MC portal's I/O object
  1132. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1133. + * @token: Token of DPDMUX object
  1134. + *
  1135. + * Return: '0' on Success; error code otherwise.
  1136. + */
  1137. +int dpdmux_destroy(struct fsl_mc_io *mc_io,
  1138. + uint32_t cmd_flags,
  1139. + uint16_t token);
  1140. +
  1141. +/**
  1142. + * dpdmux_enable() - Enable DPDMUX functionality
  1143. + * @mc_io: Pointer to MC portal's I/O object
  1144. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1145. + * @token: Token of DPDMUX object
  1146. + *
  1147. + * Return: '0' on Success; Error code otherwise.
  1148. + */
  1149. +int dpdmux_enable(struct fsl_mc_io *mc_io,
  1150. + uint32_t cmd_flags,
  1151. + uint16_t token);
  1152. +
  1153. +/**
  1154. + * dpdmux_disable() - Disable DPDMUX functionality
  1155. + * @mc_io: Pointer to MC portal's I/O object
  1156. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1157. + * @token: Token of DPDMUX object
  1158. + *
  1159. + * Return: '0' on Success; Error code otherwise.
  1160. + */
  1161. +int dpdmux_disable(struct fsl_mc_io *mc_io,
  1162. + uint32_t cmd_flags,
  1163. + uint16_t token);
  1164. +
  1165. +/**
  1166. + * dpdmux_is_enabled() - Check if the DPDMUX is enabled.
  1167. + * @mc_io: Pointer to MC portal's I/O object
  1168. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1169. + * @token: Token of DPDMUX object
  1170. + * @en: Returns '1' if object is enabled; '0' otherwise
  1171. + *
  1172. + * Return: '0' on Success; Error code otherwise.
  1173. + */
  1174. +int dpdmux_is_enabled(struct fsl_mc_io *mc_io,
  1175. + uint32_t cmd_flags,
  1176. + uint16_t token,
  1177. + int *en);
  1178. +
  1179. +/**
  1180. + * dpdmux_reset() - Reset the DPDMUX, returns the object to initial state.
  1181. + * @mc_io: Pointer to MC portal's I/O object
  1182. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1183. + * @token: Token of DPDMUX object
  1184. + *
  1185. + * Return: '0' on Success; Error code otherwise.
  1186. + */
  1187. +int dpdmux_reset(struct fsl_mc_io *mc_io,
  1188. + uint32_t cmd_flags,
  1189. + uint16_t token);
  1190. +
  1191. +/**
  1192. + * struct dpdmux_irq_cfg - IRQ configuration
  1193. + * @addr: Address that must be written to signal a message-based interrupt
  1194. + * @val: Value to write into irq_addr address
  1195. + * @irq_num: A user defined number associated with this IRQ
  1196. + */
  1197. +struct dpdmux_irq_cfg {
  1198. + uint64_t addr;
  1199. + uint32_t val;
  1200. + int irq_num;
  1201. +};
  1202. +
  1203. +/**
  1204. + * dpdmux_set_irq() - Set IRQ information for the DPDMUX to trigger an interrupt.
  1205. + * @mc_io: Pointer to MC portal's I/O object
  1206. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1207. + * @token: Token of DPDMUX object
  1208. + * @irq_index: Identifies the interrupt index to configure
  1209. + * @irq_cfg: IRQ configuration
  1210. + *
  1211. + * Return: '0' on Success; Error code otherwise.
  1212. + */
  1213. +int dpdmux_set_irq(struct fsl_mc_io *mc_io,
  1214. + uint32_t cmd_flags,
  1215. + uint16_t token,
  1216. + uint8_t irq_index,
  1217. + struct dpdmux_irq_cfg *irq_cfg);
  1218. +
  1219. +/**
  1220. + * dpdmux_get_irq() - Get IRQ information from the DPDMUX.
  1221. + * @mc_io: Pointer to MC portal's I/O object
  1222. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1223. + * @token: Token of DPDMUX object
  1224. + * @irq_index: The interrupt index to configure
  1225. + * @type: Interrupt type: 0 represents message interrupt
  1226. + * type (both irq_addr and irq_val are valid)
  1227. + * @irq_cfg: IRQ attributes
  1228. + *
  1229. + * Return: '0' on Success; Error code otherwise.
  1230. + */
  1231. +int dpdmux_get_irq(struct fsl_mc_io *mc_io,
  1232. + uint32_t cmd_flags,
  1233. + uint16_t token,
  1234. + uint8_t irq_index,
  1235. + int *type,
  1236. + struct dpdmux_irq_cfg *irq_cfg);
  1237. +
  1238. +/**
  1239. + * dpdmux_set_irq_enable() - Set overall interrupt state.
  1240. + * @mc_io: Pointer to MC portal's I/O object
  1241. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1242. + * @token: Token of DPDMUX object
  1243. + * @irq_index: The interrupt index to configure
  1244. + * @en: Interrupt state - enable = 1, disable = 0
  1245. + *
  1246. + * Allows GPP software to control when interrupts are generated.
  1247. + * Each interrupt can have up to 32 causes. The enable/disable control's the
  1248. + * overall interrupt state. if the interrupt is disabled no causes will cause
  1249. + * an interrupt.
  1250. + *
  1251. + * Return: '0' on Success; Error code otherwise.
  1252. + */
  1253. +int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io,
  1254. + uint32_t cmd_flags,
  1255. + uint16_t token,
  1256. + uint8_t irq_index,
  1257. + uint8_t en);
  1258. +
  1259. +/**
  1260. + * dpdmux_get_irq_enable() - Get overall interrupt state.
  1261. + * @mc_io: Pointer to MC portal's I/O object
  1262. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1263. + * @token: Token of DPDMUX object
  1264. + * @irq_index: The interrupt index to configure
  1265. + * @en: Returned interrupt state - enable = 1, disable = 0
  1266. + *
  1267. + * Return: '0' on Success; Error code otherwise.
  1268. + */
  1269. +int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io,
  1270. + uint32_t cmd_flags,
  1271. + uint16_t token,
  1272. + uint8_t irq_index,
  1273. + uint8_t *en);
  1274. +
  1275. +/**
  1276. + * dpdmux_set_irq_mask() - Set interrupt mask.
  1277. + * @mc_io: Pointer to MC portal's I/O object
  1278. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1279. + * @token: Token of DPDMUX object
  1280. + * @irq_index: The interrupt index to configure
  1281. + * @mask: event mask to trigger interrupt;
  1282. + * each bit:
  1283. + * 0 = ignore event
  1284. + * 1 = consider event for asserting IRQ
  1285. + *
  1286. + * Every interrupt can have up to 32 causes and the interrupt model supports
  1287. + * masking/unmasking each cause independently
  1288. + *
  1289. + * Return: '0' on Success; Error code otherwise.
  1290. + */
  1291. +int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io,
  1292. + uint32_t cmd_flags,
  1293. + uint16_t token,
  1294. + uint8_t irq_index,
  1295. + uint32_t mask);
  1296. +
  1297. +/**
  1298. + * dpdmux_get_irq_mask() - Get interrupt mask.
  1299. + * @mc_io: Pointer to MC portal's I/O object
  1300. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1301. + * @token: Token of DPDMUX object
  1302. + * @irq_index: The interrupt index to configure
  1303. + * @mask: Returned event mask to trigger interrupt
  1304. + *
  1305. + * Every interrupt can have up to 32 causes and the interrupt model supports
  1306. + * masking/unmasking each cause independently
  1307. + *
  1308. + * Return: '0' on Success; Error code otherwise.
  1309. + */
  1310. +int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io,
  1311. + uint32_t cmd_flags,
  1312. + uint16_t token,
  1313. + uint8_t irq_index,
  1314. + uint32_t *mask);
  1315. +
  1316. +/**
  1317. + * dpdmux_get_irq_status() - Get the current status of any pending interrupts.
  1318. + * @mc_io: Pointer to MC portal's I/O object
  1319. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1320. + * @token: Token of DPDMUX object
  1321. + * @irq_index: The interrupt index to configure
  1322. + * @status: Returned interrupts status - one bit per cause:
  1323. + * 0 = no interrupt pending
  1324. + * 1 = interrupt pending
  1325. + *
  1326. + * Return: '0' on Success; Error code otherwise.
  1327. + */
  1328. +int dpdmux_get_irq_status(struct fsl_mc_io *mc_io,
  1329. + uint32_t cmd_flags,
  1330. + uint16_t token,
  1331. + uint8_t irq_index,
  1332. + uint32_t *status);
  1333. +
  1334. +/**
  1335. + * dpdmux_clear_irq_status() - Clear a pending interrupt's status
  1336. + * @mc_io: Pointer to MC portal's I/O object
  1337. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1338. + * @token: Token of DPDMUX object
  1339. + * @irq_index: The interrupt index to configure
  1340. + * @status: bits to clear (W1C) - one bit per cause:
  1341. + * 0 = don't change
  1342. + * 1 = clear status bit
  1343. + *
  1344. + * Return: '0' on Success; Error code otherwise.
  1345. + */
  1346. +int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io,
  1347. + uint32_t cmd_flags,
  1348. + uint16_t token,
  1349. + uint8_t irq_index,
  1350. + uint32_t status);
  1351. +
  1352. +/**
  1353. + * struct dpdmux_attr - Structure representing DPDMUX attributes
  1354. + * @id: DPDMUX object ID
  1355. + * @version: DPDMUX version
  1356. + * @options: Configuration options (bitmap)
  1357. + * @method: DPDMUX address table method
  1358. + * @manip: DPDMUX manipulation type
  1359. + * @num_ifs: Number of interfaces (excluding the uplink interface)
  1360. + * @mem_size: DPDMUX frame storage memory size
  1361. + */
  1362. +struct dpdmux_attr {
  1363. + int id;
  1364. + /**
  1365. + * struct version - DPDMUX version
  1366. + * @major: DPDMUX major version
  1367. + * @minor: DPDMUX minor version
  1368. + */
  1369. + struct {
  1370. + uint16_t major;
  1371. + uint16_t minor;
  1372. + } version;
  1373. + uint64_t options;
  1374. + enum dpdmux_method method;
  1375. + enum dpdmux_manip manip;
  1376. + uint16_t num_ifs;
  1377. + uint16_t mem_size;
  1378. +};
  1379. +
  1380. +/**
  1381. + * dpdmux_get_attributes() - Retrieve DPDMUX attributes
  1382. + * @mc_io: Pointer to MC portal's I/O object
  1383. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1384. + * @token: Token of DPDMUX object
  1385. + * @attr: Returned object's attributes
  1386. + *
  1387. + * Return: '0' on Success; Error code otherwise.
  1388. + */
  1389. +int dpdmux_get_attributes(struct fsl_mc_io *mc_io,
  1390. + uint32_t cmd_flags,
  1391. + uint16_t token,
  1392. + struct dpdmux_attr *attr);
  1393. +
  1394. +/**
  1395. + * dpdmux_ul_set_max_frame_length() - Set the maximum frame length in DPDMUX
  1396. + * @mc_io: Pointer to MC portal's I/O object
  1397. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1398. + * @token: Token of DPDMUX object
  1399. + * @max_frame_length: The required maximum frame length
  1400. + *
  1401. + * Return: '0' on Success; Error code otherwise.
  1402. + */
  1403. +int dpdmux_ul_set_max_frame_length(struct fsl_mc_io *mc_io,
  1404. + uint32_t cmd_flags,
  1405. + uint16_t token,
  1406. + uint16_t max_frame_length);
  1407. +
  1408. +/**
  1409. + * enum dpdmux_counter_type - Counter types
  1410. + * @DPDMUX_CNT_ING_FRAME: Counts ingress frames
  1411. + * @DPDMUX_CNT_ING_BYTE: Counts ingress bytes
  1412. + * @DPDMUX_CNT_ING_FLTR_FRAME: Counts filtered ingress frames
  1413. + * @DPDMUX_CNT_ING_FRAME_DISCARD: Counts discarded ingress frames
  1414. + * @DPDMUX_CNT_ING_MCAST_FRAME: Counts ingress multicast frames
  1415. + * @DPDMUX_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes
  1416. + * @DPDMUX_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames
  1417. + * @DPDMUX_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes
  1418. + * @DPDMUX_CNT_EGR_FRAME: Counts egress frames
  1419. + * @DPDMUX_CNT_EGR_BYTE: Counts egress bytes
  1420. + * @DPDMUX_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames
  1421. + */
  1422. +enum dpdmux_counter_type {
  1423. + DPDMUX_CNT_ING_FRAME = 0x0,
  1424. + DPDMUX_CNT_ING_BYTE = 0x1,
  1425. + DPDMUX_CNT_ING_FLTR_FRAME = 0x2,
  1426. + DPDMUX_CNT_ING_FRAME_DISCARD = 0x3,
  1427. + DPDMUX_CNT_ING_MCAST_FRAME = 0x4,
  1428. + DPDMUX_CNT_ING_MCAST_BYTE = 0x5,
  1429. + DPDMUX_CNT_ING_BCAST_FRAME = 0x6,
  1430. + DPDMUX_CNT_ING_BCAST_BYTES = 0x7,
  1431. + DPDMUX_CNT_EGR_FRAME = 0x8,
  1432. + DPDMUX_CNT_EGR_BYTE = 0x9,
  1433. + DPDMUX_CNT_EGR_FRAME_DISCARD = 0xa
  1434. +};
  1435. +
  1436. +/**
  1437. + * enum dpdmux_accepted_frames_type - DPDMUX frame types
  1438. + * @DPDMUX_ADMIT_ALL: The device accepts VLAN tagged, untagged and
  1439. + * priority-tagged frames
  1440. + * @DPDMUX_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or
  1441. + * priority-tagged frames that are received on this
  1442. + * interface
  1443. + * @DPDMUX_ADMIT_ONLY_UNTAGGED: Untagged frames or priority-tagged frames
  1444. + * received on this interface are accepted
  1445. + */
  1446. +enum dpdmux_accepted_frames_type {
  1447. + DPDMUX_ADMIT_ALL = 0,
  1448. + DPDMUX_ADMIT_ONLY_VLAN_TAGGED = 1,
  1449. + DPDMUX_ADMIT_ONLY_UNTAGGED = 2
  1450. +};
  1451. +
  1452. +/**
  1453. + * enum dpdmux_action - DPDMUX action for un-accepted frames
  1454. + * @DPDMUX_ACTION_DROP: Drop un-accepted frames
  1455. + * @DPDMUX_ACTION_REDIRECT_TO_CTRL: Redirect un-accepted frames to the
  1456. + * control interface
  1457. + */
  1458. +enum dpdmux_action {
  1459. + DPDMUX_ACTION_DROP = 0,
  1460. + DPDMUX_ACTION_REDIRECT_TO_CTRL = 1
  1461. +};
  1462. +
  1463. +/**
  1464. + * struct dpdmux_accepted_frames - Frame types configuration
  1465. + * @type: Defines ingress accepted frames
  1466. + * @unaccept_act: Defines action on frames not accepted
  1467. + */
  1468. +struct dpdmux_accepted_frames {
  1469. + enum dpdmux_accepted_frames_type type;
  1470. + enum dpdmux_action unaccept_act;
  1471. +};
  1472. +
  1473. +/**
  1474. + * dpdmux_if_set_accepted_frames() - Set the accepted frame types
  1475. + * @mc_io: Pointer to MC portal's I/O object
  1476. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1477. + * @token: Token of DPDMUX object
  1478. + * @if_id: Interface ID (0 for uplink, or 1-num_ifs);
  1479. + * @cfg: Frame types configuration
  1480. + *
  1481. + * if 'DPDMUX_ADMIT_ONLY_VLAN_TAGGED' is set - untagged frames or
  1482. + * priority-tagged frames are discarded.
  1483. + * if 'DPDMUX_ADMIT_ONLY_UNTAGGED' is set - untagged frames or
  1484. + * priority-tagged frames are accepted.
  1485. + * if 'DPDMUX_ADMIT_ALL' is set (default mode) - all VLAN tagged,
  1486. + * untagged and priority-tagged frame are accepted;
  1487. + *
  1488. + * Return: '0' on Success; Error code otherwise.
  1489. + */
  1490. +int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io,
  1491. + uint32_t cmd_flags,
  1492. + uint16_t token,
  1493. + uint16_t if_id,
  1494. + const struct dpdmux_accepted_frames *cfg);
  1495. +
  1496. +/**
  1497. + * struct dpdmux_if_attr - Structure representing frame types configuration
  1498. + * @rate: Configured interface rate (in bits per second)
  1499. + * @enabled: Indicates if interface is enabled
  1500. + * @accept_frame_type: Indicates type of accepted frames for the interface
  1501. + */
  1502. +struct dpdmux_if_attr {
  1503. + uint32_t rate;
  1504. + int enabled;
  1505. + enum dpdmux_accepted_frames_type accept_frame_type;
  1506. +};
  1507. +
  1508. +/**
  1509. + * dpdmux_if_get_attributes() - Obtain DPDMUX interface attributes
  1510. + * @mc_io: Pointer to MC portal's I/O object
  1511. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1512. + * @token: Token of DPDMUX object
  1513. + * @if_id: Interface ID (0 for uplink, or 1-num_ifs);
  1514. + * @attr: Interface attributes
  1515. + *
  1516. + * Return: '0' on Success; Error code otherwise.
  1517. + */
  1518. +int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io,
  1519. + uint32_t cmd_flags,
  1520. + uint16_t token,
  1521. + uint16_t if_id,
  1522. + struct dpdmux_if_attr *attr);
  1523. +
  1524. +/**
  1525. + * struct dpdmux_l2_rule - Structure representing L2 rule
  1526. + * @mac_addr: MAC address
  1527. + * @vlan_id: VLAN ID
  1528. + */
  1529. +struct dpdmux_l2_rule {
  1530. + uint8_t mac_addr[6];
  1531. + uint16_t vlan_id;
  1532. +};
  1533. +
  1534. +/**
  1535. + * dpdmux_if_remove_l2_rule() - Remove L2 rule from DPDMUX table
  1536. + * @mc_io: Pointer to MC portal's I/O object
  1537. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1538. + * @token: Token of DPDMUX object
  1539. + * @if_id: Destination interface ID
  1540. + * @rule: L2 rule
  1541. + *
  1542. + * Function removes a L2 rule from DPDMUX table
  1543. + * or adds an interface to an existing multicast address
  1544. + *
  1545. + * Return: '0' on Success; Error code otherwise.
  1546. + */
  1547. +int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io,
  1548. + uint32_t cmd_flags,
  1549. + uint16_t token,
  1550. + uint16_t if_id,
  1551. + const struct dpdmux_l2_rule *rule);
  1552. +
  1553. +/**
  1554. + * dpdmux_if_add_l2_rule() - Add L2 rule into DPDMUX table
  1555. + * @mc_io: Pointer to MC portal's I/O object
  1556. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1557. + * @token: Token of DPDMUX object
  1558. + * @if_id: Destination interface ID
  1559. + * @rule: L2 rule
  1560. + *
  1561. + * Function adds a L2 rule into DPDMUX table
  1562. + * or adds an interface to an existing multicast address
  1563. + *
  1564. + * Return: '0' on Success; Error code otherwise.
  1565. + */
  1566. +int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io,
  1567. + uint32_t cmd_flags,
  1568. + uint16_t token,
  1569. + uint16_t if_id,
  1570. + const struct dpdmux_l2_rule *rule);
  1571. +
  1572. +/**
  1573. +* dpdmux_if_get_counter() - Functions obtains specific counter of an interface
  1574. +* @mc_io: Pointer to MC portal's I/O object
  1575. +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1576. +* @token: Token of DPDMUX object
  1577. +* @if_id: Interface Id
  1578. +* @counter_type: counter type
  1579. +* @counter: Returned specific counter information
  1580. +*
  1581. +* Return: '0' on Success; Error code otherwise.
  1582. +*/
  1583. +int dpdmux_if_get_counter(struct fsl_mc_io *mc_io,
  1584. + uint32_t cmd_flags,
  1585. + uint16_t token,
  1586. + uint16_t if_id,
  1587. + enum dpdmux_counter_type counter_type,
  1588. + uint64_t *counter);
  1589. +
  1590. +/**
  1591. +* dpdmux_ul_reset_counters() - Function resets the uplink counter
  1592. +* @mc_io: Pointer to MC portal's I/O object
  1593. +* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1594. +* @token: Token of DPDMUX object
  1595. +*
  1596. +* Return: '0' on Success; Error code otherwise.
  1597. +*/
  1598. +int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io,
  1599. + uint32_t cmd_flags,
  1600. + uint16_t token);
  1601. +
  1602. +/**
  1603. + * Enable auto-negotiation
  1604. + */
  1605. +#define DPDMUX_LINK_OPT_AUTONEG 0x0000000000000001ULL
  1606. +/**
  1607. + * Enable half-duplex mode
  1608. + */
  1609. +#define DPDMUX_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
  1610. +/**
  1611. + * Enable pause frames
  1612. + */
  1613. +#define DPDMUX_LINK_OPT_PAUSE 0x0000000000000004ULL
  1614. +/**
  1615. + * Enable a-symmetric pause frames
  1616. + */
  1617. +#define DPDMUX_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
  1618. +
  1619. +/**
  1620. + * struct dpdmux_link_cfg - Structure representing DPDMUX link configuration
  1621. + * @rate: Rate
  1622. + * @options: Mask of available options; use 'DPDMUX_LINK_OPT_<X>' values
  1623. + */
  1624. +struct dpdmux_link_cfg {
  1625. + uint32_t rate;
  1626. + uint64_t options;
  1627. +};
  1628. +
  1629. +/**
  1630. + * dpdmux_if_set_link_cfg() - set the link configuration.
  1631. + * @mc_io: Pointer to MC portal's I/O object
  1632. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1633. + * @token: Token of DPSW object
  1634. + * @if_id: interface id
  1635. + * @cfg: Link configuration
  1636. + *
  1637. + * Return: '0' on Success; Error code otherwise.
  1638. + */
  1639. +int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io,
  1640. + uint32_t cmd_flags,
  1641. + uint16_t token,
  1642. + uint16_t if_id,
  1643. + struct dpdmux_link_cfg *cfg);
  1644. +/**
  1645. + * struct dpdmux_link_state - Structure representing DPDMUX link state
  1646. + * @rate: Rate
  1647. + * @options: Mask of available options; use 'DPDMUX_LINK_OPT_<X>' values
  1648. + * @up: 0 - down, 1 - up
  1649. + */
  1650. +struct dpdmux_link_state {
  1651. + uint32_t rate;
  1652. + uint64_t options;
  1653. + int up;
  1654. +};
  1655. +
  1656. +/**
  1657. + * dpdmux_if_get_link_state - Return the link state
  1658. + * @mc_io: Pointer to MC portal's I/O object
  1659. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  1660. + * @token: Token of DPSW object
  1661. + * @if_id: interface id
  1662. + * @state: link state
  1663. + *
  1664. + * @returns '0' on Success; Error code otherwise.
  1665. + */
  1666. +int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io,
  1667. + uint32_t cmd_flags,
  1668. + uint16_t token,
  1669. + uint16_t if_id,
  1670. + struct dpdmux_link_state *state);
  1671. +
  1672. +#endif /* __FSL_DPDMUX_H */
  1673. --- /dev/null
  1674. +++ b/drivers/staging/fsl-dpaa2/evb/evb.c
  1675. @@ -0,0 +1,1216 @@
  1676. +/* Copyright 2015 Freescale Semiconductor Inc.
  1677. + *
  1678. + * Redistribution and use in source and binary forms, with or without
  1679. + * modification, are permitted provided that the following conditions are met:
  1680. + * * Redistributions of source code must retain the above copyright
  1681. + * notice, this list of conditions and the following disclaimer.
  1682. + * * Redistributions in binary form must reproduce the above copyright
  1683. + * notice, this list of conditions and the following disclaimer in the
  1684. + * documentation and/or other materials provided with the distribution.
  1685. + * * Neither the name of Freescale Semiconductor nor the
  1686. + * names of its contributors may be used to endorse or promote products
  1687. + * derived from this software without specific prior written permission.
  1688. + *
  1689. + *
  1690. + * ALTERNATIVELY, this software may be distributed under the terms of the
  1691. + * GNU General Public License ("GPL") as published by the Free Software
  1692. + * Foundation, either version 2 of that License or (at your option) any
  1693. + * later version.
  1694. + *
  1695. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  1696. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  1697. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  1698. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  1699. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  1700. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  1701. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  1702. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  1703. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  1704. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1705. + */
  1706. +#include <linux/module.h>
  1707. +#include <linux/netdevice.h>
  1708. +#include <linux/etherdevice.h>
  1709. +#include <linux/rtnetlink.h>
  1710. +#include <linux/if_vlan.h>
  1711. +#include <linux/interrupt.h>
  1712. +#include <linux/msi.h>
  1713. +
  1714. +#include <uapi/linux/if_bridge.h>
  1715. +#include <net/netlink.h>
  1716. +
  1717. +#include "../../fsl-mc/include/mc.h"
  1718. +
  1719. +#include "dpdmux.h"
  1720. +#include "dpdmux-cmd.h"
  1721. +
  1722. +/* IRQ index */
  1723. +#define DPDMUX_MAX_IRQ_NUM 2
  1724. +
  1725. +/* MAX FRAME LENGTH (currently 10k) */
  1726. +#define EVB_MAX_FRAME_LENGTH (10 * 1024)
  1727. +/* MIN FRAME LENGTH (64 bytes + 4 bytes CRC) */
  1728. +#define EVB_MIN_FRAME_LENGTH 68
  1729. +
  1730. +struct evb_port_priv {
  1731. + struct net_device *netdev;
  1732. + struct list_head list;
  1733. + u16 port_index;
  1734. + struct evb_priv *evb_priv;
  1735. + u8 vlans[VLAN_VID_MASK+1];
  1736. +};
  1737. +
  1738. +struct evb_priv {
  1739. + /* keep first */
  1740. + struct evb_port_priv uplink;
  1741. +
  1742. + struct fsl_mc_io *mc_io;
  1743. + struct list_head port_list;
  1744. + struct dpdmux_attr attr;
  1745. + uint16_t mux_handle;
  1746. + int dev_id;
  1747. +};
  1748. +
  1749. +static int _evb_port_carrier_state_sync(struct net_device *netdev)
  1750. +{
  1751. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  1752. + struct dpdmux_link_state state;
  1753. + int err;
  1754. +
  1755. + err = dpdmux_if_get_link_state(port_priv->evb_priv->mc_io, 0,
  1756. + port_priv->evb_priv->mux_handle,
  1757. + port_priv->port_index, &state);
  1758. + if (unlikely(err)) {
  1759. + netdev_err(netdev, "dpdmux_if_get_link_state() err %d\n", err);
  1760. + return err;
  1761. + }
  1762. +
  1763. + WARN_ONCE(state.up > 1, "Garbage read into link_state");
  1764. +
  1765. + if (state.up)
  1766. + netif_carrier_on(port_priv->netdev);
  1767. + else
  1768. + netif_carrier_off(port_priv->netdev);
  1769. +
  1770. + return 0;
  1771. +}
  1772. +
  1773. +static int evb_port_open(struct net_device *netdev)
  1774. +{
  1775. + int err;
  1776. +
  1777. + /* FIXME: enable port when support added */
  1778. +
  1779. + err = _evb_port_carrier_state_sync(netdev);
  1780. + if (err) {
  1781. + netdev_err(netdev, "ethsw_port_carrier_state_sync err %d\n",
  1782. + err);
  1783. + return err;
  1784. + }
  1785. +
  1786. + return 0;
  1787. +}
  1788. +
  1789. +static netdev_tx_t evb_dropframe(struct sk_buff *skb, struct net_device *dev)
  1790. +{
  1791. + /* we don't support I/O for now, drop the frame */
  1792. + dev_kfree_skb_any(skb);
  1793. + return NETDEV_TX_OK;
  1794. +}
  1795. +
  1796. +static int evb_links_state_update(struct evb_priv *priv)
  1797. +{
  1798. + struct evb_port_priv *port_priv;
  1799. + struct list_head *pos;
  1800. + int err;
  1801. +
  1802. + list_for_each(pos, &priv->port_list) {
  1803. + port_priv = list_entry(pos, struct evb_port_priv, list);
  1804. +
  1805. + err = _evb_port_carrier_state_sync(port_priv->netdev);
  1806. + if (err)
  1807. + netdev_err(port_priv->netdev,
  1808. + "_evb_port_carrier_state_sync err %d\n",
  1809. + err);
  1810. + }
  1811. +
  1812. + return 0;
  1813. +}
  1814. +
  1815. +static irqreturn_t evb_irq0_handler(int irq_num, void *arg)
  1816. +{
  1817. + return IRQ_WAKE_THREAD;
  1818. +}
  1819. +
  1820. +static irqreturn_t _evb_irq0_handler_thread(int irq_num, void *arg)
  1821. +{
  1822. + struct device *dev = (struct device *)arg;
  1823. + struct fsl_mc_device *evb_dev = to_fsl_mc_device(dev);
  1824. + struct net_device *netdev = dev_get_drvdata(dev);
  1825. + struct evb_priv *priv = netdev_priv(netdev);
  1826. + struct fsl_mc_io *io = priv->mc_io;
  1827. + uint16_t token = priv->mux_handle;
  1828. + int irq_index = DPDMUX_IRQ_INDEX_IF;
  1829. + uint32_t status = 0, clear = 0;
  1830. + int err;
  1831. +
  1832. + /* Sanity check */
  1833. + if (WARN_ON(!evb_dev || !evb_dev->irqs || !evb_dev->irqs[irq_index]))
  1834. + goto out;
  1835. + if (WARN_ON(evb_dev->irqs[irq_index]->msi_desc->irq != irq_num))
  1836. + goto out;
  1837. +
  1838. + err = dpdmux_get_irq_status(io, 0, token, irq_index, &status);
  1839. + if (unlikely(err)) {
  1840. + netdev_err(netdev, "Can't get irq status (err %d)", err);
  1841. + clear = 0xffffffff;
  1842. + goto out;
  1843. + }
  1844. +
  1845. + /* FIXME clear irq status */
  1846. +
  1847. + if (status & DPDMUX_IRQ_EVENT_LINK_CHANGED) {
  1848. + clear |= DPDMUX_IRQ_EVENT_LINK_CHANGED;
  1849. +
  1850. + err = evb_links_state_update(priv);
  1851. + if (unlikely(err))
  1852. + goto out;
  1853. + }
  1854. +out:
  1855. + err = dpdmux_clear_irq_status(io, 0, token, irq_index, clear);
  1856. + if (unlikely(err))
  1857. + netdev_err(netdev, "Can't clear irq status (err %d)", err);
  1858. + return IRQ_HANDLED;
  1859. +}
  1860. +
  1861. +static int evb_setup_irqs(struct fsl_mc_device *evb_dev)
  1862. +{
  1863. + struct device *dev = &evb_dev->dev;
  1864. + struct net_device *netdev = dev_get_drvdata(dev);
  1865. + struct evb_priv *priv = netdev_priv(netdev);
  1866. + int err = 0;
  1867. + struct fsl_mc_device_irq *irq;
  1868. + const int irq_index = DPDMUX_IRQ_INDEX_IF;
  1869. + uint32_t mask = ~0x0u; /* FIXME: unmask handled irqs */
  1870. +
  1871. + err = fsl_mc_allocate_irqs(evb_dev);
  1872. + if (unlikely(err)) {
  1873. + dev_err(dev, "MC irqs allocation failed\n");
  1874. + return err;
  1875. + }
  1876. +
  1877. + if (WARN_ON(evb_dev->obj_desc.irq_count != DPDMUX_MAX_IRQ_NUM)) {
  1878. + err = -EINVAL;
  1879. + goto free_irq;
  1880. + }
  1881. +
  1882. + err = dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
  1883. + irq_index, 0);
  1884. + if (unlikely(err)) {
  1885. + dev_err(dev, "dpdmux_set_irq_enable err %d\n", err);
  1886. + goto free_irq;
  1887. + }
  1888. +
  1889. + irq = evb_dev->irqs[irq_index];
  1890. +
  1891. + err = devm_request_threaded_irq(dev, irq->msi_desc->irq,
  1892. + evb_irq0_handler,
  1893. + _evb_irq0_handler_thread,
  1894. + IRQF_NO_SUSPEND | IRQF_ONESHOT,
  1895. + dev_name(dev), dev);
  1896. + if (unlikely(err)) {
  1897. + dev_err(dev, "devm_request_threaded_irq(): %d", err);
  1898. + goto free_irq;
  1899. + }
  1900. +
  1901. + err = dpdmux_set_irq_mask(priv->mc_io, 0, priv->mux_handle,
  1902. + irq_index, mask);
  1903. + if (unlikely(err)) {
  1904. + dev_err(dev, "dpdmux_set_irq_mask(): %d", err);
  1905. + goto free_devm_irq;
  1906. + }
  1907. +
  1908. + err = dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
  1909. + irq_index, 1);
  1910. + if (unlikely(err)) {
  1911. + dev_err(dev, "dpdmux_set_irq_enable(): %d", err);
  1912. + goto free_devm_irq;
  1913. + }
  1914. +
  1915. + return 0;
  1916. +
  1917. +free_devm_irq:
  1918. + devm_free_irq(dev, irq->msi_desc->irq, dev);
  1919. +free_irq:
  1920. + fsl_mc_free_irqs(evb_dev);
  1921. + return err;
  1922. +}
  1923. +
  1924. +static void evb_teardown_irqs(struct fsl_mc_device *evb_dev)
  1925. +{
  1926. + struct device *dev = &evb_dev->dev;
  1927. + struct net_device *netdev = dev_get_drvdata(dev);
  1928. + struct evb_priv *priv = netdev_priv(netdev);
  1929. +
  1930. + dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
  1931. + DPDMUX_IRQ_INDEX_IF, 0);
  1932. +
  1933. + devm_free_irq(dev,
  1934. + evb_dev->irqs[DPDMUX_IRQ_INDEX_IF]->msi_desc->irq,
  1935. + dev);
  1936. + fsl_mc_free_irqs(evb_dev);
  1937. +}
  1938. +
  1939. +static int evb_port_add_rule(struct net_device *netdev,
  1940. + const unsigned char *addr, u16 vid)
  1941. +{
  1942. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  1943. + struct dpdmux_l2_rule rule = { .vlan_id = vid };
  1944. + int err;
  1945. +
  1946. + if (addr)
  1947. + ether_addr_copy(rule.mac_addr, addr);
  1948. +
  1949. + err = dpdmux_if_add_l2_rule(port_priv->evb_priv->mc_io,
  1950. + 0,
  1951. + port_priv->evb_priv->mux_handle,
  1952. + port_priv->port_index, &rule);
  1953. + if (unlikely(err))
  1954. + netdev_err(netdev, "dpdmux_if_add_l2_rule err %d\n", err);
  1955. + return err;
  1956. +}
  1957. +
  1958. +static int evb_port_del_rule(struct net_device *netdev,
  1959. + const unsigned char *addr, u16 vid)
  1960. +{
  1961. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  1962. + struct dpdmux_l2_rule rule = { .vlan_id = vid };
  1963. + int err;
  1964. +
  1965. + if (addr)
  1966. + ether_addr_copy(rule.mac_addr, addr);
  1967. +
  1968. + err = dpdmux_if_remove_l2_rule(port_priv->evb_priv->mc_io,
  1969. + 0,
  1970. + port_priv->evb_priv->mux_handle,
  1971. + port_priv->port_index, &rule);
  1972. + if (unlikely(err))
  1973. + netdev_err(netdev, "dpdmux_if_remove_l2_rule err %d\n", err);
  1974. + return err;
  1975. +}
  1976. +
  1977. +static bool _lookup_address(struct net_device *netdev,
  1978. + const unsigned char *addr)
  1979. +{
  1980. + struct netdev_hw_addr *ha;
  1981. + struct netdev_hw_addr_list *list = (is_unicast_ether_addr(addr)) ?
  1982. + &netdev->uc : &netdev->mc;
  1983. +
  1984. + netif_addr_lock_bh(netdev);
  1985. + list_for_each_entry(ha, &list->list, list) {
  1986. + if (ether_addr_equal(ha->addr, addr)) {
  1987. + netif_addr_unlock_bh(netdev);
  1988. + return true;
  1989. + }
  1990. + }
  1991. + netif_addr_unlock_bh(netdev);
  1992. + return false;
  1993. +}
  1994. +
  1995. +static inline int evb_port_fdb_prep(struct nlattr *tb[],
  1996. + struct net_device *netdev,
  1997. + const unsigned char *addr, u16 *vid,
  1998. + bool del)
  1999. +{
  2000. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2001. + struct evb_priv *evb_priv = port_priv->evb_priv;
  2002. +
  2003. + *vid = 0;
  2004. +
  2005. + if (evb_priv->attr.method != DPDMUX_METHOD_MAC &&
  2006. + evb_priv->attr.method != DPDMUX_METHOD_C_VLAN_MAC) {
  2007. + netdev_err(netdev,
  2008. + "EVB mode does not support MAC classification\n");
  2009. + return -EOPNOTSUPP;
  2010. + }
  2011. +
  2012. + /* check if the address is configured on this port */
  2013. + if (_lookup_address(netdev, addr)) {
  2014. + if (!del)
  2015. + return -EEXIST;
  2016. + } else {
  2017. + if (del)
  2018. + return -ENOENT;
  2019. + }
  2020. +
  2021. + if (tb[NDA_VLAN] && evb_priv->attr.method == DPDMUX_METHOD_C_VLAN_MAC) {
  2022. + if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) {
  2023. + netdev_err(netdev, "invalid vlan size %d\n",
  2024. + nla_len(tb[NDA_VLAN]));
  2025. + return -EINVAL;
  2026. + }
  2027. +
  2028. + *vid = nla_get_u16(tb[NDA_VLAN]);
  2029. +
  2030. + if (!*vid || *vid >= VLAN_VID_MASK) {
  2031. + netdev_err(netdev, "invalid vid value 0x%04x\n", *vid);
  2032. + return -EINVAL;
  2033. + }
  2034. + } else if (evb_priv->attr.method == DPDMUX_METHOD_C_VLAN_MAC) {
  2035. + netdev_err(netdev,
  2036. + "EVB mode requires explicit VLAN configuration\n");
  2037. + return -EINVAL;
  2038. + } else if (tb[NDA_VLAN]) {
  2039. + netdev_warn(netdev, "VLAN not supported, argument ignored\n");
  2040. + }
  2041. +
  2042. + return 0;
  2043. +}
  2044. +
  2045. +static int evb_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
  2046. + struct net_device *netdev,
  2047. + const unsigned char *addr, u16 vid, u16 flags)
  2048. +{
  2049. + u16 _vid;
  2050. + int err;
  2051. +
  2052. + /* TODO: add replace support when added to iproute bridge */
  2053. + if (!(flags & NLM_F_REQUEST)) {
  2054. + netdev_err(netdev,
  2055. + "evb_port_fdb_add unexpected flags value %08x\n",
  2056. + flags);
  2057. + return -EINVAL;
  2058. + }
  2059. +
  2060. + err = evb_port_fdb_prep(tb, netdev, addr, &_vid, 0);
  2061. + if (unlikely(err))
  2062. + return err;
  2063. +
  2064. +
  2065. + err = evb_port_add_rule(netdev, addr, _vid);
  2066. + if (unlikely(err))
  2067. + return err;
  2068. +
  2069. + if (is_unicast_ether_addr(addr)) {
  2070. + err = dev_uc_add(netdev, addr);
  2071. + if (unlikely(err)) {
  2072. + netdev_err(netdev, "dev_uc_add err %d\n", err);
  2073. + return err;
  2074. + }
  2075. + } else {
  2076. + err = dev_mc_add(netdev, addr);
  2077. + if (unlikely(err)) {
  2078. + netdev_err(netdev, "dev_mc_add err %d\n", err);
  2079. + return err;
  2080. + }
  2081. + }
  2082. +
  2083. + return 0;
  2084. +}
  2085. +
  2086. +static int evb_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
  2087. + struct net_device *netdev,
  2088. + const unsigned char *addr, u16 vid)
  2089. +{
  2090. + u16 _vid;
  2091. + int err;
  2092. +
  2093. + err = evb_port_fdb_prep(tb, netdev, addr, &_vid, 1);
  2094. + if (unlikely(err))
  2095. + return err;
  2096. +
  2097. + err = evb_port_del_rule(netdev, addr, _vid);
  2098. + if (unlikely(err))
  2099. + return err;
  2100. +
  2101. + if (is_unicast_ether_addr(addr)) {
  2102. + err = dev_uc_del(netdev, addr);
  2103. + if (unlikely(err)) {
  2104. + netdev_err(netdev, "dev_uc_del err %d\n", err);
  2105. + return err;
  2106. + }
  2107. + } else {
  2108. + err = dev_mc_del(netdev, addr);
  2109. + if (unlikely(err)) {
  2110. + netdev_err(netdev, "dev_mc_del err %d\n", err);
  2111. + return err;
  2112. + }
  2113. + }
  2114. +
  2115. + return 0;
  2116. +}
  2117. +
  2118. +static int evb_change_mtu(struct net_device *netdev,
  2119. + int mtu)
  2120. +{
  2121. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2122. + struct evb_priv *evb_priv = port_priv->evb_priv;
  2123. + struct list_head *pos;
  2124. + int err = 0;
  2125. +
  2126. + /* This operation is not permitted on downlinks */
  2127. + if (port_priv->port_index > 0)
  2128. + return -EPERM;
  2129. +
  2130. + if (mtu < EVB_MIN_FRAME_LENGTH || mtu > EVB_MAX_FRAME_LENGTH) {
  2131. + netdev_err(netdev, "Invalid MTU %d. Valid range is: %d..%d\n",
  2132. + mtu, EVB_MIN_FRAME_LENGTH, EVB_MAX_FRAME_LENGTH);
  2133. + return -EINVAL;
  2134. + }
  2135. +
  2136. + err = dpdmux_ul_set_max_frame_length(evb_priv->mc_io,
  2137. + 0,
  2138. + evb_priv->mux_handle,
  2139. + (uint16_t)mtu);
  2140. +
  2141. + if (unlikely(err)) {
  2142. + netdev_err(netdev, "dpdmux_ul_set_max_frame_length err %d\n",
  2143. + err);
  2144. + return err;
  2145. + }
  2146. +
  2147. + /* Update the max frame length for downlinks */
  2148. + list_for_each(pos, &evb_priv->port_list) {
  2149. + port_priv = list_entry(pos, struct evb_port_priv, list);
  2150. + port_priv->netdev->mtu = mtu;
  2151. + }
  2152. +
  2153. + netdev->mtu = mtu;
  2154. + return 0;
  2155. +}
  2156. +
  2157. +static const struct nla_policy ifla_br_policy[IFLA_MAX+1] = {
  2158. + [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 },
  2159. + [IFLA_BRIDGE_MODE] = { .type = NLA_U16 },
  2160. + [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
  2161. + .len = sizeof(struct bridge_vlan_info), },
  2162. +};
  2163. +
  2164. +static int evb_setlink_af_spec(struct net_device *netdev,
  2165. + struct nlattr **tb)
  2166. +{
  2167. + struct bridge_vlan_info *vinfo;
  2168. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2169. + int err = 0;
  2170. +
  2171. + if (!tb[IFLA_BRIDGE_VLAN_INFO]) {
  2172. + netdev_err(netdev, "no VLAN INFO in nlmsg\n");
  2173. + return -EOPNOTSUPP;
  2174. + }
  2175. +
  2176. + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
  2177. +
  2178. + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
  2179. + return -EINVAL;
  2180. +
  2181. + err = evb_port_add_rule(netdev, NULL, vinfo->vid);
  2182. + if (unlikely(err))
  2183. + return err;
  2184. +
  2185. + port_priv->vlans[vinfo->vid] = 1;
  2186. +
  2187. + return 0;
  2188. +}
  2189. +
  2190. +static int evb_setlink(struct net_device *netdev,
  2191. + struct nlmsghdr *nlh,
  2192. + u16 flags)
  2193. +{
  2194. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2195. + struct evb_priv *evb_priv = port_priv->evb_priv;
  2196. + struct nlattr *attr;
  2197. + struct nlattr *tb[(IFLA_BRIDGE_MAX > IFLA_BRPORT_MAX) ?
  2198. + IFLA_BRIDGE_MAX : IFLA_BRPORT_MAX+1];
  2199. + int err = 0;
  2200. +
  2201. + if (evb_priv->attr.method != DPDMUX_METHOD_C_VLAN &&
  2202. + evb_priv->attr.method != DPDMUX_METHOD_S_VLAN) {
  2203. + netdev_err(netdev,
  2204. + "EVB mode does not support VLAN only classification\n");
  2205. + return -EOPNOTSUPP;
  2206. + }
  2207. +
  2208. + attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
  2209. + if (attr) {
  2210. + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, attr,
  2211. + ifla_br_policy);
  2212. + if (unlikely(err)) {
  2213. + netdev_err(netdev,
  2214. + "nla_parse_nested for br_policy err %d\n",
  2215. + err);
  2216. + return err;
  2217. + }
  2218. +
  2219. + err = evb_setlink_af_spec(netdev, tb);
  2220. + return err;
  2221. + }
  2222. +
  2223. + netdev_err(netdev, "nlmsg_find_attr found no AF_SPEC\n");
  2224. + return -EOPNOTSUPP;
  2225. +}
  2226. +
  2227. +static int __nla_put_netdev(struct sk_buff *skb, struct net_device *netdev)
  2228. +{
  2229. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2230. + struct evb_priv *evb_priv = port_priv->evb_priv;
  2231. + u8 operstate = netif_running(netdev) ?
  2232. + netdev->operstate : IF_OPER_DOWN;
  2233. + int iflink;
  2234. + int err;
  2235. +
  2236. + err = nla_put_string(skb, IFLA_IFNAME, netdev->name);
  2237. + if (unlikely(err))
  2238. + goto nla_put_err;
  2239. + err = nla_put_u32(skb, IFLA_MASTER, evb_priv->uplink.netdev->ifindex);
  2240. + if (unlikely(err))
  2241. + goto nla_put_err;
  2242. + err = nla_put_u32(skb, IFLA_MTU, netdev->mtu);
  2243. + if (unlikely(err))
  2244. + goto nla_put_err;
  2245. + err = nla_put_u8(skb, IFLA_OPERSTATE, operstate);
  2246. + if (unlikely(err))
  2247. + goto nla_put_err;
  2248. + if (netdev->addr_len) {
  2249. + err = nla_put(skb, IFLA_ADDRESS, netdev->addr_len,
  2250. + netdev->dev_addr);
  2251. + if (unlikely(err))
  2252. + goto nla_put_err;
  2253. + }
  2254. +
  2255. + iflink = dev_get_iflink(netdev);
  2256. + if (netdev->ifindex != iflink) {
  2257. + err = nla_put_u32(skb, IFLA_LINK, iflink);
  2258. + if (unlikely(err))
  2259. + goto nla_put_err;
  2260. + }
  2261. +
  2262. + return 0;
  2263. +
  2264. +nla_put_err:
  2265. + netdev_err(netdev, "nla_put_ err %d\n", err);
  2266. + return err;
  2267. +}
  2268. +
  2269. +static int __nla_put_port(struct sk_buff *skb, struct net_device *netdev)
  2270. +{
  2271. + struct nlattr *nest;
  2272. + int err;
  2273. +
  2274. + nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
  2275. + if (!nest) {
  2276. + netdev_err(netdev, "nla_nest_start failed\n");
  2277. + return -ENOMEM;
  2278. + }
  2279. +
  2280. + err = nla_put_u8(skb, IFLA_BRPORT_STATE, BR_STATE_FORWARDING);
  2281. + if (unlikely(err))
  2282. + goto nla_put_err;
  2283. + err = nla_put_u16(skb, IFLA_BRPORT_PRIORITY, 0);
  2284. + if (unlikely(err))
  2285. + goto nla_put_err;
  2286. + err = nla_put_u32(skb, IFLA_BRPORT_COST, 0);
  2287. + if (unlikely(err))
  2288. + goto nla_put_err;
  2289. + err = nla_put_u8(skb, IFLA_BRPORT_MODE, 0);
  2290. + if (unlikely(err))
  2291. + goto nla_put_err;
  2292. + err = nla_put_u8(skb, IFLA_BRPORT_GUARD, 0);
  2293. + if (unlikely(err))
  2294. + goto nla_put_err;
  2295. + err = nla_put_u8(skb, IFLA_BRPORT_PROTECT, 0);
  2296. + if (unlikely(err))
  2297. + goto nla_put_err;
  2298. + err = nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, 0);
  2299. + if (unlikely(err))
  2300. + goto nla_put_err;
  2301. + err = nla_put_u8(skb, IFLA_BRPORT_LEARNING, 0);
  2302. + if (unlikely(err))
  2303. + goto nla_put_err;
  2304. + err = nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD, 1);
  2305. + if (unlikely(err))
  2306. + goto nla_put_err;
  2307. + nla_nest_end(skb, nest);
  2308. +
  2309. + return 0;
  2310. +
  2311. +nla_put_err:
  2312. + netdev_err(netdev, "nla_put_ err %d\n", err);
  2313. + nla_nest_cancel(skb, nest);
  2314. + return err;
  2315. +}
  2316. +
  2317. +static int __nla_put_vlan(struct sk_buff *skb, struct net_device *netdev)
  2318. +{
  2319. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2320. + struct nlattr *nest;
  2321. + struct bridge_vlan_info vinfo;
  2322. + const u8 *vlans = port_priv->vlans;
  2323. + u16 i;
  2324. + int err;
  2325. +
  2326. + nest = nla_nest_start(skb, IFLA_AF_SPEC);
  2327. + if (!nest) {
  2328. + netdev_err(netdev, "nla_nest_start failed");
  2329. + return -ENOMEM;
  2330. + }
  2331. +
  2332. + for (i = 0; i < VLAN_VID_MASK+1; i++) {
  2333. + if (!vlans[i])
  2334. + continue;
  2335. +
  2336. + vinfo.flags = 0;
  2337. + vinfo.vid = i;
  2338. +
  2339. + err = nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
  2340. + sizeof(vinfo), &vinfo);
  2341. + if (unlikely(err))
  2342. + goto nla_put_err;
  2343. + }
  2344. +
  2345. + nla_nest_end(skb, nest);
  2346. +
  2347. + return 0;
  2348. +
  2349. +nla_put_err:
  2350. + netdev_err(netdev, "nla_put_ err %d\n", err);
  2351. + nla_nest_cancel(skb, nest);
  2352. + return err;
  2353. +}
  2354. +
  2355. +static int evb_getlink(struct sk_buff *skb, u32 pid, u32 seq,
  2356. + struct net_device *netdev, u32 filter_mask, int nlflags)
  2357. +{
  2358. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2359. + struct evb_priv *evb_priv = port_priv->evb_priv;
  2360. + struct ifinfomsg *hdr;
  2361. + struct nlmsghdr *nlh;
  2362. + int err;
  2363. +
  2364. + if (evb_priv->attr.method != DPDMUX_METHOD_C_VLAN &&
  2365. + evb_priv->attr.method != DPDMUX_METHOD_S_VLAN) {
  2366. + return 0;
  2367. + }
  2368. +
  2369. + nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*hdr), NLM_F_MULTI);
  2370. + if (!nlh)
  2371. + return -EMSGSIZE;
  2372. +
  2373. + hdr = nlmsg_data(nlh);
  2374. + memset(hdr, 0, sizeof(*hdr));
  2375. + hdr->ifi_family = AF_BRIDGE;
  2376. + hdr->ifi_type = netdev->type;
  2377. + hdr->ifi_index = netdev->ifindex;
  2378. + hdr->ifi_flags = dev_get_flags(netdev);
  2379. +
  2380. + err = __nla_put_netdev(skb, netdev);
  2381. + if (unlikely(err))
  2382. + goto nla_put_err;
  2383. +
  2384. + err = __nla_put_port(skb, netdev);
  2385. + if (unlikely(err))
  2386. + goto nla_put_err;
  2387. +
  2388. + /* Check if the VID information is requested */
  2389. + if (filter_mask & RTEXT_FILTER_BRVLAN) {
  2390. + err = __nla_put_vlan(skb, netdev);
  2391. + if (unlikely(err))
  2392. + goto nla_put_err;
  2393. + }
  2394. +
  2395. + nlmsg_end(skb, nlh);
  2396. + return skb->len;
  2397. +
  2398. +nla_put_err:
  2399. + nlmsg_cancel(skb, nlh);
  2400. + return -EMSGSIZE;
  2401. +}
  2402. +
  2403. +static int evb_dellink(struct net_device *netdev,
  2404. + struct nlmsghdr *nlh,
  2405. + u16 flags)
  2406. +{
  2407. + struct nlattr *tb[IFLA_BRIDGE_MAX+1];
  2408. + struct nlattr *spec;
  2409. + struct bridge_vlan_info *vinfo;
  2410. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2411. + int err = 0;
  2412. +
  2413. + spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
  2414. + if (!spec)
  2415. + return 0;
  2416. +
  2417. + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, spec, ifla_br_policy);
  2418. + if (unlikely(err))
  2419. + return err;
  2420. +
  2421. + if (!tb[IFLA_BRIDGE_VLAN_INFO])
  2422. + return -EOPNOTSUPP;
  2423. +
  2424. + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
  2425. +
  2426. + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
  2427. + return -EINVAL;
  2428. +
  2429. + err = evb_port_del_rule(netdev, NULL, vinfo->vid);
  2430. + if (unlikely(err)) {
  2431. + netdev_err(netdev, "evb_port_del_rule err %d\n", err);
  2432. + return err;
  2433. + }
  2434. + port_priv->vlans[vinfo->vid] = 0;
  2435. +
  2436. + return 0;
  2437. +}
  2438. +
  2439. +static struct rtnl_link_stats64 *
  2440. +evb_port_get_stats(struct net_device *netdev,
  2441. + struct rtnl_link_stats64 *storage)
  2442. +{
  2443. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2444. + u64 tmp;
  2445. + int err;
  2446. +
  2447. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2448. + 0,
  2449. + port_priv->evb_priv->mux_handle,
  2450. + port_priv->port_index,
  2451. + DPDMUX_CNT_ING_FRAME, &storage->rx_packets);
  2452. + if (unlikely(err))
  2453. + goto error;
  2454. +
  2455. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2456. + 0,
  2457. + port_priv->evb_priv->mux_handle,
  2458. + port_priv->port_index,
  2459. + DPDMUX_CNT_ING_BYTE, &storage->rx_bytes);
  2460. + if (unlikely(err))
  2461. + goto error;
  2462. +
  2463. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2464. + 0,
  2465. + port_priv->evb_priv->mux_handle,
  2466. + port_priv->port_index,
  2467. + DPDMUX_CNT_ING_FLTR_FRAME, &tmp);
  2468. + if (unlikely(err))
  2469. + goto error;
  2470. +
  2471. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2472. + 0,
  2473. + port_priv->evb_priv->mux_handle,
  2474. + port_priv->port_index,
  2475. + DPDMUX_CNT_ING_FRAME_DISCARD,
  2476. + &storage->rx_dropped);
  2477. + if (unlikely(err)) {
  2478. + storage->rx_dropped = tmp;
  2479. + goto error;
  2480. + }
  2481. + storage->rx_dropped += tmp;
  2482. +
  2483. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2484. + 0,
  2485. + port_priv->evb_priv->mux_handle,
  2486. + port_priv->port_index,
  2487. + DPDMUX_CNT_ING_MCAST_FRAME,
  2488. + &storage->multicast);
  2489. + if (unlikely(err))
  2490. + goto error;
  2491. +
  2492. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2493. + 0,
  2494. + port_priv->evb_priv->mux_handle,
  2495. + port_priv->port_index,
  2496. + DPDMUX_CNT_EGR_FRAME, &storage->tx_packets);
  2497. + if (unlikely(err))
  2498. + goto error;
  2499. +
  2500. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2501. + 0,
  2502. + port_priv->evb_priv->mux_handle,
  2503. + port_priv->port_index,
  2504. + DPDMUX_CNT_EGR_BYTE, &storage->tx_bytes);
  2505. + if (unlikely(err))
  2506. + goto error;
  2507. +
  2508. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2509. + 0,
  2510. + port_priv->evb_priv->mux_handle,
  2511. + port_priv->port_index,
  2512. + DPDMUX_CNT_EGR_FRAME_DISCARD,
  2513. + &storage->tx_dropped);
  2514. + if (unlikely(err))
  2515. + goto error;
  2516. +
  2517. + return storage;
  2518. +
  2519. +error:
  2520. + netdev_err(netdev, "dpdmux_if_get_counter err %d\n", err);
  2521. + return storage;
  2522. +}
  2523. +
  2524. +static const struct net_device_ops evb_port_ops = {
  2525. + .ndo_open = &evb_port_open,
  2526. +
  2527. + .ndo_start_xmit = &evb_dropframe,
  2528. +
  2529. + .ndo_fdb_add = &evb_port_fdb_add,
  2530. + .ndo_fdb_del = &evb_port_fdb_del,
  2531. +
  2532. + .ndo_get_stats64 = &evb_port_get_stats,
  2533. + .ndo_change_mtu = &evb_change_mtu,
  2534. +};
  2535. +
  2536. +static struct {
  2537. + enum dpdmux_counter_type id;
  2538. + char name[ETH_GSTRING_LEN];
  2539. +} evb_ethtool_counters[] = {
  2540. + {DPDMUX_CNT_ING_FRAME, "rx frames"},
  2541. + {DPDMUX_CNT_ING_BYTE, "rx bytes"},
  2542. + {DPDMUX_CNT_ING_FLTR_FRAME, "rx filtered frames"},
  2543. + {DPDMUX_CNT_ING_FRAME_DISCARD, "rx discarded frames"},
  2544. + {DPDMUX_CNT_ING_BCAST_FRAME, "rx b-cast frames"},
  2545. + {DPDMUX_CNT_ING_BCAST_BYTES, "rx b-cast bytes"},
  2546. + {DPDMUX_CNT_ING_MCAST_FRAME, "rx m-cast frames"},
  2547. + {DPDMUX_CNT_ING_MCAST_BYTE, "rx m-cast bytes"},
  2548. + {DPDMUX_CNT_EGR_FRAME, "tx frames"},
  2549. + {DPDMUX_CNT_EGR_BYTE, "tx bytes"},
  2550. + {DPDMUX_CNT_EGR_FRAME_DISCARD, "tx discarded frames"},
  2551. +};
  2552. +
  2553. +static int evb_ethtool_get_sset_count(struct net_device *dev, int sset)
  2554. +{
  2555. + switch (sset) {
  2556. + case ETH_SS_STATS:
  2557. + return ARRAY_SIZE(evb_ethtool_counters);
  2558. + default:
  2559. + return -EOPNOTSUPP;
  2560. + }
  2561. +}
  2562. +
  2563. +static void evb_ethtool_get_strings(struct net_device *netdev,
  2564. + u32 stringset, u8 *data)
  2565. +{
  2566. + int i;
  2567. +
  2568. + switch (stringset) {
  2569. + case ETH_SS_STATS:
  2570. + for (i = 0; i < ARRAY_SIZE(evb_ethtool_counters); i++)
  2571. + memcpy(data + i * ETH_GSTRING_LEN,
  2572. + evb_ethtool_counters[i].name, ETH_GSTRING_LEN);
  2573. + break;
  2574. + }
  2575. +}
  2576. +
  2577. +static void evb_ethtool_get_stats(struct net_device *netdev,
  2578. + struct ethtool_stats *stats,
  2579. + u64 *data)
  2580. +{
  2581. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  2582. + int i;
  2583. + int err;
  2584. +
  2585. + for (i = 0; i < ARRAY_SIZE(evb_ethtool_counters); i++) {
  2586. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  2587. + 0,
  2588. + port_priv->evb_priv->mux_handle,
  2589. + port_priv->port_index,
  2590. + evb_ethtool_counters[i].id,
  2591. + &data[i]);
  2592. + if (err)
  2593. + netdev_err(netdev, "dpdmux_if_get_counter[%s] err %d\n",
  2594. + evb_ethtool_counters[i].name, err);
  2595. + }
  2596. +}
  2597. +
  2598. +static const struct ethtool_ops evb_port_ethtool_ops = {
  2599. + .get_strings = &evb_ethtool_get_strings,
  2600. + .get_ethtool_stats = &evb_ethtool_get_stats,
  2601. + .get_sset_count = &evb_ethtool_get_sset_count,
  2602. +};
  2603. +
  2604. +static int evb_open(struct net_device *netdev)
  2605. +{
  2606. + struct evb_priv *priv = netdev_priv(netdev);
  2607. + int err = 0;
  2608. +
  2609. + err = dpdmux_enable(priv->mc_io, 0, priv->mux_handle);
  2610. + if (unlikely(err))
  2611. + netdev_err(netdev, "dpdmux_enable err %d\n", err);
  2612. +
  2613. + return err;
  2614. +}
  2615. +
  2616. +static int evb_close(struct net_device *netdev)
  2617. +{
  2618. + struct evb_priv *priv = netdev_priv(netdev);
  2619. + int err = 0;
  2620. +
  2621. + err = dpdmux_disable(priv->mc_io, 0, priv->mux_handle);
  2622. + if (unlikely(err))
  2623. + netdev_err(netdev, "dpdmux_disable err %d\n", err);
  2624. +
  2625. + return err;
  2626. +}
  2627. +
  2628. +static const struct net_device_ops evb_ops = {
  2629. + .ndo_start_xmit = &evb_dropframe,
  2630. + .ndo_open = &evb_open,
  2631. + .ndo_stop = &evb_close,
  2632. +
  2633. + .ndo_bridge_setlink = &evb_setlink,
  2634. + .ndo_bridge_getlink = &evb_getlink,
  2635. + .ndo_bridge_dellink = &evb_dellink,
  2636. +
  2637. + .ndo_get_stats64 = &evb_port_get_stats,
  2638. + .ndo_change_mtu = &evb_change_mtu,
  2639. +};
  2640. +
  2641. +static int evb_takedown(struct fsl_mc_device *evb_dev)
  2642. +{
  2643. + struct device *dev = &evb_dev->dev;
  2644. + struct net_device *netdev = dev_get_drvdata(dev);
  2645. + struct evb_priv *priv = netdev_priv(netdev);
  2646. + int err;
  2647. +
  2648. + err = dpdmux_close(priv->mc_io, 0, priv->mux_handle);
  2649. + if (unlikely(err))
  2650. + dev_warn(dev, "dpdmux_close err %d\n", err);
  2651. +
  2652. + return 0;
  2653. +}
  2654. +
  2655. +static int evb_init(struct fsl_mc_device *evb_dev)
  2656. +{
  2657. + struct device *dev = &evb_dev->dev;
  2658. + struct net_device *netdev = dev_get_drvdata(dev);
  2659. + struct evb_priv *priv = netdev_priv(netdev);
  2660. + int err = 0;
  2661. +
  2662. + priv->dev_id = evb_dev->obj_desc.id;
  2663. +
  2664. + err = dpdmux_open(priv->mc_io, 0, priv->dev_id, &priv->mux_handle);
  2665. + if (unlikely(err)) {
  2666. + dev_err(dev, "dpdmux_open err %d\n", err);
  2667. + goto err_exit;
  2668. + }
  2669. + if (!priv->mux_handle) {
  2670. + dev_err(dev, "dpdmux_open returned null handle but no error\n");
  2671. + err = -EFAULT;
  2672. + goto err_exit;
  2673. + }
  2674. +
  2675. + err = dpdmux_get_attributes(priv->mc_io, 0, priv->mux_handle,
  2676. + &priv->attr);
  2677. + if (unlikely(err)) {
  2678. + dev_err(dev, "dpdmux_get_attributes err %d\n", err);
  2679. + goto err_close;
  2680. + }
  2681. +
  2682. + err = dpdmux_reset(priv->mc_io, 0, priv->mux_handle);
  2683. + if (unlikely(err)) {
  2684. + dev_err(dev, "dpdmux_reset err %d\n", err);
  2685. + goto err_close;
  2686. + }
  2687. +
  2688. + return 0;
  2689. +
  2690. +err_close:
  2691. + dpdmux_close(priv->mc_io, 0, priv->mux_handle);
  2692. +err_exit:
  2693. + return err;
  2694. +}
  2695. +
  2696. +static int evb_remove(struct fsl_mc_device *evb_dev)
  2697. +{
  2698. + struct device *dev = &evb_dev->dev;
  2699. + struct net_device *netdev = dev_get_drvdata(dev);
  2700. + struct evb_priv *priv = netdev_priv(netdev);
  2701. + struct evb_port_priv *port_priv;
  2702. + struct list_head *pos;
  2703. +
  2704. + list_for_each(pos, &priv->port_list) {
  2705. + port_priv = list_entry(pos, struct evb_port_priv, list);
  2706. +
  2707. + rtnl_lock();
  2708. + netdev_upper_dev_unlink(port_priv->netdev, netdev);
  2709. + rtnl_unlock();
  2710. +
  2711. + unregister_netdev(port_priv->netdev);
  2712. + free_netdev(port_priv->netdev);
  2713. + }
  2714. +
  2715. + evb_teardown_irqs(evb_dev);
  2716. +
  2717. + unregister_netdev(netdev);
  2718. +
  2719. + evb_takedown(evb_dev);
  2720. + fsl_mc_portal_free(priv->mc_io);
  2721. +
  2722. + dev_set_drvdata(dev, NULL);
  2723. + free_netdev(netdev);
  2724. +
  2725. + return 0;
  2726. +}
  2727. +
  2728. +static int evb_probe(struct fsl_mc_device *evb_dev)
  2729. +{
  2730. + struct device *dev;
  2731. + struct evb_priv *priv = NULL;
  2732. + struct net_device *netdev = NULL;
  2733. + char port_name[IFNAMSIZ];
  2734. + int i;
  2735. + int err = 0;
  2736. +
  2737. + dev = &evb_dev->dev;
  2738. +
  2739. + /* register switch device, it's for management only - no I/O */
  2740. + netdev = alloc_etherdev(sizeof(*priv));
  2741. + if (!netdev) {
  2742. + dev_err(dev, "alloc_etherdev error\n");
  2743. + return -ENOMEM;
  2744. + }
  2745. + netdev->netdev_ops = &evb_ops;
  2746. +
  2747. + dev_set_drvdata(dev, netdev);
  2748. +
  2749. + priv = netdev_priv(netdev);
  2750. +
  2751. + err = fsl_mc_portal_allocate(evb_dev, 0, &priv->mc_io);
  2752. + if (unlikely(err)) {
  2753. + dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
  2754. + goto err_free_netdev;
  2755. + }
  2756. + if (!priv->mc_io) {
  2757. + dev_err(dev, "fsl_mc_portal_allocate returned null handle but no error\n");
  2758. + err = -EFAULT;
  2759. + goto err_free_netdev;
  2760. + }
  2761. +
  2762. + err = evb_init(evb_dev);
  2763. + if (unlikely(err)) {
  2764. + dev_err(dev, "evb init err %d\n", err);
  2765. + goto err_free_cmdport;
  2766. + }
  2767. +
  2768. + INIT_LIST_HEAD(&priv->port_list);
  2769. + netdev->flags |= IFF_PROMISC | IFF_MASTER;
  2770. +
  2771. + dev_alloc_name(netdev, "evb%d");
  2772. +
  2773. + /* register switch ports */
  2774. + snprintf(port_name, IFNAMSIZ, "%sp%%d", netdev->name);
  2775. +
  2776. + /* only register downlinks? */
  2777. + for (i = 0; i < priv->attr.num_ifs + 1; i++) {
  2778. + struct net_device *port_netdev;
  2779. + struct evb_port_priv *port_priv;
  2780. +
  2781. + if (i) {
  2782. + port_netdev =
  2783. + alloc_etherdev(sizeof(struct evb_port_priv));
  2784. + if (!port_netdev) {
  2785. + dev_err(dev, "alloc_etherdev error\n");
  2786. + goto err_takedown;
  2787. + }
  2788. +
  2789. + port_priv = netdev_priv(port_netdev);
  2790. +
  2791. + port_netdev->flags |= IFF_PROMISC | IFF_SLAVE;
  2792. +
  2793. + dev_alloc_name(port_netdev, port_name);
  2794. + } else {
  2795. + port_netdev = netdev;
  2796. + port_priv = &priv->uplink;
  2797. + }
  2798. +
  2799. + port_priv->netdev = port_netdev;
  2800. + port_priv->evb_priv = priv;
  2801. + port_priv->port_index = i;
  2802. +
  2803. + SET_NETDEV_DEV(port_netdev, dev);
  2804. +
  2805. + if (i) {
  2806. + port_netdev->netdev_ops = &evb_port_ops;
  2807. +
  2808. + err = register_netdev(port_netdev);
  2809. + if (err < 0) {
  2810. + dev_err(dev, "register_netdev err %d\n", err);
  2811. + free_netdev(port_netdev);
  2812. + goto err_takedown;
  2813. + }
  2814. +
  2815. + rtnl_lock();
  2816. + err = netdev_master_upper_dev_link(port_netdev, netdev, NULL, NULL);
  2817. + if (unlikely(err)) {
  2818. + dev_err(dev, "netdev_master_upper_dev_link err %d\n",
  2819. + err);
  2820. + unregister_netdev(port_netdev);
  2821. + free_netdev(port_netdev);
  2822. + rtnl_unlock();
  2823. + goto err_takedown;
  2824. + }
  2825. + rtmsg_ifinfo(RTM_NEWLINK, port_netdev,
  2826. + IFF_SLAVE, GFP_KERNEL);
  2827. + rtnl_unlock();
  2828. +
  2829. + list_add(&(port_priv->list), &(priv->port_list));
  2830. + } else {
  2831. + err = register_netdev(netdev);
  2832. +
  2833. + if (err < 0) {
  2834. + dev_err(dev, "register_netdev error %d\n", err);
  2835. + goto err_takedown;
  2836. + }
  2837. + }
  2838. +
  2839. + port_netdev->ethtool_ops = &evb_port_ethtool_ops;
  2840. +
  2841. + /* ports are up from init */
  2842. + rtnl_lock();
  2843. + err = dev_open(port_netdev);
  2844. + rtnl_unlock();
  2845. + if (unlikely(err))
  2846. + dev_warn(dev, "dev_open err %d\n", err);
  2847. + }
  2848. +
  2849. + /* setup irqs */
  2850. + err = evb_setup_irqs(evb_dev);
  2851. + if (unlikely(err)) {
  2852. + dev_warn(dev, "evb_setup_irqs err %d\n", err);
  2853. + goto err_takedown;
  2854. + }
  2855. +
  2856. + dev_info(dev, "probed evb device with %d ports\n",
  2857. + priv->attr.num_ifs);
  2858. + return 0;
  2859. +
  2860. +err_takedown:
  2861. + evb_remove(evb_dev);
  2862. +err_free_cmdport:
  2863. + fsl_mc_portal_free(priv->mc_io);
  2864. +err_free_netdev:
  2865. + return err;
  2866. +}
  2867. +
  2868. +static const struct fsl_mc_device_match_id evb_match_id_table[] = {
  2869. + {
  2870. + .vendor = FSL_MC_VENDOR_FREESCALE,
  2871. + .obj_type = "dpdmux",
  2872. + .ver_major = DPDMUX_VER_MAJOR,
  2873. + .ver_minor = DPDMUX_VER_MINOR,
  2874. + },
  2875. + {}
  2876. +};
  2877. +
  2878. +static struct fsl_mc_driver evb_drv = {
  2879. + .driver = {
  2880. + .name = KBUILD_MODNAME,
  2881. + .owner = THIS_MODULE,
  2882. + },
  2883. + .probe = evb_probe,
  2884. + .remove = evb_remove,
  2885. + .match_id_table = evb_match_id_table,
  2886. +};
  2887. +
  2888. +module_fsl_mc_driver(evb_drv);
  2889. +
  2890. +MODULE_LICENSE("GPL");
  2891. +MODULE_DESCRIPTION("Layerscape DPAA Edge Virtual Bridge driver (prototype)");