dwmac4_descs.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * This contains the functions to handle the descriptors for DesignWare databook
  4. * 4.xx.
  5. *
  6. * Copyright (C) 2015 STMicroelectronics Ltd
  7. *
  8. * Author: Alexandre Torgue <alexandre.torgue@st.com>
  9. */
  10. #include <linux/stmmac.h>
  11. #include "common.h"
  12. #include "dwmac4.h"
  13. #include "dwmac4_descs.h"
  14. static int dwmac4_wrback_get_tx_status(struct stmmac_extra_stats *x,
  15. struct dma_desc *p,
  16. void __iomem *ioaddr)
  17. {
  18. unsigned int tdes3;
  19. int ret = tx_done;
  20. tdes3 = le32_to_cpu(p->des3);
  21. /* Get tx owner first */
  22. if (unlikely(tdes3 & TDES3_OWN))
  23. return tx_dma_own;
  24. /* Verify tx error by looking at the last segment. */
  25. if (likely(!(tdes3 & TDES3_LAST_DESCRIPTOR)))
  26. return tx_not_ls;
  27. if (unlikely(tdes3 & TDES3_ERROR_SUMMARY)) {
  28. ret = tx_err;
  29. if (unlikely(tdes3 & TDES3_JABBER_TIMEOUT))
  30. x->tx_jabber++;
  31. if (unlikely(tdes3 & TDES3_PACKET_FLUSHED))
  32. x->tx_frame_flushed++;
  33. if (unlikely(tdes3 & TDES3_LOSS_CARRIER)) {
  34. x->tx_losscarrier++;
  35. }
  36. if (unlikely(tdes3 & TDES3_NO_CARRIER)) {
  37. x->tx_carrier++;
  38. }
  39. if (unlikely((tdes3 & TDES3_LATE_COLLISION) ||
  40. (tdes3 & TDES3_EXCESSIVE_COLLISION)))
  41. x->tx_collision +=
  42. (tdes3 & TDES3_COLLISION_COUNT_MASK)
  43. >> TDES3_COLLISION_COUNT_SHIFT;
  44. if (unlikely(tdes3 & TDES3_EXCESSIVE_DEFERRAL))
  45. x->tx_deferred++;
  46. if (unlikely(tdes3 & TDES3_UNDERFLOW_ERROR)) {
  47. x->tx_underflow++;
  48. ret |= tx_err_bump_tc;
  49. }
  50. if (unlikely(tdes3 & TDES3_IP_HDR_ERROR))
  51. x->tx_ip_header_error++;
  52. if (unlikely(tdes3 & TDES3_PAYLOAD_ERROR))
  53. x->tx_payload_error++;
  54. }
  55. if (unlikely(tdes3 & TDES3_DEFERRED))
  56. x->tx_deferred++;
  57. return ret;
  58. }
  59. static int dwmac4_wrback_get_rx_status(struct stmmac_extra_stats *x,
  60. struct dma_desc *p)
  61. {
  62. unsigned int rdes1 = le32_to_cpu(p->des1);
  63. unsigned int rdes2 = le32_to_cpu(p->des2);
  64. unsigned int rdes3 = le32_to_cpu(p->des3);
  65. int message_type;
  66. int ret = good_frame;
  67. if (unlikely(rdes3 & RDES3_OWN))
  68. return dma_own;
  69. if (unlikely(rdes3 & RDES3_CONTEXT_DESCRIPTOR))
  70. return discard_frame;
  71. if (likely(!(rdes3 & RDES3_LAST_DESCRIPTOR)))
  72. return rx_not_ls;
  73. if (unlikely(rdes3 & RDES3_ERROR_SUMMARY)) {
  74. if (unlikely(rdes3 & RDES3_GIANT_PACKET))
  75. x->rx_length++;
  76. if (unlikely(rdes3 & RDES3_OVERFLOW_ERROR))
  77. x->rx_gmac_overflow++;
  78. if (unlikely(rdes3 & RDES3_RECEIVE_WATCHDOG))
  79. x->rx_watchdog++;
  80. if (unlikely(rdes3 & RDES3_RECEIVE_ERROR))
  81. x->rx_mii++;
  82. if (unlikely(rdes3 & RDES3_CRC_ERROR))
  83. x->rx_crc_errors++;
  84. if (unlikely(rdes3 & RDES3_DRIBBLE_ERROR))
  85. x->dribbling_bit++;
  86. ret = discard_frame;
  87. }
  88. message_type = (rdes1 & ERDES4_MSG_TYPE_MASK) >> 8;
  89. if (rdes1 & RDES1_IP_HDR_ERROR)
  90. x->ip_hdr_err++;
  91. if (rdes1 & RDES1_IP_CSUM_BYPASSED)
  92. x->ip_csum_bypassed++;
  93. if (rdes1 & RDES1_IPV4_HEADER)
  94. x->ipv4_pkt_rcvd++;
  95. if (rdes1 & RDES1_IPV6_HEADER)
  96. x->ipv6_pkt_rcvd++;
  97. if (message_type == RDES_EXT_NO_PTP)
  98. x->no_ptp_rx_msg_type_ext++;
  99. else if (message_type == RDES_EXT_SYNC)
  100. x->ptp_rx_msg_type_sync++;
  101. else if (message_type == RDES_EXT_FOLLOW_UP)
  102. x->ptp_rx_msg_type_follow_up++;
  103. else if (message_type == RDES_EXT_DELAY_REQ)
  104. x->ptp_rx_msg_type_delay_req++;
  105. else if (message_type == RDES_EXT_DELAY_RESP)
  106. x->ptp_rx_msg_type_delay_resp++;
  107. else if (message_type == RDES_EXT_PDELAY_REQ)
  108. x->ptp_rx_msg_type_pdelay_req++;
  109. else if (message_type == RDES_EXT_PDELAY_RESP)
  110. x->ptp_rx_msg_type_pdelay_resp++;
  111. else if (message_type == RDES_EXT_PDELAY_FOLLOW_UP)
  112. x->ptp_rx_msg_type_pdelay_follow_up++;
  113. else if (message_type == RDES_PTP_ANNOUNCE)
  114. x->ptp_rx_msg_type_announce++;
  115. else if (message_type == RDES_PTP_MANAGEMENT)
  116. x->ptp_rx_msg_type_management++;
  117. else if (message_type == RDES_PTP_PKT_RESERVED_TYPE)
  118. x->ptp_rx_msg_pkt_reserved_type++;
  119. if (rdes1 & RDES1_PTP_PACKET_TYPE)
  120. x->ptp_frame_type++;
  121. if (rdes1 & RDES1_PTP_VER)
  122. x->ptp_ver++;
  123. if (rdes1 & RDES1_TIMESTAMP_DROPPED)
  124. x->timestamp_dropped++;
  125. if (unlikely(rdes2 & RDES2_SA_FILTER_FAIL)) {
  126. x->sa_rx_filter_fail++;
  127. ret = discard_frame;
  128. }
  129. if (unlikely(rdes2 & RDES2_DA_FILTER_FAIL)) {
  130. x->da_rx_filter_fail++;
  131. ret = discard_frame;
  132. }
  133. if (rdes2 & RDES2_L3_FILTER_MATCH)
  134. x->l3_filter_match++;
  135. if (rdes2 & RDES2_L4_FILTER_MATCH)
  136. x->l4_filter_match++;
  137. if ((rdes2 & RDES2_L3_L4_FILT_NB_MATCH_MASK)
  138. >> RDES2_L3_L4_FILT_NB_MATCH_SHIFT)
  139. x->l3_l4_filter_no_match++;
  140. return ret;
  141. }
  142. static int dwmac4_rd_get_tx_len(struct dma_desc *p)
  143. {
  144. return (le32_to_cpu(p->des2) & TDES2_BUFFER1_SIZE_MASK);
  145. }
  146. static int dwmac4_get_tx_owner(struct dma_desc *p)
  147. {
  148. return (le32_to_cpu(p->des3) & TDES3_OWN) >> TDES3_OWN_SHIFT;
  149. }
  150. static void dwmac4_set_tx_owner(struct dma_desc *p)
  151. {
  152. p->des3 |= cpu_to_le32(TDES3_OWN);
  153. }
  154. static void dwmac4_set_rx_owner(struct dma_desc *p, int disable_rx_ic)
  155. {
  156. u32 flags = (RDES3_OWN | RDES3_BUFFER1_VALID_ADDR);
  157. if (!disable_rx_ic)
  158. flags |= RDES3_INT_ON_COMPLETION_EN;
  159. p->des3 |= cpu_to_le32(flags);
  160. }
  161. static int dwmac4_get_tx_ls(struct dma_desc *p)
  162. {
  163. return (le32_to_cpu(p->des3) & TDES3_LAST_DESCRIPTOR)
  164. >> TDES3_LAST_DESCRIPTOR_SHIFT;
  165. }
  166. static u16 dwmac4_wrback_get_rx_vlan_tci(struct dma_desc *p)
  167. {
  168. return (le32_to_cpu(p->des0) & RDES0_VLAN_TAG_MASK);
  169. }
  170. static bool dwmac4_wrback_get_rx_vlan_valid(struct dma_desc *p)
  171. {
  172. return ((le32_to_cpu(p->des3) & RDES3_LAST_DESCRIPTOR) &&
  173. (le32_to_cpu(p->des3) & RDES3_RDES0_VALID));
  174. }
  175. static int dwmac4_wrback_get_rx_frame_len(struct dma_desc *p, int rx_coe)
  176. {
  177. return (le32_to_cpu(p->des3) & RDES3_PACKET_SIZE_MASK);
  178. }
  179. static void dwmac4_rd_enable_tx_timestamp(struct dma_desc *p)
  180. {
  181. p->des2 |= cpu_to_le32(TDES2_TIMESTAMP_ENABLE);
  182. }
  183. static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p)
  184. {
  185. /* Context type from W/B descriptor must be zero */
  186. if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE)
  187. return 0;
  188. /* Tx Timestamp Status is 1 so des0 and des1'll have valid values */
  189. if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS)
  190. return 1;
  191. return 0;
  192. }
  193. static inline void dwmac4_get_timestamp(void *desc, u32 ats, u64 *ts)
  194. {
  195. struct dma_desc *p = (struct dma_desc *)desc;
  196. u64 ns;
  197. ns = le32_to_cpu(p->des0);
  198. /* convert high/sec time stamp value to nanosecond */
  199. ns += le32_to_cpu(p->des1) * 1000000000ULL;
  200. *ts = ns;
  201. }
  202. static int dwmac4_rx_check_timestamp(void *desc)
  203. {
  204. struct dma_desc *p = (struct dma_desc *)desc;
  205. unsigned int rdes0 = le32_to_cpu(p->des0);
  206. unsigned int rdes1 = le32_to_cpu(p->des1);
  207. unsigned int rdes3 = le32_to_cpu(p->des3);
  208. u32 own, ctxt;
  209. int ret = 1;
  210. own = rdes3 & RDES3_OWN;
  211. ctxt = ((rdes3 & RDES3_CONTEXT_DESCRIPTOR)
  212. >> RDES3_CONTEXT_DESCRIPTOR_SHIFT);
  213. if (likely(!own && ctxt)) {
  214. if ((rdes0 == 0xffffffff) && (rdes1 == 0xffffffff))
  215. /* Corrupted value */
  216. ret = -EINVAL;
  217. else
  218. /* A valid Timestamp is ready to be read */
  219. ret = 0;
  220. }
  221. /* Timestamp not ready */
  222. return ret;
  223. }
  224. static int dwmac4_wrback_get_rx_timestamp_status(void *desc, void *next_desc,
  225. u32 ats)
  226. {
  227. struct dma_desc *p = (struct dma_desc *)desc;
  228. int ret = -EINVAL;
  229. /* Get the status from normal w/b descriptor */
  230. if (likely(le32_to_cpu(p->des3) & RDES3_RDES1_VALID)) {
  231. if (likely(le32_to_cpu(p->des1) & RDES1_TIMESTAMP_AVAILABLE)) {
  232. int i = 0;
  233. /* Check if timestamp is OK from context descriptor */
  234. do {
  235. ret = dwmac4_rx_check_timestamp(next_desc);
  236. if (ret < 0)
  237. goto exit;
  238. i++;
  239. } while ((ret == 1) && (i < 10));
  240. if (i == 10)
  241. ret = -EBUSY;
  242. }
  243. }
  244. exit:
  245. if (likely(ret == 0))
  246. return 1;
  247. return 0;
  248. }
  249. static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
  250. int mode, int end, int bfsize)
  251. {
  252. dwmac4_set_rx_owner(p, disable_rx_ic);
  253. }
  254. static void dwmac4_rd_init_tx_desc(struct dma_desc *p, int mode, int end)
  255. {
  256. p->des0 = 0;
  257. p->des1 = 0;
  258. p->des2 = 0;
  259. p->des3 = 0;
  260. }
  261. static void dwmac4_rd_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
  262. bool csum_flag, int mode, bool tx_own,
  263. bool ls, unsigned int tot_pkt_len)
  264. {
  265. unsigned int tdes3 = le32_to_cpu(p->des3);
  266. p->des2 |= cpu_to_le32(len & TDES2_BUFFER1_SIZE_MASK);
  267. tdes3 |= tot_pkt_len & TDES3_PACKET_SIZE_MASK;
  268. if (is_fs)
  269. tdes3 |= TDES3_FIRST_DESCRIPTOR;
  270. else
  271. tdes3 &= ~TDES3_FIRST_DESCRIPTOR;
  272. if (likely(csum_flag))
  273. tdes3 |= (TX_CIC_FULL << TDES3_CHECKSUM_INSERTION_SHIFT);
  274. else
  275. tdes3 &= ~(TX_CIC_FULL << TDES3_CHECKSUM_INSERTION_SHIFT);
  276. if (ls)
  277. tdes3 |= TDES3_LAST_DESCRIPTOR;
  278. else
  279. tdes3 &= ~TDES3_LAST_DESCRIPTOR;
  280. /* Finally set the OWN bit. Later the DMA will start! */
  281. if (tx_own)
  282. tdes3 |= TDES3_OWN;
  283. if (is_fs && tx_own)
  284. /* When the own bit, for the first frame, has to be set, all
  285. * descriptors for the same frame has to be set before, to
  286. * avoid race condition.
  287. */
  288. dma_wmb();
  289. p->des3 = cpu_to_le32(tdes3);
  290. }
  291. static void dwmac4_rd_prepare_tso_tx_desc(struct dma_desc *p, int is_fs,
  292. int len1, int len2, bool tx_own,
  293. bool ls, unsigned int tcphdrlen,
  294. unsigned int tcppayloadlen)
  295. {
  296. unsigned int tdes3 = le32_to_cpu(p->des3);
  297. if (len1)
  298. p->des2 |= cpu_to_le32((len1 & TDES2_BUFFER1_SIZE_MASK));
  299. if (len2)
  300. p->des2 |= cpu_to_le32((len2 << TDES2_BUFFER2_SIZE_MASK_SHIFT)
  301. & TDES2_BUFFER2_SIZE_MASK);
  302. if (is_fs) {
  303. tdes3 |= TDES3_FIRST_DESCRIPTOR |
  304. TDES3_TCP_SEGMENTATION_ENABLE |
  305. ((tcphdrlen << TDES3_HDR_LEN_SHIFT) &
  306. TDES3_SLOT_NUMBER_MASK) |
  307. ((tcppayloadlen & TDES3_TCP_PKT_PAYLOAD_MASK));
  308. } else {
  309. tdes3 &= ~TDES3_FIRST_DESCRIPTOR;
  310. }
  311. if (ls)
  312. tdes3 |= TDES3_LAST_DESCRIPTOR;
  313. else
  314. tdes3 &= ~TDES3_LAST_DESCRIPTOR;
  315. /* Finally set the OWN bit. Later the DMA will start! */
  316. if (tx_own)
  317. tdes3 |= TDES3_OWN;
  318. if (is_fs && tx_own)
  319. /* When the own bit, for the first frame, has to be set, all
  320. * descriptors for the same frame has to be set before, to
  321. * avoid race condition.
  322. */
  323. dma_wmb();
  324. p->des3 = cpu_to_le32(tdes3);
  325. }
  326. static void dwmac4_release_tx_desc(struct dma_desc *p, int mode)
  327. {
  328. p->des0 = 0;
  329. p->des1 = 0;
  330. p->des2 = 0;
  331. p->des3 = 0;
  332. }
  333. static void dwmac4_rd_set_tx_ic(struct dma_desc *p)
  334. {
  335. p->des2 |= cpu_to_le32(TDES2_INTERRUPT_ON_COMPLETION);
  336. }
  337. static void dwmac4_display_ring(void *head, unsigned int size, bool rx,
  338. dma_addr_t dma_rx_phy, unsigned int desc_size)
  339. {
  340. dma_addr_t dma_addr;
  341. int i;
  342. pr_info("%s descriptor ring:\n", rx ? "RX" : "TX");
  343. if (desc_size == sizeof(struct dma_desc)) {
  344. struct dma_desc *p = (struct dma_desc *)head;
  345. for (i = 0; i < size; i++) {
  346. dma_addr = dma_rx_phy + i * sizeof(*p);
  347. pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x\n",
  348. i, &dma_addr,
  349. le32_to_cpu(p->des0), le32_to_cpu(p->des1),
  350. le32_to_cpu(p->des2), le32_to_cpu(p->des3));
  351. p++;
  352. }
  353. } else if (desc_size == sizeof(struct dma_extended_desc)) {
  354. struct dma_extended_desc *extp = (struct dma_extended_desc *)head;
  355. for (i = 0; i < size; i++) {
  356. dma_addr = dma_rx_phy + i * sizeof(*extp);
  357. pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
  358. i, &dma_addr,
  359. le32_to_cpu(extp->basic.des0), le32_to_cpu(extp->basic.des1),
  360. le32_to_cpu(extp->basic.des2), le32_to_cpu(extp->basic.des3),
  361. le32_to_cpu(extp->des4), le32_to_cpu(extp->des5),
  362. le32_to_cpu(extp->des6), le32_to_cpu(extp->des7));
  363. extp++;
  364. }
  365. } else if (desc_size == sizeof(struct dma_edesc)) {
  366. struct dma_edesc *ep = (struct dma_edesc *)head;
  367. for (i = 0; i < size; i++) {
  368. dma_addr = dma_rx_phy + i * sizeof(*ep);
  369. pr_info("%03d [%pad]: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
  370. i, &dma_addr,
  371. le32_to_cpu(ep->des4), le32_to_cpu(ep->des5),
  372. le32_to_cpu(ep->des6), le32_to_cpu(ep->des7),
  373. le32_to_cpu(ep->basic.des0), le32_to_cpu(ep->basic.des1),
  374. le32_to_cpu(ep->basic.des2), le32_to_cpu(ep->basic.des3));
  375. ep++;
  376. }
  377. } else {
  378. pr_err("unsupported descriptor!");
  379. }
  380. }
  381. static void dwmac4_set_mss_ctxt(struct dma_desc *p, unsigned int mss)
  382. {
  383. p->des0 = 0;
  384. p->des1 = 0;
  385. p->des2 = cpu_to_le32(mss);
  386. p->des3 = cpu_to_le32(TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV);
  387. }
  388. static void dwmac4_set_addr(struct dma_desc *p, dma_addr_t addr)
  389. {
  390. p->des0 = cpu_to_le32(lower_32_bits(addr));
  391. p->des1 = cpu_to_le32(upper_32_bits(addr));
  392. }
  393. static void dwmac4_clear(struct dma_desc *p)
  394. {
  395. p->des0 = 0;
  396. p->des1 = 0;
  397. p->des2 = 0;
  398. p->des3 = 0;
  399. }
  400. static void dwmac4_set_sarc(struct dma_desc *p, u32 sarc_type)
  401. {
  402. sarc_type <<= TDES3_SA_INSERT_CTRL_SHIFT;
  403. p->des3 |= cpu_to_le32(sarc_type & TDES3_SA_INSERT_CTRL_MASK);
  404. }
  405. static int set_16kib_bfsize(int mtu)
  406. {
  407. int ret = 0;
  408. if (unlikely(mtu >= BUF_SIZE_8KiB))
  409. ret = BUF_SIZE_16KiB;
  410. return ret;
  411. }
  412. static void dwmac4_set_vlan_tag(struct dma_desc *p, u16 tag, u16 inner_tag,
  413. u32 inner_type)
  414. {
  415. p->des0 = 0;
  416. p->des1 = 0;
  417. p->des2 = 0;
  418. p->des3 = 0;
  419. /* Inner VLAN */
  420. if (inner_type) {
  421. u32 des = inner_tag << TDES2_IVT_SHIFT;
  422. des &= TDES2_IVT_MASK;
  423. p->des2 = cpu_to_le32(des);
  424. des = inner_type << TDES3_IVTIR_SHIFT;
  425. des &= TDES3_IVTIR_MASK;
  426. p->des3 = cpu_to_le32(des | TDES3_IVLTV);
  427. }
  428. /* Outer VLAN */
  429. p->des3 |= cpu_to_le32(tag & TDES3_VLAN_TAG);
  430. p->des3 |= cpu_to_le32(TDES3_VLTV);
  431. p->des3 |= cpu_to_le32(TDES3_CONTEXT_TYPE);
  432. }
  433. static void dwmac4_set_vlan(struct dma_desc *p, u32 type)
  434. {
  435. type <<= TDES2_VLAN_TAG_SHIFT;
  436. p->des2 |= cpu_to_le32(type & TDES2_VLAN_TAG_MASK);
  437. }
  438. static void dwmac4_get_rx_header_len(struct dma_desc *p, unsigned int *len)
  439. {
  440. *len = le32_to_cpu(p->des2) & RDES2_HL;
  441. }
  442. static void dwmac4_set_sec_addr(struct dma_desc *p, dma_addr_t addr, bool buf2_valid)
  443. {
  444. p->des2 = cpu_to_le32(lower_32_bits(addr));
  445. p->des3 = cpu_to_le32(upper_32_bits(addr));
  446. if (buf2_valid)
  447. p->des3 |= cpu_to_le32(RDES3_BUFFER2_VALID_ADDR);
  448. else
  449. p->des3 &= cpu_to_le32(~RDES3_BUFFER2_VALID_ADDR);
  450. }
  451. static void dwmac4_set_tbs(struct dma_edesc *p, u32 sec, u32 nsec)
  452. {
  453. p->des4 = cpu_to_le32((sec & TDES4_LT) | TDES4_LTV);
  454. p->des5 = cpu_to_le32(nsec & TDES5_LT);
  455. p->des6 = 0;
  456. p->des7 = 0;
  457. }
  458. const struct stmmac_desc_ops dwmac4_desc_ops = {
  459. .tx_status = dwmac4_wrback_get_tx_status,
  460. .rx_status = dwmac4_wrback_get_rx_status,
  461. .get_tx_len = dwmac4_rd_get_tx_len,
  462. .get_tx_owner = dwmac4_get_tx_owner,
  463. .set_tx_owner = dwmac4_set_tx_owner,
  464. .set_rx_owner = dwmac4_set_rx_owner,
  465. .get_tx_ls = dwmac4_get_tx_ls,
  466. .get_rx_vlan_tci = dwmac4_wrback_get_rx_vlan_tci,
  467. .get_rx_vlan_valid = dwmac4_wrback_get_rx_vlan_valid,
  468. .get_rx_frame_len = dwmac4_wrback_get_rx_frame_len,
  469. .enable_tx_timestamp = dwmac4_rd_enable_tx_timestamp,
  470. .get_tx_timestamp_status = dwmac4_wrback_get_tx_timestamp_status,
  471. .get_rx_timestamp_status = dwmac4_wrback_get_rx_timestamp_status,
  472. .get_timestamp = dwmac4_get_timestamp,
  473. .set_tx_ic = dwmac4_rd_set_tx_ic,
  474. .prepare_tx_desc = dwmac4_rd_prepare_tx_desc,
  475. .prepare_tso_tx_desc = dwmac4_rd_prepare_tso_tx_desc,
  476. .release_tx_desc = dwmac4_release_tx_desc,
  477. .init_rx_desc = dwmac4_rd_init_rx_desc,
  478. .init_tx_desc = dwmac4_rd_init_tx_desc,
  479. .display_ring = dwmac4_display_ring,
  480. .set_mss = dwmac4_set_mss_ctxt,
  481. .set_addr = dwmac4_set_addr,
  482. .clear = dwmac4_clear,
  483. .set_sarc = dwmac4_set_sarc,
  484. .set_vlan_tag = dwmac4_set_vlan_tag,
  485. .set_vlan = dwmac4_set_vlan,
  486. .get_rx_header_len = dwmac4_get_rx_header_len,
  487. .set_sec_addr = dwmac4_set_sec_addr,
  488. .set_tbs = dwmac4_set_tbs,
  489. };
  490. const struct stmmac_mode_ops dwmac4_ring_mode_ops = {
  491. .set_16kib_bfsize = set_16kib_bfsize,
  492. };