ipath_sysfs.c

来自「linux 内核源代码」· C语言 代码 · 共 807 行 · 第 1/2 页

C
807
字号
/* * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. * Copyright (c) 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. */#include <linux/ctype.h>#include "ipath_kernel.h"#include "ipath_common.h"/** * ipath_parse_ushort - parse an unsigned short value in an arbitrary base * @str: the string containing the number * @valp: where to put the result * * returns the number of bytes consumed, or negative value on error */int ipath_parse_ushort(const char *str, unsigned short *valp){	unsigned long val;	char *end;	int ret;	if (!isdigit(str[0])) {		ret = -EINVAL;		goto bail;	}	val = simple_strtoul(str, &end, 0);	if (val > 0xffff) {		ret = -EINVAL;		goto bail;	}	*valp = val;	ret = end + 1 - str;	if (ret == 0)		ret = -EINVAL;bail:	return ret;}static ssize_t show_version(struct device_driver *dev, char *buf){	/* The string printed here is already newline-terminated. */	return scnprintf(buf, PAGE_SIZE, "%s", ib_ipath_version);}static ssize_t show_num_units(struct device_driver *dev, char *buf){	return scnprintf(buf, PAGE_SIZE, "%d\n",			 ipath_count_units(NULL, NULL, NULL));}static ssize_t show_status(struct device *dev,			   struct device_attribute *attr,			   char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	ssize_t ret;	if (!dd->ipath_statusp) {		ret = -EINVAL;		goto bail;	}	ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n",			(unsigned long long) *(dd->ipath_statusp));bail:	return ret;}static const char *ipath_status_str[] = {	"Initted",	"Disabled",	"Admin_Disabled",	"", /* This used to be the old "OIB_SMA" status. */	"", /* This used to be the old "SMA" status. */	"Present",	"IB_link_up",	"IB_configured",	"NoIBcable",	"Fatal_Hardware_Error",	NULL,};static ssize_t show_status_str(struct device *dev,			       struct device_attribute *attr,			       char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	int i, any;	u64 s;	ssize_t ret;	if (!dd->ipath_statusp) {		ret = -EINVAL;		goto bail;	}	s = *(dd->ipath_statusp);	*buf = '\0';	for (any = i = 0; s && ipath_status_str[i]; i++) {		if (s & 1) {			if (any && strlcat(buf, " ", PAGE_SIZE) >=			    PAGE_SIZE)				/* overflow */				break;			if (strlcat(buf, ipath_status_str[i],				    PAGE_SIZE) >= PAGE_SIZE)				break;			any = 1;		}		s >>= 1;	}	if (any)		strlcat(buf, "\n", PAGE_SIZE);	ret = strlen(buf);bail:	return ret;}static ssize_t show_boardversion(struct device *dev,			       struct device_attribute *attr,			       char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	/* The string printed here is already newline-terminated. */	return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);}static ssize_t show_lmc(struct device *dev,			struct device_attribute *attr,			char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_lmc);}static ssize_t store_lmc(struct device *dev,			 struct device_attribute *attr,			 const char *buf,			 size_t count){	struct ipath_devdata *dd = dev_get_drvdata(dev);	u16 lmc = 0;	int ret;	ret = ipath_parse_ushort(buf, &lmc);	if (ret < 0)		goto invalid;	if (lmc > 7) {		ret = -EINVAL;		goto invalid;	}	ipath_set_lid(dd, dd->ipath_lid, lmc);	goto bail;invalid:	ipath_dev_err(dd, "attempt to set invalid LMC %u\n", lmc);bail:	return ret;}static ssize_t show_lid(struct device *dev,			struct device_attribute *attr,			char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid);}static ssize_t store_lid(struct device *dev,			 struct device_attribute *attr,			  const char *buf,			  size_t count){	struct ipath_devdata *dd = dev_get_drvdata(dev);	u16 lid = 0;	int ret;	ret = ipath_parse_ushort(buf, &lid);	if (ret < 0)		goto invalid;	if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) {		ret = -EINVAL;		goto invalid;	}	ipath_set_lid(dd, lid, dd->ipath_lmc);	goto bail;invalid:	ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid);bail:	return ret;}static ssize_t show_mlid(struct device *dev,			 struct device_attribute *attr,			 char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid);}static ssize_t store_mlid(struct device *dev,			 struct device_attribute *attr,			  const char *buf,			  size_t count){	struct ipath_devdata *dd = dev_get_drvdata(dev);	u16 mlid;	int ret;	ret = ipath_parse_ushort(buf, &mlid);	if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE)		goto invalid;	dd->ipath_mlid = mlid;	goto bail;invalid:	ipath_dev_err(dd, "attempt to set invalid MLID\n");bail:	return ret;}static ssize_t show_guid(struct device *dev,			 struct device_attribute *attr,			 char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	u8 *guid;	guid = (u8 *) & (dd->ipath_guid);	return scnprintf(buf, PAGE_SIZE,			 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",			 guid[0], guid[1], guid[2], guid[3],			 guid[4], guid[5], guid[6], guid[7]);}static ssize_t store_guid(struct device *dev,			 struct device_attribute *attr,			  const char *buf,			  size_t count){	struct ipath_devdata *dd = dev_get_drvdata(dev);	ssize_t ret;	unsigned short guid[8];	__be64 new_guid;	u8 *ng;	int i;	if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",		   &guid[0], &guid[1], &guid[2], &guid[3],		   &guid[4], &guid[5], &guid[6], &guid[7]) != 8)		goto invalid;	ng = (u8 *) &new_guid;	for (i = 0; i < 8; i++) {		if (guid[i] > 0xff)			goto invalid;		ng[i] = guid[i];	}	if (new_guid == 0)		goto invalid;	dd->ipath_guid = new_guid;	dd->ipath_nguid = 1;	ret = strlen(buf);	goto bail;invalid:	ipath_dev_err(dd, "attempt to set invalid GUID\n");	ret = -EINVAL;bail:	return ret;}static ssize_t show_nguid(struct device *dev,			  struct device_attribute *attr,			  char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);}static ssize_t show_nports(struct device *dev,			   struct device_attribute *attr,			   char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	/* Return the number of user ports available. */	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_cfgports - 1);}static ssize_t show_serial(struct device *dev,			   struct device_attribute *attr,			   char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	buf[sizeof dd->ipath_serial] = '\0';	memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial);	strcat(buf, "\n");	return strlen(buf);}static ssize_t show_unit(struct device *dev,			 struct device_attribute *attr,			 char *buf){	struct ipath_devdata *dd = dev_get_drvdata(dev);	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);}#define DEVICE_COUNTER(name, attr) \	static ssize_t show_counter_##name(struct device *dev, \					   struct device_attribute *attr, \					   char *buf) \	{ \		struct ipath_devdata *dd = dev_get_drvdata(dev); \		return scnprintf(\			buf, PAGE_SIZE, "%llu\n", (unsigned long long) \			ipath_snap_cntr( \				dd, offsetof(struct infinipath_counters, \					     attr) / sizeof(u64)));	\	} \	static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL);DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt);DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt);DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt);DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt);DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt);DEVICE_COUNTER(lb_ints, LBIntCnt);DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt);DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt);DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt);DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt);DEVICE_COUNTER(rx_dwords, RxDwordCnt);DEVICE_COUNTER(rx_ebps, RxEBPCnt);DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt);DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt);DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt);DEVICE_COUNTER(rx_len_errs, RxLenErrCnt);DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt);DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt);DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt);DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt);DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt);DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt);DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt);DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt);DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?