2 * Copyright (c) 2006 QLogic, Inc. All rights reserved.
3 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
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:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
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.
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
35 * This file contains support for diagnostic functions. It is accessed by
36 * opening the ipath_diag device, normally minor number 129. Diagnostic use
37 * of the InfiniPath chip may render the chip or board unusable until the
38 * driver is unloaded, or in some cases, until the system is rebooted.
40 * Accesses to the chip through this interface are not similar to going
41 * through the /sys/bus/pci resource mmap interface.
45 #include <linux/pci.h>
46 #include <linux/vmalloc.h>
47 #include <asm/uaccess.h>
49 #include "ipath_kernel.h"
50 #include "ipath_common.h"
53 static int diag_set_link
;
55 static int ipath_diag_open(struct inode
*in
, struct file
*fp
);
56 static int ipath_diag_release(struct inode
*in
, struct file
*fp
);
57 static ssize_t
ipath_diag_read(struct file
*fp
, char __user
*data
,
58 size_t count
, loff_t
*off
);
59 static ssize_t
ipath_diag_write(struct file
*fp
, const char __user
*data
,
60 size_t count
, loff_t
*off
);
62 static const struct file_operations diag_file_ops
= {
64 .write
= ipath_diag_write
,
65 .read
= ipath_diag_read
,
66 .open
= ipath_diag_open
,
67 .release
= ipath_diag_release
70 static ssize_t
ipath_diagpkt_write(struct file
*fp
,
71 const char __user
*data
,
72 size_t count
, loff_t
*off
);
74 static const struct file_operations diagpkt_file_ops
= {
76 .write
= ipath_diagpkt_write
,
79 static atomic_t diagpkt_count
= ATOMIC_INIT(0);
80 static struct cdev
*diagpkt_cdev
;
81 static struct class_device
*diagpkt_class_dev
;
83 int ipath_diag_add(struct ipath_devdata
*dd
)
88 if (atomic_inc_return(&diagpkt_count
) == 1) {
89 ret
= ipath_cdev_init(IPATH_DIAGPKT_MINOR
,
90 "ipath_diagpkt", &diagpkt_file_ops
,
91 &diagpkt_cdev
, &diagpkt_class_dev
);
94 ipath_dev_err(dd
, "Couldn't create ipath_diagpkt "
100 snprintf(name
, sizeof(name
), "ipath_diag%d", dd
->ipath_unit
);
102 ret
= ipath_cdev_init(IPATH_DIAG_MINOR_BASE
+ dd
->ipath_unit
, name
,
103 &diag_file_ops
, &dd
->diag_cdev
,
104 &dd
->diag_class_dev
);
106 ipath_dev_err(dd
, "Couldn't create %s device: %d",
113 void ipath_diag_remove(struct ipath_devdata
*dd
)
115 if (atomic_dec_and_test(&diagpkt_count
))
116 ipath_cdev_cleanup(&diagpkt_cdev
, &diagpkt_class_dev
);
118 ipath_cdev_cleanup(&dd
->diag_cdev
, &dd
->diag_class_dev
);
122 * ipath_read_umem64 - read a 64-bit quantity from the chip into user space
123 * @dd: the infinipath device
124 * @uaddr: the location to store the data in user memory
125 * @caddr: the source chip address (full pointer, not offset)
126 * @count: number of bytes to copy (multiple of 32 bits)
128 * This function also localizes all chip memory accesses.
129 * The copy should be written such that we read full cacheline packets
130 * from the chip. This is usually used for a single qword
132 * NOTE: This assumes the chip address is 64-bit aligned.
134 static int ipath_read_umem64(struct ipath_devdata
*dd
, void __user
*uaddr
,
135 const void __iomem
*caddr
, size_t count
)
137 const u64 __iomem
*reg_addr
= caddr
;
138 const u64 __iomem
*reg_end
= reg_addr
+ (count
/ sizeof(u64
));
141 /* not very efficient, but it works for now */
142 if (reg_addr
< dd
->ipath_kregbase
|| reg_end
> dd
->ipath_kregend
) {
146 while (reg_addr
< reg_end
) {
147 u64 data
= readq(reg_addr
);
148 if (copy_to_user(uaddr
, &data
, sizeof(u64
))) {
153 uaddr
+= sizeof(u64
);
161 * ipath_write_umem64 - write a 64-bit quantity to the chip from user space
162 * @dd: the infinipath device
163 * @caddr: the destination chip address (full pointer, not offset)
164 * @uaddr: the source of the data in user memory
165 * @count: the number of bytes to copy (multiple of 32 bits)
167 * This is usually used for a single qword
168 * NOTE: This assumes the chip address is 64-bit aligned.
171 static int ipath_write_umem64(struct ipath_devdata
*dd
, void __iomem
*caddr
,
172 const void __user
*uaddr
, size_t count
)
174 u64 __iomem
*reg_addr
= caddr
;
175 const u64 __iomem
*reg_end
= reg_addr
+ (count
/ sizeof(u64
));
178 /* not very efficient, but it works for now */
179 if (reg_addr
< dd
->ipath_kregbase
|| reg_end
> dd
->ipath_kregend
) {
183 while (reg_addr
< reg_end
) {
185 if (copy_from_user(&data
, uaddr
, sizeof(data
))) {
189 writeq(data
, reg_addr
);
192 uaddr
+= sizeof(u64
);
200 * ipath_read_umem32 - read a 32-bit quantity from the chip into user space
201 * @dd: the infinipath device
202 * @uaddr: the location to store the data in user memory
203 * @caddr: the source chip address (full pointer, not offset)
204 * @count: number of bytes to copy
206 * read 32 bit values, not 64 bit; for memories that only
207 * support 32 bit reads; usually a single dword.
209 static int ipath_read_umem32(struct ipath_devdata
*dd
, void __user
*uaddr
,
210 const void __iomem
*caddr
, size_t count
)
212 const u32 __iomem
*reg_addr
= caddr
;
213 const u32 __iomem
*reg_end
= reg_addr
+ (count
/ sizeof(u32
));
216 if (reg_addr
< (u32 __iomem
*) dd
->ipath_kregbase
||
217 reg_end
> (u32 __iomem
*) dd
->ipath_kregend
) {
221 /* not very efficient, but it works for now */
222 while (reg_addr
< reg_end
) {
223 u32 data
= readl(reg_addr
);
224 if (copy_to_user(uaddr
, &data
, sizeof(data
))) {
230 uaddr
+= sizeof(u32
);
239 * ipath_write_umem32 - write a 32-bit quantity to the chip from user space
240 * @dd: the infinipath device
241 * @caddr: the destination chip address (full pointer, not offset)
242 * @uaddr: the source of the data in user memory
243 * @count: number of bytes to copy
245 * write 32 bit values, not 64 bit; for memories that only
246 * support 32 bit write; usually a single dword.
249 static int ipath_write_umem32(struct ipath_devdata
*dd
, void __iomem
*caddr
,
250 const void __user
*uaddr
, size_t count
)
252 u32 __iomem
*reg_addr
= caddr
;
253 const u32 __iomem
*reg_end
= reg_addr
+ (count
/ sizeof(u32
));
256 if (reg_addr
< (u32 __iomem
*) dd
->ipath_kregbase
||
257 reg_end
> (u32 __iomem
*) dd
->ipath_kregend
) {
261 while (reg_addr
< reg_end
) {
263 if (copy_from_user(&data
, uaddr
, sizeof(data
))) {
267 writel(data
, reg_addr
);
270 uaddr
+= sizeof(u32
);
277 static int ipath_diag_open(struct inode
*in
, struct file
*fp
)
279 int unit
= iminor(in
) - IPATH_DIAG_MINOR_BASE
;
280 struct ipath_devdata
*dd
;
283 mutex_lock(&ipath_mutex
);
285 if (ipath_diag_inuse
) {
290 dd
= ipath_lookup(unit
);
292 if (dd
== NULL
|| !(dd
->ipath_flags
& IPATH_PRESENT
) ||
293 !dd
->ipath_kregbase
) {
298 fp
->private_data
= dd
;
299 ipath_diag_inuse
= -2;
303 /* Only expose a way to reset the device if we
304 make it into diag mode. */
305 ipath_expose_reset(&dd
->pcidev
->dev
);
308 mutex_unlock(&ipath_mutex
);
314 * ipath_diagpkt_write - write an IB packet
315 * @fp: the diag data device file pointer
316 * @data: ipath_diag_pkt structure saying where to get the packet
317 * @count: size of data to write
318 * @off: unused by this code
320 static ssize_t
ipath_diagpkt_write(struct file
*fp
,
321 const char __user
*data
,
322 size_t count
, loff_t
*off
)
325 u32 plen
, clen
, pbufn
;
326 struct ipath_diag_pkt dp
;
328 struct ipath_devdata
*dd
;
332 if (count
< sizeof(dp
)) {
337 if (copy_from_user(&dp
, data
, sizeof(dp
))) {
342 /* send count must be an exact number of dwords */
350 dd
= ipath_lookup(dp
.unit
);
351 if (!dd
|| !(dd
->ipath_flags
& IPATH_PRESENT
) ||
352 !dd
->ipath_kregbase
) {
353 ipath_cdbg(VERBOSE
, "illegal unit %u for diag data send\n",
359 if (ipath_diag_inuse
&& !diag_set_link
&&
360 !(dd
->ipath_flags
& IPATH_LINKACTIVE
)) {
362 ipath_cdbg(VERBOSE
, "Trying to set to set link active for "
364 ipath_set_linkstate(dd
, IPATH_IB_LINKARM
);
365 ipath_set_linkstate(dd
, IPATH_IB_LINKACTIVE
);
368 if (!(dd
->ipath_flags
& IPATH_INITTED
)) {
369 /* no hardware, freeze, etc. */
370 ipath_cdbg(VERBOSE
, "unit %u not usable\n", dd
->ipath_unit
);
374 val
= dd
->ipath_lastibcstat
& IPATH_IBSTATE_MASK
;
375 if (val
!= IPATH_IBSTATE_INIT
&& val
!= IPATH_IBSTATE_ARM
&&
376 val
!= IPATH_IBSTATE_ACTIVE
) {
377 ipath_cdbg(VERBOSE
, "unit %u not ready (state %llx)\n",
378 dd
->ipath_unit
, (unsigned long long) val
);
383 /* need total length before first word written */
384 /* +1 word is for the qword padding */
385 plen
= sizeof(u32
) + dp
.len
;
387 if ((plen
+ 4) > dd
->ipath_ibmaxlen
) {
388 ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n",
389 plen
- 4, dd
->ipath_ibmaxlen
);
391 goto bail
; /* before writing pbc */
393 tmpbuf
= vmalloc(plen
);
395 dev_info(&dd
->pcidev
->dev
, "Unable to allocate tmp buffer, "
401 if (copy_from_user(tmpbuf
,
402 (const void __user
*) (unsigned long) dp
.data
,
408 piobuf
= ipath_getpiobuf(dd
, &pbufn
);
410 ipath_cdbg(VERBOSE
, "No PIO buffers avail unit for %u\n",
416 plen
>>= 2; /* in dwords */
418 if (ipath_debug
& __IPATH_PKTDBG
)
419 ipath_cdbg(VERBOSE
, "unit %u 0x%x+1w pio%d\n",
420 dd
->ipath_unit
, plen
- 1, pbufn
);
422 /* we have to flush after the PBC for correctness on some cpus
423 * or WC buffer can be written out of order */
424 writeq(plen
, piobuf
);
426 /* copy all by the trigger word, then flush, so it's written
427 * to chip before trigger word, then write trigger word, then
428 * flush again, so packet is sent. */
429 __iowrite32_copy(piobuf
+ 2, tmpbuf
, clen
- 1);
431 __raw_writel(tmpbuf
[clen
- 1], piobuf
+ clen
+ 1);
441 static int ipath_diag_release(struct inode
*in
, struct file
*fp
)
443 mutex_lock(&ipath_mutex
);
444 ipath_diag_inuse
= 0;
445 fp
->private_data
= NULL
;
446 mutex_unlock(&ipath_mutex
);
450 static ssize_t
ipath_diag_read(struct file
*fp
, char __user
*data
,
451 size_t count
, loff_t
*off
)
453 struct ipath_devdata
*dd
= fp
->private_data
;
454 void __iomem
*kreg_base
;
457 kreg_base
= dd
->ipath_kregbase
;
461 else if ((count
% 4) || (*off
% 4))
462 /* address or length is not 32-bit aligned, hence invalid */
464 else if (ipath_diag_inuse
< 1 && (*off
|| count
!= 8))
465 ret
= -EINVAL
; /* prevent cat /dev/ipath_diag* */
466 else if ((count
% 8) || (*off
% 8))
467 /* address or length not 64-bit aligned; do 32-bit reads */
468 ret
= ipath_read_umem32(dd
, data
, kreg_base
+ *off
, count
);
470 ret
= ipath_read_umem64(dd
, data
, kreg_base
+ *off
, count
);
475 if (ipath_diag_inuse
== -2)
482 static ssize_t
ipath_diag_write(struct file
*fp
, const char __user
*data
,
483 size_t count
, loff_t
*off
)
485 struct ipath_devdata
*dd
= fp
->private_data
;
486 void __iomem
*kreg_base
;
489 kreg_base
= dd
->ipath_kregbase
;
493 else if ((count
% 4) || (*off
% 4))
494 /* address or length is not 32-bit aligned, hence invalid */
496 else if ((ipath_diag_inuse
== -1 && (*off
|| count
!= 8)) ||
497 ipath_diag_inuse
== -2) /* read qw off 0, write qw off 0 */
498 ret
= -EINVAL
; /* before any other write allowed */
499 else if ((count
% 8) || (*off
% 8))
500 /* address or length not 64-bit aligned; do 32-bit writes */
501 ret
= ipath_write_umem32(dd
, kreg_base
+ *off
, data
, count
);
503 ret
= ipath_write_umem64(dd
, kreg_base
+ *off
, data
, count
);
508 if (ipath_diag_inuse
== -1)
509 ipath_diag_inuse
= 1; /* all read/write OK now */