Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Compaq Hot Plug Controller Driver
0004  *
0005  * Copyright (C) 1995,2001 Compaq Computer Corporation
0006  * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
0007  * Copyright (C) 2001 IBM Corp.
0008  *
0009  * All rights reserved.
0010  *
0011  * Send feedback to <greg@kroah.com>
0012  *
0013  */
0014 
0015 #include <linux/module.h>
0016 #include <linux/kernel.h>
0017 #include <linux/slab.h>
0018 #include <linux/types.h>
0019 #include <linux/proc_fs.h>
0020 #include <linux/workqueue.h>
0021 #include <linux/pci.h>
0022 #include <linux/pci_hotplug.h>
0023 #include <linux/mutex.h>
0024 #include <linux/debugfs.h>
0025 #include "cpqphp.h"
0026 
0027 static DEFINE_MUTEX(cpqphp_mutex);
0028 static int show_ctrl(struct controller *ctrl, char *buf)
0029 {
0030     char *out = buf;
0031     int index;
0032     struct pci_resource *res;
0033 
0034     out += sprintf(buf, "Free resources: memory\n");
0035     index = 11;
0036     res = ctrl->mem_head;
0037     while (res && index--) {
0038         out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0039         res = res->next;
0040     }
0041     out += sprintf(out, "Free resources: prefetchable memory\n");
0042     index = 11;
0043     res = ctrl->p_mem_head;
0044     while (res && index--) {
0045         out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0046         res = res->next;
0047     }
0048     out += sprintf(out, "Free resources: IO\n");
0049     index = 11;
0050     res = ctrl->io_head;
0051     while (res && index--) {
0052         out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0053         res = res->next;
0054     }
0055     out += sprintf(out, "Free resources: bus numbers\n");
0056     index = 11;
0057     res = ctrl->bus_head;
0058     while (res && index--) {
0059         out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0060         res = res->next;
0061     }
0062 
0063     return out - buf;
0064 }
0065 
0066 static int show_dev(struct controller *ctrl, char *buf)
0067 {
0068     char *out = buf;
0069     int index;
0070     struct pci_resource *res;
0071     struct pci_func *new_slot;
0072     struct slot *slot;
0073 
0074     slot = ctrl->slot;
0075 
0076     while (slot) {
0077         new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
0078         if (!new_slot)
0079             break;
0080         out += sprintf(out, "assigned resources: memory\n");
0081         index = 11;
0082         res = new_slot->mem_head;
0083         while (res && index--) {
0084             out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0085             res = res->next;
0086         }
0087         out += sprintf(out, "assigned resources: prefetchable memory\n");
0088         index = 11;
0089         res = new_slot->p_mem_head;
0090         while (res && index--) {
0091             out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0092             res = res->next;
0093         }
0094         out += sprintf(out, "assigned resources: IO\n");
0095         index = 11;
0096         res = new_slot->io_head;
0097         while (res && index--) {
0098             out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0099             res = res->next;
0100         }
0101         out += sprintf(out, "assigned resources: bus numbers\n");
0102         index = 11;
0103         res = new_slot->bus_head;
0104         while (res && index--) {
0105             out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0106             res = res->next;
0107         }
0108         slot = slot->next;
0109     }
0110 
0111     return out - buf;
0112 }
0113 
0114 static int spew_debug_info(struct controller *ctrl, char *data, int size)
0115 {
0116     int used;
0117 
0118     used = size - show_ctrl(ctrl, data);
0119     used = (size - used) - show_dev(ctrl, &data[used]);
0120     return used;
0121 }
0122 
0123 struct ctrl_dbg {
0124     int size;
0125     char *data;
0126     struct controller *ctrl;
0127 };
0128 
0129 #define MAX_OUTPUT  (4*PAGE_SIZE)
0130 
0131 static int open(struct inode *inode, struct file *file)
0132 {
0133     struct controller *ctrl = inode->i_private;
0134     struct ctrl_dbg *dbg;
0135     int retval = -ENOMEM;
0136 
0137     mutex_lock(&cpqphp_mutex);
0138     dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
0139     if (!dbg)
0140         goto exit;
0141     dbg->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
0142     if (!dbg->data) {
0143         kfree(dbg);
0144         goto exit;
0145     }
0146     dbg->size = spew_debug_info(ctrl, dbg->data, MAX_OUTPUT);
0147     file->private_data = dbg;
0148     retval = 0;
0149 exit:
0150     mutex_unlock(&cpqphp_mutex);
0151     return retval;
0152 }
0153 
0154 static loff_t lseek(struct file *file, loff_t off, int whence)
0155 {
0156     struct ctrl_dbg *dbg = file->private_data;
0157     return fixed_size_llseek(file, off, whence, dbg->size);
0158 }
0159 
0160 static ssize_t read(struct file *file, char __user *buf,
0161             size_t nbytes, loff_t *ppos)
0162 {
0163     struct ctrl_dbg *dbg = file->private_data;
0164     return simple_read_from_buffer(buf, nbytes, ppos, dbg->data, dbg->size);
0165 }
0166 
0167 static int release(struct inode *inode, struct file *file)
0168 {
0169     struct ctrl_dbg *dbg = file->private_data;
0170 
0171     kfree(dbg->data);
0172     kfree(dbg);
0173     return 0;
0174 }
0175 
0176 static const struct file_operations debug_ops = {
0177     .owner = THIS_MODULE,
0178     .open = open,
0179     .llseek = lseek,
0180     .read = read,
0181     .release = release,
0182 };
0183 
0184 static struct dentry *root;
0185 
0186 void cpqhp_initialize_debugfs(void)
0187 {
0188     if (!root)
0189         root = debugfs_create_dir("cpqhp", NULL);
0190 }
0191 
0192 void cpqhp_shutdown_debugfs(void)
0193 {
0194     debugfs_remove(root);
0195 }
0196 
0197 void cpqhp_create_debugfs_files(struct controller *ctrl)
0198 {
0199     ctrl->dentry = debugfs_create_file(dev_name(&ctrl->pci_dev->dev),
0200                        S_IRUGO, root, ctrl, &debug_ops);
0201 }
0202 
0203 void cpqhp_remove_debugfs_files(struct controller *ctrl)
0204 {
0205     debugfs_remove(ctrl->dentry);
0206     ctrl->dentry = NULL;
0207 }
0208