PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c

http://github.com/mirrors/linux-2.6
C | 3751 lines | 3110 code | 468 blank | 173 comment | 361 complexity | 3676bcd3035bf02ae526d9d1ca1afd41 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * This file is part of the Chelsio T4 Ethernet driver for Linux.
  3. *
  4. * Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved.
  5. *
  6. * This software is available to you under a choice of one of two
  7. * licenses. You may choose to be licensed under the terms of the GNU
  8. * General Public License (GPL) Version 2, available from the file
  9. * COPYING in the main directory of this source tree, or the
  10. * OpenIB.org BSD license below:
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above
  17. * copyright notice, this list of conditions and the following
  18. * disclaimer.
  19. *
  20. * - Redistributions in binary form must reproduce the above
  21. * copyright notice, this list of conditions and the following
  22. * disclaimer in the documentation and/or other materials
  23. * provided with the distribution.
  24. *
  25. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  29. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  30. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  31. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  32. * SOFTWARE.
  33. */
  34. #include <linux/seq_file.h>
  35. #include <linux/debugfs.h>
  36. #include <linux/string_helpers.h>
  37. #include <linux/sort.h>
  38. #include <linux/ctype.h>
  39. #include "cxgb4.h"
  40. #include "t4_regs.h"
  41. #include "t4_values.h"
  42. #include "t4fw_api.h"
  43. #include "cxgb4_debugfs.h"
  44. #include "clip_tbl.h"
  45. #include "l2t.h"
  46. #include "cudbg_if.h"
  47. #include "cudbg_lib_common.h"
  48. #include "cudbg_entity.h"
  49. #include "cudbg_lib.h"
  50. /* generic seq_file support for showing a table of size rows x width. */
  51. static void *seq_tab_get_idx(struct seq_tab *tb, loff_t pos)
  52. {
  53. pos -= tb->skip_first;
  54. return pos >= tb->rows ? NULL : &tb->data[pos * tb->width];
  55. }
  56. static void *seq_tab_start(struct seq_file *seq, loff_t *pos)
  57. {
  58. struct seq_tab *tb = seq->private;
  59. if (tb->skip_first && *pos == 0)
  60. return SEQ_START_TOKEN;
  61. return seq_tab_get_idx(tb, *pos);
  62. }
  63. static void *seq_tab_next(struct seq_file *seq, void *v, loff_t *pos)
  64. {
  65. v = seq_tab_get_idx(seq->private, *pos + 1);
  66. ++(*pos);
  67. return v;
  68. }
  69. static void seq_tab_stop(struct seq_file *seq, void *v)
  70. {
  71. }
  72. static int seq_tab_show(struct seq_file *seq, void *v)
  73. {
  74. const struct seq_tab *tb = seq->private;
  75. return tb->show(seq, v, ((char *)v - tb->data) / tb->width);
  76. }
  77. static const struct seq_operations seq_tab_ops = {
  78. .start = seq_tab_start,
  79. .next = seq_tab_next,
  80. .stop = seq_tab_stop,
  81. .show = seq_tab_show
  82. };
  83. struct seq_tab *seq_open_tab(struct file *f, unsigned int rows,
  84. unsigned int width, unsigned int have_header,
  85. int (*show)(struct seq_file *seq, void *v, int i))
  86. {
  87. struct seq_tab *p;
  88. p = __seq_open_private(f, &seq_tab_ops, sizeof(*p) + rows * width);
  89. if (p) {
  90. p->show = show;
  91. p->rows = rows;
  92. p->width = width;
  93. p->skip_first = have_header != 0;
  94. }
  95. return p;
  96. }
  97. /* Trim the size of a seq_tab to the supplied number of rows. The operation is
  98. * irreversible.
  99. */
  100. static int seq_tab_trim(struct seq_tab *p, unsigned int new_rows)
  101. {
  102. if (new_rows > p->rows)
  103. return -EINVAL;
  104. p->rows = new_rows;
  105. return 0;
  106. }
  107. static int cim_la_show(struct seq_file *seq, void *v, int idx)
  108. {
  109. if (v == SEQ_START_TOKEN)
  110. seq_puts(seq, "Status Data PC LS0Stat LS0Addr "
  111. " LS0Data\n");
  112. else {
  113. const u32 *p = v;
  114. seq_printf(seq,
  115. " %02x %x%07x %x%07x %08x %08x %08x%08x%08x%08x\n",
  116. (p[0] >> 4) & 0xff, p[0] & 0xf, p[1] >> 4,
  117. p[1] & 0xf, p[2] >> 4, p[2] & 0xf, p[3], p[4], p[5],
  118. p[6], p[7]);
  119. }
  120. return 0;
  121. }
  122. static int cim_la_show_3in1(struct seq_file *seq, void *v, int idx)
  123. {
  124. if (v == SEQ_START_TOKEN) {
  125. seq_puts(seq, "Status Data PC\n");
  126. } else {
  127. const u32 *p = v;
  128. seq_printf(seq, " %02x %08x %08x\n", p[5] & 0xff, p[6],
  129. p[7]);
  130. seq_printf(seq, " %02x %02x%06x %02x%06x\n",
  131. (p[3] >> 8) & 0xff, p[3] & 0xff, p[4] >> 8,
  132. p[4] & 0xff, p[5] >> 8);
  133. seq_printf(seq, " %02x %x%07x %x%07x\n", (p[0] >> 4) & 0xff,
  134. p[0] & 0xf, p[1] >> 4, p[1] & 0xf, p[2] >> 4);
  135. }
  136. return 0;
  137. }
  138. static int cim_la_show_t6(struct seq_file *seq, void *v, int idx)
  139. {
  140. if (v == SEQ_START_TOKEN) {
  141. seq_puts(seq, "Status Inst Data PC LS0Stat "
  142. "LS0Addr LS0Data LS1Stat LS1Addr LS1Data\n");
  143. } else {
  144. const u32 *p = v;
  145. seq_printf(seq, " %02x %04x%04x %04x%04x %04x%04x %08x %08x %08x %08x %08x %08x\n",
  146. (p[9] >> 16) & 0xff, /* Status */
  147. p[9] & 0xffff, p[8] >> 16, /* Inst */
  148. p[8] & 0xffff, p[7] >> 16, /* Data */
  149. p[7] & 0xffff, p[6] >> 16, /* PC */
  150. p[2], p[1], p[0], /* LS0 Stat, Addr and Data */
  151. p[5], p[4], p[3]); /* LS1 Stat, Addr and Data */
  152. }
  153. return 0;
  154. }
  155. static int cim_la_show_pc_t6(struct seq_file *seq, void *v, int idx)
  156. {
  157. if (v == SEQ_START_TOKEN) {
  158. seq_puts(seq, "Status Inst Data PC\n");
  159. } else {
  160. const u32 *p = v;
  161. seq_printf(seq, " %02x %08x %08x %08x\n",
  162. p[3] & 0xff, p[2], p[1], p[0]);
  163. seq_printf(seq, " %02x %02x%06x %02x%06x %02x%06x\n",
  164. (p[6] >> 8) & 0xff, p[6] & 0xff, p[5] >> 8,
  165. p[5] & 0xff, p[4] >> 8, p[4] & 0xff, p[3] >> 8);
  166. seq_printf(seq, " %02x %04x%04x %04x%04x %04x%04x\n",
  167. (p[9] >> 16) & 0xff, p[9] & 0xffff, p[8] >> 16,
  168. p[8] & 0xffff, p[7] >> 16, p[7] & 0xffff,
  169. p[6] >> 16);
  170. }
  171. return 0;
  172. }
  173. static int cim_la_open(struct inode *inode, struct file *file)
  174. {
  175. int ret;
  176. unsigned int cfg;
  177. struct seq_tab *p;
  178. struct adapter *adap = inode->i_private;
  179. ret = t4_cim_read(adap, UP_UP_DBG_LA_CFG_A, 1, &cfg);
  180. if (ret)
  181. return ret;
  182. if (is_t6(adap->params.chip)) {
  183. /* +1 to account for integer division of CIMLA_SIZE/10 */
  184. p = seq_open_tab(file, (adap->params.cim_la_size / 10) + 1,
  185. 10 * sizeof(u32), 1,
  186. cfg & UPDBGLACAPTPCONLY_F ?
  187. cim_la_show_pc_t6 : cim_la_show_t6);
  188. } else {
  189. p = seq_open_tab(file, adap->params.cim_la_size / 8,
  190. 8 * sizeof(u32), 1,
  191. cfg & UPDBGLACAPTPCONLY_F ? cim_la_show_3in1 :
  192. cim_la_show);
  193. }
  194. if (!p)
  195. return -ENOMEM;
  196. ret = t4_cim_read_la(adap, (u32 *)p->data, NULL);
  197. if (ret)
  198. seq_release_private(inode, file);
  199. return ret;
  200. }
  201. static const struct file_operations cim_la_fops = {
  202. .owner = THIS_MODULE,
  203. .open = cim_la_open,
  204. .read = seq_read,
  205. .llseek = seq_lseek,
  206. .release = seq_release_private
  207. };
  208. static int cim_pif_la_show(struct seq_file *seq, void *v, int idx)
  209. {
  210. const u32 *p = v;
  211. if (v == SEQ_START_TOKEN) {
  212. seq_puts(seq, "Cntl ID DataBE Addr Data\n");
  213. } else if (idx < CIM_PIFLA_SIZE) {
  214. seq_printf(seq, " %02x %02x %04x %08x %08x%08x%08x%08x\n",
  215. (p[5] >> 22) & 0xff, (p[5] >> 16) & 0x3f,
  216. p[5] & 0xffff, p[4], p[3], p[2], p[1], p[0]);
  217. } else {
  218. if (idx == CIM_PIFLA_SIZE)
  219. seq_puts(seq, "\nCntl ID Data\n");
  220. seq_printf(seq, " %02x %02x %08x%08x%08x%08x\n",
  221. (p[4] >> 6) & 0xff, p[4] & 0x3f,
  222. p[3], p[2], p[1], p[0]);
  223. }
  224. return 0;
  225. }
  226. static int cim_pif_la_open(struct inode *inode, struct file *file)
  227. {
  228. struct seq_tab *p;
  229. struct adapter *adap = inode->i_private;
  230. p = seq_open_tab(file, 2 * CIM_PIFLA_SIZE, 6 * sizeof(u32), 1,
  231. cim_pif_la_show);
  232. if (!p)
  233. return -ENOMEM;
  234. t4_cim_read_pif_la(adap, (u32 *)p->data,
  235. (u32 *)p->data + 6 * CIM_PIFLA_SIZE, NULL, NULL);
  236. return 0;
  237. }
  238. static const struct file_operations cim_pif_la_fops = {
  239. .owner = THIS_MODULE,
  240. .open = cim_pif_la_open,
  241. .read = seq_read,
  242. .llseek = seq_lseek,
  243. .release = seq_release_private
  244. };
  245. static int cim_ma_la_show(struct seq_file *seq, void *v, int idx)
  246. {
  247. const u32 *p = v;
  248. if (v == SEQ_START_TOKEN) {
  249. seq_puts(seq, "\n");
  250. } else if (idx < CIM_MALA_SIZE) {
  251. seq_printf(seq, "%02x%08x%08x%08x%08x\n",
  252. p[4], p[3], p[2], p[1], p[0]);
  253. } else {
  254. if (idx == CIM_MALA_SIZE)
  255. seq_puts(seq,
  256. "\nCnt ID Tag UE Data RDY VLD\n");
  257. seq_printf(seq, "%3u %2u %x %u %08x%08x %u %u\n",
  258. (p[2] >> 10) & 0xff, (p[2] >> 7) & 7,
  259. (p[2] >> 3) & 0xf, (p[2] >> 2) & 1,
  260. (p[1] >> 2) | ((p[2] & 3) << 30),
  261. (p[0] >> 2) | ((p[1] & 3) << 30), (p[0] >> 1) & 1,
  262. p[0] & 1);
  263. }
  264. return 0;
  265. }
  266. static int cim_ma_la_open(struct inode *inode, struct file *file)
  267. {
  268. struct seq_tab *p;
  269. struct adapter *adap = inode->i_private;
  270. p = seq_open_tab(file, 2 * CIM_MALA_SIZE, 5 * sizeof(u32), 1,
  271. cim_ma_la_show);
  272. if (!p)
  273. return -ENOMEM;
  274. t4_cim_read_ma_la(adap, (u32 *)p->data,
  275. (u32 *)p->data + 5 * CIM_MALA_SIZE);
  276. return 0;
  277. }
  278. static const struct file_operations cim_ma_la_fops = {
  279. .owner = THIS_MODULE,
  280. .open = cim_ma_la_open,
  281. .read = seq_read,
  282. .llseek = seq_lseek,
  283. .release = seq_release_private
  284. };
  285. static int cim_qcfg_show(struct seq_file *seq, void *v)
  286. {
  287. static const char * const qname[] = {
  288. "TP0", "TP1", "ULP", "SGE0", "SGE1", "NC-SI",
  289. "ULP0", "ULP1", "ULP2", "ULP3", "SGE", "NC-SI",
  290. "SGE0-RX", "SGE1-RX"
  291. };
  292. int i;
  293. struct adapter *adap = seq->private;
  294. u16 base[CIM_NUM_IBQ + CIM_NUM_OBQ_T5];
  295. u16 size[CIM_NUM_IBQ + CIM_NUM_OBQ_T5];
  296. u32 stat[(4 * (CIM_NUM_IBQ + CIM_NUM_OBQ_T5))];
  297. u16 thres[CIM_NUM_IBQ];
  298. u32 obq_wr_t4[2 * CIM_NUM_OBQ], *wr;
  299. u32 obq_wr_t5[2 * CIM_NUM_OBQ_T5];
  300. u32 *p = stat;
  301. int cim_num_obq = is_t4(adap->params.chip) ?
  302. CIM_NUM_OBQ : CIM_NUM_OBQ_T5;
  303. i = t4_cim_read(adap, is_t4(adap->params.chip) ? UP_IBQ_0_RDADDR_A :
  304. UP_IBQ_0_SHADOW_RDADDR_A,
  305. ARRAY_SIZE(stat), stat);
  306. if (!i) {
  307. if (is_t4(adap->params.chip)) {
  308. i = t4_cim_read(adap, UP_OBQ_0_REALADDR_A,
  309. ARRAY_SIZE(obq_wr_t4), obq_wr_t4);
  310. wr = obq_wr_t4;
  311. } else {
  312. i = t4_cim_read(adap, UP_OBQ_0_SHADOW_REALADDR_A,
  313. ARRAY_SIZE(obq_wr_t5), obq_wr_t5);
  314. wr = obq_wr_t5;
  315. }
  316. }
  317. if (i)
  318. return i;
  319. t4_read_cimq_cfg(adap, base, size, thres);
  320. seq_printf(seq,
  321. " Queue Base Size Thres RdPtr WrPtr SOP EOP Avail\n");
  322. for (i = 0; i < CIM_NUM_IBQ; i++, p += 4)
  323. seq_printf(seq, "%7s %5x %5u %5u %6x %4x %4u %4u %5u\n",
  324. qname[i], base[i], size[i], thres[i],
  325. IBQRDADDR_G(p[0]), IBQWRADDR_G(p[1]),
  326. QUESOPCNT_G(p[3]), QUEEOPCNT_G(p[3]),
  327. QUEREMFLITS_G(p[2]) * 16);
  328. for ( ; i < CIM_NUM_IBQ + cim_num_obq; i++, p += 4, wr += 2)
  329. seq_printf(seq, "%7s %5x %5u %12x %4x %4u %4u %5u\n",
  330. qname[i], base[i], size[i],
  331. QUERDADDR_G(p[0]) & 0x3fff, wr[0] - base[i],
  332. QUESOPCNT_G(p[3]), QUEEOPCNT_G(p[3]),
  333. QUEREMFLITS_G(p[2]) * 16);
  334. return 0;
  335. }
  336. DEFINE_SHOW_ATTRIBUTE(cim_qcfg);
  337. static int cimq_show(struct seq_file *seq, void *v, int idx)
  338. {
  339. const u32 *p = v;
  340. seq_printf(seq, "%#06x: %08x %08x %08x %08x\n", idx * 16, p[0], p[1],
  341. p[2], p[3]);
  342. return 0;
  343. }
  344. static int cim_ibq_open(struct inode *inode, struct file *file)
  345. {
  346. int ret;
  347. struct seq_tab *p;
  348. unsigned int qid = (uintptr_t)inode->i_private & 7;
  349. struct adapter *adap = inode->i_private - qid;
  350. p = seq_open_tab(file, CIM_IBQ_SIZE, 4 * sizeof(u32), 0, cimq_show);
  351. if (!p)
  352. return -ENOMEM;
  353. ret = t4_read_cim_ibq(adap, qid, (u32 *)p->data, CIM_IBQ_SIZE * 4);
  354. if (ret < 0)
  355. seq_release_private(inode, file);
  356. else
  357. ret = 0;
  358. return ret;
  359. }
  360. static const struct file_operations cim_ibq_fops = {
  361. .owner = THIS_MODULE,
  362. .open = cim_ibq_open,
  363. .read = seq_read,
  364. .llseek = seq_lseek,
  365. .release = seq_release_private
  366. };
  367. static int cim_obq_open(struct inode *inode, struct file *file)
  368. {
  369. int ret;
  370. struct seq_tab *p;
  371. unsigned int qid = (uintptr_t)inode->i_private & 7;
  372. struct adapter *adap = inode->i_private - qid;
  373. p = seq_open_tab(file, 6 * CIM_OBQ_SIZE, 4 * sizeof(u32), 0, cimq_show);
  374. if (!p)
  375. return -ENOMEM;
  376. ret = t4_read_cim_obq(adap, qid, (u32 *)p->data, 6 * CIM_OBQ_SIZE * 4);
  377. if (ret < 0) {
  378. seq_release_private(inode, file);
  379. } else {
  380. seq_tab_trim(p, ret / 4);
  381. ret = 0;
  382. }
  383. return ret;
  384. }
  385. static const struct file_operations cim_obq_fops = {
  386. .owner = THIS_MODULE,
  387. .open = cim_obq_open,
  388. .read = seq_read,
  389. .llseek = seq_lseek,
  390. .release = seq_release_private
  391. };
  392. struct field_desc {
  393. const char *name;
  394. unsigned int start;
  395. unsigned int width;
  396. };
  397. static void field_desc_show(struct seq_file *seq, u64 v,
  398. const struct field_desc *p)
  399. {
  400. char buf[32];
  401. int line_size = 0;
  402. while (p->name) {
  403. u64 mask = (1ULL << p->width) - 1;
  404. int len = scnprintf(buf, sizeof(buf), "%s: %llu", p->name,
  405. ((unsigned long long)v >> p->start) & mask);
  406. if (line_size + len >= 79) {
  407. line_size = 8;
  408. seq_puts(seq, "\n ");
  409. }
  410. seq_printf(seq, "%s ", buf);
  411. line_size += len + 1;
  412. p++;
  413. }
  414. seq_putc(seq, '\n');
  415. }
  416. static struct field_desc tp_la0[] = {
  417. { "RcfOpCodeOut", 60, 4 },
  418. { "State", 56, 4 },
  419. { "WcfState", 52, 4 },
  420. { "RcfOpcSrcOut", 50, 2 },
  421. { "CRxError", 49, 1 },
  422. { "ERxError", 48, 1 },
  423. { "SanityFailed", 47, 1 },
  424. { "SpuriousMsg", 46, 1 },
  425. { "FlushInputMsg", 45, 1 },
  426. { "FlushInputCpl", 44, 1 },
  427. { "RssUpBit", 43, 1 },
  428. { "RssFilterHit", 42, 1 },
  429. { "Tid", 32, 10 },
  430. { "InitTcb", 31, 1 },
  431. { "LineNumber", 24, 7 },
  432. { "Emsg", 23, 1 },
  433. { "EdataOut", 22, 1 },
  434. { "Cmsg", 21, 1 },
  435. { "CdataOut", 20, 1 },
  436. { "EreadPdu", 19, 1 },
  437. { "CreadPdu", 18, 1 },
  438. { "TunnelPkt", 17, 1 },
  439. { "RcfPeerFin", 16, 1 },
  440. { "RcfReasonOut", 12, 4 },
  441. { "TxCchannel", 10, 2 },
  442. { "RcfTxChannel", 8, 2 },
  443. { "RxEchannel", 6, 2 },
  444. { "RcfRxChannel", 5, 1 },
  445. { "RcfDataOutSrdy", 4, 1 },
  446. { "RxDvld", 3, 1 },
  447. { "RxOoDvld", 2, 1 },
  448. { "RxCongestion", 1, 1 },
  449. { "TxCongestion", 0, 1 },
  450. { NULL }
  451. };
  452. static int tp_la_show(struct seq_file *seq, void *v, int idx)
  453. {
  454. const u64 *p = v;
  455. field_desc_show(seq, *p, tp_la0);
  456. return 0;
  457. }
  458. static int tp_la_show2(struct seq_file *seq, void *v, int idx)
  459. {
  460. const u64 *p = v;
  461. if (idx)
  462. seq_putc(seq, '\n');
  463. field_desc_show(seq, p[0], tp_la0);
  464. if (idx < (TPLA_SIZE / 2 - 1) || p[1] != ~0ULL)
  465. field_desc_show(seq, p[1], tp_la0);
  466. return 0;
  467. }
  468. static int tp_la_show3(struct seq_file *seq, void *v, int idx)
  469. {
  470. static struct field_desc tp_la1[] = {
  471. { "CplCmdIn", 56, 8 },
  472. { "CplCmdOut", 48, 8 },
  473. { "ESynOut", 47, 1 },
  474. { "EAckOut", 46, 1 },
  475. { "EFinOut", 45, 1 },
  476. { "ERstOut", 44, 1 },
  477. { "SynIn", 43, 1 },
  478. { "AckIn", 42, 1 },
  479. { "FinIn", 41, 1 },
  480. { "RstIn", 40, 1 },
  481. { "DataIn", 39, 1 },
  482. { "DataInVld", 38, 1 },
  483. { "PadIn", 37, 1 },
  484. { "RxBufEmpty", 36, 1 },
  485. { "RxDdp", 35, 1 },
  486. { "RxFbCongestion", 34, 1 },
  487. { "TxFbCongestion", 33, 1 },
  488. { "TxPktSumSrdy", 32, 1 },
  489. { "RcfUlpType", 28, 4 },
  490. { "Eread", 27, 1 },
  491. { "Ebypass", 26, 1 },
  492. { "Esave", 25, 1 },
  493. { "Static0", 24, 1 },
  494. { "Cread", 23, 1 },
  495. { "Cbypass", 22, 1 },
  496. { "Csave", 21, 1 },
  497. { "CPktOut", 20, 1 },
  498. { "RxPagePoolFull", 18, 2 },
  499. { "RxLpbkPkt", 17, 1 },
  500. { "TxLpbkPkt", 16, 1 },
  501. { "RxVfValid", 15, 1 },
  502. { "SynLearned", 14, 1 },
  503. { "SetDelEntry", 13, 1 },
  504. { "SetInvEntry", 12, 1 },
  505. { "CpcmdDvld", 11, 1 },
  506. { "CpcmdSave", 10, 1 },
  507. { "RxPstructsFull", 8, 2 },
  508. { "EpcmdDvld", 7, 1 },
  509. { "EpcmdFlush", 6, 1 },
  510. { "EpcmdTrimPrefix", 5, 1 },
  511. { "EpcmdTrimPostfix", 4, 1 },
  512. { "ERssIp4Pkt", 3, 1 },
  513. { "ERssIp6Pkt", 2, 1 },
  514. { "ERssTcpUdpPkt", 1, 1 },
  515. { "ERssFceFipPkt", 0, 1 },
  516. { NULL }
  517. };
  518. static struct field_desc tp_la2[] = {
  519. { "CplCmdIn", 56, 8 },
  520. { "MpsVfVld", 55, 1 },
  521. { "MpsPf", 52, 3 },
  522. { "MpsVf", 44, 8 },
  523. { "SynIn", 43, 1 },
  524. { "AckIn", 42, 1 },
  525. { "FinIn", 41, 1 },
  526. { "RstIn", 40, 1 },
  527. { "DataIn", 39, 1 },
  528. { "DataInVld", 38, 1 },
  529. { "PadIn", 37, 1 },
  530. { "RxBufEmpty", 36, 1 },
  531. { "RxDdp", 35, 1 },
  532. { "RxFbCongestion", 34, 1 },
  533. { "TxFbCongestion", 33, 1 },
  534. { "TxPktSumSrdy", 32, 1 },
  535. { "RcfUlpType", 28, 4 },
  536. { "Eread", 27, 1 },
  537. { "Ebypass", 26, 1 },
  538. { "Esave", 25, 1 },
  539. { "Static0", 24, 1 },
  540. { "Cread", 23, 1 },
  541. { "Cbypass", 22, 1 },
  542. { "Csave", 21, 1 },
  543. { "CPktOut", 20, 1 },
  544. { "RxPagePoolFull", 18, 2 },
  545. { "RxLpbkPkt", 17, 1 },
  546. { "TxLpbkPkt", 16, 1 },
  547. { "RxVfValid", 15, 1 },
  548. { "SynLearned", 14, 1 },
  549. { "SetDelEntry", 13, 1 },
  550. { "SetInvEntry", 12, 1 },
  551. { "CpcmdDvld", 11, 1 },
  552. { "CpcmdSave", 10, 1 },
  553. { "RxPstructsFull", 8, 2 },
  554. { "EpcmdDvld", 7, 1 },
  555. { "EpcmdFlush", 6, 1 },
  556. { "EpcmdTrimPrefix", 5, 1 },
  557. { "EpcmdTrimPostfix", 4, 1 },
  558. { "ERssIp4Pkt", 3, 1 },
  559. { "ERssIp6Pkt", 2, 1 },
  560. { "ERssTcpUdpPkt", 1, 1 },
  561. { "ERssFceFipPkt", 0, 1 },
  562. { NULL }
  563. };
  564. const u64 *p = v;
  565. if (idx)
  566. seq_putc(seq, '\n');
  567. field_desc_show(seq, p[0], tp_la0);
  568. if (idx < (TPLA_SIZE / 2 - 1) || p[1] != ~0ULL)
  569. field_desc_show(seq, p[1], (p[0] & BIT(17)) ? tp_la2 : tp_la1);
  570. return 0;
  571. }
  572. static int tp_la_open(struct inode *inode, struct file *file)
  573. {
  574. struct seq_tab *p;
  575. struct adapter *adap = inode->i_private;
  576. switch (DBGLAMODE_G(t4_read_reg(adap, TP_DBG_LA_CONFIG_A))) {
  577. case 2:
  578. p = seq_open_tab(file, TPLA_SIZE / 2, 2 * sizeof(u64), 0,
  579. tp_la_show2);
  580. break;
  581. case 3:
  582. p = seq_open_tab(file, TPLA_SIZE / 2, 2 * sizeof(u64), 0,
  583. tp_la_show3);
  584. break;
  585. default:
  586. p = seq_open_tab(file, TPLA_SIZE, sizeof(u64), 0, tp_la_show);
  587. }
  588. if (!p)
  589. return -ENOMEM;
  590. t4_tp_read_la(adap, (u64 *)p->data, NULL);
  591. return 0;
  592. }
  593. static ssize_t tp_la_write(struct file *file, const char __user *buf,
  594. size_t count, loff_t *pos)
  595. {
  596. int err;
  597. char s[32];
  598. unsigned long val;
  599. size_t size = min(sizeof(s) - 1, count);
  600. struct adapter *adap = file_inode(file)->i_private;
  601. if (copy_from_user(s, buf, size))
  602. return -EFAULT;
  603. s[size] = '\0';
  604. err = kstrtoul(s, 0, &val);
  605. if (err)
  606. return err;
  607. if (val > 0xffff)
  608. return -EINVAL;
  609. adap->params.tp.la_mask = val << 16;
  610. t4_set_reg_field(adap, TP_DBG_LA_CONFIG_A, 0xffff0000U,
  611. adap->params.tp.la_mask);
  612. return count;
  613. }
  614. static const struct file_operations tp_la_fops = {
  615. .owner = THIS_MODULE,
  616. .open = tp_la_open,
  617. .read = seq_read,
  618. .llseek = seq_lseek,
  619. .release = seq_release_private,
  620. .write = tp_la_write
  621. };
  622. static int ulprx_la_show(struct seq_file *seq, void *v, int idx)
  623. {
  624. const u32 *p = v;
  625. if (v == SEQ_START_TOKEN)
  626. seq_puts(seq, " Pcmd Type Message"
  627. " Data\n");
  628. else
  629. seq_printf(seq, "%08x%08x %4x %08x %08x%08x%08x%08x\n",
  630. p[1], p[0], p[2], p[3], p[7], p[6], p[5], p[4]);
  631. return 0;
  632. }
  633. static int ulprx_la_open(struct inode *inode, struct file *file)
  634. {
  635. struct seq_tab *p;
  636. struct adapter *adap = inode->i_private;
  637. p = seq_open_tab(file, ULPRX_LA_SIZE, 8 * sizeof(u32), 1,
  638. ulprx_la_show);
  639. if (!p)
  640. return -ENOMEM;
  641. t4_ulprx_read_la(adap, (u32 *)p->data);
  642. return 0;
  643. }
  644. static const struct file_operations ulprx_la_fops = {
  645. .owner = THIS_MODULE,
  646. .open = ulprx_la_open,
  647. .read = seq_read,
  648. .llseek = seq_lseek,
  649. .release = seq_release_private
  650. };
  651. /* Show the PM memory stats. These stats include:
  652. *
  653. * TX:
  654. * Read: memory read operation
  655. * Write Bypass: cut-through
  656. * Bypass + mem: cut-through and save copy
  657. *
  658. * RX:
  659. * Read: memory read
  660. * Write Bypass: cut-through
  661. * Flush: payload trim or drop
  662. */
  663. static int pm_stats_show(struct seq_file *seq, void *v)
  664. {
  665. static const char * const tx_pm_stats[] = {
  666. "Read:", "Write bypass:", "Write mem:", "Bypass + mem:"
  667. };
  668. static const char * const rx_pm_stats[] = {
  669. "Read:", "Write bypass:", "Write mem:", "Flush:"
  670. };
  671. int i;
  672. u32 tx_cnt[T6_PM_NSTATS], rx_cnt[T6_PM_NSTATS];
  673. u64 tx_cyc[T6_PM_NSTATS], rx_cyc[T6_PM_NSTATS];
  674. struct adapter *adap = seq->private;
  675. t4_pmtx_get_stats(adap, tx_cnt, tx_cyc);
  676. t4_pmrx_get_stats(adap, rx_cnt, rx_cyc);
  677. seq_printf(seq, "%13s %10s %20s\n", " ", "Tx pcmds", "Tx bytes");
  678. for (i = 0; i < PM_NSTATS - 1; i++)
  679. seq_printf(seq, "%-13s %10u %20llu\n",
  680. tx_pm_stats[i], tx_cnt[i], tx_cyc[i]);
  681. seq_printf(seq, "%13s %10s %20s\n", " ", "Rx pcmds", "Rx bytes");
  682. for (i = 0; i < PM_NSTATS - 1; i++)
  683. seq_printf(seq, "%-13s %10u %20llu\n",
  684. rx_pm_stats[i], rx_cnt[i], rx_cyc[i]);
  685. if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) {
  686. /* In T5 the granularity of the total wait is too fine.
  687. * It is not useful as it reaches the max value too fast.
  688. * Hence display this Input FIFO wait for T6 onwards.
  689. */
  690. seq_printf(seq, "%13s %10s %20s\n",
  691. " ", "Total wait", "Total Occupancy");
  692. seq_printf(seq, "Tx FIFO wait %10u %20llu\n",
  693. tx_cnt[i], tx_cyc[i]);
  694. seq_printf(seq, "Rx FIFO wait %10u %20llu\n",
  695. rx_cnt[i], rx_cyc[i]);
  696. /* Skip index 6 as there is nothing useful ihere */
  697. i += 2;
  698. /* At index 7, a new stat for read latency (count, total wait)
  699. * is added.
  700. */
  701. seq_printf(seq, "%13s %10s %20s\n",
  702. " ", "Reads", "Total wait");
  703. seq_printf(seq, "Tx latency %10u %20llu\n",
  704. tx_cnt[i], tx_cyc[i]);
  705. seq_printf(seq, "Rx latency %10u %20llu\n",
  706. rx_cnt[i], rx_cyc[i]);
  707. }
  708. return 0;
  709. }
  710. static int pm_stats_open(struct inode *inode, struct file *file)
  711. {
  712. return single_open(file, pm_stats_show, inode->i_private);
  713. }
  714. static ssize_t pm_stats_clear(struct file *file, const char __user *buf,
  715. size_t count, loff_t *pos)
  716. {
  717. struct adapter *adap = file_inode(file)->i_private;
  718. t4_write_reg(adap, PM_RX_STAT_CONFIG_A, 0);
  719. t4_write_reg(adap, PM_TX_STAT_CONFIG_A, 0);
  720. return count;
  721. }
  722. static const struct file_operations pm_stats_debugfs_fops = {
  723. .owner = THIS_MODULE,
  724. .open = pm_stats_open,
  725. .read = seq_read,
  726. .llseek = seq_lseek,
  727. .release = single_release,
  728. .write = pm_stats_clear
  729. };
  730. static int tx_rate_show(struct seq_file *seq, void *v)
  731. {
  732. u64 nrate[NCHAN], orate[NCHAN];
  733. struct adapter *adap = seq->private;
  734. t4_get_chan_txrate(adap, nrate, orate);
  735. if (adap->params.arch.nchan == NCHAN) {
  736. seq_puts(seq, " channel 0 channel 1 "
  737. "channel 2 channel 3\n");
  738. seq_printf(seq, "NIC B/s: %10llu %10llu %10llu %10llu\n",
  739. (unsigned long long)nrate[0],
  740. (unsigned long long)nrate[1],
  741. (unsigned long long)nrate[2],
  742. (unsigned long long)nrate[3]);
  743. seq_printf(seq, "Offload B/s: %10llu %10llu %10llu %10llu\n",
  744. (unsigned long long)orate[0],
  745. (unsigned long long)orate[1],
  746. (unsigned long long)orate[2],
  747. (unsigned long long)orate[3]);
  748. } else {
  749. seq_puts(seq, " channel 0 channel 1\n");
  750. seq_printf(seq, "NIC B/s: %10llu %10llu\n",
  751. (unsigned long long)nrate[0],
  752. (unsigned long long)nrate[1]);
  753. seq_printf(seq, "Offload B/s: %10llu %10llu\n",
  754. (unsigned long long)orate[0],
  755. (unsigned long long)orate[1]);
  756. }
  757. return 0;
  758. }
  759. DEFINE_SHOW_ATTRIBUTE(tx_rate);
  760. static int cctrl_tbl_show(struct seq_file *seq, void *v)
  761. {
  762. static const char * const dec_fac[] = {
  763. "0.5", "0.5625", "0.625", "0.6875", "0.75", "0.8125", "0.875",
  764. "0.9375" };
  765. int i;
  766. u16 (*incr)[NCCTRL_WIN];
  767. struct adapter *adap = seq->private;
  768. incr = kmalloc_array(NMTUS, sizeof(*incr), GFP_KERNEL);
  769. if (!incr)
  770. return -ENOMEM;
  771. t4_read_cong_tbl(adap, incr);
  772. for (i = 0; i < NCCTRL_WIN; ++i) {
  773. seq_printf(seq, "%2d: %4u %4u %4u %4u %4u %4u %4u %4u\n", i,
  774. incr[0][i], incr[1][i], incr[2][i], incr[3][i],
  775. incr[4][i], incr[5][i], incr[6][i], incr[7][i]);
  776. seq_printf(seq, "%8u %4u %4u %4u %4u %4u %4u %4u %5u %s\n",
  777. incr[8][i], incr[9][i], incr[10][i], incr[11][i],
  778. incr[12][i], incr[13][i], incr[14][i], incr[15][i],
  779. adap->params.a_wnd[i],
  780. dec_fac[adap->params.b_wnd[i]]);
  781. }
  782. kfree(incr);
  783. return 0;
  784. }
  785. DEFINE_SHOW_ATTRIBUTE(cctrl_tbl);
  786. /* Format a value in a unit that differs from the value's native unit by the
  787. * given factor.
  788. */
  789. static char *unit_conv(char *buf, size_t len, unsigned int val,
  790. unsigned int factor)
  791. {
  792. unsigned int rem = val % factor;
  793. if (rem == 0) {
  794. snprintf(buf, len, "%u", val / factor);
  795. } else {
  796. while (rem % 10 == 0)
  797. rem /= 10;
  798. snprintf(buf, len, "%u.%u", val / factor, rem);
  799. }
  800. return buf;
  801. }
  802. static int clk_show(struct seq_file *seq, void *v)
  803. {
  804. char buf[32];
  805. struct adapter *adap = seq->private;
  806. unsigned int cclk_ps = 1000000000 / adap->params.vpd.cclk; /* in ps */
  807. u32 res = t4_read_reg(adap, TP_TIMER_RESOLUTION_A);
  808. unsigned int tre = TIMERRESOLUTION_G(res);
  809. unsigned int dack_re = DELAYEDACKRESOLUTION_G(res);
  810. unsigned long long tp_tick_us = (cclk_ps << tre) / 1000000; /* in us */
  811. seq_printf(seq, "Core clock period: %s ns\n",
  812. unit_conv(buf, sizeof(buf), cclk_ps, 1000));
  813. seq_printf(seq, "TP timer tick: %s us\n",
  814. unit_conv(buf, sizeof(buf), (cclk_ps << tre), 1000000));
  815. seq_printf(seq, "TCP timestamp tick: %s us\n",
  816. unit_conv(buf, sizeof(buf),
  817. (cclk_ps << TIMESTAMPRESOLUTION_G(res)), 1000000));
  818. seq_printf(seq, "DACK tick: %s us\n",
  819. unit_conv(buf, sizeof(buf), (cclk_ps << dack_re), 1000000));
  820. seq_printf(seq, "DACK timer: %u us\n",
  821. ((cclk_ps << dack_re) / 1000000) *
  822. t4_read_reg(adap, TP_DACK_TIMER_A));
  823. seq_printf(seq, "Retransmit min: %llu us\n",
  824. tp_tick_us * t4_read_reg(adap, TP_RXT_MIN_A));
  825. seq_printf(seq, "Retransmit max: %llu us\n",
  826. tp_tick_us * t4_read_reg(adap, TP_RXT_MAX_A));
  827. seq_printf(seq, "Persist timer min: %llu us\n",
  828. tp_tick_us * t4_read_reg(adap, TP_PERS_MIN_A));
  829. seq_printf(seq, "Persist timer max: %llu us\n",
  830. tp_tick_us * t4_read_reg(adap, TP_PERS_MAX_A));
  831. seq_printf(seq, "Keepalive idle timer: %llu us\n",
  832. tp_tick_us * t4_read_reg(adap, TP_KEEP_IDLE_A));
  833. seq_printf(seq, "Keepalive interval: %llu us\n",
  834. tp_tick_us * t4_read_reg(adap, TP_KEEP_INTVL_A));
  835. seq_printf(seq, "Initial SRTT: %llu us\n",
  836. tp_tick_us * INITSRTT_G(t4_read_reg(adap, TP_INIT_SRTT_A)));
  837. seq_printf(seq, "FINWAIT2 timer: %llu us\n",
  838. tp_tick_us * t4_read_reg(adap, TP_FINWAIT2_TIMER_A));
  839. return 0;
  840. }
  841. DEFINE_SHOW_ATTRIBUTE(clk);
  842. /* Firmware Device Log dump. */
  843. static const char * const devlog_level_strings[] = {
  844. [FW_DEVLOG_LEVEL_EMERG] = "EMERG",
  845. [FW_DEVLOG_LEVEL_CRIT] = "CRIT",
  846. [FW_DEVLOG_LEVEL_ERR] = "ERR",
  847. [FW_DEVLOG_LEVEL_NOTICE] = "NOTICE",
  848. [FW_DEVLOG_LEVEL_INFO] = "INFO",
  849. [FW_DEVLOG_LEVEL_DEBUG] = "DEBUG"
  850. };
  851. static const char * const devlog_facility_strings[] = {
  852. [FW_DEVLOG_FACILITY_CORE] = "CORE",
  853. [FW_DEVLOG_FACILITY_CF] = "CF",
  854. [FW_DEVLOG_FACILITY_SCHED] = "SCHED",
  855. [FW_DEVLOG_FACILITY_TIMER] = "TIMER",
  856. [FW_DEVLOG_FACILITY_RES] = "RES",
  857. [FW_DEVLOG_FACILITY_HW] = "HW",
  858. [FW_DEVLOG_FACILITY_FLR] = "FLR",
  859. [FW_DEVLOG_FACILITY_DMAQ] = "DMAQ",
  860. [FW_DEVLOG_FACILITY_PHY] = "PHY",
  861. [FW_DEVLOG_FACILITY_MAC] = "MAC",
  862. [FW_DEVLOG_FACILITY_PORT] = "PORT",
  863. [FW_DEVLOG_FACILITY_VI] = "VI",
  864. [FW_DEVLOG_FACILITY_FILTER] = "FILTER",
  865. [FW_DEVLOG_FACILITY_ACL] = "ACL",
  866. [FW_DEVLOG_FACILITY_TM] = "TM",
  867. [FW_DEVLOG_FACILITY_QFC] = "QFC",
  868. [FW_DEVLOG_FACILITY_DCB] = "DCB",
  869. [FW_DEVLOG_FACILITY_ETH] = "ETH",
  870. [FW_DEVLOG_FACILITY_OFLD] = "OFLD",
  871. [FW_DEVLOG_FACILITY_RI] = "RI",
  872. [FW_DEVLOG_FACILITY_ISCSI] = "ISCSI",
  873. [FW_DEVLOG_FACILITY_FCOE] = "FCOE",
  874. [FW_DEVLOG_FACILITY_FOISCSI] = "FOISCSI",
  875. [FW_DEVLOG_FACILITY_FOFCOE] = "FOFCOE"
  876. };
  877. /* Information gathered by Device Log Open routine for the display routine.
  878. */
  879. struct devlog_info {
  880. unsigned int nentries; /* number of entries in log[] */
  881. unsigned int first; /* first [temporal] entry in log[] */
  882. struct fw_devlog_e log[]; /* Firmware Device Log */
  883. };
  884. /* Dump a Firmaware Device Log entry.
  885. */
  886. static int devlog_show(struct seq_file *seq, void *v)
  887. {
  888. if (v == SEQ_START_TOKEN)
  889. seq_printf(seq, "%10s %15s %8s %8s %s\n",
  890. "Seq#", "Tstamp", "Level", "Facility", "Message");
  891. else {
  892. struct devlog_info *dinfo = seq->private;
  893. int fidx = (uintptr_t)v - 2;
  894. unsigned long index;
  895. struct fw_devlog_e *e;
  896. /* Get a pointer to the log entry to display. Skip unused log
  897. * entries.
  898. */
  899. index = dinfo->first + fidx;
  900. if (index >= dinfo->nentries)
  901. index -= dinfo->nentries;
  902. e = &dinfo->log[index];
  903. if (e->timestamp == 0)
  904. return 0;
  905. /* Print the message. This depends on the firmware using
  906. * exactly the same formating strings as the kernel so we may
  907. * eventually have to put a format interpreter in here ...
  908. */
  909. seq_printf(seq, "%10d %15llu %8s %8s ",
  910. be32_to_cpu(e->seqno),
  911. be64_to_cpu(e->timestamp),
  912. (e->level < ARRAY_SIZE(devlog_level_strings)
  913. ? devlog_level_strings[e->level]
  914. : "UNKNOWN"),
  915. (e->facility < ARRAY_SIZE(devlog_facility_strings)
  916. ? devlog_facility_strings[e->facility]
  917. : "UNKNOWN"));
  918. seq_printf(seq, e->fmt,
  919. be32_to_cpu(e->params[0]),
  920. be32_to_cpu(e->params[1]),
  921. be32_to_cpu(e->params[2]),
  922. be32_to_cpu(e->params[3]),
  923. be32_to_cpu(e->params[4]),
  924. be32_to_cpu(e->params[5]),
  925. be32_to_cpu(e->params[6]),
  926. be32_to_cpu(e->params[7]));
  927. }
  928. return 0;
  929. }
  930. /* Sequential File Operations for Device Log.
  931. */
  932. static inline void *devlog_get_idx(struct devlog_info *dinfo, loff_t pos)
  933. {
  934. if (pos > dinfo->nentries)
  935. return NULL;
  936. return (void *)(uintptr_t)(pos + 1);
  937. }
  938. static void *devlog_start(struct seq_file *seq, loff_t *pos)
  939. {
  940. struct devlog_info *dinfo = seq->private;
  941. return (*pos
  942. ? devlog_get_idx(dinfo, *pos)
  943. : SEQ_START_TOKEN);
  944. }
  945. static void *devlog_next(struct seq_file *seq, void *v, loff_t *pos)
  946. {
  947. struct devlog_info *dinfo = seq->private;
  948. (*pos)++;
  949. return devlog_get_idx(dinfo, *pos);
  950. }
  951. static void devlog_stop(struct seq_file *seq, void *v)
  952. {
  953. }
  954. static const struct seq_operations devlog_seq_ops = {
  955. .start = devlog_start,
  956. .next = devlog_next,
  957. .stop = devlog_stop,
  958. .show = devlog_show
  959. };
  960. /* Set up for reading the firmware's device log. We read the entire log here
  961. * and then display it incrementally in devlog_show().
  962. */
  963. static int devlog_open(struct inode *inode, struct file *file)
  964. {
  965. struct adapter *adap = inode->i_private;
  966. struct devlog_params *dparams = &adap->params.devlog;
  967. struct devlog_info *dinfo;
  968. unsigned int index;
  969. u32 fseqno;
  970. int ret;
  971. /* If we don't know where the log is we can't do anything.
  972. */
  973. if (dparams->start == 0)
  974. return -ENXIO;
  975. /* Allocate the space to read in the firmware's device log and set up
  976. * for the iterated call to our display function.
  977. */
  978. dinfo = __seq_open_private(file, &devlog_seq_ops,
  979. sizeof(*dinfo) + dparams->size);
  980. if (!dinfo)
  981. return -ENOMEM;
  982. /* Record the basic log buffer information and read in the raw log.
  983. */
  984. dinfo->nentries = (dparams->size / sizeof(struct fw_devlog_e));
  985. dinfo->first = 0;
  986. spin_lock(&adap->win0_lock);
  987. ret = t4_memory_rw(adap, adap->params.drv_memwin, dparams->memtype,
  988. dparams->start, dparams->size, (__be32 *)dinfo->log,
  989. T4_MEMORY_READ);
  990. spin_unlock(&adap->win0_lock);
  991. if (ret) {
  992. seq_release_private(inode, file);
  993. return ret;
  994. }
  995. /* Find the earliest (lowest Sequence Number) log entry in the
  996. * circular Device Log.
  997. */
  998. for (fseqno = ~((u32)0), index = 0; index < dinfo->nentries; index++) {
  999. struct fw_devlog_e *e = &dinfo->log[index];
  1000. __u32 seqno;
  1001. if (e->timestamp == 0)
  1002. continue;
  1003. seqno = be32_to_cpu(e->seqno);
  1004. if (seqno < fseqno) {
  1005. fseqno = seqno;
  1006. dinfo->first = index;
  1007. }
  1008. }
  1009. return 0;
  1010. }
  1011. static const struct file_operations devlog_fops = {
  1012. .owner = THIS_MODULE,
  1013. .open = devlog_open,
  1014. .read = seq_read,
  1015. .llseek = seq_lseek,
  1016. .release = seq_release_private
  1017. };
  1018. /* Show Firmware Mailbox Command/Reply Log
  1019. *
  1020. * Note that we don't do any locking when dumping the Firmware Mailbox Log so
  1021. * it's possible that we can catch things during a log update and therefore
  1022. * see partially corrupted log entries. But it's probably Good Enough(tm).
  1023. * If we ever decide that we want to make sure that we're dumping a coherent
  1024. * log, we'd need to perform locking in the mailbox logging and in
  1025. * mboxlog_open() where we'd need to grab the entire mailbox log in one go
  1026. * like we do for the Firmware Device Log.
  1027. */
  1028. static int mboxlog_show(struct seq_file *seq, void *v)
  1029. {
  1030. struct adapter *adapter = seq->private;
  1031. struct mbox_cmd_log *log = adapter->mbox_log;
  1032. struct mbox_cmd *entry;
  1033. int entry_idx, i;
  1034. if (v == SEQ_START_TOKEN) {
  1035. seq_printf(seq,
  1036. "%10s %15s %5s %5s %s\n",
  1037. "Seq#", "Tstamp", "Atime", "Etime",
  1038. "Command/Reply");
  1039. return 0;
  1040. }
  1041. entry_idx = log->cursor + ((uintptr_t)v - 2);
  1042. if (entry_idx >= log->size)
  1043. entry_idx -= log->size;
  1044. entry = mbox_cmd_log_entry(log, entry_idx);
  1045. /* skip over unused entries */
  1046. if (entry->timestamp == 0)
  1047. return 0;
  1048. seq_printf(seq, "%10u %15llu %5d %5d",
  1049. entry->seqno, entry->timestamp,
  1050. entry->access, entry->execute);
  1051. for (i = 0; i < MBOX_LEN / 8; i++) {
  1052. u64 flit = entry->cmd[i];
  1053. u32 hi = (u32)(flit >> 32);
  1054. u32 lo = (u32)flit;
  1055. seq_printf(seq, " %08x %08x", hi, lo);
  1056. }
  1057. seq_puts(seq, "\n");
  1058. return 0;
  1059. }
  1060. static inline void *mboxlog_get_idx(struct seq_file *seq, loff_t pos)
  1061. {
  1062. struct adapter *adapter = seq->private;
  1063. struct mbox_cmd_log *log = adapter->mbox_log;
  1064. return ((pos <= log->size) ? (void *)(uintptr_t)(pos + 1) : NULL);
  1065. }
  1066. static void *mboxlog_start(struct seq_file *seq, loff_t *pos)
  1067. {
  1068. return *pos ? mboxlog_get_idx(seq, *pos) : SEQ_START_TOKEN;
  1069. }
  1070. static void *mboxlog_next(struct seq_file *seq, void *v, loff_t *pos)
  1071. {
  1072. ++*pos;
  1073. return mboxlog_get_idx(seq, *pos);
  1074. }
  1075. static void mboxlog_stop(struct seq_file *seq, void *v)
  1076. {
  1077. }
  1078. static const struct seq_operations mboxlog_seq_ops = {
  1079. .start = mboxlog_start,
  1080. .next = mboxlog_next,
  1081. .stop = mboxlog_stop,
  1082. .show = mboxlog_show
  1083. };
  1084. static int mboxlog_open(struct inode *inode, struct file *file)
  1085. {
  1086. int res = seq_open(file, &mboxlog_seq_ops);
  1087. if (!res) {
  1088. struct seq_file *seq = file->private_data;
  1089. seq->private = inode->i_private;
  1090. }
  1091. return res;
  1092. }
  1093. static const struct file_operations mboxlog_fops = {
  1094. .owner = THIS_MODULE,
  1095. .open = mboxlog_open,
  1096. .read = seq_read,
  1097. .llseek = seq_lseek,
  1098. .release = seq_release,
  1099. };
  1100. static int mbox_show(struct seq_file *seq, void *v)
  1101. {
  1102. static const char * const owner[] = { "none", "FW", "driver",
  1103. "unknown", "<unread>" };
  1104. int i;
  1105. unsigned int mbox = (uintptr_t)seq->private & 7;
  1106. struct adapter *adap = seq->private - mbox;
  1107. void __iomem *addr = adap->regs + PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
  1108. /* For T4 we don't have a shadow copy of the Mailbox Control register.
  1109. * And since reading that real register causes a side effect of
  1110. * granting ownership, we're best of simply not reading it at all.
  1111. */
  1112. if (is_t4(adap->params.chip)) {
  1113. i = 4; /* index of "<unread>" */
  1114. } else {
  1115. unsigned int ctrl_reg = CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A;
  1116. void __iomem *ctrl = adap->regs + PF_REG(mbox, ctrl_reg);
  1117. i = MBOWNER_G(readl(ctrl));
  1118. }
  1119. seq_printf(seq, "mailbox owned by %s\n\n", owner[i]);
  1120. for (i = 0; i < MBOX_LEN; i += 8)
  1121. seq_printf(seq, "%016llx\n",
  1122. (unsigned long long)readq(addr + i));
  1123. return 0;
  1124. }
  1125. static int mbox_open(struct inode *inode, struct file *file)
  1126. {
  1127. return single_open(file, mbox_show, inode->i_private);
  1128. }
  1129. static ssize_t mbox_write(struct file *file, const char __user *buf,
  1130. size_t count, loff_t *pos)
  1131. {
  1132. int i;
  1133. char c = '\n', s[256];
  1134. unsigned long long data[8];
  1135. const struct inode *ino;
  1136. unsigned int mbox;
  1137. struct adapter *adap;
  1138. void __iomem *addr;
  1139. void __iomem *ctrl;
  1140. if (count > sizeof(s) - 1 || !count)
  1141. return -EINVAL;
  1142. if (copy_from_user(s, buf, count))
  1143. return -EFAULT;
  1144. s[count] = '\0';
  1145. if (sscanf(s, "%llx %llx %llx %llx %llx %llx %llx %llx%c", &data[0],
  1146. &data[1], &data[2], &data[3], &data[4], &data[5], &data[6],
  1147. &data[7], &c) < 8 || c != '\n')
  1148. return -EINVAL;
  1149. ino = file_inode(file);
  1150. mbox = (uintptr_t)ino->i_private & 7;
  1151. adap = ino->i_private - mbox;
  1152. addr = adap->regs + PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
  1153. ctrl = addr + MBOX_LEN;
  1154. if (MBOWNER_G(readl(ctrl)) != X_MBOWNER_PL)
  1155. return -EBUSY;
  1156. for (i = 0; i < 8; i++)
  1157. writeq(data[i], addr + 8 * i);
  1158. writel(MBMSGVALID_F | MBOWNER_V(X_MBOWNER_FW), ctrl);
  1159. return count;
  1160. }
  1161. static const struct file_operations mbox_debugfs_fops = {
  1162. .owner = THIS_MODULE,
  1163. .open = mbox_open,
  1164. .read = seq_read,
  1165. .llseek = seq_lseek,
  1166. .release = single_release,
  1167. .write = mbox_write
  1168. };
  1169. static int mps_trc_show(struct seq_file *seq, void *v)
  1170. {
  1171. int enabled, i;
  1172. struct trace_params tp;
  1173. unsigned int trcidx = (uintptr_t)seq->private & 3;
  1174. struct adapter *adap = seq->private - trcidx;
  1175. t4_get_trace_filter(adap, &tp, trcidx, &enabled);
  1176. if (!enabled) {
  1177. seq_puts(seq, "tracer is disabled\n");
  1178. return 0;
  1179. }
  1180. if (tp.skip_ofst * 8 >= TRACE_LEN) {
  1181. dev_err(adap->pdev_dev, "illegal trace pattern skip offset\n");
  1182. return -EINVAL;
  1183. }
  1184. if (tp.port < 8) {
  1185. i = adap->chan_map[tp.port & 3];
  1186. if (i >= MAX_NPORTS) {
  1187. dev_err(adap->pdev_dev, "tracer %u is assigned "
  1188. "to non-existing port\n", trcidx);
  1189. return -EINVAL;
  1190. }
  1191. seq_printf(seq, "tracer is capturing %s %s, ",
  1192. adap->port[i]->name, tp.port < 4 ? "Rx" : "Tx");
  1193. } else
  1194. seq_printf(seq, "tracer is capturing loopback %d, ",
  1195. tp.port - 8);
  1196. seq_printf(seq, "snap length: %u, min length: %u\n", tp.snap_len,
  1197. tp.min_len);
  1198. seq_printf(seq, "packets captured %smatch filter\n",
  1199. tp.invert ? "do not " : "");
  1200. if (tp.skip_ofst) {
  1201. seq_puts(seq, "filter pattern: ");
  1202. for (i = 0; i < tp.skip_ofst * 2; i += 2)
  1203. seq_printf(seq, "%08x%08x", tp.data[i], tp.data[i + 1]);
  1204. seq_putc(seq, '/');
  1205. for (i = 0; i < tp.skip_ofst * 2; i += 2)
  1206. seq_printf(seq, "%08x%08x", tp.mask[i], tp.mask[i + 1]);
  1207. seq_puts(seq, "@0\n");
  1208. }
  1209. seq_puts(seq, "filter pattern: ");
  1210. for (i = tp.skip_ofst * 2; i < TRACE_LEN / 4; i += 2)
  1211. seq_printf(seq, "%08x%08x", tp.data[i], tp.data[i + 1]);
  1212. seq_putc(seq, '/');
  1213. for (i = tp.skip_ofst * 2; i < TRACE_LEN / 4; i += 2)
  1214. seq_printf(seq, "%08x%08x", tp.mask[i], tp.mask[i + 1]);
  1215. seq_printf(seq, "@%u\n", (tp.skip_ofst + tp.skip_len) * 8);
  1216. return 0;
  1217. }
  1218. static int mps_trc_open(struct inode *inode, struct file *file)
  1219. {
  1220. return single_open(file, mps_trc_show, inode->i_private);
  1221. }
  1222. static unsigned int xdigit2int(unsigned char c)
  1223. {
  1224. return isdigit(c) ? c - '0' : tolower(c) - 'a' + 10;
  1225. }
  1226. #define TRC_PORT_NONE 0xff
  1227. #define TRC_RSS_ENABLE 0x33
  1228. #define TRC_RSS_DISABLE 0x13
  1229. /* Set an MPS trace filter. Syntax is:
  1230. *
  1231. * disable
  1232. *
  1233. * to disable tracing, or
  1234. *
  1235. * interface qid=<qid no> [snaplen=<val>] [minlen=<val>] [not] [<pattern>]...
  1236. *
  1237. * where interface is one of rxN, txN, or loopbackN, N = 0..3, qid can be one
  1238. * of the NIC's response qid obtained from sge_qinfo and pattern has the form
  1239. *
  1240. * <pattern data>[/<pattern mask>][@<anchor>]
  1241. *
  1242. * Up to 2 filter patterns can be specified. If 2 are supplied the first one
  1243. * must be anchored at 0. An omitted mask is taken as a mask of 1s, an omitted
  1244. * anchor is taken as 0.
  1245. */
  1246. static ssize_t mps_trc_write(struct file *file, const char __user *buf,
  1247. size_t count, loff_t *pos)
  1248. {
  1249. int i, enable, ret;
  1250. u32 *data, *mask;
  1251. struct trace_params tp;
  1252. const struct inode *ino;
  1253. unsigned int trcidx;
  1254. char *s, *p, *word, *end;
  1255. struct adapter *adap;
  1256. u32 j;
  1257. ino = file_inode(file);
  1258. trcidx = (uintptr_t)ino->i_private & 3;
  1259. adap = ino->i_private - trcidx;
  1260. /* Don't accept input more than 1K, can't be anything valid except lots
  1261. * of whitespace. Well, use less.
  1262. */
  1263. if (count > 1024)
  1264. return -EFBIG;
  1265. p = s = kzalloc(count + 1, GFP_USER);
  1266. if (!s)
  1267. return -ENOMEM;
  1268. if (copy_from_user(s, buf, count)) {
  1269. count = -EFAULT;
  1270. goto out;
  1271. }
  1272. if (s[count - 1] == '\n')
  1273. s[count - 1] = '\0';
  1274. enable = strcmp("disable", s) != 0;
  1275. if (!enable)
  1276. goto apply;
  1277. /* enable or disable trace multi rss filter */
  1278. if (adap->trace_rss)
  1279. t4_write_reg(adap, MPS_TRC_CFG_A, TRC_RSS_ENABLE);
  1280. else
  1281. t4_write_reg(adap, MPS_TRC_CFG_A, TRC_RSS_DISABLE);
  1282. memset(&tp, 0, sizeof(tp));
  1283. tp.port = TRC_PORT_NONE;
  1284. i = 0; /* counts pattern nibbles */
  1285. while (p) {
  1286. while (isspace(*p))
  1287. p++;
  1288. word = strsep(&p, " ");
  1289. if (!*word)
  1290. break;
  1291. if (!strncmp(word, "qid=", 4)) {
  1292. end = (char *)word + 4;
  1293. ret = kstrtouint(end, 10, &j);
  1294. if (ret)
  1295. goto out;
  1296. if (!adap->trace_rss) {
  1297. t4_write_reg(adap, MPS_T5_TRC_RSS_CONTROL_A, j);
  1298. continue;
  1299. }
  1300. switch (trcidx) {
  1301. case 0:
  1302. t4_write_reg(adap, MPS_TRC_RSS_CONTROL_A, j);
  1303. break;
  1304. case 1:
  1305. t4_write_reg(adap,
  1306. MPS_TRC_FILTER1_RSS_CONTROL_A, j);
  1307. break;
  1308. case 2:
  1309. t4_write_reg(adap,
  1310. MPS_TRC_FILTER2_RSS_CONTROL_A, j);
  1311. break;
  1312. case 3:
  1313. t4_write_reg(adap,
  1314. MPS_TRC_FILTER3_RSS_CONTROL_A, j);
  1315. break;
  1316. }
  1317. continue;
  1318. }
  1319. if (!strncmp(word, "snaplen=", 8)) {
  1320. end = (char *)word + 8;
  1321. ret = kstrtouint(end, 10, &j);
  1322. if (ret || j > 9600) {
  1323. inval: count = -EINVAL;
  1324. goto out;
  1325. }
  1326. tp.snap_len = j;
  1327. continue;
  1328. }
  1329. if (!strncmp(word, "minlen=", 7)) {
  1330. end = (char *)word + 7;
  1331. ret = kstrtouint(end, 10, &j);
  1332. if (ret || j > TFMINPKTSIZE_M)
  1333. goto inval;
  1334. tp.min_len = j;
  1335. continue;
  1336. }
  1337. if (!strcmp(word, "not")) {
  1338. tp.invert = !tp.invert;
  1339. continue;
  1340. }
  1341. if (!strncmp(word, "loopback", 8) && tp.port == TRC_PORT_NONE) {
  1342. if (word[8] < '0' || word[8] > '3' || word[9])
  1343. goto inval;
  1344. tp.port = word[8] - '0' + 8;
  1345. continue;
  1346. }
  1347. if (!strncmp(word, "tx", 2) && tp.port == TRC_PORT_NONE) {
  1348. if (word[2] < '0' || word[2] > '3' || word[3])
  1349. goto inval;
  1350. tp.port = word[2] - '0' + 4;
  1351. if (adap->chan_map[tp.port & 3] >= MAX_NPORTS)
  1352. goto inval;
  1353. continue;
  1354. }
  1355. if (!strncmp(word, "rx", 2) && tp.port == TRC_PORT_NONE) {
  1356. if (word[2] < '0' || word[2] > '3' || word[3])
  1357. goto inval;
  1358. tp.port = word[2] - '0';
  1359. if (adap->chan_map[tp.port] >= MAX_NPORTS)
  1360. goto inval;
  1361. continue;
  1362. }
  1363. if (!isxdigit(*word))
  1364. goto inval;
  1365. /* we have found a trace pattern */
  1366. if (i) { /* split pattern */
  1367. if (tp.skip_len) /* too many splits */
  1368. goto inval;
  1369. tp.skip_ofst = i / 16;
  1370. }
  1371. data = &tp.data[i / 8];
  1372. mask = &tp.mask[i / 8];
  1373. j = i;
  1374. while (isxdigit(*word)) {
  1375. if (i >= TRACE_LEN * 2) {
  1376. count = -EFBIG;
  1377. goto out;
  1378. }
  1379. *data = (*data << 4) + xdigit2int(*word++);
  1380. if (++i % 8 == 0)
  1381. data++;
  1382. }
  1383. if (*word == '/') {
  1384. word++;
  1385. while (isxdigit(*word)) {
  1386. if (j >= i) /* mask longer than data */
  1387. goto inval;
  1388. *mask = (*mask << 4) + xdigit2int(*word++);
  1389. if (++j % 8 == 0)
  1390. mask++;
  1391. }
  1392. if (i != j) /* mask shorter than data */
  1393. goto inval;
  1394. } else { /* no mask, use all 1s */
  1395. for ( ; i - j >= 8; j += 8)
  1396. *mask++ = 0xffffffff;
  1397. if (i % 8)
  1398. *mask = (1 << (i % 8) * 4) - 1;
  1399. }
  1400. if (*word == '@') {
  1401. end = (char *)word + 1;
  1402. ret = kstrtouint(end, 10, &j);
  1403. if (*end && *end != '\n')
  1404. goto inval;
  1405. if (j & 7) /* doesn't start at multiple of 8 */
  1406. goto inval;
  1407. j /= 8;
  1408. if (j < tp.skip_ofst) /* overlaps earlier pattern */
  1409. goto inval;
  1410. if (j - tp.skip_ofst > 31) /* skip too big */
  1411. goto inval;
  1412. tp.skip_len = j - tp.skip_ofst;
  1413. }
  1414. if (i % 8) {
  1415. *data <<= (8 - i % 8) * 4;
  1416. *mask <<= (8 - i % 8) * 4;
  1417. i = (i + 15) & ~15; /* 8-byte align */
  1418. }
  1419. }
  1420. if (tp.port == TRC_PORT_NONE)
  1421. goto inval;
  1422. apply:
  1423. i = t4_set_trace_filter(adap, &tp, trcidx, enable);
  1424. if (i)
  1425. count = i;
  1426. out:
  1427. kfree(s);
  1428. return count;
  1429. }
  1430. static const struct file_operations mps_trc_debugfs_fops = {
  1431. .owner = THIS_MODULE,
  1432. .open = mps_trc_open,
  1433. .read = seq_read,
  1434. .llseek = seq_lseek,
  1435. .release = single_release,
  1436. .write = mps_trc_write
  1437. };
  1438. static ssize_t flash_read(struct file *file, char __user *buf, size_t count,
  1439. loff_t *ppos)
  1440. {
  1441. loff_t pos = *ppos;
  1442. loff_t avail = file_inode(file)->i_size;
  1443. struct adapter *adap = file->private_data;
  1444. if (pos < 0)
  1445. return -EINVAL;
  1446. if (pos >= avail)
  1447. return 0;
  1448. if (count > avail - pos)
  1449. count = avail - pos;
  1450. while (count) {
  1451. size_t len;
  1452. int ret, ofst;
  1453. u8 data[256];
  1454. ofst = pos & 3;
  1455. len = min(count + ofst, sizeof(data));
  1456. ret = t4_read_flash(adap, pos - ofst, (len + 3) / 4,
  1457. (u32 *)data, 1);
  1458. if (ret)
  1459. return ret;
  1460. len -= ofst;
  1461. if (copy_to_user(buf, data + ofst, len))
  1462. return -EFAULT;
  1463. buf += len;
  1464. pos += len;
  1465. count -= len;
  1466. }
  1467. count = pos - *ppos;
  1468. *ppos = pos;
  1469. return count;
  1470. }
  1471. static const struct file_operations flash_debugfs_fops = {
  1472. .owner = THIS_MODULE,
  1473. .open = mem_open,
  1474. .read = flash_read,
  1475. .llseek = default_llseek,
  1476. };
  1477. static inline void tcamxy2valmask(u64 x, u64 y, u8 *addr, u64 *mask)
  1478. {
  1479. *mask = x | y;
  1480. y = (__force u64)cpu_to_be64(y);
  1481. memcpy(addr, (char *)&y + 2, ETH_ALEN);
  1482. }
  1483. static int mps_tcam_show(struct seq_file *seq, void *v)
  1484. {
  1485. struct adapter *adap = seq->private;
  1486. unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip);
  1487. if (v == SEQ_START_TOKEN) {
  1488. if (chip_ver > CHELSIO_T5) {
  1489. seq_puts(seq, "Idx Ethernet address Mask "
  1490. " VNI Mask IVLAN Vld "
  1491. "DIP_Hit Lookup Port "
  1492. "Vld Ports PF VF "
  1493. "Replication "
  1494. " P0 P1 P2 P3 ML\n");
  1495. } else {
  1496. if (adap->params.arch.mps_rplc_size > 128)
  1497. seq_puts(seq, "Idx Ethernet address Mask "
  1498. "Vld Ports PF VF "
  1499. "Replication "
  1500. " P0 P1 P2 P3 ML\n");
  1501. else
  1502. seq_puts(seq, "Idx Ethernet address Mask "
  1503. "Vld Ports PF VF Replication"
  1504. " P0 P1 P2 P3 ML\n");
  1505. }
  1506. } else {
  1507. u64 mask;
  1508. u8 addr[ETH_ALEN];
  1509. bool replicate, dip_hit = false, vlan_vld = false;
  1510. unsigned int idx = (uintptr_t)v - 2;
  1511. u64 tcamy, tcamx, val;
  1512. u32 cls_lo, cls_hi, ctl, data2, vnix = 0, vniy = 0;
  1513. u32 rplc[8] = {0};
  1514. u8 lookup_type = 0, port_num = 0;
  1515. u16 ivlan = 0;
  1516. if (chip_ver > CHELSIO_T5) {
  1517. /* CtlCmdType - 0: Read, 1: Write
  1518. * CtlTcamSel - 0: TCAM0, 1: TCAM1
  1519. * CtlXYBitSel- 0: Y bit, 1: X bit
  1520. */
  1521. /* Read tcamy */
  1522. ctl = CTLCMDTYPE_V(0) | CTLXYBITSEL_V(0);
  1523. if (idx < 256)
  1524. ctl |= CTLTCAMINDEX_V(idx) | CTLTCAMSEL_V(0);
  1525. else
  1526. ctl |= CTLTCAMINDEX_V(idx - 256) |
  1527. CTLTCAMSEL_V(1);
  1528. t4_write_reg(adap, MPS_CLS_TCAM_DATA2_CTL_A, ctl);
  1529. val = t4_read_reg(adap, MPS_CLS_TCAM_DATA1_A);
  1530. tcamy = DMACH_G(val) << 32;
  1531. tcamy |= t4_read_reg(adap, MPS_CLS_TCAM_DATA0_A);
  1532. data2 = t4_read_reg(adap, MPS_CLS_TCAM_DATA2_CTL_A);
  1533. lookup_type = DATALKPTYPE_G(data2);
  1534. /* 0 - Outer header, 1 - Inner header
  1535. * [71:48] bit locations are overloaded for
  1536. * outer vs. inner lookup types.
  1537. */
  1538. if (lookup_type && (lookup_type != DATALKPTYPE_M)) {
  1539. /* Inner header VNI */
  1540. vniy = (data2 & DATAVIDH2_F) |
  1541. (DATAVIDH1_G(data2) << 16) | VIDL_G(val);
  1542. dip_hit = data2 & DATADIPHIT_F;
  1543. } else {
  1544. vlan_vld = data2 & DATAVIDH2_F;
  1545. ivlan = VIDL_G(val);
  1546. }
  1547. port_num = DATAPORTNUM_G(data2);
  1548. /* Read tcamx. Change the control param */
  1549. vnix = 0;
  1550. ctl |= CTLXYBITSEL_V(1);
  1551. t4_write_reg(adap, MPS_CLS_TCAM_DATA2_CTL_A, ctl);
  1552. val = t4_read_reg(adap, MPS_CLS_TCAM_DATA1_A);
  1553. tcamx = DMACH_G(val) << 32;
  1554. tcamx |= t4_read_reg(adap, MPS_CLS_TCAM_DATA0_A);
  1555. data2 = t4_read_reg(adap, MPS_CLS_TCAM_DATA2_CTL_A);
  1556. if (lookup_type && (lookup_type != DATALKPTYPE_M)) {
  1557. /* Inner header VNI mask */
  1558. vnix = (data2 & DATAVIDH2_F) |
  1559. (DATAVIDH1_G(data2) << 16) | VIDL_G(val);
  1560. }
  1561. } else {
  1562. tcamy = t4_read_reg64(adap, MPS_CLS_TCAM_Y_L(idx));
  1563. tcamx = t4_read_reg64(adap, MPS_CLS_TCAM_X_L(idx));
  1564. }
  1565. cls_lo = t4_read_reg(adap, MPS_CLS_SRAM_L(idx));
  1566. cls_hi = t4_read_reg(adap, MPS_CLS_SRAM_H(idx));
  1567. if (tcamx & tcamy) {
  1568. seq_printf(seq, "%3u -\n", idx);
  1569. goto out;
  1570. }
  1571. rplc[0] = rplc[1] = rplc[2] = rplc[3] = 0;
  1572. if (chip_ver > CHELSIO_T5)
  1573. replicate = (cls_lo & T6_REPLICATE_F);
  1574. else
  1575. replicate = (cls_lo & REPLICATE_F);
  1576. if (replicate) {
  1577. struct fw_ldst_cmd ldst_cmd;
  1578. int ret;
  1579. struct fw_ldst_mps_rplc mps_rplc;
  1580. u32 ldst_addrspc;
  1581. memset(&ldst_cmd, 0, sizeof(ldst_cmd));
  1582. ldst_addrspc =
  1583. FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_MPS);
  1584. ldst_cmd.op_to_addrspace =
  1585. htonl(FW_CMD_OP_V(FW_LDST_CMD) |
  1586. FW_CMD_REQUEST_F |
  1587. FW_CMD_READ_F |
  1588. ldst_addrspc);
  1589. ldst_cmd.cycles_to_len16 = htonl(FW_LEN16(ldst_cmd));
  1590. ldst_cmd.u.mps.rplc.fid_idx =
  1591. htons(FW_LDST_CMD_FID_V(FW_LDST_MPS_RPLC) |
  1592. FW_LDST_CMD_IDX_V(idx));
  1593. ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd,
  1594. sizeof(ldst_cmd), &ldst_cmd);
  1595. if (ret)
  1596. dev_warn(adap->pdev_dev, "Can't read MPS "
  1597. "replication map for idx %d: %d\n",
  1598. idx, -ret);
  1599. else {
  1600. mps_rplc = ldst_cmd.u.mps.rplc;
  1601. rplc[0] = ntohl(mps_rplc.rplc31_0);
  1602. rplc[1] = ntohl(mps_rplc.rplc63_32);
  1603. rplc[2] = ntohl(mps_rplc.rplc95_64);
  1604. rplc[3] = ntohl(mps_rplc.rplc127_96);
  1605. if (adap->params.arch.mps_rplc_size > 128) {
  1606. rplc[4] = ntohl(mps_rplc.rplc159_128);
  1607. rplc[5] = ntohl(mps_rplc.rplc191_160);
  1608. rplc[6] = ntohl(mps_rplc.rplc223_192);
  1609. rplc[7] = ntohl(mps_rplc.rplc255_224);
  1610. }
  1611. }
  1612. }
  1613. tcamxy2valmask(tcamx, tcamy, addr, &mask);
  1614. if (chip_ver > CHELSIO_T5) {
  1615. /* Inner header lookup */
  1616. if (lookup_type && (lookup_type != DATALKPTYPE_M)) {
  1617. seq_printf(seq,
  1618. "%3u %02x:%02x:%02x:%02x:%02x:%02x "
  1619. "%012llx %06x %06x - - %3c"
  1620. " 'I' %4x "
  1621. "%3c %#x%4u%4d", idx, addr[0],
  1622. addr[1], addr[2], addr[3],
  1623. addr[4], addr[5],
  1624. (unsigned long long)mask,
  1625. vniy, (vnix | vniy),
  1626. dip_hit ? 'Y' : 'N',
  1627. port_num,
  1628. (cls_lo & T6_SRAM_VLD_F) ? 'Y' : 'N',
  1629. PORTMAP_G(cls_hi),
  1630. T6_PF_G(cls_lo),
  1631. (cls_lo & T6_VF_VALID_F) ?
  1632. T6_VF_G(cls_lo) : -1);
  1633. } else {
  1634. seq_printf(seq,
  1635. "%3u %02x:%02x:%02x:%02x:%02x:%02x "
  1636. "%012llx - - ",
  1637. idx, addr[0], addr[1], addr[2],
  1638. addr[3], addr[4], addr[5],
  1639. (unsigned long long)mask);
  1640. if (vlan_vld)
  1641. seq_printf(seq, "%4u Y ", ivlan);
  1642. else
  1643. seq_puts(seq, " - N ");
  1644. seq_printf(seq,
  1645. "- %3c %4x %3c %#x%4u%4d",
  1646. lookup_type ? 'I' : 'O', port_num,
  1647. (cls_lo & T6_SRAM_VLD_F) ? 'Y' :

Large files files are truncated, but you can click here to view the full file