From: Vaios Papadimitriou Date: Tue, 8 May 2012 22:01:25 +0000 (-0500) Subject: Fix management communication issues by creating character device to take a reference... X-Git-Tag: v2.6.39-400.9.0~423^2~123^2~16 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=20803ce4a7305e8e4b0ce20368974f23e6f29099;p=users%2Fjedix%2Flinux-maple.git Fix management communication issues by creating character device to take a reference on the driver (CR 126082) The management userspace applications have no way to take a lock on the driver to prevent it from unloading. To remedy this a character device is created that will up the reference count on lpfc by one when it is opened and decrement it by one when it is closed. commit id: 3ef6d24cd9f473518dd7941e86cc2a5f8992eed0 Signed-off-by: Maxim Uvarov --- diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b1af6624b94f..f5a04ea880ee 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -10048,6 +10049,36 @@ lpfc_io_resume(struct pci_dev *pdev) return; } +/** + * lpfc_mgmt_open - method called when 'lpfcmgmt' is opened from userspace + * @inode: pointer to the inode representing the lpfcmgmt device + * @filep: pointer to the file representing the open lpfcmgmt device + * + * This routine puts a reference count on the lpfc module whenever the + * character device is opened + **/ +static int +lpfc_mgmt_open(struct inode *inode, struct file *filep) +{ + try_module_get(THIS_MODULE); + return 0; +} + +/** + * lpfc_mgmt_release - method called when 'lpfcmgmt' is closed in userspace + * @inode: pointer to the inode representing the lpfcmgmt device + * @filep: pointer to the file representing the open lpfcmgmt device + * + * This routine removes a reference count from the lpfc module when the + * character device is closed + **/ +static int +lpfc_mgmt_release(struct inode *inode, struct file *filep) +{ + module_put(THIS_MODULE); + return 0; +} + static struct pci_device_id lpfc_id_table[] = { {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER, PCI_ANY_ID, PCI_ANY_ID, }, @@ -10160,6 +10191,17 @@ static struct pci_driver lpfc_driver = { .err_handler = &lpfc_err_handler, }; +static const struct file_operations lpfc_mgmt_fop = { + .open = lpfc_mgmt_open, + .release = lpfc_mgmt_release, +}; + +static struct miscdevice lpfc_mgmt_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "lpfcmgmt", + .fops = &lpfc_mgmt_fop, +}; + /** * lpfc_init - lpfc module initialization routine * @@ -10180,6 +10222,11 @@ lpfc_init(void) printk(LPFC_MODULE_DESC "\n"); printk(LPFC_COPYRIGHT "\n"); + error = misc_register(&lpfc_mgmt_dev); + if (error) + printk(KERN_ERR "Could not register lpfcmgmt device, " + "misc_register returned with status %d", error); + if (lpfc_enable_npiv) { lpfc_transport_functions.vport_create = lpfc_vport_create; lpfc_transport_functions.vport_delete = lpfc_vport_delete; @@ -10216,6 +10263,7 @@ lpfc_init(void) static void __exit lpfc_exit(void) { + misc_deregister(&lpfc_mgmt_dev); pci_unregister_driver(&lpfc_driver); fc_release_transport(lpfc_transport_template); if (lpfc_enable_npiv)