mvpp2_cls.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * RSS and Classifier helpers for Marvell PPv2 Network Controller
  3. *
  4. * Copyright (C) 2014 Marvell
  5. *
  6. * Marcin Wojtas <mw@semihalf.com>
  7. *
  8. * This file is licensed under the terms of the GNU General Public
  9. * License version 2. This program is licensed "as is" without any
  10. * warranty of any kind, whether express or implied.
  11. */
  12. #include "mvpp2.h"
  13. #include "mvpp2_cls.h"
  14. /* Update classification flow table registers */
  15. static void mvpp2_cls_flow_write(struct mvpp2 *priv,
  16. struct mvpp2_cls_flow_entry *fe)
  17. {
  18. mvpp2_write(priv, MVPP2_CLS_FLOW_INDEX_REG, fe->index);
  19. mvpp2_write(priv, MVPP2_CLS_FLOW_TBL0_REG, fe->data[0]);
  20. mvpp2_write(priv, MVPP2_CLS_FLOW_TBL1_REG, fe->data[1]);
  21. mvpp2_write(priv, MVPP2_CLS_FLOW_TBL2_REG, fe->data[2]);
  22. }
  23. /* Update classification lookup table register */
  24. static void mvpp2_cls_lookup_write(struct mvpp2 *priv,
  25. struct mvpp2_cls_lookup_entry *le)
  26. {
  27. u32 val;
  28. val = (le->way << MVPP2_CLS_LKP_INDEX_WAY_OFFS) | le->lkpid;
  29. mvpp2_write(priv, MVPP2_CLS_LKP_INDEX_REG, val);
  30. mvpp2_write(priv, MVPP2_CLS_LKP_TBL_REG, le->data);
  31. }
  32. /* Classifier default initialization */
  33. void mvpp2_cls_init(struct mvpp2 *priv)
  34. {
  35. struct mvpp2_cls_lookup_entry le;
  36. struct mvpp2_cls_flow_entry fe;
  37. int index;
  38. /* Enable classifier */
  39. mvpp2_write(priv, MVPP2_CLS_MODE_REG, MVPP2_CLS_MODE_ACTIVE_MASK);
  40. /* Clear classifier flow table */
  41. memset(&fe.data, 0, sizeof(fe.data));
  42. for (index = 0; index < MVPP2_CLS_FLOWS_TBL_SIZE; index++) {
  43. fe.index = index;
  44. mvpp2_cls_flow_write(priv, &fe);
  45. }
  46. /* Clear classifier lookup table */
  47. le.data = 0;
  48. for (index = 0; index < MVPP2_CLS_LKP_TBL_SIZE; index++) {
  49. le.lkpid = index;
  50. le.way = 0;
  51. mvpp2_cls_lookup_write(priv, &le);
  52. le.way = 1;
  53. mvpp2_cls_lookup_write(priv, &le);
  54. }
  55. }
  56. void mvpp2_cls_port_config(struct mvpp2_port *port)
  57. {
  58. struct mvpp2_cls_lookup_entry le;
  59. u32 val;
  60. /* Set way for the port */
  61. val = mvpp2_read(port->priv, MVPP2_CLS_PORT_WAY_REG);
  62. val &= ~MVPP2_CLS_PORT_WAY_MASK(port->id);
  63. mvpp2_write(port->priv, MVPP2_CLS_PORT_WAY_REG, val);
  64. /* Pick the entry to be accessed in lookup ID decoding table
  65. * according to the way and lkpid.
  66. */
  67. le.lkpid = port->id;
  68. le.way = 0;
  69. le.data = 0;
  70. /* Set initial CPU queue for receiving packets */
  71. le.data &= ~MVPP2_CLS_LKP_TBL_RXQ_MASK;
  72. le.data |= port->first_rxq;
  73. /* Disable classification engines */
  74. le.data &= ~MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK;
  75. /* Update lookup ID table entry */
  76. mvpp2_cls_lookup_write(port->priv, &le);
  77. }
  78. /* Set CPU queue number for oversize packets */
  79. void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
  80. {
  81. u32 val;
  82. mvpp2_write(port->priv, MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port->id),
  83. port->first_rxq & MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK);
  84. mvpp2_write(port->priv, MVPP2_CLS_SWFWD_P2HQ_REG(port->id),
  85. (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS));
  86. val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG);
  87. val |= MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
  88. mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
  89. }
  90. void mvpp22_init_rss(struct mvpp2_port *port)
  91. {
  92. struct mvpp2 *priv = port->priv;
  93. int i;
  94. /* Set the table width: replace the whole classifier Rx queue number
  95. * with the ones configured in RSS table entries.
  96. */
  97. mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_TABLE(0));
  98. mvpp2_write(priv, MVPP22_RSS_WIDTH, 8);
  99. /* Loop through the classifier Rx Queues and map them to a RSS table.
  100. * Map them all to the first table (0) by default.
  101. */
  102. for (i = 0; i < MVPP2_CLS_RX_QUEUES; i++) {
  103. mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_QUEUE(i));
  104. mvpp2_write(priv, MVPP22_RSS_TABLE,
  105. MVPP22_RSS_TABLE_POINTER(0));
  106. }
  107. /* Configure the first table to evenly distribute the packets across
  108. * real Rx Queues. The table entries map a hash to an port Rx Queue.
  109. */
  110. for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) {
  111. u32 sel = MVPP22_RSS_INDEX_TABLE(0) |
  112. MVPP22_RSS_INDEX_TABLE_ENTRY(i);
  113. mvpp2_write(priv, MVPP22_RSS_INDEX, sel);
  114. mvpp2_write(priv, MVPP22_RSS_TABLE_ENTRY, i % port->nrxqs);
  115. }
  116. }