This patch adds the virtpci debugfs directory and the info entry inside of it. Signed-off-by: Erik Arfvidson <erik.arfvidson@xxxxxxxxxx> Signed-off-by: Benjamin Romer <benjamin.romer@xxxxxxxxxx> --- drivers/staging/unisys/virtpci/virtpci.c | 122 ++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 4 deletions(-) diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c index 7d840b0..6c0aa96 100644 --- a/drivers/staging/unisys/virtpci/virtpci.c +++ b/drivers/staging/unisys/virtpci/virtpci.c @@ -37,6 +37,7 @@ #include <linux/if_ether.h> #include <linux/version.h> #include "version.h" + #include <linux/debugfs.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,95 @@ 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; + int l = *(p->length); + + *(p->length) = l + sprintf(p->buf + l, "bus_id:%s\n", dev_name(vbus)); + return 0; /* no error */ +} + +static ssize_t info_debugfs_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + int length = 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; + + vbuf = kzalloc(len, GFP_KERNEL); + if (!vbuf) + return -ENOMEM; + + length += sprintf(vbuf + length, "CHANSOCK is not defined.\n"); + + length += sprintf(vbuf + length, "\n Virtual PCI Bus devices\n"); + printparam.length = &length; + printparam.buf = vbuf; + if (bus_for_each_dev(&virtpci_bus_type, NULL, + (void *) &printparam, print_vbus)) + LOGERR("delete of all vbus failed\n"); + + length += sprintf(vbuf + length, "\n Virtual PCI devices\n"); + read_lock_irqsave(&VpcidevListLock, flags); + tmpvpcidev = VpcidevListHead; + while (tmpvpcidev) { + if (tmpvpcidev->devtype == VIRTHBA_TYPE) { + length += sprintf(vbuf + length, + "[%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 { + length += sprintf(vbuf + length, "[%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); + } + length += + sprintf(vbuf + length, " chanptr:%p\n", + tmpvpcidev->queueinfo.chan); + tmpvpcidev = tmpvpcidev->next; + } + read_unlock_irqrestore(&VpcidevListLock, flags); + + length += sprintf(vbuf + length, "\n"); + if (copy_to_user(buf, vbuf, length)) { + kfree(vbuf); + return -EFAULT; + } + + kfree(vbuf); + *offset += length; + return length; +} /*****************************************************/ /* Module Init & Exit functions */ @@ -1426,7 +1535,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, 0660, + virtpci_debugfs_dir, NULL, &debugfs_info_fops); LOGINF("Leaving\n"); POSTCODE_LINUX_2(VPCI_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO); return 0; @@ -1442,7 +1554,9 @@ static void __exit virtpci_mod_exit(void) device_unregister(&virtpci_rootbus_device); bus_unregister(&virtpci_bus_type); - + /*debug_fs file and direcroty removal*/ + debugfs_remove(info_debugfs_entry); + debugfs_remove(virtpci_debugfs_dir); LOGINF("Leaving\n"); } -- 1.9.1 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel