Master-Reservierung und Use-Count f?r NIC-Treiber.
--- 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");