mscc_macsec.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. // SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2. /*
  3. * Driver for Microsemi VSC85xx PHYs - MACsec support
  4. *
  5. * Author: Antoine Tenart
  6. * License: Dual MIT/GPL
  7. * Copyright (c) 2020 Microsemi Corporation
  8. */
  9. #include <linux/phy.h>
  10. #include <dt-bindings/net/mscc-phy-vsc8531.h>
  11. #include <crypto/aes.h>
  12. #include <net/macsec.h>
  13. #include "mscc.h"
  14. #include "mscc_mac.h"
  15. #include "mscc_macsec.h"
  16. #include "mscc_fc_buffer.h"
  17. static u32 vsc8584_macsec_phy_read(struct phy_device *phydev,
  18. enum macsec_bank bank, u32 reg)
  19. {
  20. u32 val, val_l = 0, val_h = 0;
  21. unsigned long deadline;
  22. int rc;
  23. rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
  24. if (rc < 0)
  25. goto failed;
  26. __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
  27. MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
  28. if (bank >> 2 == 0x1)
  29. /* non-MACsec access */
  30. bank &= 0x3;
  31. else
  32. bank = 0;
  33. __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
  34. MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_READ |
  35. MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
  36. MSCC_PHY_MACSEC_19_TARGET(bank));
  37. deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
  38. do {
  39. val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
  40. } while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
  41. val_l = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_17);
  42. val_h = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_18);
  43. failed:
  44. phy_restore_page(phydev, rc, rc);
  45. return (val_h << 16) | val_l;
  46. }
  47. static void vsc8584_macsec_phy_write(struct phy_device *phydev,
  48. enum macsec_bank bank, u32 reg, u32 val)
  49. {
  50. unsigned long deadline;
  51. int rc;
  52. rc = phy_select_page(phydev, MSCC_PHY_PAGE_MACSEC);
  53. if (rc < 0)
  54. goto failed;
  55. __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_20,
  56. MSCC_PHY_MACSEC_20_TARGET(bank >> 2));
  57. if ((bank >> 2 == 0x1) || (bank >> 2 == 0x3))
  58. bank &= 0x3;
  59. else
  60. /* MACsec access */
  61. bank = 0;
  62. __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_17, (u16)val);
  63. __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_18, (u16)(val >> 16));
  64. __phy_write(phydev, MSCC_EXT_PAGE_MACSEC_19,
  65. MSCC_PHY_MACSEC_19_CMD | MSCC_PHY_MACSEC_19_REG_ADDR(reg) |
  66. MSCC_PHY_MACSEC_19_TARGET(bank));
  67. deadline = jiffies + msecs_to_jiffies(PROC_CMD_NCOMPLETED_TIMEOUT_MS);
  68. do {
  69. val = __phy_read(phydev, MSCC_EXT_PAGE_MACSEC_19);
  70. } while (time_before(jiffies, deadline) && !(val & MSCC_PHY_MACSEC_19_CMD));
  71. failed:
  72. phy_restore_page(phydev, rc, rc);
  73. }
  74. static void vsc8584_macsec_classification(struct phy_device *phydev,
  75. enum macsec_bank bank)
  76. {
  77. /* enable VLAN tag parsing */
  78. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_CP_TAG,
  79. MSCC_MS_SAM_CP_TAG_PARSE_STAG |
  80. MSCC_MS_SAM_CP_TAG_PARSE_QTAG |
  81. MSCC_MS_SAM_CP_TAG_PARSE_QINQ);
  82. }
  83. static void vsc8584_macsec_flow_default_action(struct phy_device *phydev,
  84. enum macsec_bank bank,
  85. bool block)
  86. {
  87. u32 port = (bank == MACSEC_INGR) ?
  88. MSCC_MS_PORT_UNCONTROLLED : MSCC_MS_PORT_COMMON;
  89. u32 action = MSCC_MS_FLOW_BYPASS;
  90. if (block)
  91. action = MSCC_MS_FLOW_DROP;
  92. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_NCP,
  93. /* MACsec untagged */
  94. MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
  95. MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  96. MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_DEST_PORT(port) |
  97. /* MACsec tagged */
  98. MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
  99. MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  100. MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_DEST_PORT(port) |
  101. /* Bad tag */
  102. MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
  103. MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  104. MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_DEST_PORT(port) |
  105. /* Kay tag */
  106. MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
  107. MSCC_MS_SAM_NM_FLOW_NCP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  108. MSCC_MS_SAM_NM_FLOW_NCP_KAY_DEST_PORT(port));
  109. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_NM_FLOW_CP,
  110. /* MACsec untagged */
  111. MSCC_MS_SAM_NM_FLOW_NCP_UNTAGGED_FLOW_TYPE(action) |
  112. MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  113. MSCC_MS_SAM_NM_FLOW_CP_UNTAGGED_DEST_PORT(port) |
  114. /* MACsec tagged */
  115. MSCC_MS_SAM_NM_FLOW_NCP_TAGGED_FLOW_TYPE(action) |
  116. MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  117. MSCC_MS_SAM_NM_FLOW_CP_TAGGED_DEST_PORT(port) |
  118. /* Bad tag */
  119. MSCC_MS_SAM_NM_FLOW_NCP_BADTAG_FLOW_TYPE(action) |
  120. MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  121. MSCC_MS_SAM_NM_FLOW_CP_BADTAG_DEST_PORT(port) |
  122. /* Kay tag */
  123. MSCC_MS_SAM_NM_FLOW_NCP_KAY_FLOW_TYPE(action) |
  124. MSCC_MS_SAM_NM_FLOW_CP_KAY_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  125. MSCC_MS_SAM_NM_FLOW_CP_KAY_DEST_PORT(port));
  126. }
  127. static void vsc8584_macsec_integrity_checks(struct phy_device *phydev,
  128. enum macsec_bank bank)
  129. {
  130. u32 val;
  131. if (bank != MACSEC_INGR)
  132. return;
  133. /* Set default rules to pass unmatched frames */
  134. val = vsc8584_macsec_phy_read(phydev, bank,
  135. MSCC_MS_PARAMS2_IG_CC_CONTROL);
  136. val |= MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_CTRL_ACT |
  137. MSCC_MS_PARAMS2_IG_CC_CONTROL_NON_MATCH_ACT;
  138. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CC_CONTROL,
  139. val);
  140. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PARAMS2_IG_CP_TAG,
  141. MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_STAG |
  142. MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QTAG |
  143. MSCC_MS_PARAMS2_IG_CP_TAG_PARSE_QINQ);
  144. }
  145. static void vsc8584_macsec_block_init(struct phy_device *phydev,
  146. enum macsec_bank bank)
  147. {
  148. u32 val;
  149. int i;
  150. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
  151. MSCC_MS_ENA_CFG_SW_RST |
  152. MSCC_MS_ENA_CFG_MACSEC_BYPASS_ENA);
  153. /* Set the MACsec block out of s/w reset and enable clocks */
  154. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
  155. MSCC_MS_ENA_CFG_CLK_ENA);
  156. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_STATUS_CONTEXT_CTRL,
  157. bank == MACSEC_INGR ? 0xe5880214 : 0xe5880218);
  158. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_MISC_CONTROL,
  159. MSCC_MS_MISC_CONTROL_MC_LATENCY_FIX(bank == MACSEC_INGR ? 57 : 40) |
  160. MSCC_MS_MISC_CONTROL_XFORM_REC_SIZE(bank == MACSEC_INGR ? 1 : 2));
  161. /* Clear the counters */
  162. val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
  163. val |= MSCC_MS_COUNT_CONTROL_AUTO_CNTR_RESET;
  164. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
  165. /* Enable octet increment mode */
  166. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_PP_CTRL,
  167. MSCC_MS_PP_CTRL_MACSEC_OCTET_INCR_MODE);
  168. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_BLOCK_CTX_UPDATE, 0x3);
  169. val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_COUNT_CONTROL);
  170. val |= MSCC_MS_COUNT_CONTROL_RESET_ALL;
  171. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_COUNT_CONTROL, val);
  172. /* Set the MTU */
  173. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_NON_VLAN_MTU_CHECK,
  174. MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMPARE(32761) |
  175. MSCC_MS_NON_VLAN_MTU_CHECK_NV_MTU_COMP_DROP);
  176. for (i = 0; i < 8; i++)
  177. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_VLAN_MTU_CHECK(i),
  178. MSCC_MS_VLAN_MTU_CHECK_MTU_COMPARE(32761) |
  179. MSCC_MS_VLAN_MTU_CHECK_MTU_COMP_DROP);
  180. if (bank == MACSEC_EGR) {
  181. val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_INTR_CTRL_STATUS);
  182. val &= ~MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE_M;
  183. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_INTR_CTRL_STATUS, val);
  184. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_FC_CFG,
  185. MSCC_MS_FC_CFG_FCBUF_ENA |
  186. MSCC_MS_FC_CFG_LOW_THRESH(0x1) |
  187. MSCC_MS_FC_CFG_HIGH_THRESH(0x4) |
  188. MSCC_MS_FC_CFG_LOW_BYTES_VAL(0x4) |
  189. MSCC_MS_FC_CFG_HIGH_BYTES_VAL(0x6));
  190. }
  191. vsc8584_macsec_classification(phydev, bank);
  192. vsc8584_macsec_flow_default_action(phydev, bank, false);
  193. vsc8584_macsec_integrity_checks(phydev, bank);
  194. /* Enable the MACsec block */
  195. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_ENA_CFG,
  196. MSCC_MS_ENA_CFG_CLK_ENA |
  197. MSCC_MS_ENA_CFG_MACSEC_ENA |
  198. MSCC_MS_ENA_CFG_MACSEC_SPEED_MODE(0x5));
  199. }
  200. static void vsc8584_macsec_mac_init(struct phy_device *phydev,
  201. enum macsec_bank bank)
  202. {
  203. u32 val;
  204. int i;
  205. /* Clear host & line stats */
  206. for (i = 0; i < 36; i++)
  207. vsc8584_macsec_phy_write(phydev, bank, 0x1c + i, 0);
  208. val = vsc8584_macsec_phy_read(phydev, bank,
  209. MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL);
  210. val &= ~MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE_M;
  211. val |= MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_MODE(2) |
  212. MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_PAUSE_VALUE(0xffff);
  213. vsc8584_macsec_phy_write(phydev, bank,
  214. MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL, val);
  215. val = vsc8584_macsec_phy_read(phydev, bank,
  216. MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2);
  217. val |= 0xffff;
  218. vsc8584_macsec_phy_write(phydev, bank,
  219. MSCC_MAC_PAUSE_CFG_TX_FRAME_CTRL_2, val);
  220. val = vsc8584_macsec_phy_read(phydev, bank,
  221. MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL);
  222. if (bank == HOST_MAC)
  223. val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_TIMER_ENA |
  224. MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA;
  225. else
  226. val |= MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_REACT_ENA |
  227. MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_FRAME_DROP_ENA |
  228. MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_PAUSE_MODE |
  229. MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL_EARLY_PAUSE_DETECT_ENA;
  230. vsc8584_macsec_phy_write(phydev, bank,
  231. MSCC_MAC_PAUSE_CFG_RX_FRAME_CTRL, val);
  232. vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_PKTINF_CFG,
  233. MSCC_MAC_CFG_PKTINF_CFG_STRIP_FCS_ENA |
  234. MSCC_MAC_CFG_PKTINF_CFG_INSERT_FCS_ENA |
  235. MSCC_MAC_CFG_PKTINF_CFG_LPI_RELAY_ENA |
  236. MSCC_MAC_CFG_PKTINF_CFG_STRIP_PREAMBLE_ENA |
  237. MSCC_MAC_CFG_PKTINF_CFG_INSERT_PREAMBLE_ENA |
  238. (bank == HOST_MAC ?
  239. MSCC_MAC_CFG_PKTINF_CFG_ENABLE_TX_PADDING : 0) |
  240. (IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING) ?
  241. MSCC_MAC_CFG_PKTINF_CFG_MACSEC_BYPASS_NUM_PTP_STALL_CLKS(0x8) : 0));
  242. val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MODE_CFG);
  243. val &= ~MSCC_MAC_CFG_MODE_CFG_DISABLE_DIC;
  244. vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MODE_CFG, val);
  245. val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG);
  246. val &= ~MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN_M;
  247. val |= MSCC_MAC_CFG_MAXLEN_CFG_MAX_LEN(10240);
  248. vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_MAXLEN_CFG, val);
  249. vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ADV_CHK_CFG,
  250. MSCC_MAC_CFG_ADV_CHK_CFG_SFD_CHK_ENA |
  251. MSCC_MAC_CFG_ADV_CHK_CFG_PRM_CHK_ENA |
  252. MSCC_MAC_CFG_ADV_CHK_CFG_OOR_ERR_ENA |
  253. MSCC_MAC_CFG_ADV_CHK_CFG_INR_ERR_ENA);
  254. val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MAC_CFG_LFS_CFG);
  255. val &= ~MSCC_MAC_CFG_LFS_CFG_LFS_MODE_ENA;
  256. vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_LFS_CFG, val);
  257. vsc8584_macsec_phy_write(phydev, bank, MSCC_MAC_CFG_ENA_CFG,
  258. MSCC_MAC_CFG_ENA_CFG_RX_CLK_ENA |
  259. MSCC_MAC_CFG_ENA_CFG_TX_CLK_ENA |
  260. MSCC_MAC_CFG_ENA_CFG_RX_ENA |
  261. MSCC_MAC_CFG_ENA_CFG_TX_ENA);
  262. }
  263. /* Must be called with mdio_lock taken */
  264. static int __vsc8584_macsec_init(struct phy_device *phydev)
  265. {
  266. struct vsc8531_private *priv = phydev->priv;
  267. enum macsec_bank proc_bank;
  268. u32 val;
  269. vsc8584_macsec_block_init(phydev, MACSEC_INGR);
  270. vsc8584_macsec_block_init(phydev, MACSEC_EGR);
  271. vsc8584_macsec_mac_init(phydev, HOST_MAC);
  272. vsc8584_macsec_mac_init(phydev, LINE_MAC);
  273. vsc8584_macsec_phy_write(phydev, FC_BUFFER,
  274. MSCC_FCBUF_FC_READ_THRESH_CFG,
  275. MSCC_FCBUF_FC_READ_THRESH_CFG_TX_THRESH(4) |
  276. MSCC_FCBUF_FC_READ_THRESH_CFG_RX_THRESH(5));
  277. val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG);
  278. val |= MSCC_FCBUF_MODE_CFG_PAUSE_GEN_ENA |
  279. MSCC_FCBUF_MODE_CFG_RX_PPM_RATE_ADAPT_ENA |
  280. MSCC_FCBUF_MODE_CFG_TX_PPM_RATE_ADAPT_ENA;
  281. vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_MODE_CFG, val);
  282. vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG,
  283. MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_THRESH(8) |
  284. MSCC_FCBUF_PPM_RATE_ADAPT_THRESH_CFG_TX_OFFSET(9));
  285. val = vsc8584_macsec_phy_read(phydev, FC_BUFFER,
  286. MSCC_FCBUF_TX_DATA_QUEUE_CFG);
  287. val &= ~(MSCC_FCBUF_TX_DATA_QUEUE_CFG_START_M |
  288. MSCC_FCBUF_TX_DATA_QUEUE_CFG_END_M);
  289. val |= MSCC_FCBUF_TX_DATA_QUEUE_CFG_START(0) |
  290. MSCC_FCBUF_TX_DATA_QUEUE_CFG_END(5119);
  291. vsc8584_macsec_phy_write(phydev, FC_BUFFER,
  292. MSCC_FCBUF_TX_DATA_QUEUE_CFG, val);
  293. val = vsc8584_macsec_phy_read(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG);
  294. val |= MSCC_FCBUF_ENA_CFG_TX_ENA | MSCC_FCBUF_ENA_CFG_RX_ENA;
  295. vsc8584_macsec_phy_write(phydev, FC_BUFFER, MSCC_FCBUF_ENA_CFG, val);
  296. proc_bank = (priv->addr < 2) ? PROC_0 : PROC_2;
  297. val = vsc8584_macsec_phy_read(phydev, proc_bank,
  298. MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL);
  299. val &= ~MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE_M;
  300. val |= MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL_PROTOCOL_MODE(4);
  301. vsc8584_macsec_phy_write(phydev, proc_bank,
  302. MSCC_PROC_IP_1588_TOP_CFG_STAT_MODE_CTL, val);
  303. return 0;
  304. }
  305. static void vsc8584_macsec_flow(struct phy_device *phydev,
  306. struct macsec_flow *flow)
  307. {
  308. struct vsc8531_private *priv = phydev->priv;
  309. enum macsec_bank bank = flow->bank;
  310. u32 val, match = 0, mask = 0, action = 0, idx = flow->index;
  311. if (flow->match.tagged)
  312. match |= MSCC_MS_SAM_MISC_MATCH_TAGGED;
  313. if (flow->match.untagged)
  314. match |= MSCC_MS_SAM_MISC_MATCH_UNTAGGED;
  315. if (bank == MACSEC_INGR && flow->assoc_num >= 0) {
  316. match |= MSCC_MS_SAM_MISC_MATCH_AN(flow->assoc_num);
  317. mask |= MSCC_MS_SAM_MASK_AN_MASK(0x3);
  318. }
  319. if (bank == MACSEC_INGR && flow->match.sci && flow->rx_sa->sc->sci) {
  320. u64 sci = (__force u64)flow->rx_sa->sc->sci;
  321. match |= MSCC_MS_SAM_MISC_MATCH_TCI(BIT(3));
  322. mask |= MSCC_MS_SAM_MASK_TCI_MASK(BIT(3)) |
  323. MSCC_MS_SAM_MASK_SCI_MASK;
  324. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_LO(idx),
  325. lower_32_bits(sci));
  326. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MATCH_SCI_HI(idx),
  327. upper_32_bits(sci));
  328. }
  329. if (flow->match.etype) {
  330. mask |= MSCC_MS_SAM_MASK_MAC_ETYPE_MASK;
  331. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MAC_SA_MATCH_HI(idx),
  332. MSCC_MS_SAM_MAC_SA_MATCH_HI_ETYPE((__force u32)htons(flow->etype)));
  333. }
  334. match |= MSCC_MS_SAM_MISC_MATCH_PRIORITY(flow->priority);
  335. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MISC_MATCH(idx), match);
  336. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_MASK(idx), mask);
  337. /* Action for matching packets */
  338. if (flow->action.drop)
  339. action = MSCC_MS_FLOW_DROP;
  340. else if (flow->action.bypass || flow->port == MSCC_MS_PORT_UNCONTROLLED)
  341. action = MSCC_MS_FLOW_BYPASS;
  342. else
  343. action = (bank == MACSEC_INGR) ?
  344. MSCC_MS_FLOW_INGRESS : MSCC_MS_FLOW_EGRESS;
  345. val = MSCC_MS_SAM_FLOW_CTRL_FLOW_TYPE(action) |
  346. MSCC_MS_SAM_FLOW_CTRL_DROP_ACTION(MSCC_MS_ACTION_DROP) |
  347. MSCC_MS_SAM_FLOW_CTRL_DEST_PORT(flow->port);
  348. if (action == MSCC_MS_FLOW_BYPASS)
  349. goto write_ctrl;
  350. if (bank == MACSEC_INGR) {
  351. if (priv->secy->replay_protect)
  352. val |= MSCC_MS_SAM_FLOW_CTRL_REPLAY_PROTECT;
  353. if (priv->secy->validate_frames == MACSEC_VALIDATE_STRICT)
  354. val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_STRICT);
  355. else if (priv->secy->validate_frames == MACSEC_VALIDATE_CHECK)
  356. val |= MSCC_MS_SAM_FLOW_CTRL_VALIDATE_FRAMES(MSCC_MS_VALIDATE_CHECK);
  357. } else if (bank == MACSEC_EGR) {
  358. if (priv->secy->protect_frames)
  359. val |= MSCC_MS_SAM_FLOW_CTRL_PROTECT_FRAME;
  360. if (priv->secy->tx_sc.encrypt)
  361. val |= MSCC_MS_SAM_FLOW_CTRL_CONF_PROTECT;
  362. if (priv->secy->tx_sc.send_sci)
  363. val |= MSCC_MS_SAM_FLOW_CTRL_INCLUDE_SCI;
  364. }
  365. write_ctrl:
  366. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
  367. }
  368. static struct macsec_flow *vsc8584_macsec_find_flow(struct macsec_context *ctx,
  369. enum macsec_bank bank)
  370. {
  371. struct vsc8531_private *priv = ctx->phydev->priv;
  372. struct macsec_flow *pos, *tmp;
  373. list_for_each_entry_safe(pos, tmp, &priv->macsec_flows, list)
  374. if (pos->assoc_num == ctx->sa.assoc_num && pos->bank == bank)
  375. return pos;
  376. return ERR_PTR(-ENOENT);
  377. }
  378. static void vsc8584_macsec_flow_enable(struct phy_device *phydev,
  379. struct macsec_flow *flow)
  380. {
  381. enum macsec_bank bank = flow->bank;
  382. u32 val, idx = flow->index;
  383. if ((flow->bank == MACSEC_INGR && flow->rx_sa && !flow->rx_sa->active) ||
  384. (flow->bank == MACSEC_EGR && flow->tx_sa && !flow->tx_sa->active))
  385. return;
  386. /* Enable */
  387. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_SET1, BIT(idx));
  388. /* Set in-use */
  389. val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
  390. val |= MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
  391. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
  392. }
  393. static void vsc8584_macsec_flow_disable(struct phy_device *phydev,
  394. struct macsec_flow *flow)
  395. {
  396. enum macsec_bank bank = flow->bank;
  397. u32 val, idx = flow->index;
  398. /* Disable */
  399. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_ENTRY_CLEAR1, BIT(idx));
  400. /* Clear in-use */
  401. val = vsc8584_macsec_phy_read(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx));
  402. val &= ~MSCC_MS_SAM_FLOW_CTRL_SA_IN_USE;
  403. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_SAM_FLOW_CTRL(idx), val);
  404. }
  405. static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow)
  406. {
  407. if (flow->bank == MACSEC_INGR)
  408. return flow->index + MSCC_MS_MAX_FLOWS;
  409. return flow->index;
  410. }
  411. /* Derive the AES key to get a key for the hash autentication */
  412. static int vsc8584_macsec_derive_key(const u8 key[MACSEC_MAX_KEY_LEN],
  413. u16 key_len, u8 hkey[16])
  414. {
  415. const u8 input[AES_BLOCK_SIZE] = {0};
  416. struct crypto_aes_ctx ctx;
  417. int ret;
  418. ret = aes_expandkey(&ctx, key, key_len);
  419. if (ret)
  420. return ret;
  421. aes_encrypt(&ctx, hkey, input);
  422. memzero_explicit(&ctx, sizeof(ctx));
  423. return 0;
  424. }
  425. static int vsc8584_macsec_transformation(struct phy_device *phydev,
  426. struct macsec_flow *flow)
  427. {
  428. struct vsc8531_private *priv = phydev->priv;
  429. enum macsec_bank bank = flow->bank;
  430. int i, ret, index = flow->index;
  431. u32 rec = 0, control = 0;
  432. u8 hkey[16];
  433. u64 sci;
  434. ret = vsc8584_macsec_derive_key(flow->key, priv->secy->key_len, hkey);
  435. if (ret)
  436. return ret;
  437. switch (priv->secy->key_len) {
  438. case 16:
  439. control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_128);
  440. break;
  441. case 32:
  442. control |= CONTROL_CRYPTO_ALG(CTRYPTO_ALG_AES_CTR_256);
  443. break;
  444. default:
  445. return -EINVAL;
  446. }
  447. control |= (bank == MACSEC_EGR) ?
  448. (CONTROL_TYPE_EGRESS | CONTROL_AN(priv->secy->tx_sc.encoding_sa)) :
  449. (CONTROL_TYPE_INGRESS | CONTROL_SEQ_MASK);
  450. control |= CONTROL_UPDATE_SEQ | CONTROL_ENCRYPT_AUTH | CONTROL_KEY_IN_CTX |
  451. CONTROL_IV0 | CONTROL_IV1 | CONTROL_IV_IN_SEQ |
  452. CONTROL_DIGEST_TYPE(0x2) | CONTROL_SEQ_TYPE(0x1) |
  453. CONTROL_AUTH_ALG(AUTH_ALG_AES_GHAS) | CONTROL_CONTEXT_ID;
  454. /* Set the control word */
  455. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
  456. control);
  457. /* Set the context ID. Must be unique. */
  458. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
  459. vsc8584_macsec_flow_context_id(flow));
  460. /* Set the encryption/decryption key */
  461. for (i = 0; i < priv->secy->key_len / sizeof(u32); i++)
  462. vsc8584_macsec_phy_write(phydev, bank,
  463. MSCC_MS_XFORM_REC(index, rec++),
  464. ((u32 *)flow->key)[i]);
  465. /* Set the authentication key */
  466. for (i = 0; i < 4; i++)
  467. vsc8584_macsec_phy_write(phydev, bank,
  468. MSCC_MS_XFORM_REC(index, rec++),
  469. ((u32 *)hkey)[i]);
  470. /* Initial sequence number */
  471. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
  472. bank == MACSEC_INGR ?
  473. flow->rx_sa->next_pn : flow->tx_sa->next_pn);
  474. if (bank == MACSEC_INGR)
  475. /* Set the mask (replay window size) */
  476. vsc8584_macsec_phy_write(phydev, bank,
  477. MSCC_MS_XFORM_REC(index, rec++),
  478. priv->secy->replay_window);
  479. /* Set the input vectors */
  480. sci = (__force u64)(bank == MACSEC_INGR ? flow->rx_sa->sc->sci : priv->secy->sci);
  481. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
  482. lower_32_bits(sci));
  483. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
  484. upper_32_bits(sci));
  485. while (rec < 20)
  486. vsc8584_macsec_phy_write(phydev, bank, MSCC_MS_XFORM_REC(index, rec++),
  487. 0);
  488. flow->has_transformation = true;
  489. return 0;
  490. }
  491. static struct macsec_flow *vsc8584_macsec_alloc_flow(struct vsc8531_private *priv,
  492. enum macsec_bank bank)
  493. {
  494. unsigned long *bitmap = bank == MACSEC_INGR ?
  495. &priv->ingr_flows : &priv->egr_flows;
  496. struct macsec_flow *flow;
  497. int index;
  498. index = find_first_zero_bit(bitmap, MSCC_MS_MAX_FLOWS);
  499. if (index == MSCC_MS_MAX_FLOWS)
  500. return ERR_PTR(-ENOMEM);
  501. flow = kzalloc(sizeof(*flow), GFP_KERNEL);
  502. if (!flow)
  503. return ERR_PTR(-ENOMEM);
  504. set_bit(index, bitmap);
  505. flow->index = index;
  506. flow->bank = bank;
  507. flow->priority = 8;
  508. flow->assoc_num = -1;
  509. list_add_tail(&flow->list, &priv->macsec_flows);
  510. return flow;
  511. }
  512. static void vsc8584_macsec_free_flow(struct vsc8531_private *priv,
  513. struct macsec_flow *flow)
  514. {
  515. unsigned long *bitmap = flow->bank == MACSEC_INGR ?
  516. &priv->ingr_flows : &priv->egr_flows;
  517. list_del(&flow->list);
  518. clear_bit(flow->index, bitmap);
  519. memzero_explicit(flow->key, sizeof(flow->key));
  520. kfree(flow);
  521. }
  522. static int vsc8584_macsec_add_flow(struct phy_device *phydev,
  523. struct macsec_flow *flow, bool update)
  524. {
  525. int ret;
  526. flow->port = MSCC_MS_PORT_CONTROLLED;
  527. vsc8584_macsec_flow(phydev, flow);
  528. if (update)
  529. return 0;
  530. ret = vsc8584_macsec_transformation(phydev, flow);
  531. if (ret) {
  532. vsc8584_macsec_free_flow(phydev->priv, flow);
  533. return ret;
  534. }
  535. return 0;
  536. }
  537. static int vsc8584_macsec_default_flows(struct phy_device *phydev)
  538. {
  539. struct macsec_flow *flow;
  540. /* Add a rule to let the MKA traffic go through, ingress */
  541. flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_INGR);
  542. if (IS_ERR(flow))
  543. return PTR_ERR(flow);
  544. flow->priority = 15;
  545. flow->port = MSCC_MS_PORT_UNCONTROLLED;
  546. flow->match.tagged = 1;
  547. flow->match.untagged = 1;
  548. flow->match.etype = 1;
  549. flow->etype = ETH_P_PAE;
  550. flow->action.bypass = 1;
  551. vsc8584_macsec_flow(phydev, flow);
  552. vsc8584_macsec_flow_enable(phydev, flow);
  553. /* Add a rule to let the MKA traffic go through, egress */
  554. flow = vsc8584_macsec_alloc_flow(phydev->priv, MACSEC_EGR);
  555. if (IS_ERR(flow))
  556. return PTR_ERR(flow);
  557. flow->priority = 15;
  558. flow->port = MSCC_MS_PORT_COMMON;
  559. flow->match.untagged = 1;
  560. flow->match.etype = 1;
  561. flow->etype = ETH_P_PAE;
  562. flow->action.bypass = 1;
  563. vsc8584_macsec_flow(phydev, flow);
  564. vsc8584_macsec_flow_enable(phydev, flow);
  565. return 0;
  566. }
  567. static void vsc8584_macsec_del_flow(struct phy_device *phydev,
  568. struct macsec_flow *flow)
  569. {
  570. vsc8584_macsec_flow_disable(phydev, flow);
  571. vsc8584_macsec_free_flow(phydev->priv, flow);
  572. }
  573. static int __vsc8584_macsec_add_rxsa(struct macsec_context *ctx,
  574. struct macsec_flow *flow, bool update)
  575. {
  576. struct phy_device *phydev = ctx->phydev;
  577. struct vsc8531_private *priv = phydev->priv;
  578. flow->assoc_num = ctx->sa.assoc_num;
  579. flow->rx_sa = ctx->sa.rx_sa;
  580. /* Always match tagged packets on ingress */
  581. flow->match.tagged = 1;
  582. flow->match.sci = 1;
  583. if (priv->secy->validate_frames != MACSEC_VALIDATE_DISABLED)
  584. flow->match.untagged = 1;
  585. return vsc8584_macsec_add_flow(phydev, flow, update);
  586. }
  587. static int __vsc8584_macsec_add_txsa(struct macsec_context *ctx,
  588. struct macsec_flow *flow, bool update)
  589. {
  590. flow->assoc_num = ctx->sa.assoc_num;
  591. flow->tx_sa = ctx->sa.tx_sa;
  592. /* Always match untagged packets on egress */
  593. flow->match.untagged = 1;
  594. return vsc8584_macsec_add_flow(ctx->phydev, flow, update);
  595. }
  596. static int vsc8584_macsec_dev_open(struct macsec_context *ctx)
  597. {
  598. struct vsc8531_private *priv = ctx->phydev->priv;
  599. struct macsec_flow *flow, *tmp;
  600. list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
  601. vsc8584_macsec_flow_enable(ctx->phydev, flow);
  602. return 0;
  603. }
  604. static int vsc8584_macsec_dev_stop(struct macsec_context *ctx)
  605. {
  606. struct vsc8531_private *priv = ctx->phydev->priv;
  607. struct macsec_flow *flow, *tmp;
  608. list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
  609. vsc8584_macsec_flow_disable(ctx->phydev, flow);
  610. return 0;
  611. }
  612. static int vsc8584_macsec_add_secy(struct macsec_context *ctx)
  613. {
  614. struct vsc8531_private *priv = ctx->phydev->priv;
  615. struct macsec_secy *secy = ctx->secy;
  616. if (priv->secy)
  617. return -EEXIST;
  618. priv->secy = secy;
  619. vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR,
  620. secy->validate_frames != MACSEC_VALIDATE_DISABLED);
  621. vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR,
  622. secy->validate_frames != MACSEC_VALIDATE_DISABLED);
  623. return vsc8584_macsec_default_flows(ctx->phydev);
  624. }
  625. static int vsc8584_macsec_del_secy(struct macsec_context *ctx)
  626. {
  627. struct vsc8531_private *priv = ctx->phydev->priv;
  628. struct macsec_flow *flow, *tmp;
  629. list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list)
  630. vsc8584_macsec_del_flow(ctx->phydev, flow);
  631. vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_EGR, false);
  632. vsc8584_macsec_flow_default_action(ctx->phydev, MACSEC_INGR, false);
  633. priv->secy = NULL;
  634. return 0;
  635. }
  636. static int vsc8584_macsec_upd_secy(struct macsec_context *ctx)
  637. {
  638. vsc8584_macsec_del_secy(ctx);
  639. return vsc8584_macsec_add_secy(ctx);
  640. }
  641. static int vsc8584_macsec_add_rxsc(struct macsec_context *ctx)
  642. {
  643. /* Nothing to do */
  644. return 0;
  645. }
  646. static int vsc8584_macsec_upd_rxsc(struct macsec_context *ctx)
  647. {
  648. return -EOPNOTSUPP;
  649. }
  650. static int vsc8584_macsec_del_rxsc(struct macsec_context *ctx)
  651. {
  652. struct vsc8531_private *priv = ctx->phydev->priv;
  653. struct macsec_flow *flow, *tmp;
  654. list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
  655. if (flow->bank == MACSEC_INGR && flow->rx_sa &&
  656. flow->rx_sa->sc->sci == ctx->rx_sc->sci)
  657. vsc8584_macsec_del_flow(ctx->phydev, flow);
  658. }
  659. return 0;
  660. }
  661. static int vsc8584_macsec_add_rxsa(struct macsec_context *ctx)
  662. {
  663. struct phy_device *phydev = ctx->phydev;
  664. struct vsc8531_private *priv = phydev->priv;
  665. struct macsec_flow *flow;
  666. int ret;
  667. flow = vsc8584_macsec_alloc_flow(priv, MACSEC_INGR);
  668. if (IS_ERR(flow))
  669. return PTR_ERR(flow);
  670. memcpy(flow->key, ctx->sa.key, priv->secy->key_len);
  671. ret = __vsc8584_macsec_add_rxsa(ctx, flow, false);
  672. if (ret)
  673. return ret;
  674. vsc8584_macsec_flow_enable(phydev, flow);
  675. return 0;
  676. }
  677. static int vsc8584_macsec_upd_rxsa(struct macsec_context *ctx)
  678. {
  679. struct macsec_flow *flow;
  680. int ret;
  681. flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
  682. if (IS_ERR(flow))
  683. return PTR_ERR(flow);
  684. /* Make sure the flow is disabled before updating it */
  685. vsc8584_macsec_flow_disable(ctx->phydev, flow);
  686. ret = __vsc8584_macsec_add_rxsa(ctx, flow, true);
  687. if (ret)
  688. return ret;
  689. vsc8584_macsec_flow_enable(ctx->phydev, flow);
  690. return 0;
  691. }
  692. static int vsc8584_macsec_del_rxsa(struct macsec_context *ctx)
  693. {
  694. struct macsec_flow *flow;
  695. flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR);
  696. if (IS_ERR(flow))
  697. return PTR_ERR(flow);
  698. vsc8584_macsec_del_flow(ctx->phydev, flow);
  699. return 0;
  700. }
  701. static int vsc8584_macsec_add_txsa(struct macsec_context *ctx)
  702. {
  703. struct phy_device *phydev = ctx->phydev;
  704. struct vsc8531_private *priv = phydev->priv;
  705. struct macsec_flow *flow;
  706. int ret;
  707. flow = vsc8584_macsec_alloc_flow(priv, MACSEC_EGR);
  708. if (IS_ERR(flow))
  709. return PTR_ERR(flow);
  710. memcpy(flow->key, ctx->sa.key, priv->secy->key_len);
  711. ret = __vsc8584_macsec_add_txsa(ctx, flow, false);
  712. if (ret)
  713. return ret;
  714. vsc8584_macsec_flow_enable(phydev, flow);
  715. return 0;
  716. }
  717. static int vsc8584_macsec_upd_txsa(struct macsec_context *ctx)
  718. {
  719. struct macsec_flow *flow;
  720. int ret;
  721. flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
  722. if (IS_ERR(flow))
  723. return PTR_ERR(flow);
  724. /* Make sure the flow is disabled before updating it */
  725. vsc8584_macsec_flow_disable(ctx->phydev, flow);
  726. ret = __vsc8584_macsec_add_txsa(ctx, flow, true);
  727. if (ret)
  728. return ret;
  729. vsc8584_macsec_flow_enable(ctx->phydev, flow);
  730. return 0;
  731. }
  732. static int vsc8584_macsec_del_txsa(struct macsec_context *ctx)
  733. {
  734. struct macsec_flow *flow;
  735. flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR);
  736. if (IS_ERR(flow))
  737. return PTR_ERR(flow);
  738. vsc8584_macsec_del_flow(ctx->phydev, flow);
  739. return 0;
  740. }
  741. static const struct macsec_ops vsc8584_macsec_ops = {
  742. .mdo_dev_open = vsc8584_macsec_dev_open,
  743. .mdo_dev_stop = vsc8584_macsec_dev_stop,
  744. .mdo_add_secy = vsc8584_macsec_add_secy,
  745. .mdo_upd_secy = vsc8584_macsec_upd_secy,
  746. .mdo_del_secy = vsc8584_macsec_del_secy,
  747. .mdo_add_rxsc = vsc8584_macsec_add_rxsc,
  748. .mdo_upd_rxsc = vsc8584_macsec_upd_rxsc,
  749. .mdo_del_rxsc = vsc8584_macsec_del_rxsc,
  750. .mdo_add_rxsa = vsc8584_macsec_add_rxsa,
  751. .mdo_upd_rxsa = vsc8584_macsec_upd_rxsa,
  752. .mdo_del_rxsa = vsc8584_macsec_del_rxsa,
  753. .mdo_add_txsa = vsc8584_macsec_add_txsa,
  754. .mdo_upd_txsa = vsc8584_macsec_upd_txsa,
  755. .mdo_del_txsa = vsc8584_macsec_del_txsa,
  756. };
  757. int vsc8584_macsec_init(struct phy_device *phydev)
  758. {
  759. struct vsc8531_private *vsc8531 = phydev->priv;
  760. switch (phydev->phy_id & phydev->drv->phy_id_mask) {
  761. case PHY_ID_VSC856X:
  762. case PHY_ID_VSC8582:
  763. case PHY_ID_VSC8584:
  764. INIT_LIST_HEAD(&vsc8531->macsec_flows);
  765. vsc8531->secy = NULL;
  766. phydev->macsec_ops = &vsc8584_macsec_ops;
  767. return __vsc8584_macsec_init(phydev);
  768. }
  769. return 0;
  770. }
  771. void vsc8584_handle_macsec_interrupt(struct phy_device *phydev)
  772. {
  773. struct vsc8531_private *priv = phydev->priv;
  774. struct macsec_flow *flow, *tmp;
  775. u32 cause, rec;
  776. /* Check MACsec PN rollover */
  777. cause = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
  778. MSCC_MS_INTR_CTRL_STATUS);
  779. cause &= MSCC_MS_INTR_CTRL_STATUS_INTR_CLR_STATUS_M;
  780. if (!(cause & MACSEC_INTR_CTRL_STATUS_ROLLOVER))
  781. return;
  782. rec = 6 + priv->secy->key_len / sizeof(u32);
  783. list_for_each_entry_safe(flow, tmp, &priv->macsec_flows, list) {
  784. u32 val;
  785. if (flow->bank != MACSEC_EGR || !flow->has_transformation)
  786. continue;
  787. val = vsc8584_macsec_phy_read(phydev, MACSEC_EGR,
  788. MSCC_MS_XFORM_REC(flow->index, rec));
  789. if (val == 0xffffffff) {
  790. vsc8584_macsec_flow_disable(phydev, flow);
  791. macsec_pn_wrapped(priv->secy, flow->tx_sa);
  792. return;
  793. }
  794. }
  795. }
  796. void vsc8584_config_macsec_intr(struct phy_device *phydev)
  797. {
  798. phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXTENDED_2);
  799. phy_write(phydev, MSCC_PHY_EXTENDED_INT, MSCC_PHY_EXTENDED_INT_MS_EGR);
  800. phy_write(phydev, MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_STANDARD);
  801. vsc8584_macsec_phy_write(phydev, MACSEC_EGR, MSCC_MS_AIC_CTRL, 0xf);
  802. vsc8584_macsec_phy_write(phydev, MACSEC_EGR, MSCC_MS_INTR_CTRL_STATUS,
  803. MSCC_MS_INTR_CTRL_STATUS_INTR_ENABLE(MACSEC_INTR_CTRL_STATUS_ROLLOVER));
  804. }