]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Fix management communication issues by creating character device to take a reference...
authorVaios Papadimitriou <vaios.papadimitriou@emulex.com>
Tue, 8 May 2012 22:01:25 +0000 (17:01 -0500)
committerMaxim Uvarov <maxim.uvarov@oracle.com>
Wed, 9 May 2012 00:01:25 +0000 (17:01 -0700)
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 <maxim.uvarov@oracle.com>
drivers/scsi/lpfc/lpfc_init.c

index b1af6624b94f005a7de809d85e1851aa18e1982c..f5a04ea880ee9d10cdcb81194801cc9cff7f4aa2 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/aer.h>
 #include <linux/slab.h>
 #include <linux/firmware.h>
+#include <linux/miscdevice.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -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)