ipath_diag.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /*
  2. * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.
  3. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  4. *
  5. * This software is available to you under a choice of one of two
  6. * licenses. You may choose to be licensed under the terms of the GNU
  7. * General Public License (GPL) Version 2, available from the file
  8. * COPYING in the main directory of this source tree, or the
  9. * OpenIB.org BSD license below:
  10. *
  11. * Redistribution and use in source and binary forms, with or
  12. * without modification, are permitted provided that the following
  13. * conditions are met:
  14. *
  15. * - Redistributions of source code must retain the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials
  22. * provided with the distribution.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31. * SOFTWARE.
  32. */
  33. /*
  34. * This file contains support for diagnostic functions. It is accessed by
  35. * opening the ipath_diag device, normally minor number 129. Diagnostic use
  36. * of the InfiniPath chip may render the chip or board unusable until the
  37. * driver is unloaded, or in some cases, until the system is rebooted.
  38. *
  39. * Accesses to the chip through this interface are not similar to going
  40. * through the /sys/bus/pci resource mmap interface.
  41. */
  42. #include <linux/io.h>
  43. #include <linux/pci.h>
  44. #include <linux/vmalloc.h>
  45. #include <linux/fs.h>
  46. #include <asm/uaccess.h>
  47. #include "ipath_kernel.h"
  48. #include "ipath_common.h"
  49. int ipath_diag_inuse;
  50. static int diag_set_link;
  51. static int ipath_diag_open(struct inode *in, struct file *fp);
  52. static int ipath_diag_release(struct inode *in, struct file *fp);
  53. static ssize_t ipath_diag_read(struct file *fp, char __user *data,
  54. size_t count, loff_t *off);
  55. static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
  56. size_t count, loff_t *off);
  57. static const struct file_operations diag_file_ops = {
  58. .owner = THIS_MODULE,
  59. .write = ipath_diag_write,
  60. .read = ipath_diag_read,
  61. .open = ipath_diag_open,
  62. .release = ipath_diag_release,
  63. .llseek = default_llseek,
  64. };
  65. static ssize_t ipath_diagpkt_write(struct file *fp,
  66. const char __user *data,
  67. size_t count, loff_t *off);
  68. static const struct file_operations diagpkt_file_ops = {
  69. .owner = THIS_MODULE,
  70. .write = ipath_diagpkt_write,
  71. .llseek = noop_llseek,
  72. };
  73. static atomic_t diagpkt_count = ATOMIC_INIT(0);
  74. static struct cdev *diagpkt_cdev;
  75. static struct device *diagpkt_dev;
  76. int ipath_diag_add(struct ipath_devdata *dd)
  77. {
  78. char name[16];
  79. int ret = 0;
  80. if (atomic_inc_return(&diagpkt_count) == 1) {
  81. ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR,
  82. "ipath_diagpkt", &diagpkt_file_ops,
  83. &diagpkt_cdev, &diagpkt_dev);
  84. if (ret) {
  85. ipath_dev_err(dd, "Couldn't create ipath_diagpkt "
  86. "device: %d", ret);
  87. goto done;
  88. }
  89. }
  90. snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit);
  91. ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name,
  92. &diag_file_ops, &dd->diag_cdev,
  93. &dd->diag_dev);
  94. if (ret)
  95. ipath_dev_err(dd, "Couldn't create %s device: %d",
  96. name, ret);
  97. done:
  98. return ret;
  99. }
  100. void ipath_diag_remove(struct ipath_devdata *dd)
  101. {
  102. if (atomic_dec_and_test(&diagpkt_count))
  103. ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_dev);
  104. ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_dev);
  105. }
  106. /**
  107. * ipath_read_umem64 - read a 64-bit quantity from the chip into user space
  108. * @dd: the infinipath device
  109. * @uaddr: the location to store the data in user memory
  110. * @caddr: the source chip address (full pointer, not offset)
  111. * @count: number of bytes to copy (multiple of 32 bits)
  112. *
  113. * This function also localizes all chip memory accesses.
  114. * The copy should be written such that we read full cacheline packets
  115. * from the chip. This is usually used for a single qword
  116. *
  117. * NOTE: This assumes the chip address is 64-bit aligned.
  118. */
  119. static int ipath_read_umem64(struct ipath_devdata *dd, void __user *uaddr,
  120. const void __iomem *caddr, size_t count)
  121. {
  122. const u64 __iomem *reg_addr = caddr;
  123. const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64));
  124. int ret;
  125. /* not very efficient, but it works for now */
  126. if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) {
  127. ret = -EINVAL;
  128. goto bail;
  129. }
  130. while (reg_addr < reg_end) {
  131. u64 data = readq(reg_addr);
  132. if (copy_to_user(uaddr, &data, sizeof(u64))) {
  133. ret = -EFAULT;
  134. goto bail;
  135. }
  136. reg_addr++;
  137. uaddr += sizeof(u64);
  138. }
  139. ret = 0;
  140. bail:
  141. return ret;
  142. }
  143. /**
  144. * ipath_write_umem64 - write a 64-bit quantity to the chip from user space
  145. * @dd: the infinipath device
  146. * @caddr: the destination chip address (full pointer, not offset)
  147. * @uaddr: the source of the data in user memory
  148. * @count: the number of bytes to copy (multiple of 32 bits)
  149. *
  150. * This is usually used for a single qword
  151. * NOTE: This assumes the chip address is 64-bit aligned.
  152. */
  153. static int ipath_write_umem64(struct ipath_devdata *dd, void __iomem *caddr,
  154. const void __user *uaddr, size_t count)
  155. {
  156. u64 __iomem *reg_addr = caddr;
  157. const u64 __iomem *reg_end = reg_addr + (count / sizeof(u64));
  158. int ret;
  159. /* not very efficient, but it works for now */
  160. if (reg_addr < dd->ipath_kregbase || reg_end > dd->ipath_kregend) {
  161. ret = -EINVAL;
  162. goto bail;
  163. }
  164. while (reg_addr < reg_end) {
  165. u64 data;
  166. if (copy_from_user(&data, uaddr, sizeof(data))) {
  167. ret = -EFAULT;
  168. goto bail;
  169. }
  170. writeq(data, reg_addr);
  171. reg_addr++;
  172. uaddr += sizeof(u64);
  173. }
  174. ret = 0;
  175. bail:
  176. return ret;
  177. }
  178. /**
  179. * ipath_read_umem32 - read a 32-bit quantity from the chip into user space
  180. * @dd: the infinipath device
  181. * @uaddr: the location to store the data in user memory
  182. * @caddr: the source chip address (full pointer, not offset)
  183. * @count: number of bytes to copy
  184. *
  185. * read 32 bit values, not 64 bit; for memories that only
  186. * support 32 bit reads; usually a single dword.
  187. */
  188. static int ipath_read_umem32(struct ipath_devdata *dd, void __user *uaddr,
  189. const void __iomem *caddr, size_t count)
  190. {
  191. const u32 __iomem *reg_addr = caddr;
  192. const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32));
  193. int ret;
  194. if (reg_addr < (u32 __iomem *) dd->ipath_kregbase ||
  195. reg_end > (u32 __iomem *) dd->ipath_kregend) {
  196. ret = -EINVAL;
  197. goto bail;
  198. }
  199. /* not very efficient, but it works for now */
  200. while (reg_addr < reg_end) {
  201. u32 data = readl(reg_addr);
  202. if (copy_to_user(uaddr, &data, sizeof(data))) {
  203. ret = -EFAULT;
  204. goto bail;
  205. }
  206. reg_addr++;
  207. uaddr += sizeof(u32);
  208. }
  209. ret = 0;
  210. bail:
  211. return ret;
  212. }
  213. /**
  214. * ipath_write_umem32 - write a 32-bit quantity to the chip from user space
  215. * @dd: the infinipath device
  216. * @caddr: the destination chip address (full pointer, not offset)
  217. * @uaddr: the source of the data in user memory
  218. * @count: number of bytes to copy
  219. *
  220. * write 32 bit values, not 64 bit; for memories that only
  221. * support 32 bit write; usually a single dword.
  222. */
  223. static int ipath_write_umem32(struct ipath_devdata *dd, void __iomem *caddr,
  224. const void __user *uaddr, size_t count)
  225. {
  226. u32 __iomem *reg_addr = caddr;
  227. const u32 __iomem *reg_end = reg_addr + (count / sizeof(u32));
  228. int ret;
  229. if (reg_addr < (u32 __iomem *) dd->ipath_kregbase ||
  230. reg_end > (u32 __iomem *) dd->ipath_kregend) {
  231. ret = -EINVAL;
  232. goto bail;
  233. }
  234. while (reg_addr < reg_end) {
  235. u32 data;
  236. if (copy_from_user(&data, uaddr, sizeof(data))) {
  237. ret = -EFAULT;
  238. goto bail;
  239. }
  240. writel(data, reg_addr);
  241. reg_addr++;
  242. uaddr += sizeof(u32);
  243. }
  244. ret = 0;
  245. bail:
  246. return ret;
  247. }
  248. static int ipath_diag_open(struct inode *in, struct file *fp)
  249. {
  250. int unit = iminor(in) - IPATH_DIAG_MINOR_BASE;
  251. struct ipath_devdata *dd;
  252. int ret;
  253. mutex_lock(&ipath_mutex);
  254. if (ipath_diag_inuse) {
  255. ret = -EBUSY;
  256. goto bail;
  257. }
  258. dd = ipath_lookup(unit);
  259. if (dd == NULL || !(dd->ipath_flags & IPATH_PRESENT) ||
  260. !dd->ipath_kregbase) {
  261. ret = -ENODEV;
  262. goto bail;
  263. }
  264. fp->private_data = dd;
  265. ipath_diag_inuse = -2;
  266. diag_set_link = 0;
  267. ret = 0;
  268. /* Only expose a way to reset the device if we
  269. make it into diag mode. */
  270. ipath_expose_reset(&dd->pcidev->dev);
  271. bail:
  272. mutex_unlock(&ipath_mutex);
  273. return ret;
  274. }
  275. /**
  276. * ipath_diagpkt_write - write an IB packet
  277. * @fp: the diag data device file pointer
  278. * @data: ipath_diag_pkt structure saying where to get the packet
  279. * @count: size of data to write
  280. * @off: unused by this code
  281. */
  282. static ssize_t ipath_diagpkt_write(struct file *fp,
  283. const char __user *data,
  284. size_t count, loff_t *off)
  285. {
  286. u32 __iomem *piobuf;
  287. u32 plen, clen, pbufn;
  288. struct ipath_diag_pkt odp;
  289. struct ipath_diag_xpkt dp;
  290. u32 *tmpbuf = NULL;
  291. struct ipath_devdata *dd;
  292. ssize_t ret = 0;
  293. u64 val;
  294. u32 l_state, lt_state; /* LinkState, LinkTrainingState */
  295. if (count < sizeof(odp)) {
  296. ret = -EINVAL;
  297. goto bail;
  298. }
  299. if (count == sizeof(dp)) {
  300. if (copy_from_user(&dp, data, sizeof(dp))) {
  301. ret = -EFAULT;
  302. goto bail;
  303. }
  304. } else if (copy_from_user(&odp, data, sizeof(odp))) {
  305. ret = -EFAULT;
  306. goto bail;
  307. }
  308. /*
  309. * Due to padding/alignment issues (lessened with new struct)
  310. * the old and new structs are the same length. We need to
  311. * disambiguate them, which we can do because odp.len has never
  312. * been less than the total of LRH+BTH+DETH so far, while
  313. * dp.unit (same offset) unit is unlikely to get that high.
  314. * Similarly, dp.data, the pointer to user at the same offset
  315. * as odp.unit, is almost certainly at least one (512byte)page
  316. * "above" NULL. The if-block below can be omitted if compatibility
  317. * between a new driver and older diagnostic code is unimportant.
  318. * compatibility the other direction (new diags, old driver) is
  319. * handled in the diagnostic code, with a warning.
  320. */
  321. if (dp.unit >= 20 && dp.data < 512) {
  322. /* very probable version mismatch. Fix it up */
  323. memcpy(&odp, &dp, sizeof(odp));
  324. /* We got a legacy dp, copy elements to dp */
  325. dp.unit = odp.unit;
  326. dp.data = odp.data;
  327. dp.len = odp.len;
  328. dp.pbc_wd = 0; /* Indicate we need to compute PBC wd */
  329. }
  330. /* send count must be an exact number of dwords */
  331. if (dp.len & 3) {
  332. ret = -EINVAL;
  333. goto bail;
  334. }
  335. clen = dp.len >> 2;
  336. dd = ipath_lookup(dp.unit);
  337. if (!dd || !(dd->ipath_flags & IPATH_PRESENT) ||
  338. !dd->ipath_kregbase) {
  339. ipath_cdbg(VERBOSE, "illegal unit %u for diag data send\n",
  340. dp.unit);
  341. ret = -ENODEV;
  342. goto bail;
  343. }
  344. if (ipath_diag_inuse && !diag_set_link &&
  345. !(dd->ipath_flags & IPATH_LINKACTIVE)) {
  346. diag_set_link = 1;
  347. ipath_cdbg(VERBOSE, "Trying to set to set link active for "
  348. "diag pkt\n");
  349. ipath_set_linkstate(dd, IPATH_IB_LINKARM);
  350. ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE);
  351. }
  352. if (!(dd->ipath_flags & IPATH_INITTED)) {
  353. /* no hardware, freeze, etc. */
  354. ipath_cdbg(VERBOSE, "unit %u not usable\n", dd->ipath_unit);
  355. ret = -ENODEV;
  356. goto bail;
  357. }
  358. /*
  359. * Want to skip check for l_state if using custom PBC,
  360. * because we might be trying to force an SM packet out.
  361. * first-cut, skip _all_ state checking in that case.
  362. */
  363. val = ipath_ib_state(dd, dd->ipath_lastibcstat);
  364. lt_state = ipath_ib_linktrstate(dd, dd->ipath_lastibcstat);
  365. l_state = ipath_ib_linkstate(dd, dd->ipath_lastibcstat);
  366. if (!dp.pbc_wd && (lt_state != INFINIPATH_IBCS_LT_STATE_LINKUP ||
  367. (val != dd->ib_init && val != dd->ib_arm &&
  368. val != dd->ib_active))) {
  369. ipath_cdbg(VERBOSE, "unit %u not ready (state %llx)\n",
  370. dd->ipath_unit, (unsigned long long) val);
  371. ret = -EINVAL;
  372. goto bail;
  373. }
  374. /* need total length before first word written */
  375. /* +1 word is for the qword padding */
  376. plen = sizeof(u32) + dp.len;
  377. if ((plen + 4) > dd->ipath_ibmaxlen) {
  378. ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n",
  379. plen - 4, dd->ipath_ibmaxlen);
  380. ret = -EINVAL;
  381. goto bail; /* before writing pbc */
  382. }
  383. tmpbuf = vmalloc(plen);
  384. if (!tmpbuf) {
  385. dev_info(&dd->pcidev->dev, "Unable to allocate tmp buffer, "
  386. "failing\n");
  387. ret = -ENOMEM;
  388. goto bail;
  389. }
  390. if (copy_from_user(tmpbuf,
  391. (const void __user *) (unsigned long) dp.data,
  392. dp.len)) {
  393. ret = -EFAULT;
  394. goto bail;
  395. }
  396. plen >>= 2; /* in dwords */
  397. piobuf = ipath_getpiobuf(dd, plen, &pbufn);
  398. if (!piobuf) {
  399. ipath_cdbg(VERBOSE, "No PIO buffers avail unit for %u\n",
  400. dd->ipath_unit);
  401. ret = -EBUSY;
  402. goto bail;
  403. }
  404. /* disarm it just to be extra sure */
  405. ipath_disarm_piobufs(dd, pbufn, 1);
  406. if (ipath_debug & __IPATH_PKTDBG)
  407. ipath_cdbg(VERBOSE, "unit %u 0x%x+1w pio%d\n",
  408. dd->ipath_unit, plen - 1, pbufn);
  409. if (dp.pbc_wd == 0)
  410. dp.pbc_wd = plen;
  411. writeq(dp.pbc_wd, piobuf);
  412. /*
  413. * Copy all by the trigger word, then flush, so it's written
  414. * to chip before trigger word, then write trigger word, then
  415. * flush again, so packet is sent.
  416. */
  417. if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) {
  418. ipath_flush_wc();
  419. __iowrite32_copy(piobuf + 2, tmpbuf, clen - 1);
  420. ipath_flush_wc();
  421. __raw_writel(tmpbuf[clen - 1], piobuf + clen + 1);
  422. } else
  423. __iowrite32_copy(piobuf + 2, tmpbuf, clen);
  424. ipath_flush_wc();
  425. ret = sizeof(dp);
  426. bail:
  427. vfree(tmpbuf);
  428. return ret;
  429. }
  430. static int ipath_diag_release(struct inode *in, struct file *fp)
  431. {
  432. mutex_lock(&ipath_mutex);
  433. ipath_diag_inuse = 0;
  434. fp->private_data = NULL;
  435. mutex_unlock(&ipath_mutex);
  436. return 0;
  437. }
  438. static ssize_t ipath_diag_read(struct file *fp, char __user *data,
  439. size_t count, loff_t *off)
  440. {
  441. struct ipath_devdata *dd = fp->private_data;
  442. void __iomem *kreg_base;
  443. ssize_t ret;
  444. kreg_base = dd->ipath_kregbase;
  445. if (count == 0)
  446. ret = 0;
  447. else if ((count % 4) || (*off % 4))
  448. /* address or length is not 32-bit aligned, hence invalid */
  449. ret = -EINVAL;
  450. else if (ipath_diag_inuse < 1 && (*off || count != 8))
  451. ret = -EINVAL; /* prevent cat /dev/ipath_diag* */
  452. else if ((count % 8) || (*off % 8))
  453. /* address or length not 64-bit aligned; do 32-bit reads */
  454. ret = ipath_read_umem32(dd, data, kreg_base + *off, count);
  455. else
  456. ret = ipath_read_umem64(dd, data, kreg_base + *off, count);
  457. if (ret >= 0) {
  458. *off += count;
  459. ret = count;
  460. if (ipath_diag_inuse == -2)
  461. ipath_diag_inuse++;
  462. }
  463. return ret;
  464. }
  465. static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
  466. size_t count, loff_t *off)
  467. {
  468. struct ipath_devdata *dd = fp->private_data;
  469. void __iomem *kreg_base;
  470. ssize_t ret;
  471. kreg_base = dd->ipath_kregbase;
  472. if (count == 0)
  473. ret = 0;
  474. else if ((count % 4) || (*off % 4))
  475. /* address or length is not 32-bit aligned, hence invalid */
  476. ret = -EINVAL;
  477. else if ((ipath_diag_inuse == -1 && (*off || count != 8)) ||
  478. ipath_diag_inuse == -2) /* read qw off 0, write qw off 0 */
  479. ret = -EINVAL; /* before any other write allowed */
  480. else if ((count % 8) || (*off % 8))
  481. /* address or length not 64-bit aligned; do 32-bit writes */
  482. ret = ipath_write_umem32(dd, kreg_base + *off, data, count);
  483. else
  484. ret = ipath_write_umem64(dd, kreg_base + *off, data, count);
  485. if (ret >= 0) {
  486. *off += count;
  487. ret = count;
  488. if (ipath_diag_inuse == -1)
  489. ipath_diag_inuse = 1; /* all read/write OK now */
  490. }
  491. return ret;
  492. }