Master-Reservierung und Use-Count f?r NIC-Treiber. kernel2.6
authorFlorian Pose <fp@igh-essen.com>
Fri, 16 Dec 2005 12:04:59 +0000
branchkernel2.6
changeset 33 f4171b8aadf8
parent 32 7d9809fbf7b9
child 34 c1e8d61fa395
Master-Reservierung und Use-Count f?r NIC-Treiber.
drivers/8139too.c
drivers/ec_device.c
drivers/ec_device.h
drivers/ec_master.c
drivers/ec_master.h
drivers/ec_module.c
drivers/ec_module.h
mini/ec_mini.c
rt/msr_module.c
--- a/drivers/8139too.c	Fri Dec 16 09:44:54 2005 +0000
+++ b/drivers/8139too.c	Fri Dec 16 12:04:59 2005 +0000
@@ -202,7 +202,7 @@
 static int ec_device_master_index = 0;
 
 static EtherCAT_device_t rtl_ecat_dev;
-static EtherCAT_master_t *rtl_ecat_master = NULL;
+int rtl_ecat_dev_registered = 0;
 
 /* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
 
@@ -2966,6 +2966,7 @@
 
         EtherCAT_device_init(&rtl_ecat_dev);
         rtl_ecat_dev.isr = rtl8139_interrupt;
+        rtl_ecat_dev.module = THIS_MODULE;
 
         if (pci_module_init(&rtl8139_pci_driver) < 0)
         {
@@ -2977,20 +2978,15 @@
 
         if (rtl_ecat_dev.dev)
         {
-          if ((rtl_ecat_master = EtherCAT_master(ec_device_master_index)) == NULL)
-          {
-            printk(KERN_ERR "Could not get EtherCAT master %i.\n",
-                   ec_device_master_index);
-            goto out_module;
-          }
-
           printk(KERN_INFO "Registering EtherCAT device...\n");
-          if (EtherCAT_register_device(rtl_ecat_master, &rtl_ecat_dev) < 0)
+          if (EtherCAT_register_device(ec_device_master_index, &rtl_ecat_dev) < 0)
           {
             printk(KERN_ERR "Could not register device.\n");
             goto out_module;
           }
 
+          rtl_ecat_dev_registered = 1;
+
           printk(KERN_INFO "EtherCAT device registered and opened.\n");
         }
         else
@@ -3015,10 +3011,10 @@
 
         printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
 
-        if (rtl_ecat_master && rtl_ecat_dev.dev)
+        if (rtl_ecat_dev_registered && rtl_ecat_dev.dev)
         {
           printk(KERN_INFO "Unregistering RTL8139-EtherCAT device...\n");
-          EtherCAT_unregister_device(rtl_ecat_master, &rtl_ecat_dev);
+          EtherCAT_unregister_device(ec_device_master_index, &rtl_ecat_dev);
         }
 
 	pci_unregister_driver(&rtl8139_pci_driver);
--- a/drivers/ec_device.c	Fri Dec 16 09:44:54 2005 +0000
+++ b/drivers/ec_device.c	Fri Dec 16 12:04:59 2005 +0000
@@ -41,6 +41,7 @@
   ecd->state = ECAT_DS_READY;
   ecd->rx_data_length = 0;
   ecd->isr = NULL;
+  ecd->module = NULL;
 }
 
 /***************************************************************/
--- a/drivers/ec_device.h	Fri Dec 16 09:44:54 2005 +0000
+++ b/drivers/ec_device.h	Fri Dec 16 12:04:59 2005 +0000
@@ -63,6 +63,8 @@
   volatile unsigned int rx_data_length; /**< Länge des zuletzt
                                            empfangenen Rahmens */
   irqreturn_t (*isr)(int, void *, struct pt_regs *); /**< Adresse der ISR */
+  struct module *module; /**< Zeiger auf das Modul, das das Gerät zur
+                            Verfügung stellt. */
 }
 EtherCAT_device_t;
 
--- a/drivers/ec_master.c	Fri Dec 16 09:44:54 2005 +0000
+++ b/drivers/ec_master.c	Fri Dec 16 12:04:59 2005 +0000
@@ -69,9 +69,9 @@
 /***************************************************************/
 
 /**
-   Setzt das EtherCAT-Geraet, auf dem der Master arbeitet.
-
-   Registriert das Geraet beim master, der es daraufhin oeffnet.
+   Öffnet ein EtherCAT-Geraet für den Master.
+
+   Registriert das Geraet beim Master, der es daraufhin oeffnet.
 
    @param master Der EtherCAT-Master
    @param device Das EtherCAT-Geraet
@@ -80,12 +80,12 @@
            oder das Geraet nicht geoeffnet werden konnte.
 */
 
-int EtherCAT_register_device(EtherCAT_master_t *master,
-                             EtherCAT_device_t *device)
+int EtherCAT_master_open(EtherCAT_master_t *master,
+                         EtherCAT_device_t *device)
 {
   if (!master || !device)
   {
-    printk(KERN_ERR "EtherCAT: Illegal parameters for register_device()!\n");
+    printk(KERN_ERR "EtherCAT: Illegal parameters for master_open()!\n");
     return -1;
   }
 
@@ -110,18 +110,18 @@
 /***************************************************************/
 
 /**
-   Loescht das EtherCAT-Geraet, auf dem der Master arbeitet.
+   Schliesst das EtherCAT-Geraet, auf dem der Master arbeitet.
 
    @param master Der EtherCAT-Master
    @param device Das EtherCAT-Geraet
 */
 
-void EtherCAT_unregister_device(EtherCAT_master_t *master,
-                                EtherCAT_device_t *device)
+void EtherCAT_master_close(EtherCAT_master_t *master,
+                           EtherCAT_device_t *device)
 {
   if (master->dev != device)
   {
-    printk(KERN_WARNING "EtherCAT: Trying to unregister unknown device.\n");
+    printk(KERN_WARNING "EtherCAT: Trying to close an unknown device!\n");
     return;
   }
 
@@ -1138,8 +1138,8 @@
 
 EXPORT_SYMBOL(EtherCAT_master_init);
 EXPORT_SYMBOL(EtherCAT_master_clear);
-EXPORT_SYMBOL(EtherCAT_register_device);
-EXPORT_SYMBOL(EtherCAT_unregister_device);
+EXPORT_SYMBOL(EtherCAT_master_open);
+EXPORT_SYMBOL(EtherCAT_master_close);
 EXPORT_SYMBOL(EtherCAT_read_process_data);
 EXPORT_SYMBOL(EtherCAT_write_process_data);
 EXPORT_SYMBOL(EtherCAT_check_slaves);
--- a/drivers/ec_master.h	Fri Dec 16 09:44:54 2005 +0000
+++ b/drivers/ec_master.h	Fri Dec 16 12:04:59 2005 +0000
@@ -60,8 +60,8 @@
 void EtherCAT_master_clear(EtherCAT_master_t *);
 
 // Registration of devices
-int EtherCAT_register_device(EtherCAT_master_t *, EtherCAT_device_t *);
-void EtherCAT_unregister_device(EtherCAT_master_t *, EtherCAT_device_t *);
+int EtherCAT_master_open(EtherCAT_master_t *, EtherCAT_device_t *);
+void EtherCAT_master_close(EtherCAT_master_t *, EtherCAT_device_t *);
 
 // Sending and receiving
 int EtherCAT_simple_send_receive(EtherCAT_master_t *, EtherCAT_command_t *);
--- a/drivers/ec_module.c	Fri Dec 16 09:44:54 2005 +0000
+++ b/drivers/ec_module.c	Fri Dec 16 12:04:59 2005 +0000
@@ -30,6 +30,7 @@
 
 int ecat_master_count = 1;
 EtherCAT_master_t *ecat_masters = NULL;
+int *ecat_masters_reserved = NULL;
 
 /******************************************************************************/
 
@@ -44,7 +45,10 @@
 module_init(ecat_init_module);
 module_exit(ecat_cleanup_module);
 
-EXPORT_SYMBOL(EtherCAT_master);
+EXPORT_SYMBOL(EtherCAT_register_device);
+EXPORT_SYMBOL(EtherCAT_unregister_device);
+EXPORT_SYMBOL(EtherCAT_request);
+EXPORT_SYMBOL(EtherCAT_release);
 
 /******************************************************************************/
 
@@ -82,9 +86,18 @@
     return -1;
   }
 
+  if ((ecat_masters_reserved = (int *) kmalloc(sizeof(int) * ecat_master_count,
+                                               GFP_KERNEL)) == NULL)
+  {
+    printk(KERN_ERR "EtherCAT: Could not allocate memory for reservation flags!\n");
+    kfree(ecat_masters);
+    return -1;
+  }
+
   for (i = 0; i < ecat_master_count; i++)
   {
     EtherCAT_master_init(&ecat_masters[i]);
+    ecat_masters_reserved[i] = 0;
   }
 
   printk(KERN_ERR "EtherCAT: Master driver initialized.\n");
@@ -110,6 +123,10 @@
   {
     for (i = 0; i < ecat_master_count; i++)
     {
+      if (ecat_masters_reserved[i]) {
+        printk(KERN_WARNING "EtherCAT: Warning - Master %i is still in use!\n", i);
+      }
+
       EtherCAT_master_clear(&ecat_masters[i]);
     }
 
@@ -119,24 +136,129 @@
   printk(KERN_ERR "EtherCAT: Master driver cleaned up.\n");
 }
 
-/******************************************************************************/
-
-/**
-   Gibt einen Zeiger auf einen bestimmten EtherCAT-Master zurueck.
+/***************************************************************/
+
+/**
+   Setzt das EtherCAT-Geraet, auf dem der Master arbeitet.
+
+   Registriert das Geraet beim Master, der es daraufhin oeffnet.
+
+   @param master Der EtherCAT-Master
+   @param device Das EtherCAT-Geraet
+   @return 0, wenn alles o.k.,
+           < 0, wenn bereits ein Geraet registriert
+           oder das Geraet nicht geoeffnet werden konnte.
+*/
+
+int EtherCAT_register_device(int index, EtherCAT_device_t *device)
+{
+  if (index < 0 || index >= ecat_master_count)
+  {
+    printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index);
+    return -1;
+  }
+
+  return EtherCAT_master_open(&ecat_masters[index], device);
+}
+
+/***************************************************************/
+
+/**
+   Loescht das EtherCAT-Geraet, auf dem der Master arbeitet.
+
+   @param master Der EtherCAT-Master
+   @param device Das EtherCAT-Geraet
+*/
+
+void EtherCAT_unregister_device(int index, EtherCAT_device_t *device)
+{
+  if (index < 0 || index >= ecat_master_count)
+  {
+    printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n", index);
+    return;
+  }
+
+  EtherCAT_master_close(&ecat_masters[index], device);
+}
+
+/******************************************************************************/
+
+/**
+   Reserviert einen bestimmten EtherCAT-Master und das zugehörige Gerät.
+
+   Gibt einen Zeiger auf den reservierten EtherCAT-Master zurueck.
 
    @param index Index des gewuenschten Masters
    @returns Zeiger auf EtherCAT-Master oder NULL, wenn Parameter ungueltig.
 */
 
-EtherCAT_master_t *EtherCAT_master(int index)
-{
-  if (index < 0 || index >= ecat_master_count)
-  {
+EtherCAT_master_t *EtherCAT_request(int index)
+{
+  if (index < 0 || index >= ecat_master_count) {
     printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", index);
     return NULL;
   }
 
+  if (ecat_masters_reserved[index]) {
+    printk(KERN_ERR "EtherCAT: Master %i already in use!\n", index);
+    return NULL;
+  }
+
+  if (!ecat_masters[index].dev) {
+    printk(KERN_ERR "EtherCAT: Master %i has no device assigned yet!\n", index);
+    return NULL;
+  }
+
+  if (!ecat_masters[index].dev->module) {
+    printk(KERN_ERR "EtherCAT: Master %i device module is not set!\n", index);
+    return NULL;
+  }
+
+  if (!try_module_get(ecat_masters[index].dev->module)) {
+    printk(KERN_ERR "EtherCAT: Could not reserve device module!\n");
+    return NULL;
+  }
+
+  ecat_masters_reserved[index] = 1;
+
+  printk(KERN_INFO "EtherCAT: Reserved master %i.\n", index);
+
   return &ecat_masters[index];
 }
 
 /******************************************************************************/
+
+/**
+   Gibt einen zuvor reservierten EtherCAT-Master wieder frei.
+
+   @param master Zeiger auf den freizugebenden EtherCAT-Master.
+*/
+
+void EtherCAT_release(EtherCAT_master_t *master)
+{
+  unsigned int i;
+
+  for (i = 0; i < ecat_master_count; i++)
+  {
+    if (&ecat_masters[i] == master)
+    {
+      if (!ecat_masters[i].dev) {
+        printk(KERN_WARNING "EtherCAT: Could not release device"
+               "module because of no device!\n");
+        return;
+      }
+
+      module_put(ecat_masters[i].dev->module);
+      ecat_masters_reserved[i] = 0;
+
+      printk(KERN_INFO "EtherCAT: Released master %i.\n", i);
+
+      return;
+    }
+  }
+
+  printk(KERN_WARNING "EtherCAT: Master %X was never reserved!\n",
+         (unsigned int) master);
+}
+
+/******************************************************************************/
--- a/drivers/ec_module.h	Fri Dec 16 09:44:54 2005 +0000
+++ b/drivers/ec_module.h	Fri Dec 16 12:04:59 2005 +0000
@@ -29,6 +29,11 @@
 int __init ecat_init_module(void);
 void __exit ecat_cleanup_module(void);
 
-EtherCAT_master_t *EtherCAT_master(int);
+// Registration of devices
+int EtherCAT_register_device(int, EtherCAT_device_t *);
+void EtherCAT_unregister_device(int, EtherCAT_device_t *);
+
+EtherCAT_master_t *EtherCAT_request(int);
+void EtherCAT_release(EtherCAT_master_t *);
 
 /******************************************************************************/
--- a/mini/ec_mini.c	Fri Dec 16 09:44:54 2005 +0000
+++ b/mini/ec_mini.c	Fri Dec 16 12:04:59 2005 +0000
@@ -230,9 +230,9 @@
 {
   printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n");
 
-  if ((ecat_master = EtherCAT_master(0)) == NULL)
+  if ((ecat_master = EtherCAT_request(0)) == NULL)
   {
-    printk(KERN_ERR "No EtherCAT master available!\n");
+    printk(KERN_ERR "EtherCAT master 0 not available!\n");
     return -1;
   }
 
@@ -290,6 +290,8 @@
 
       printk(KERN_INFO "Deactivating slaves.\n");
       EtherCAT_deactivate_all_slaves(ecat_master);
+
+      EtherCAT_release(ecat_master);
     }
 
     printk(KERN_INFO "=== Minimal EtherCAT environment stopped. ===\n");
--- a/rt/msr_module.c	Fri Dec 16 09:44:54 2005 +0000
+++ b/rt/msr_module.c	Fri Dec 16 12:04:59 2005 +0000
@@ -399,9 +399,9 @@
     msr_jitter_init();
   printk(KERN_INFO "=== Starting EtherCAT environment... ===\n");
 
-  if ((ecat_master = EtherCAT_master(0)) == NULL)
+  if ((ecat_master = EtherCAT_request(0)) == NULL)
   {
-    printk(KERN_ERR "No EtherCAT master available!\n");
+    printk(KERN_ERR "EtherCAT master 0 not available!\n");
     msr_rtlib_cleanup();    
     return -1;
   }
@@ -469,6 +469,8 @@
       EtherCAT_clear_process_data(ecat_master);
       printk(KERN_INFO "Deactivating slaves.\n");
       EtherCAT_deactivate_all_slaves(ecat_master);
+
+      EtherCAT_release(ecat_master);
     }
 
     printk(KERN_INFO "=== EtherCAT environment stopped. ===\n");