patch-2.4.19 linux-2.4.19/arch/ppc64/kernel/proc_pcifr.c
Next file: linux-2.4.19/arch/ppc64/kernel/proc_pmc.c
Previous file: linux-2.4.19/arch/ppc64/kernel/ppc_ksyms.c
Back to the patch index
Back to the overall index
- Lines: 252
- Date:
Fri Aug 2 17:39:43 2002
- Orig file:
linux-2.4.18/arch/ppc64/kernel/proc_pcifr.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -urN linux-2.4.18/arch/ppc64/kernel/proc_pcifr.c linux-2.4.19/arch/ppc64/kernel/proc_pcifr.c
@@ -0,0 +1,251 @@
+/************************************************************************/
+/* File pcifr_proc.c created by Allan Trautman on Thu Aug 2 2001. */
+/************************************************************************/
+/* Supports the ../proc/ppc64/pcifr for the pci flight recorder. */
+/* Copyright (C) 20yy <Allan H Trautman> <IBM Corp> */
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the: */
+/* Free Software Foundation, Inc., */
+/* 59 Temple Place, Suite 330, */
+/* Boston, MA 02111-1307 USA */
+/************************************************************************/
+#include <stdarg.h>
+#include <linux/kernel.h>
+
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <asm/time.h>
+
+#include <linux/pci.h>
+#include <asm/pci-bridge.h>
+#include <linux/netdevice.h>
+
+#include <asm/flight_recorder.h>
+#include <asm/iSeries/iSeries_pci.h>
+#include "pci.h"
+
+void pci_Fr_TestCode(void);
+
+static spinlock_t proc_pcifr_lock;
+struct flightRecorder* PciFr = NULL;
+
+extern long Pci_Interrupt_Count;
+extern long Pci_Event_Count;
+extern long Pci_Io_Read_Count;
+extern long Pci_Io_Write_Count;
+extern long Pci_Cfg_Read_Count;
+extern long Pci_Cfg_Write_Count;
+extern long Pci_Error_Count;
+
+/************************************************************************/
+/* Forward declares. */
+/************************************************************************/
+static struct proc_dir_entry *pciFr_proc_root = NULL;
+int proc_pciFr_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
+int proc_pciFr_write_proc(struct file *file, const char *buffer, unsigned long count, void *data);
+
+static struct proc_dir_entry *pciDev_proc_root = NULL;
+int proc_pciDev_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
+int proc_pciDev_write_proc(struct file *file, const char *buffer, unsigned long count, void *data);
+
+/************************************************************************/
+/* Create entry ../proc/ppc64/pcifr */
+/************************************************************************/
+void proc_pciFr_init(struct proc_dir_entry *proc_ppc64_root)
+{
+ if (proc_ppc64_root == NULL) return;
+
+ /* Read = User,Group,Other, Write User */
+ printk("PCI: Creating ../proc/ppc64/pcifr \n");
+ spin_lock(&proc_pcifr_lock);
+ pciFr_proc_root = create_proc_entry("pcifr", S_IFREG | S_IRUGO | S_IWUSR, proc_ppc64_root);
+ spin_unlock(&proc_pcifr_lock);
+
+ if (pciFr_proc_root == NULL) return;
+
+ pciFr_proc_root->nlink = 1;
+ pciFr_proc_root->data = (void *)0;
+ pciFr_proc_root->read_proc = proc_pciFr_read_proc;
+ pciFr_proc_root->write_proc = proc_pciFr_write_proc;
+
+ PciFr = alloc_Flight_Recorder(NULL,"PciFr", 4096);
+
+ printk("PCI: Creating ../proc/ppc64/pci \n");
+ spin_lock(&proc_pcifr_lock);
+ pciDev_proc_root = create_proc_entry("pci", S_IFREG | S_IRUGO | S_IWUSR, proc_ppc64_root);
+ spin_unlock(&proc_pcifr_lock);
+
+ if (pciDev_proc_root == NULL) return;
+
+ pciDev_proc_root->nlink = 1;
+ pciDev_proc_root->data = (void *)0;
+ pciDev_proc_root->read_proc = proc_pciDev_read_proc;
+ pciDev_proc_root->write_proc = proc_pciDev_write_proc;
+}
+
+static char* PciFrBuffer = NULL;
+static int PciFrBufLen = 0;
+static char* PciFrBufPtr = NULL;
+static int PciFileSize = 0;
+
+/*******************************************************************************/
+/* Read function for ../proc/ppc64/pcifr. */
+/* -> Function grabs a copy of the pcifr(could change) and writes the data to */
+/* the caller. Note, it may not all fit in the buffer. The function */
+/* handles the repeated calls until all the data has been read. */
+/* Tip: */
+/* ./fs/proc/generic.c::proc_file_read is the caller of this routine. */
+/*******************************************************************************/
+int proc_pciFr_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ /* First call will have offset 0, get snapshot the pcifr */
+ if( off == 0) {
+ spin_lock(&proc_pcifr_lock);
+ PciFrBuffer = (char*)kmalloc(PciFr->Size, GFP_KERNEL);
+ PciFrBufLen = fr_Dump(PciFr,PciFrBuffer, PciFr->Size);
+ PciFrBufPtr = PciFrBuffer;
+ PciFileSize = 0;
+ }
+ /* For the persistant folks, set eof and return zero length. */
+ else if( PciFrBuffer == NULL) {
+ *eof = 1;
+ return 0;
+ }
+ /* - If there is more data than will fit, move what will fit. */
+ /* - The rest will get moved on the next call. */
+ int MoveSize = PciFrBufLen;
+ if( MoveSize > count) MoveSize = count;
+
+ /* Move the data info the FileSystem buffer. */
+ memcpy(page+off,PciFrBufPtr,MoveSize);
+ PciFrBufPtr += MoveSize;
+ PciFileSize += MoveSize;
+ PciFrBufLen -= MoveSize;
+
+ /* If all the data has been moved, free the buffer and set EOF. */
+ if( PciFrBufLen == 0) {
+ kfree(PciFrBuffer);
+ PciFrBuffer = NULL;
+ spin_unlock(&proc_pcifr_lock);
+ *eof = 1;
+ }
+ return PciFileSize;
+}
+/*******************************************************************************/
+/* Gets called when client writes to ../proc/ppc64/pcifr */
+/*******************************************************************************/
+int proc_pciFr_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
+{
+ return count;
+}
+static spinlock_t ProcBufferLock;
+static char* ProcBuffer = NULL;
+static int ProcBufSize = 0;
+static char* ProcBufPtr = NULL;
+static int ProcFileSize = 0;
+
+/*******************************************************************************/
+/* Build Device Buffer for /proc/ppc64/pci */
+/*******************************************************************************/
+static int build_PciDev_Buffer(int BufferSize)
+{
+ ProcBuffer = (char*)kmalloc(BufferSize, GFP_KERNEL);
+ ProcBufPtr = ProcBuffer;
+
+ int BufLen = 0;
+
+ BufLen += sprintf(ProcBuffer+BufLen,"Pci I/O Reads. %8ld ",Pci_Io_Read_Count);
+ BufLen += sprintf(ProcBuffer+BufLen,"Pci I/O Writes %8ld\n",Pci_Io_Write_Count);
+
+ BufLen += sprintf(ProcBuffer+BufLen,"Pci Cfg Reads. %8ld ",Pci_Cfg_Read_Count);
+ BufLen += sprintf(ProcBuffer+BufLen,"Pci Cfg Writes %8ld\n",Pci_Cfg_Write_Count);
+
+ BufLen += sprintf(ProcBuffer+BufLen,"Pci I/O Errors %8ld\n",Pci_Error_Count);
+ BufLen += sprintf(ProcBuffer+BufLen,"\n");
+
+ /***************************************************************************/
+ /* List the devices */
+ /***************************************************************************/
+ struct pci_dev* PciDev; /* Device pointer */
+ struct net_device* dev; /* net_device pointer */
+ int DeviceCount = 0;
+ pci_for_each_dev(PciDev) {
+ if ( BufLen > BufferSize-128) { /* Room for another line? */
+ BufLen +=sprintf(ProcBuffer+BufLen,"Buffer Full\n");
+ break;
+ }
+ if( PCI_SLOT(PciDev->devfn) != 0) {
+ ++DeviceCount;
+ BufLen += sprintf(ProcBuffer+BufLen,"%3d. ",DeviceCount);
+ if ( PciDev->sysdata != NULL ) {
+ BufLen += format_device_location(PciDev,ProcBuffer+BufLen,128);
+ }
+ else {
+ BufLen += sprintf(ProcBuffer+BufLen,"No Device Node!\n");
+ }
+ BufLen += sprintf(ProcBuffer+BufLen,"\n");
+
+ /* look for the net devices out */
+ for (dev = dev_base; dev != NULL; dev = dev->next) {
+ if (dev->base_addr == PciDev->resource[0].start ) {
+ BufLen += sprintf(ProcBuffer+BufLen, " - Net device: %s\n", dev->name);
+ break;
+ } /* if */
+ } /* for */
+ } /* if(PCI_SLOT(PciDev->devfn) != 0) */
+ }
+ return BufLen;
+}
+/*******************************************************************************/
+/* Get called when client reads the ../proc/ppc64/pcifr. */
+/*******************************************************************************/
+int proc_pciDev_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ /* First call will have offset 0 */
+ if( off == 0) {
+ spin_lock(&ProcBufferLock);
+ ProcBufSize = build_PciDev_Buffer(4096);
+ ProcFileSize = 0;
+ }
+ /* For the persistant folks, set eof and return zero length. */
+ else if( ProcBuffer == NULL) {
+ *eof = 1;
+ return 0;
+ }
+ /* How much data can be moved */
+ int MoveSize = ProcBufSize;
+ if( MoveSize > count) MoveSize = count;
+
+ /* Move the data info the FileSystem buffer. */
+ memcpy(page+off,ProcBufPtr,MoveSize);
+ ProcBufPtr += MoveSize;
+ ProcBufSize -= MoveSize;
+ ProcFileSize += MoveSize;
+
+ /* If all the data has been moved, free the buffer and set EOF. */
+ if( ProcBufSize == 0) {
+ kfree(ProcBuffer );
+ ProcBuffer = NULL;
+ spin_unlock(&ProcBufferLock);
+ *eof = 1;
+ }
+ return ProcFileSize;
+}
+/*******************************************************************************/
+/* Gets called when client writes to ../proc/ppc64/pcifr */
+/*******************************************************************************/
+int proc_pciDev_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
+{
+ return count;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)