/* * Copyright (c) 2012 Intel Corporation. All rights reserved. * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* * This file contains support for diagnostic functions. It is accessed by * opening the qib_diag device, normally minor number 129. Diagnostic use * of the QLogic_IB chip may render the chip or board unusable until the * driver is unloaded, or in some cases, until the system is rebooted. * * Accesses to the chip through this interface are not similar to going * through the /sys/bus/pci resource mmap interface. */ #include <linux/io.h> #include <linux/pci.h> #include <linux/poll.h> #include <linux/vmalloc.h> #include <linux/export.h> #include <linux/fs.h> #include <linux/uaccess.h> #include "qib.h" #include "qib_common.h" #undef pr_fmt #define pr_fmt(fmt) … /* * Each client that opens the diag device must read then write * offset 0, to prevent lossage from random cat or od. diag_state * sequences this "handshake". */ enum diag_state { … }; /* State for an individual client. PID so children cannot abuse handshake */ static struct qib_diag_client { … } *client_pool; /* * Get a client struct. Recycled if possible, else kmalloc. * Must be called with qib_mutex held */ static struct qib_diag_client *get_client(struct qib_devdata *dd) { … } /* * Return to pool. Must be called with qib_mutex held */ static void return_client(struct qib_diag_client *dc) { … } static int qib_diag_open(struct inode *in, struct file *fp); static int qib_diag_release(struct inode *in, struct file *fp); static ssize_t qib_diag_read(struct file *fp, char __user *data, size_t count, loff_t *off); static ssize_t qib_diag_write(struct file *fp, const char __user *data, size_t count, loff_t *off); static const struct file_operations diag_file_ops = …; static atomic_t diagpkt_count = …; static struct cdev *diagpkt_cdev; static struct device *diagpkt_device; static ssize_t qib_diagpkt_write(struct file *fp, const char __user *data, size_t count, loff_t *off); static const struct file_operations diagpkt_file_ops = …; int qib_diag_add(struct qib_devdata *dd) { … } static void qib_unregister_observers(struct qib_devdata *dd); void qib_diag_remove(struct qib_devdata *dd) { … } /* qib_remap_ioaddr32 - remap an offset into chip address space to __iomem * * * @dd: the qlogic_ib device * @offs: the offset in chip-space * @cntp: Pointer to max (byte) count for transfer starting at offset * This returns a u32 __iomem * so it can be used for both 64 and 32-bit * mapping. It is needed because with the use of PAT for control of * write-combining, the logically contiguous address-space of the chip * may be split into virtually non-contiguous spaces, with different * attributes, which are them mapped to contiguous physical space * based from the first BAR. * * The code below makes the same assumptions as were made in * init_chip_wc_pat() (qib_init.c), copied here: * Assumes chip address space looks like: * - kregs + sregs + cregs + uregs (in any order) * - piobufs (2K and 4K bufs in either order) * or: * - kregs + sregs + cregs (in any order) * - piobufs (2K and 4K bufs in either order) * - uregs * * If cntp is non-NULL, returns how many bytes from offset can be accessed * Returns 0 if the offset is not mapped. */ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset, u32 *cntp) { … } /* * qib_read_umem64 - read a 64-bit quantity from the chip into user space * @dd: the qlogic_ib device * @uaddr: the location to store the data in user memory * @regoffs: the offset from BAR0 (_NOT_ full pointer, anymore) * @count: number of bytes to copy (multiple of 32 bits) * * This function also localizes all chip memory accesses. * The copy should be written such that we read full cacheline packets * from the chip. This is usually used for a single qword * * NOTE: This assumes the chip address is 64-bit aligned. */ static int qib_read_umem64(struct qib_devdata *dd, void __user *uaddr, u32 regoffs, size_t count) { … } /* * qib_write_umem64 - write a 64-bit quantity to the chip from user space * @dd: the qlogic_ib device * @regoffs: the offset from BAR0 (_NOT_ full pointer, anymore) * @uaddr: the source of the data in user memory * @count: the number of bytes to copy (multiple of 32 bits) * * This is usually used for a single qword * NOTE: This assumes the chip address is 64-bit aligned. */ static int qib_write_umem64(struct qib_devdata *dd, u32 regoffs, const void __user *uaddr, size_t count) { … } /* * qib_read_umem32 - read a 32-bit quantity from the chip into user space * @dd: the qlogic_ib device * @uaddr: the location to store the data in user memory * @regoffs: the offset from BAR0 (_NOT_ full pointer, anymore) * @count: number of bytes to copy * * read 32 bit values, not 64 bit; for memories that only * support 32 bit reads; usually a single dword. */ static int qib_read_umem32(struct qib_devdata *dd, void __user *uaddr, u32 regoffs, size_t count) { … } /* * qib_write_umem32 - write a 32-bit quantity to the chip from user space * @dd: the qlogic_ib device * @regoffs: the offset from BAR0 (_NOT_ full pointer, anymore) * @uaddr: the source of the data in user memory * @count: number of bytes to copy * * write 32 bit values, not 64 bit; for memories that only * support 32 bit write; usually a single dword. */ static int qib_write_umem32(struct qib_devdata *dd, u32 regoffs, const void __user *uaddr, size_t count) { … } static int qib_diag_open(struct inode *in, struct file *fp) { … } /** * qib_diagpkt_write - write an IB packet * @fp: the diag data device file pointer * @data: qib_diag_pkt structure saying where to get the packet * @count: size of data to write * @off: unused by this code */ static ssize_t qib_diagpkt_write(struct file *fp, const char __user *data, size_t count, loff_t *off) { … } static int qib_diag_release(struct inode *in, struct file *fp) { … } /* * Chip-specific code calls to register its interest in * a specific range. */ struct diag_observer_list_elt { … }; int qib_register_observer(struct qib_devdata *dd, const struct diag_observer *op) { … } /* Remove all registered observers when device is closed */ static void qib_unregister_observers(struct qib_devdata *dd) { … } /* * Find the observer, if any, for the specified address. Initial implementation * is simple stack of observers. This must be called with diag transaction * lock held. */ static const struct diag_observer *diag_get_observer(struct qib_devdata *dd, u32 addr) { … } static ssize_t qib_diag_read(struct file *fp, char __user *data, size_t count, loff_t *off) { … } static ssize_t qib_diag_write(struct file *fp, const char __user *data, size_t count, loff_t *off) { … }