|  | /****************************************************************************** | 
|  | * | 
|  | * Name:	skproc.c | 
|  | * Project:	GEnesis, PCI Gigabit Ethernet Adapter | 
|  | * Version:	$Revision: 1.11 $ | 
|  | * Date:	$Date: 2003/12/11 16:03:57 $ | 
|  | * Purpose:	Funktions to display statictic data | 
|  | * | 
|  | ******************************************************************************/ | 
|  |  | 
|  | /****************************************************************************** | 
|  | * | 
|  | *	(C)Copyright 1998-2002 SysKonnect GmbH. | 
|  | *	(C)Copyright 2002-2003 Marvell. | 
|  | * | 
|  | *	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. | 
|  | * | 
|  | *	Created 22-Nov-2000 | 
|  | *	Author: Mirko Lindner (mlindner@syskonnect.de) | 
|  | * | 
|  | *	The information in this file is provided "AS IS" without warranty. | 
|  | * | 
|  | ******************************************************************************/ | 
|  | #include <linux/proc_fs.h> | 
|  | #include <linux/seq_file.h> | 
|  |  | 
|  | #include "h/skdrv1st.h" | 
|  | #include "h/skdrv2nd.h" | 
|  | #include "h/skversion.h" | 
|  |  | 
|  | static int sk_seq_show(struct seq_file *seq, void *v); | 
|  | static int sk_proc_open(struct inode *inode, struct file *file); | 
|  |  | 
|  | struct file_operations sk_proc_fops = { | 
|  | .owner		= THIS_MODULE, | 
|  | .open		= sk_proc_open, | 
|  | .read		= seq_read, | 
|  | .llseek		= seq_lseek, | 
|  | .release	= single_release, | 
|  | }; | 
|  |  | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | *      sk_seq_show - show proc information of a particular adapter | 
|  | * | 
|  | * Description: | 
|  | *  This function fills the proc entry with statistic data about | 
|  | *  the ethernet device. It invokes the generic sk_gen_browse() to | 
|  | *  print out all items one per one. | 
|  | * | 
|  | * Returns: 0 | 
|  | * | 
|  | */ | 
|  | static int sk_seq_show(struct seq_file *seq, void *v) | 
|  | { | 
|  | struct net_device *dev = seq->private; | 
|  | DEV_NET			*pNet = netdev_priv(dev); | 
|  | SK_AC			*pAC = pNet->pAC; | 
|  | SK_PNMI_STRUCT_DATA 	*pPnmiStruct = &pAC->PnmiStruct; | 
|  | unsigned long		Flags; | 
|  | unsigned int		Size; | 
|  | char			sens_msg[50]; | 
|  | int 			t; | 
|  | int 			i; | 
|  |  | 
|  | /* NetIndex in GetStruct is now required, zero is only dummy */ | 
|  | for (t=pAC->GIni.GIMacsFound; t > 0; t--) { | 
|  | if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1) | 
|  | t--; | 
|  |  | 
|  | spin_lock_irqsave(&pAC->SlowPathLock, Flags); | 
|  | Size = SK_PNMI_STRUCT_SIZE; | 
|  | #ifdef SK_DIAG_SUPPORT | 
|  | if (pAC->BoardLevel == SK_INIT_DATA) { | 
|  | SK_MEMCPY(&(pAC->PnmiStruct), &(pAC->PnmiBackup), sizeof(SK_PNMI_STRUCT_DATA)); | 
|  | if (pAC->DiagModeActive == DIAG_NOTACTIVE) { | 
|  | pAC->Pnmi.DiagAttached = SK_DIAG_IDLE; | 
|  | } | 
|  | } else { | 
|  | SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, t-1); | 
|  | } | 
|  | #else | 
|  | SkPnmiGetStruct(pAC, pAC->IoBase, | 
|  | pPnmiStruct, &Size, t-1); | 
|  | #endif | 
|  | spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); | 
|  |  | 
|  | if (pAC->dev[t-1] == dev) { | 
|  | SK_PNMI_STAT	*pPnmiStat = &pPnmiStruct->Stat[0]; | 
|  |  | 
|  | seq_printf(seq, "\nDetailed statistic for device %s\n", | 
|  | pAC->dev[t-1]->name); | 
|  | seq_printf(seq, "=======================================\n"); | 
|  |  | 
|  | /* Board statistics */ | 
|  | seq_printf(seq, "\nBoard statistics\n\n"); | 
|  | seq_printf(seq, "Active Port                    %c\n", | 
|  | 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. | 
|  | Net[t-1].PrefPort]->PortNumber); | 
|  | seq_printf(seq, "Preferred Port                 %c\n", | 
|  | 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt. | 
|  | Net[t-1].PrefPort]->PortNumber); | 
|  |  | 
|  | seq_printf(seq, "Bus speed (MHz)                %d\n", | 
|  | pPnmiStruct->BusSpeed); | 
|  |  | 
|  | seq_printf(seq, "Bus width (Bit)                %d\n", | 
|  | pPnmiStruct->BusWidth); | 
|  | seq_printf(seq, "Driver version                 %s\n", | 
|  | VER_STRING); | 
|  | seq_printf(seq, "Hardware revision              v%d.%d\n", | 
|  | (pAC->GIni.GIPciHwRev >> 4) & 0x0F, | 
|  | pAC->GIni.GIPciHwRev & 0x0F); | 
|  |  | 
|  | /* Print sensor informations */ | 
|  | for (i=0; i < pAC->I2c.MaxSens; i ++) { | 
|  | /* Check type */ | 
|  | switch (pAC->I2c.SenTable[i].SenType) { | 
|  | case 1: | 
|  | strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); | 
|  | strcat(sens_msg, " (C)"); | 
|  | seq_printf(seq, "%-25s      %d.%02d\n", | 
|  | sens_msg, | 
|  | pAC->I2c.SenTable[i].SenValue / 10, | 
|  | pAC->I2c.SenTable[i].SenValue % 10); | 
|  |  | 
|  | strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); | 
|  | strcat(sens_msg, " (F)"); | 
|  | seq_printf(seq, "%-25s      %d.%02d\n", | 
|  | sens_msg, | 
|  | ((((pAC->I2c.SenTable[i].SenValue) | 
|  | *10)*9)/5 + 3200)/100, | 
|  | ((((pAC->I2c.SenTable[i].SenValue) | 
|  | *10)*9)/5 + 3200) % 10); | 
|  | break; | 
|  | case 2: | 
|  | strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); | 
|  | strcat(sens_msg, " (V)"); | 
|  | seq_printf(seq, "%-25s      %d.%03d\n", | 
|  | sens_msg, | 
|  | pAC->I2c.SenTable[i].SenValue / 1000, | 
|  | pAC->I2c.SenTable[i].SenValue % 1000); | 
|  | break; | 
|  | case 3: | 
|  | strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc); | 
|  | strcat(sens_msg, " (rpm)"); | 
|  | seq_printf(seq, "%-25s      %d\n", | 
|  | sens_msg, | 
|  | pAC->I2c.SenTable[i].SenValue); | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /*Receive statistics */ | 
|  | seq_printf(seq, "\nReceive statistics\n\n"); | 
|  |  | 
|  | seq_printf(seq, "Received bytes                 %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxOctetsOkCts); | 
|  | seq_printf(seq, "Received packets               %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxOkCts); | 
|  | #if 0 | 
|  | if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && | 
|  | pAC->HWRevision < 12) { | 
|  | pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - | 
|  | pPnmiStat->StatRxShortsCts; | 
|  | pPnmiStat->StatRxShortsCts = 0; | 
|  | } | 
|  | #endif | 
|  | if (dev->mtu > 1500) | 
|  | pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts - | 
|  | pPnmiStat->StatRxTooLongCts; | 
|  |  | 
|  | seq_printf(seq, "Receive errors                 %Lu\n", | 
|  | (unsigned long long) pPnmiStruct->InErrorsCts); | 
|  | seq_printf(seq, "Receive dropped                %Lu\n", | 
|  | (unsigned long long) pPnmiStruct->RxNoBufCts); | 
|  | seq_printf(seq, "Received multicast             %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxMulticastOkCts); | 
|  | seq_printf(seq, "Receive error types\n"); | 
|  | seq_printf(seq, "   length                      %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxRuntCts); | 
|  | seq_printf(seq, "   buffer overflow             %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxFifoOverflowCts); | 
|  | seq_printf(seq, "   bad crc                     %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxFcsCts); | 
|  | seq_printf(seq, "   framing                     %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxFramingCts); | 
|  | seq_printf(seq, "   missed frames               %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxMissedCts); | 
|  |  | 
|  | if (dev->mtu > 1500) | 
|  | pPnmiStat->StatRxTooLongCts = 0; | 
|  |  | 
|  | seq_printf(seq, "   too long                    %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxTooLongCts); | 
|  | seq_printf(seq, "   carrier extension           %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxCextCts); | 
|  | seq_printf(seq, "   too short                   %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxShortsCts); | 
|  | seq_printf(seq, "   symbol                      %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxSymbolCts); | 
|  | seq_printf(seq, "   LLC MAC size                %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxIRLengthCts); | 
|  | seq_printf(seq, "   carrier event               %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxCarrierCts); | 
|  | seq_printf(seq, "   jabber                      %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatRxJabberCts); | 
|  |  | 
|  |  | 
|  | /*Transmit statistics */ | 
|  | seq_printf(seq, "\nTransmit statistics\n\n"); | 
|  |  | 
|  | seq_printf(seq, "Transmited bytes               %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatTxOctetsOkCts); | 
|  | seq_printf(seq, "Transmited packets             %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatTxOkCts); | 
|  | seq_printf(seq, "Transmit errors                %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatTxSingleCollisionCts); | 
|  | seq_printf(seq, "Transmit dropped               %Lu\n", | 
|  | (unsigned long long) pPnmiStruct->TxNoBufCts); | 
|  | seq_printf(seq, "Transmit collisions            %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatTxSingleCollisionCts); | 
|  | seq_printf(seq, "Transmit error types\n"); | 
|  | seq_printf(seq, "   excessive collision         %ld\n", | 
|  | pAC->stats.tx_aborted_errors); | 
|  | seq_printf(seq, "   carrier                     %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatTxCarrierCts); | 
|  | seq_printf(seq, "   fifo underrun               %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatTxFifoUnderrunCts); | 
|  | seq_printf(seq, "   heartbeat                   %Lu\n", | 
|  | (unsigned long long) pPnmiStat->StatTxCarrierCts); | 
|  | seq_printf(seq, "   window                      %ld\n", | 
|  | pAC->stats.tx_window_errors); | 
|  |  | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | *      sk_proc_open - register the show function when proc is open'ed | 
|  | * | 
|  | * Description: | 
|  | *  This function is called whenever a sk98lin proc file is queried. | 
|  | * | 
|  | * Returns: the return value of single_open() | 
|  | * | 
|  | */ | 
|  | static int sk_proc_open(struct inode *inode, struct file *file) | 
|  | { | 
|  | return single_open(file, sk_seq_show, PDE(inode)->data); | 
|  | } | 
|  |  | 
|  | /******************************************************************************* | 
|  | * | 
|  | * End of file | 
|  | * | 
|  | ******************************************************************************/ |