📄 pci_hotplug_core.c
字号:
if (ops->owner) \ __MOD_DEC_USE_COUNT(ops->owner); \ return retval; \}GET_STATUS(power)GET_STATUS(attention)GET_STATUS(latch)GET_STATUS(adapter)static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset){ struct hotplug_slot *slot = file->private_data; unsigned char *page; int retval; int len; u8 value; dbg(" count = %d, offset = %lld\n", count, *offset); if (*offset < 0) return -EINVAL; if (count <= 0) return 0; if (*offset != 0) return 0; if (slot == NULL) { dbg("slot == NULL???\n"); return -ENODEV; } page = (unsigned char *)__get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; retval = get_power_status (slot, &value); if (retval) goto exit; len = sprintf (page, "%d\n", value); if (copy_to_user (buf, page, len)) { retval = -EFAULT; goto exit; } *offset += len; retval = len;exit: free_page((unsigned long)page); return retval;}static ssize_t power_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset){ struct hotplug_slot *slot = file->private_data; char *buff; unsigned long lpower; u8 power; int retval = 0; if (*offset < 0) return -EINVAL; if (count <= 0) return 0; if (*offset != 0) return 0; if (slot == NULL) { dbg("slot == NULL???\n"); return -ENODEV; } buff = kmalloc (count + 1, GFP_KERNEL); if (!buff) return -ENOMEM; memset (buff, 0x00, count + 1); if (copy_from_user ((void *)buff, (void *)ubuff, count)) { retval = -EFAULT; goto exit; } lpower = simple_strtoul (buff, NULL, 10); power = (u8)(lpower & 0xff); dbg ("power = %d\n", power); switch (power) { case 0: if (!slot->ops->disable_slot) break; if (slot->ops->owner) __MOD_INC_USE_COUNT(slot->ops->owner); retval = slot->ops->disable_slot(slot); if (slot->ops->owner) __MOD_DEC_USE_COUNT(slot->ops->owner); break; case 1: if (!slot->ops->enable_slot) break; if (slot->ops->owner) __MOD_INC_USE_COUNT(slot->ops->owner); retval = slot->ops->enable_slot(slot); if (slot->ops->owner) __MOD_DEC_USE_COUNT(slot->ops->owner); break; default: err ("Illegal value specified for power\n"); retval = -EFAULT; }exit: kfree (buff); if (retval) return retval; return count;}static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset){ struct hotplug_slot *slot = file->private_data; unsigned char *page; int retval; int len; u8 value; dbg("count = %d, offset = %lld\n", count, *offset); if (*offset < 0) return -EINVAL; if (count <= 0) return 0; if (*offset != 0) return 0; if (slot == NULL) { dbg("slot == NULL???\n"); return -ENODEV; } page = (unsigned char *)__get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; retval = get_attention_status (slot, &value); if (retval) goto exit; len = sprintf (page, "%d\n", value); if (copy_to_user (buf, page, len)) { retval = -EFAULT; goto exit; } *offset += len; retval = len;exit: free_page((unsigned long)page); return retval;}static ssize_t attention_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset){ struct hotplug_slot *slot = file->private_data; char *buff; unsigned long lattention; u8 attention; int retval = 0; if (*offset < 0) return -EINVAL; if (count <= 0) return 0; if (*offset != 0) return 0; if (slot == NULL) { dbg("slot == NULL???\n"); return -ENODEV; } buff = kmalloc (count + 1, GFP_KERNEL); if (!buff) return -ENOMEM; memset (buff, 0x00, count + 1); if (copy_from_user ((void *)buff, (void *)ubuff, count)) { retval = -EFAULT; goto exit; } lattention = simple_strtoul (buff, NULL, 10); attention = (u8)(lattention & 0xff); dbg (" - attention = %d\n", attention); if (slot->ops->set_attention_status) { if (slot->ops->owner) __MOD_INC_USE_COUNT(slot->ops->owner); retval = slot->ops->set_attention_status(slot, attention); if (slot->ops->owner) __MOD_DEC_USE_COUNT(slot->ops->owner); }exit: kfree (buff); if (retval) return retval; return count;}static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset){ struct hotplug_slot *slot = file->private_data; unsigned char *page; int retval; int len; u8 value; dbg("count = %d, offset = %lld\n", count, *offset); if (*offset < 0) return -EINVAL; if (count <= 0) return 0; if (*offset != 0) return 0; if (slot == NULL) { dbg("slot == NULL???\n"); return -ENODEV; } page = (unsigned char *)__get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; retval = get_latch_status (slot, &value); if (retval) goto exit; len = sprintf (page, "%d\n", value); if (copy_to_user (buf, page, len)) { retval = -EFAULT; goto exit; } *offset += len; retval = len;exit: free_page((unsigned long)page); return retval;}static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset){ struct hotplug_slot *slot = file->private_data; unsigned char *page; int retval; int len; u8 value; dbg("count = %d, offset = %lld\n", count, *offset); if (*offset < 0) return -EINVAL; if (count <= 0) return 0; if (*offset != 0) return 0; if (slot == NULL) { dbg("slot == NULL???\n"); return -ENODEV; } page = (unsigned char *)__get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; retval = get_adapter_status (slot, &value); if (retval) goto exit; len = sprintf (page, "%d\n", value); if (copy_to_user (buf, page, len)) { retval = -EFAULT; goto exit; } *offset += len; retval = len;exit: free_page((unsigned long)page); return retval;}static ssize_t test_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset){ struct hotplug_slot *slot = file->private_data; char *buff; unsigned long ltest; u32 test; int retval = 0; if (*offset < 0) return -EINVAL; if (count <= 0) return 0; if (*offset != 0) return 0; if (slot == NULL) { dbg("slot == NULL???\n"); return -ENODEV; } buff = kmalloc (count + 1, GFP_KERNEL); if (!buff) return -ENOMEM; memset (buff, 0x00, count + 1); if (copy_from_user ((void *)buff, (void *)ubuff, count)) { retval = -EFAULT; goto exit; } ltest = simple_strtoul (buff, NULL, 10); test = (u32)(ltest & 0xffffffff); dbg ("test = %d\n", test); if (slot->ops->hardware_test) { if (slot->ops->owner) __MOD_INC_USE_COUNT(slot->ops->owner); retval = slot->ops->hardware_test(slot, test); if (slot->ops->owner) __MOD_DEC_USE_COUNT(slot->ops->owner); }exit: kfree (buff); if (retval) return retval; return count;}static int fs_add_slot (struct hotplug_slot *slot){ struct hotplug_slot_core *core = slot->core_priv; int result; result = get_mount(); if (result) return result; core->dir_dentry = fs_create_file (slot->name, S_IFDIR | S_IXUGO | S_IRUGO, NULL, NULL, NULL); if (core->dir_dentry != NULL) { core->power_dentry = fs_create_file ("power", S_IFREG | S_IRUGO | S_IWUSR, core->dir_dentry, slot, &power_file_operations); core->attention_dentry = fs_create_file ("attention", S_IFREG | S_IRUGO | S_IWUSR, core->dir_dentry, slot, &attention_file_operations); core->latch_dentry = fs_create_file ("latch", S_IFREG | S_IRUGO, core->dir_dentry, slot, &latch_file_operations); core->adapter_dentry = fs_create_file ("adapter", S_IFREG | S_IRUGO, core->dir_dentry, slot, &presence_file_operations); core->test_dentry = fs_create_file ("test", S_IFREG | S_IRUGO | S_IWUSR, core->dir_dentry, slot, &test_file_operations); } return 0;}static void fs_remove_slot (struct hotplug_slot *slot){ struct hotplug_slot_core *core = slot->core_priv; if (core->dir_dentry) { if (core->power_dentry) fs_remove_file (core->power_dentry); if (core->attention_dentry) fs_remove_file (core->attention_dentry); if (core->latch_dentry) fs_remove_file (core->latch_dentry); if (core->adapter_dentry) fs_remove_file (core->adapter_dentry); if (core->test_dentry) fs_remove_file (core->test_dentry); fs_remove_file (core->dir_dentry); } remove_mount();}static struct hotplug_slot *get_slot_from_name (const char *name){ struct hotplug_slot *slot; struct list_head *tmp; list_for_each (tmp, &pci_hotplug_slot_list) { slot = list_entry (tmp, struct hotplug_slot, slot_list); if (strcmp(slot->name, name) == 0) return slot; } return NULL;}/** * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem * @slot: pointer to the &struct hotplug_slot to register * * Registers a hotplug slot with the pci hotplug subsystem, which will allow * userspace interaction to the slot. * * Returns 0 if successful, anything else for an error. */int pci_hp_register (struct hotplug_slot *slot){ struct hotplug_slot_core *core; int result; if (slot == NULL) return -ENODEV; if ((slot->info == NULL) || (slot->ops == NULL)) return -EFAULT; core = kmalloc (sizeof (struct hotplug_slot_core), GFP_KERNEL); if (!core) return -ENOMEM; /* make sure we have not already registered this slot */ spin_lock (&list_lock); if (get_slot_from_name (slot->name) != NULL) { spin_unlock (&list_lock); kfree (core); return -EFAULT; } slot->core_priv = core; list_add (&slot->slot_list, &pci_hotplug_slot_list); spin_unlock (&list_lock); result = fs_add_slot (slot); dbg ("Added slot %s to the list\n", slot->name); return result;}/** * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem * @slot: pointer to the &struct hotplug_slot to deregister * * The @slot must have been registered with the pci hotplug subsystem * previously with a call to pci_hp_register(). * * Returns 0 if successful, anything else for an error. */int pci_hp_deregister (struct hotplug_slot *slot){ struct hotplug_slot *temp; if (slot == NULL) return -ENODEV; /* make sure we have this slot in our list before trying to delete it */ spin_lock (&list_lock); temp = get_slot_from_name (slot->name); if (temp != slot) { spin_unlock (&list_lock); return -ENODEV; } list_del (&slot->slot_list); spin_unlock (&list_lock); fs_remove_slot (slot); kfree(slot->core_priv); dbg ("Removed slot %s from the list\n", slot->name); return 0;}/** * pci_hp_change_slot_info - changes the slot's information structure in the core * @name: the name of the slot whose info has changed * @info: pointer to the info copy into the slot's info structure * * A slot with @name must have been registered with the pci * hotplug subsystem previously with a call to pci_hp_register(). * * Returns 0 if successful, anything else for an error. */int pci_hp_change_slot_info (const char *name, struct hotplug_slot_info *info){ struct hotplug_slot *temp; if (info == NULL) return -ENODEV; spin_lock (&list_lock); temp = get_slot_from_name (name); if (temp == NULL) { spin_unlock (&list_lock); return -ENODEV; } memcpy (temp->info, info, sizeof (struct hotplug_slot_info)); spin_unlock (&list_lock); return 0;}static int __init pci_hotplug_init (void){ int result; spin_lock_init(&mount_lock); spin_lock_init(&list_lock); dbg("registering filesystem.\n"); result = register_filesystem(&pcihpfs_fs_type); if (result) { err("register_filesystem failed with %d\n", result); goto exit; } info (DRIVER_DESC " version: " DRIVER_VERSION "\n");exit: return result;}static void __exit pci_hotplug_exit (void){ unregister_filesystem(&pcihpfs_fs_type);}module_init(pci_hotplug_init);module_exit(pci_hotplug_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debugging mode enabled or not");EXPORT_SYMBOL_GPL(pci_hp_register);EXPORT_SYMBOL_GPL(pci_hp_deregister);EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -