Re: [PATCH] staging: unisys: added virtpci info entry

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jul 10, 2014 at 02:45:12PM -0400, Erik Arfvidson wrote:
> This patch adds the virtpci debugfs directory and the info entry
> inside of it.
> 
> Signed-off-by: Erik Arfvidson <erik.arfvidson@xxxxxxxxxx>
> ---
>  drivers/staging/unisys/virtpci/virtpci.c | 123 ++++++++++++++++++++++++++++++-
>  1 file changed, 119 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c
> index 7d840b0..722bc1b 100644
> --- a/drivers/staging/unisys/virtpci/virtpci.c
> +++ b/drivers/staging/unisys/virtpci/virtpci.c
> @@ -36,6 +36,7 @@
>  #include <linux/mod_devicetable.h>
>  #include <linux/if_ether.h>
>  #include <linux/version.h>
> +#include <linux/debugfs.h>
>  #include "version.h"
>  #include "guestlinuxdebug.h"
>  #include "timskmodutils.h"
> @@ -100,6 +101,12 @@ static int virtpci_device_resume(struct device *dev);
>  static int virtpci_device_probe(struct device *dev);
>  static int virtpci_device_remove(struct device *dev);
>  
> +static ssize_t info_debugfs_read(struct file *file, char __user *buf,
> +			      size_t len, loff_t *offset);
> +
> +static const struct file_operations debugfs_info_fops = {
> +	.read = info_debugfs_read,
> +};
>  
>  /*****************************************************/
>  /* Globals                                           */
> @@ -139,7 +146,19 @@ static DEFINE_RWLOCK(VpcidevListLock);
>  
>  /* filled in with info about this driver, wrt it servicing client busses */
>  static ULTRA_VBUS_DEVICEINFO Bus_DriverInfo;
> -
> +/*****************************************************/
> +/* DebugFS entries                                   */
> +/*****************************************************/
> +/* dentry is used to create the debugfs entry directory
> + * for virtpci
> + */
> +static struct dentry *virtpci_debugfs_dir;
> +static struct dentry *info_debugfs_entry;
> +/* info_debugfs_entry is used to tell virtpci to display current info
> + * kept in the driver
> + */
> +#define DIR_DEBUGFS_ENTRY "virtpci"
> +#define INFO_DEBUGFS_ENTRY_FN "info"
>  
>  struct virtpci_busdev {
>  	struct device virtpci_bus_device;
> @@ -588,7 +607,8 @@ static void delete_all(void)
>  /* deletes all vnics or vhbas
>   * returns 0 failure, 1 success,
>   */
> -static int delete_all_virt(VIRTPCI_DEV_TYPE devtype, struct del_vbus_guestpart *delparams)
> +static int delete_all_virt(VIRTPCI_DEV_TYPE devtype,
> +			struct del_vbus_guestpart *delparams)
>  {
>  	int i;
>  	unsigned char busid[BUS_ID_SIZE];
> @@ -1375,6 +1395,97 @@ void virtpci_unregister_driver(struct virtpci_driver *drv)
>  	DBGINF("Leaving\n");
>  }
>  EXPORT_SYMBOL_GPL(virtpci_unregister_driver);
> +/*****************************************************/
> +/* debugfs filesystem functions						*/
> +/*****************************************************/
> +struct print_vbus_info {
> +	int *length;
> +	char *buf;
> +};
> +
> +static int print_vbus(struct device *vbus, void *data)
> +{
> +	struct print_vbus_info *p = (struct print_vbus_info *)data;
> +
> +	*p->length += sprintf(p->buf + *p->length, "bus_id:%s\n",
> +			      dev_name(vbus));
> +	return 0;		/* no error */

Of course 0 is "no error", that's by definition how Linux kernel
functions work.  No need to add that comment, especially to the right of
the line (which is not kernel coding style at all.)

> +}
> +
> +static ssize_t info_debugfs_read(struct file *file, char __user *buf,
> +			      size_t len, loff_t *offset)
> +{
> +	int str_pos = 0;
> +	struct virtpci_dev *tmpvpcidev;
> +	unsigned long flags;
> +	struct print_vbus_info printparam;
> +	char *vbuf;
> +	loff_t pos = *offset;
> +
> +	if (pos < 0)
> +		return -EINVAL;
> +
> +	if (pos > 0 || !len)
> +		return 0;

So no moving about the file?  Why not?  Why not just use
simple_read_from_buffer() with the string you generate here?  That
handles all the nasty offset mess for you automatically.

> +
> +	vbuf = kzalloc(len, GFP_KERNEL);
> +	if (!vbuf)
> +		return -ENOMEM;
> +
> +

2 blank lines?

Yes, I'm being picky, but this is new code.

> +	str_pos += snprintf(vbuf + str_pos, len - str_pos,
> +			"\n Virtual PCI Bus devices\n");

You start the buffer with an empty line?

> +	printparam.length = &str_pos;
> +	printparam.buf = vbuf;
> +	if (bus_for_each_dev(&virtpci_bus_type, NULL,
> +			     (void *) &printparam, print_vbus))
> +		LOGERR("Failed to find bus\n");
> +
> +	str_pos += snprintf(vbuf + str_pos, len - str_pos,
> +			"\n Virtual PCI devices\n");
> +	read_lock_irqsave(&VpcidevListLock, flags);
> +	tmpvpcidev = VpcidevListHead;
> +	while (tmpvpcidev) {
> +		if (tmpvpcidev->devtype == VIRTHBA_TYPE) {
> +			str_pos += snprintf(vbuf + str_pos, len - str_pos,
> +					"[%d:%d] VHba:%08x:%08x max-config:%d-%d-%d-%d",
> +				    tmpvpcidev->busNo, tmpvpcidev->deviceNo,
> +				    tmpvpcidev->scsi.wwnn.wwnn1,
> +				    tmpvpcidev->scsi.wwnn.wwnn2,
> +				    tmpvpcidev->scsi.max.max_channel,
> +				    tmpvpcidev->scsi.max.max_id,
> +				    tmpvpcidev->scsi.max.max_lun,
> +				    tmpvpcidev->scsi.max.cmd_per_lun);
> +		} else {
> +			str_pos += snprintf(vbuf + str_pos, len - str_pos,
> +					"[%d:%d] VNic:%02x:%02x:%02x:%02x:%02x:%02x num_rcv_bufs:%d mtu:%d",
> +				    tmpvpcidev->busNo, tmpvpcidev->deviceNo,
> +				    tmpvpcidev->net.mac_addr[0],
> +				    tmpvpcidev->net.mac_addr[1],
> +				    tmpvpcidev->net.mac_addr[2],
> +				    tmpvpcidev->net.mac_addr[3],
> +				    tmpvpcidev->net.mac_addr[4],
> +				    tmpvpcidev->net.mac_addr[5],
> +				    tmpvpcidev->net.num_rcv_bufs,
> +				    tmpvpcidev->net.mtu);
> +		}
> +		str_pos +=
> +		    snprintf(vbuf + str_pos, len - str_pos, " chanptr:%p\n",
> +			    tmpvpcidev->queueinfo.chan);
> +		tmpvpcidev = tmpvpcidev->next;
> +	}
> +	read_unlock_irqrestore(&VpcidevListLock, flags);
> +
> +	str_pos += snprintf(vbuf + str_pos, len - str_pos, "\n");
> +	if (copy_to_user(buf, vbuf, str_pos)) {
> +		kfree(vbuf);
> +		return -EFAULT;
> +	}
> +
> +	kfree(vbuf);
> +	*offset += str_pos;
> +	return str_pos;
> +}
>  
>  /*****************************************************/
>  /* Module Init & Exit functions                      */
> @@ -1426,7 +1537,10 @@ static int __init virtpci_mod_init(void)
>  
>  	LOGINF("successfully registered virtpci_ctrlchan_func (0x%p) as callback.\n",
>  	     (void *) &virtpci_ctrlchan_func);
> -
> +	/* create debugfs directory. */
> +	virtpci_debugfs_dir = debugfs_create_dir(DIR_DEBUGFS_ENTRY, NULL);
> +	info_debugfs_entry = debugfs_create_file(INFO_DEBUGFS_ENTRY_FN, S_IRUSR,
> +				virtpci_debugfs_dir, NULL, &debugfs_info_fops);
>  	LOGINF("Leaving\n");
>  	POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO);
>  	return 0;
> @@ -1442,7 +1556,8 @@ static void __exit virtpci_mod_exit(void)
>  
>  	device_unregister(&virtpci_rootbus_device);
>  	bus_unregister(&virtpci_bus_type);
> -
> +	/* debug_fs file and directory removal. */
> +	debugfs_remove(virtpci_debugfs_dir);

Did you test this?  I think you mean to call debugfs_remove_recursive(),
right?

thanks,

greg k-h
_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux