txgbe_fdir.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */
  3. #include <linux/string.h>
  4. #include <linux/types.h>
  5. #include <linux/pci.h>
  6. #include "../libwx/wx_type.h"
  7. #include "../libwx/wx_lib.h"
  8. #include "../libwx/wx_hw.h"
  9. #include "txgbe_type.h"
  10. #include "txgbe_fdir.h"
  11. /* These defines allow us to quickly generate all of the necessary instructions
  12. * in the function below by simply calling out TXGBE_COMPUTE_SIG_HASH_ITERATION
  13. * for values 0 through 15
  14. */
  15. #define TXGBE_ATR_COMMON_HASH_KEY \
  16. (TXGBE_ATR_BUCKET_HASH_KEY & TXGBE_ATR_SIGNATURE_HASH_KEY)
  17. #define TXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \
  18. do { \
  19. u32 n = (_n); \
  20. if (TXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \
  21. common_hash ^= lo_hash_dword >> n; \
  22. else if (TXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
  23. bucket_hash ^= lo_hash_dword >> n; \
  24. else if (TXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \
  25. sig_hash ^= lo_hash_dword << (16 - n); \
  26. if (TXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \
  27. common_hash ^= hi_hash_dword >> n; \
  28. else if (TXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
  29. bucket_hash ^= hi_hash_dword >> n; \
  30. else if (TXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \
  31. sig_hash ^= hi_hash_dword << (16 - n); \
  32. } while (0)
  33. /**
  34. * txgbe_atr_compute_sig_hash - Compute the signature hash
  35. * @input: input bitstream to compute the hash on
  36. * @common: compressed common input dword
  37. * @hash: pointer to the computed hash
  38. *
  39. * This function is almost identical to the function above but contains
  40. * several optimizations such as unwinding all of the loops, letting the
  41. * compiler work out all of the conditional ifs since the keys are static
  42. * defines, and computing two keys at once since the hashed dword stream
  43. * will be the same for both keys.
  44. **/
  45. static void txgbe_atr_compute_sig_hash(union txgbe_atr_hash_dword input,
  46. union txgbe_atr_hash_dword common,
  47. u32 *hash)
  48. {
  49. u32 sig_hash = 0, bucket_hash = 0, common_hash = 0;
  50. u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
  51. u32 i;
  52. /* record the flow_vm_vlan bits as they are a key part to the hash */
  53. flow_vm_vlan = ntohl(input.dword);
  54. /* generate common hash dword */
  55. hi_hash_dword = ntohl(common.dword);
  56. /* low dword is word swapped version of common */
  57. lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
  58. /* apply flow ID/VM pool/VLAN ID bits to hash words */
  59. hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
  60. /* Process bits 0 and 16 */
  61. TXGBE_COMPUTE_SIG_HASH_ITERATION(0);
  62. /* apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
  63. * delay this because bit 0 of the stream should not be processed
  64. * so we do not add the VLAN until after bit 0 was processed
  65. */
  66. lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
  67. /* Process remaining 30 bit of the key */
  68. for (i = 1; i <= 15; i++)
  69. TXGBE_COMPUTE_SIG_HASH_ITERATION(i);
  70. /* combine common_hash result with signature and bucket hashes */
  71. bucket_hash ^= common_hash;
  72. bucket_hash &= TXGBE_ATR_HASH_MASK;
  73. sig_hash ^= common_hash << 16;
  74. sig_hash &= TXGBE_ATR_HASH_MASK << 16;
  75. /* return completed signature hash */
  76. *hash = sig_hash ^ bucket_hash;
  77. }
  78. #define TXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
  79. do { \
  80. u32 n = (_n); \
  81. if (TXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \
  82. bucket_hash ^= lo_hash_dword >> n; \
  83. if (TXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \
  84. bucket_hash ^= hi_hash_dword >> n; \
  85. } while (0)
  86. /**
  87. * txgbe_atr_compute_perfect_hash - Compute the perfect filter hash
  88. * @input: input bitstream to compute the hash on
  89. * @input_mask: mask for the input bitstream
  90. *
  91. * This function serves two main purposes. First it applies the input_mask
  92. * to the atr_input resulting in a cleaned up atr_input data stream.
  93. * Secondly it computes the hash and stores it in the bkt_hash field at
  94. * the end of the input byte stream. This way it will be available for
  95. * future use without needing to recompute the hash.
  96. **/
  97. void txgbe_atr_compute_perfect_hash(union txgbe_atr_input *input,
  98. union txgbe_atr_input *input_mask)
  99. {
  100. u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
  101. u32 bucket_hash = 0;
  102. __be32 hi_dword = 0;
  103. u32 i = 0;
  104. /* Apply masks to input data */
  105. for (i = 0; i < 11; i++)
  106. input->dword_stream[i] &= input_mask->dword_stream[i];
  107. /* record the flow_vm_vlan bits as they are a key part to the hash */
  108. flow_vm_vlan = ntohl(input->dword_stream[0]);
  109. /* generate common hash dword */
  110. for (i = 1; i <= 10; i++)
  111. hi_dword ^= input->dword_stream[i];
  112. hi_hash_dword = ntohl(hi_dword);
  113. /* low dword is word swapped version of common */
  114. lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
  115. /* apply flow ID/VM pool/VLAN ID bits to hash words */
  116. hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
  117. /* Process bits 0 and 16 */
  118. TXGBE_COMPUTE_BKT_HASH_ITERATION(0);
  119. /* apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
  120. * delay this because bit 0 of the stream should not be processed
  121. * so we do not add the VLAN until after bit 0 was processed
  122. */
  123. lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
  124. /* Process remaining 30 bit of the key */
  125. for (i = 1; i <= 15; i++)
  126. TXGBE_COMPUTE_BKT_HASH_ITERATION(i);
  127. /* Limit hash to 13 bits since max bucket count is 8K.
  128. * Store result at the end of the input stream.
  129. */
  130. input->formatted.bkt_hash = (__force __be16)(bucket_hash & 0x1FFF);
  131. }
  132. static int txgbe_fdir_check_cmd_complete(struct wx *wx)
  133. {
  134. u32 val;
  135. return read_poll_timeout_atomic(rd32, val,
  136. !(val & TXGBE_RDB_FDIR_CMD_CMD_MASK),
  137. 10, 100, false,
  138. wx, TXGBE_RDB_FDIR_CMD);
  139. }
  140. /**
  141. * txgbe_fdir_add_signature_filter - Adds a signature hash filter
  142. * @wx: pointer to hardware structure
  143. * @input: unique input dword
  144. * @common: compressed common input dword
  145. * @queue: queue index to direct traffic to
  146. *
  147. * @return: 0 on success and negative on failure
  148. **/
  149. static int txgbe_fdir_add_signature_filter(struct wx *wx,
  150. union txgbe_atr_hash_dword input,
  151. union txgbe_atr_hash_dword common,
  152. u8 queue)
  153. {
  154. u32 fdirhashcmd, fdircmd;
  155. u8 flow_type;
  156. int err;
  157. /* Get the flow_type in order to program FDIRCMD properly
  158. * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
  159. * fifth is FDIRCMD.TUNNEL_FILTER
  160. */
  161. flow_type = input.formatted.flow_type;
  162. switch (flow_type) {
  163. case TXGBE_ATR_FLOW_TYPE_TCPV4:
  164. case TXGBE_ATR_FLOW_TYPE_UDPV4:
  165. case TXGBE_ATR_FLOW_TYPE_SCTPV4:
  166. case TXGBE_ATR_FLOW_TYPE_TCPV6:
  167. case TXGBE_ATR_FLOW_TYPE_UDPV6:
  168. case TXGBE_ATR_FLOW_TYPE_SCTPV6:
  169. break;
  170. default:
  171. wx_err(wx, "Error on flow type input\n");
  172. return -EINVAL;
  173. }
  174. /* configure FDIRCMD register */
  175. fdircmd = TXGBE_RDB_FDIR_CMD_CMD_ADD_FLOW |
  176. TXGBE_RDB_FDIR_CMD_FILTER_UPDATE |
  177. TXGBE_RDB_FDIR_CMD_LAST | TXGBE_RDB_FDIR_CMD_QUEUE_EN;
  178. fdircmd |= TXGBE_RDB_FDIR_CMD_FLOW_TYPE(flow_type);
  179. fdircmd |= TXGBE_RDB_FDIR_CMD_RX_QUEUE(queue);
  180. txgbe_atr_compute_sig_hash(input, common, &fdirhashcmd);
  181. fdirhashcmd |= TXGBE_RDB_FDIR_HASH_BUCKET_VALID;
  182. wr32(wx, TXGBE_RDB_FDIR_HASH, fdirhashcmd);
  183. wr32(wx, TXGBE_RDB_FDIR_CMD, fdircmd);
  184. wx_dbg(wx, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
  185. err = txgbe_fdir_check_cmd_complete(wx);
  186. if (err)
  187. wx_err(wx, "Flow Director command did not complete!\n");
  188. return err;
  189. }
  190. void txgbe_atr(struct wx_ring *ring, struct wx_tx_buffer *first, u8 ptype)
  191. {
  192. union txgbe_atr_hash_dword common = { .dword = 0 };
  193. union txgbe_atr_hash_dword input = { .dword = 0 };
  194. struct wx_q_vector *q_vector = ring->q_vector;
  195. struct wx_dec_ptype dptype;
  196. union network_header {
  197. struct ipv6hdr *ipv6;
  198. struct iphdr *ipv4;
  199. void *raw;
  200. } hdr;
  201. struct tcphdr *th;
  202. /* if ring doesn't have a interrupt vector, cannot perform ATR */
  203. if (!q_vector)
  204. return;
  205. ring->atr_count++;
  206. dptype = wx_decode_ptype(ptype);
  207. if (dptype.etype) {
  208. if (WX_PTYPE_TYPL4(ptype) != WX_PTYPE_TYP_TCP)
  209. return;
  210. hdr.raw = (void *)skb_inner_network_header(first->skb);
  211. th = inner_tcp_hdr(first->skb);
  212. } else {
  213. if (WX_PTYPE_PKT(ptype) != WX_PTYPE_PKT_IP ||
  214. WX_PTYPE_TYPL4(ptype) != WX_PTYPE_TYP_TCP)
  215. return;
  216. hdr.raw = (void *)skb_network_header(first->skb);
  217. th = tcp_hdr(first->skb);
  218. }
  219. /* skip this packet since it is invalid or the socket is closing */
  220. if (!th || th->fin)
  221. return;
  222. /* sample on all syn packets or once every atr sample count */
  223. if (!th->syn && ring->atr_count < ring->atr_sample_rate)
  224. return;
  225. /* reset sample count */
  226. ring->atr_count = 0;
  227. /* src and dst are inverted, think how the receiver sees them
  228. *
  229. * The input is broken into two sections, a non-compressed section
  230. * containing vm_pool, vlan_id, and flow_type. The rest of the data
  231. * is XORed together and stored in the compressed dword.
  232. */
  233. input.formatted.vlan_id = htons((u16)ptype);
  234. /* since src port and flex bytes occupy the same word XOR them together
  235. * and write the value to source port portion of compressed dword
  236. */
  237. if (first->tx_flags & WX_TX_FLAGS_SW_VLAN)
  238. common.port.src ^= th->dest ^ first->skb->protocol;
  239. else if (first->tx_flags & WX_TX_FLAGS_HW_VLAN)
  240. common.port.src ^= th->dest ^ first->skb->vlan_proto;
  241. else
  242. common.port.src ^= th->dest ^ first->protocol;
  243. common.port.dst ^= th->source;
  244. if (WX_PTYPE_PKT_IPV6 & WX_PTYPE_PKT(ptype)) {
  245. input.formatted.flow_type = TXGBE_ATR_FLOW_TYPE_TCPV6;
  246. common.ip ^= hdr.ipv6->saddr.s6_addr32[0] ^
  247. hdr.ipv6->saddr.s6_addr32[1] ^
  248. hdr.ipv6->saddr.s6_addr32[2] ^
  249. hdr.ipv6->saddr.s6_addr32[3] ^
  250. hdr.ipv6->daddr.s6_addr32[0] ^
  251. hdr.ipv6->daddr.s6_addr32[1] ^
  252. hdr.ipv6->daddr.s6_addr32[2] ^
  253. hdr.ipv6->daddr.s6_addr32[3];
  254. } else {
  255. input.formatted.flow_type = TXGBE_ATR_FLOW_TYPE_TCPV4;
  256. common.ip ^= hdr.ipv4->saddr ^ hdr.ipv4->daddr;
  257. }
  258. /* This assumes the Rx queue and Tx queue are bound to the same CPU */
  259. txgbe_fdir_add_signature_filter(q_vector->wx, input, common,
  260. ring->queue_index);
  261. }
  262. int txgbe_fdir_set_input_mask(struct wx *wx, union txgbe_atr_input *input_mask)
  263. {
  264. u32 fdirm = 0, fdirtcpm = 0, flex = 0;
  265. /* Program the relevant mask registers. If src/dst_port or src/dst_addr
  266. * are zero, then assume a full mask for that field. Also assume that
  267. * a VLAN of 0 is unspecified, so mask that out as well. L4type
  268. * cannot be masked out in this implementation.
  269. *
  270. * This also assumes IPv4 only. IPv6 masking isn't supported at this
  271. * point in time.
  272. */
  273. /* verify bucket hash is cleared on hash generation */
  274. if (input_mask->formatted.bkt_hash)
  275. wx_dbg(wx, "bucket hash should always be 0 in mask\n");
  276. /* Program FDIRM and verify partial masks */
  277. switch (input_mask->formatted.vm_pool & 0x7F) {
  278. case 0x0:
  279. fdirm |= TXGBE_RDB_FDIR_OTHER_MSK_POOL;
  280. break;
  281. case 0x7F:
  282. break;
  283. default:
  284. wx_err(wx, "Error on vm pool mask\n");
  285. return -EINVAL;
  286. }
  287. switch (input_mask->formatted.flow_type & TXGBE_ATR_L4TYPE_MASK) {
  288. case 0x0:
  289. fdirm |= TXGBE_RDB_FDIR_OTHER_MSK_L4P;
  290. if (input_mask->formatted.dst_port ||
  291. input_mask->formatted.src_port) {
  292. wx_err(wx, "Error on src/dst port mask\n");
  293. return -EINVAL;
  294. }
  295. break;
  296. case TXGBE_ATR_L4TYPE_MASK:
  297. break;
  298. default:
  299. wx_err(wx, "Error on flow type mask\n");
  300. return -EINVAL;
  301. }
  302. /* Now mask VM pool and destination IPv6 - bits 5 and 2 */
  303. wr32(wx, TXGBE_RDB_FDIR_OTHER_MSK, fdirm);
  304. flex = rd32(wx, TXGBE_RDB_FDIR_FLEX_CFG(0));
  305. flex &= ~TXGBE_RDB_FDIR_FLEX_CFG_FIELD0;
  306. flex |= (TXGBE_RDB_FDIR_FLEX_CFG_BASE_MAC |
  307. TXGBE_RDB_FDIR_FLEX_CFG_OFST(0x6));
  308. switch ((__force u16)input_mask->formatted.flex_bytes & 0xFFFF) {
  309. case 0x0000:
  310. /* Mask Flex Bytes */
  311. flex |= TXGBE_RDB_FDIR_FLEX_CFG_MSK;
  312. break;
  313. case 0xFFFF:
  314. break;
  315. default:
  316. wx_err(wx, "Error on flexible byte mask\n");
  317. return -EINVAL;
  318. }
  319. wr32(wx, TXGBE_RDB_FDIR_FLEX_CFG(0), flex);
  320. /* store the TCP/UDP port masks, bit reversed from port layout */
  321. fdirtcpm = ntohs(input_mask->formatted.dst_port);
  322. fdirtcpm <<= TXGBE_RDB_FDIR_PORT_DESTINATION_SHIFT;
  323. fdirtcpm |= ntohs(input_mask->formatted.src_port);
  324. /* write both the same so that UDP and TCP use the same mask */
  325. wr32(wx, TXGBE_RDB_FDIR_TCP_MSK, ~fdirtcpm);
  326. wr32(wx, TXGBE_RDB_FDIR_UDP_MSK, ~fdirtcpm);
  327. wr32(wx, TXGBE_RDB_FDIR_SCTP_MSK, ~fdirtcpm);
  328. /* store source and destination IP masks (little-enian) */
  329. wr32(wx, TXGBE_RDB_FDIR_SA4_MSK,
  330. ntohl(~input_mask->formatted.src_ip[0]));
  331. wr32(wx, TXGBE_RDB_FDIR_DA4_MSK,
  332. ntohl(~input_mask->formatted.dst_ip[0]));
  333. return 0;
  334. }
  335. int txgbe_fdir_write_perfect_filter(struct wx *wx,
  336. union txgbe_atr_input *input,
  337. u16 soft_id, u8 queue)
  338. {
  339. u32 fdirport, fdirvlan, fdirhash, fdircmd;
  340. int err = 0;
  341. /* currently IPv6 is not supported, must be programmed with 0 */
  342. wr32(wx, TXGBE_RDB_FDIR_IP6(2), ntohl(input->formatted.src_ip[0]));
  343. wr32(wx, TXGBE_RDB_FDIR_IP6(1), ntohl(input->formatted.src_ip[1]));
  344. wr32(wx, TXGBE_RDB_FDIR_IP6(0), ntohl(input->formatted.src_ip[2]));
  345. /* record the source address (little-endian) */
  346. wr32(wx, TXGBE_RDB_FDIR_SA, ntohl(input->formatted.src_ip[0]));
  347. /* record the first 32 bits of the destination address
  348. * (little-endian)
  349. */
  350. wr32(wx, TXGBE_RDB_FDIR_DA, ntohl(input->formatted.dst_ip[0]));
  351. /* record source and destination port (little-endian)*/
  352. fdirport = ntohs(input->formatted.dst_port);
  353. fdirport <<= TXGBE_RDB_FDIR_PORT_DESTINATION_SHIFT;
  354. fdirport |= ntohs(input->formatted.src_port);
  355. wr32(wx, TXGBE_RDB_FDIR_PORT, fdirport);
  356. /* record packet type and flex_bytes (little-endian) */
  357. fdirvlan = ntohs(input->formatted.flex_bytes);
  358. fdirvlan <<= TXGBE_RDB_FDIR_FLEX_FLEX_SHIFT;
  359. fdirvlan |= ntohs(input->formatted.vlan_id);
  360. wr32(wx, TXGBE_RDB_FDIR_FLEX, fdirvlan);
  361. /* configure FDIRHASH register */
  362. fdirhash = (__force u32)input->formatted.bkt_hash |
  363. TXGBE_RDB_FDIR_HASH_BUCKET_VALID |
  364. TXGBE_RDB_FDIR_HASH_SIG_SW_INDEX(soft_id);
  365. wr32(wx, TXGBE_RDB_FDIR_HASH, fdirhash);
  366. /* flush all previous writes to make certain registers are
  367. * programmed prior to issuing the command
  368. */
  369. WX_WRITE_FLUSH(wx);
  370. /* configure FDIRCMD register */
  371. fdircmd = TXGBE_RDB_FDIR_CMD_CMD_ADD_FLOW |
  372. TXGBE_RDB_FDIR_CMD_FILTER_UPDATE |
  373. TXGBE_RDB_FDIR_CMD_LAST | TXGBE_RDB_FDIR_CMD_QUEUE_EN;
  374. if (queue == TXGBE_RDB_FDIR_DROP_QUEUE)
  375. fdircmd |= TXGBE_RDB_FDIR_CMD_DROP;
  376. fdircmd |= TXGBE_RDB_FDIR_CMD_FLOW_TYPE(input->formatted.flow_type);
  377. fdircmd |= TXGBE_RDB_FDIR_CMD_RX_QUEUE(queue);
  378. fdircmd |= TXGBE_RDB_FDIR_CMD_VT_POOL(input->formatted.vm_pool);
  379. wr32(wx, TXGBE_RDB_FDIR_CMD, fdircmd);
  380. err = txgbe_fdir_check_cmd_complete(wx);
  381. if (err)
  382. wx_err(wx, "Flow Director command did not complete!\n");
  383. return err;
  384. }
  385. int txgbe_fdir_erase_perfect_filter(struct wx *wx,
  386. union txgbe_atr_input *input,
  387. u16 soft_id)
  388. {
  389. u32 fdirhash, fdircmd;
  390. int err = 0;
  391. /* configure FDIRHASH register */
  392. fdirhash = (__force u32)input->formatted.bkt_hash;
  393. fdirhash |= TXGBE_RDB_FDIR_HASH_SIG_SW_INDEX(soft_id);
  394. wr32(wx, TXGBE_RDB_FDIR_HASH, fdirhash);
  395. /* flush hash to HW */
  396. WX_WRITE_FLUSH(wx);
  397. /* Query if filter is present */
  398. wr32(wx, TXGBE_RDB_FDIR_CMD, TXGBE_RDB_FDIR_CMD_CMD_QUERY_REM_FILT);
  399. err = txgbe_fdir_check_cmd_complete(wx);
  400. if (err) {
  401. wx_err(wx, "Flow Director command did not complete!\n");
  402. return err;
  403. }
  404. fdircmd = rd32(wx, TXGBE_RDB_FDIR_CMD);
  405. /* if filter exists in hardware then remove it */
  406. if (fdircmd & TXGBE_RDB_FDIR_CMD_FILTER_VALID) {
  407. wr32(wx, TXGBE_RDB_FDIR_HASH, fdirhash);
  408. WX_WRITE_FLUSH(wx);
  409. wr32(wx, TXGBE_RDB_FDIR_CMD,
  410. TXGBE_RDB_FDIR_CMD_CMD_REMOVE_FLOW);
  411. }
  412. return 0;
  413. }
  414. /**
  415. * txgbe_fdir_enable - Initialize Flow Director control registers
  416. * @wx: pointer to hardware structure
  417. * @fdirctrl: value to write to flow director control register
  418. **/
  419. static void txgbe_fdir_enable(struct wx *wx, u32 fdirctrl)
  420. {
  421. u32 val;
  422. int ret;
  423. /* Prime the keys for hashing */
  424. wr32(wx, TXGBE_RDB_FDIR_HKEY, TXGBE_ATR_BUCKET_HASH_KEY);
  425. wr32(wx, TXGBE_RDB_FDIR_SKEY, TXGBE_ATR_SIGNATURE_HASH_KEY);
  426. wr32(wx, TXGBE_RDB_FDIR_CTL, fdirctrl);
  427. WX_WRITE_FLUSH(wx);
  428. ret = read_poll_timeout(rd32, val, val & TXGBE_RDB_FDIR_CTL_INIT_DONE,
  429. 1000, 10000, false, wx, TXGBE_RDB_FDIR_CTL);
  430. if (ret < 0)
  431. wx_dbg(wx, "Flow Director poll time exceeded!\n");
  432. }
  433. /**
  434. * txgbe_init_fdir_signature -Initialize Flow Director sig filters
  435. * @wx: pointer to hardware structure
  436. **/
  437. static void txgbe_init_fdir_signature(struct wx *wx)
  438. {
  439. u32 fdirctrl = TXGBE_FDIR_PBALLOC_64K;
  440. u32 flex = 0;
  441. flex = rd32(wx, TXGBE_RDB_FDIR_FLEX_CFG(0));
  442. flex &= ~TXGBE_RDB_FDIR_FLEX_CFG_FIELD0;
  443. flex |= (TXGBE_RDB_FDIR_FLEX_CFG_BASE_MAC |
  444. TXGBE_RDB_FDIR_FLEX_CFG_OFST(0x6));
  445. wr32(wx, TXGBE_RDB_FDIR_FLEX_CFG(0), flex);
  446. /* Continue setup of fdirctrl register bits:
  447. * Move the flexible bytes to use the ethertype - shift 6 words
  448. * Set the maximum length per hash bucket to 0xA filters
  449. * Send interrupt when 64 filters are left
  450. */
  451. fdirctrl |= TXGBE_RDB_FDIR_CTL_HASH_BITS(0xF) |
  452. TXGBE_RDB_FDIR_CTL_MAX_LENGTH(0xA) |
  453. TXGBE_RDB_FDIR_CTL_FULL_THRESH(4);
  454. /* write hashes and fdirctrl register, poll for completion */
  455. txgbe_fdir_enable(wx, fdirctrl);
  456. }
  457. /**
  458. * txgbe_init_fdir_perfect - Initialize Flow Director perfect filters
  459. * @wx: pointer to hardware structure
  460. **/
  461. static void txgbe_init_fdir_perfect(struct wx *wx)
  462. {
  463. u32 fdirctrl = TXGBE_FDIR_PBALLOC_64K;
  464. /* Continue setup of fdirctrl register bits:
  465. * Turn perfect match filtering on
  466. * Report hash in RSS field of Rx wb descriptor
  467. * Initialize the drop queue
  468. * Move the flexible bytes to use the ethertype - shift 6 words
  469. * Set the maximum length per hash bucket to 0xA filters
  470. * Send interrupt when 64 (0x4 * 16) filters are left
  471. */
  472. fdirctrl |= TXGBE_RDB_FDIR_CTL_PERFECT_MATCH |
  473. TXGBE_RDB_FDIR_CTL_DROP_Q(TXGBE_RDB_FDIR_DROP_QUEUE) |
  474. TXGBE_RDB_FDIR_CTL_HASH_BITS(0xF) |
  475. TXGBE_RDB_FDIR_CTL_MAX_LENGTH(0xA) |
  476. TXGBE_RDB_FDIR_CTL_FULL_THRESH(4);
  477. /* write hashes and fdirctrl register, poll for completion */
  478. txgbe_fdir_enable(wx, fdirctrl);
  479. }
  480. static void txgbe_fdir_filter_restore(struct wx *wx)
  481. {
  482. struct txgbe_fdir_filter *filter;
  483. struct txgbe *txgbe = wx->priv;
  484. struct hlist_node *node;
  485. u8 queue = 0;
  486. int ret = 0;
  487. spin_lock(&txgbe->fdir_perfect_lock);
  488. if (!hlist_empty(&txgbe->fdir_filter_list))
  489. ret = txgbe_fdir_set_input_mask(wx, &txgbe->fdir_mask);
  490. if (ret)
  491. goto unlock;
  492. hlist_for_each_entry_safe(filter, node,
  493. &txgbe->fdir_filter_list, fdir_node) {
  494. if (filter->action == TXGBE_RDB_FDIR_DROP_QUEUE) {
  495. queue = TXGBE_RDB_FDIR_DROP_QUEUE;
  496. } else {
  497. u32 ring = ethtool_get_flow_spec_ring(filter->action);
  498. if (ring >= wx->num_rx_queues) {
  499. wx_err(wx, "FDIR restore failed, ring:%u\n",
  500. ring);
  501. continue;
  502. }
  503. /* Map the ring onto the absolute queue index */
  504. queue = wx->rx_ring[ring]->reg_idx;
  505. }
  506. ret = txgbe_fdir_write_perfect_filter(wx,
  507. &filter->filter,
  508. filter->sw_idx,
  509. queue);
  510. if (ret)
  511. wx_err(wx, "FDIR restore failed, index:%u\n",
  512. filter->sw_idx);
  513. }
  514. unlock:
  515. spin_unlock(&txgbe->fdir_perfect_lock);
  516. }
  517. void txgbe_configure_fdir(struct wx *wx)
  518. {
  519. wx_disable_sec_rx_path(wx);
  520. if (test_bit(WX_FLAG_FDIR_HASH, wx->flags)) {
  521. txgbe_init_fdir_signature(wx);
  522. } else if (test_bit(WX_FLAG_FDIR_PERFECT, wx->flags)) {
  523. txgbe_init_fdir_perfect(wx);
  524. txgbe_fdir_filter_restore(wx);
  525. }
  526. wx_enable_sec_rx_path(wx);
  527. }
  528. void txgbe_fdir_filter_exit(struct wx *wx)
  529. {
  530. struct txgbe_fdir_filter *filter;
  531. struct txgbe *txgbe = wx->priv;
  532. struct hlist_node *node;
  533. spin_lock(&txgbe->fdir_perfect_lock);
  534. hlist_for_each_entry_safe(filter, node,
  535. &txgbe->fdir_filter_list, fdir_node) {
  536. hlist_del(&filter->fdir_node);
  537. kfree(filter);
  538. }
  539. txgbe->fdir_filter_count = 0;
  540. spin_unlock(&txgbe->fdir_perfect_lock);
  541. }