This patch adds the virtpci debugfs directory and the info entry
inside of it.

Signed-off-by: Erik Arfvidson <erik.arfvid...@unisys.com>
---
 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..68fbe85 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,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 */
+}
+
+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;
+
+       vbuf = kzalloc(len, GFP_KERNEL);
+       if (!vbuf)
+               return -ENOMEM;
+
+
+       str_pos += snprintf(vbuf + str_pos, len - str_pos,
+                       "\n Virtual PCI Bus devices\n");
+       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);
        LOGINF("Leaving\n");
 
 }
-- 
1.9.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to