Improved ecdev_offer().

This commit is contained in:
Florian Pose 2008-06-17 10:19:52 +00:00
parent 9aa0789b33
commit 06f499078d
19 changed files with 192 additions and 245 deletions

2
NEWS
View File

@ -49,6 +49,8 @@ Changes in version 1.4.0:
- Exported ecrt_slave_config_sdo(), the generic Sdo configuration
function.
- Removed the bus_state and bus_tainted flags from ec_master_state_t.
* Device interface changes:
- Moved device output parameter of ecdev_offer() to return value.
* Replaces the Sysfs interface with a new 'ethercat' command-line tool. See
'ethercat --help'.
* Removed include/ecdb.h.

View File

@ -1069,10 +1069,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* dev is fully set up and ready to use now */
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) {
printk(KERN_ERR PFX "Failed to offer device.\n");
goto err_out;
}
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (!tp->ecdev) {
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);

View File

@ -1073,10 +1073,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* dev is fully set up and ready to use now */
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) {
printk(KERN_ERR PFX "Failed to offer device.\n");
goto err_out;
}
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (!tp->ecdev) {
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);

View File

@ -1074,10 +1074,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* dev is fully set up and ready to use now */
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) {
printk(KERN_ERR PFX "Failed to offer device.\n");
goto err_out;
}
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (!tp->ecdev) {
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);

View File

@ -1073,10 +1073,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* dev is fully set up and ready to use now */
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) {
printk(KERN_ERR PFX "Failed to offer device.\n");
goto err_out;
}
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (!tp->ecdev) {
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);

View File

@ -1073,10 +1073,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* dev is fully set up and ready to use now */
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) {
printk(KERN_ERR PFX "Failed to offer device.\n");
goto err_out;
}
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (!tp->ecdev) {
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);

View File

@ -1070,10 +1070,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* dev is fully set up and ready to use now */
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) {
printk(KERN_ERR PFX "Failed to offer device.\n");
goto err_out;
}
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (!tp->ecdev) {
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);

View File

@ -1066,10 +1066,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* dev is fully set up and ready to use now */
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) {
printk(KERN_ERR PFX "Failed to offer device.\n");
goto err_out;
}
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (!tp->ecdev) {
DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);

View File

@ -713,11 +713,7 @@ e1000_probe(struct pci_dev *pdev,
}
// offer device to EtherCAT master module
if (ecdev_offer(netdev, ec_poll, THIS_MODULE, &adapter->ecdev)) {
DPRINTK(PROBE, ERR, "Failed to offer device.\n");
goto err_register;
}
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
if (adapter->ecdev) {
if (ecdev_open(adapter->ecdev)) {
ecdev_withdraw(adapter->ecdev);

View File

@ -973,11 +973,7 @@ e1000_probe(struct pci_dev *pdev,
e1000_get_hw_control(adapter);
// offer device to EtherCAT master module
if (ecdev_offer(netdev, ec_poll, THIS_MODULE, &adapter->ecdev)) {
DPRINTK(PROBE, ERR, "Failed to offer device.\n");
goto err_register;
}
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
if (adapter->ecdev) {
if (ecdev_open(adapter->ecdev)) {
ecdev_withdraw(adapter->ecdev);

View File

@ -1180,11 +1180,7 @@ e1000_probe(struct pci_dev *pdev,
e1000_get_hw_control(adapter);
// offer device to EtherCAT master module
if (ecdev_offer(netdev, ec_poll, THIS_MODULE, &adapter->ecdev)) {
DPRINTK(PROBE, ERR, "Failed to offer device.\n");
goto err_register;
}
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
if (adapter->ecdev) {
if (ecdev_open(adapter->ecdev)) {
ecdev_withdraw(adapter->ecdev);

View File

@ -1163,11 +1163,7 @@ e1000_probe(struct pci_dev *pdev,
e1000_get_hw_control(adapter);
// offer device to EtherCAT master module
if (ecdev_offer(netdev, ec_poll, THIS_MODULE, &adapter->ecdev)) {
DPRINTK(PROBE, ERR, "Failed to offer device.\n");
goto err_register;
}
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
if (adapter->ecdev) {
if (ecdev_open(adapter->ecdev)) {
ecdev_withdraw(adapter->ecdev);

View File

@ -1167,11 +1167,7 @@ e1000_probe(struct pci_dev *pdev,
e1000_get_hw_control(adapter);
// offer device to EtherCAT master module
if (ecdev_offer(netdev, ec_poll, THIS_MODULE, &adapter->ecdev)) {
DPRINTK(PROBE, ERR, "Failed to offer device.\n");
goto err_register;
}
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
if (adapter->ecdev) {
if (ecdev_open(adapter->ecdev)) {
ecdev_withdraw(adapter->ecdev);

View File

@ -56,27 +56,27 @@
struct ec_device;
typedef struct ec_device ec_device_t; /**< \see ec_device */
/**
Device poll function type.
*/
/** Device poll function type.
*/
typedef void (*ec_pollfunc_t)(struct net_device *);
/*****************************************************************************/
// Offering/withdrawal functions
/******************************************************************************
* Offering/withdrawal functions
*****************************************************************************/
int ecdev_offer(struct net_device *net_dev, ec_pollfunc_t poll,
struct module *module, ec_device_t **);
ec_device_t *ecdev_offer(struct net_device *net_dev, ec_pollfunc_t poll,
struct module *module);
void ecdev_withdraw(ec_device_t *device);
/*****************************************************************************/
// Device methods
/******************************************************************************
* Device methods
*****************************************************************************/
int ecdev_open(ec_device_t *device);
void ecdev_close(ec_device_t *device);
void ecdev_receive(ec_device_t *device, const void *data, size_t size);
void ecdev_set_link(ec_device_t *device, uint8_t state);
uint8_t ecdev_get_link(ec_device_t *device);
uint8_t ecdev_get_link(const ec_device_t *device);
/*****************************************************************************/

View File

@ -3336,18 +3336,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->autoneg = 1;
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &np->ecdev)) {
printk(KERN_ERR "forcedeth: Failed to offer device.\n");
goto out_freering;
}
np->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (np->ecdev) {
if (ecdev_open(np->ecdev)) {
ecdev_withdraw(np->ecdev);
goto out_freering;
}
}
else {
} else {
err = register_netdev(dev);
if (err) {
printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);

View File

@ -4628,18 +4628,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->autoneg = 1;
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &np->ecdev)) {
printk(KERN_ERR "forcedeth: Failed to offer device.\n");
goto out_error;
}
np->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (np->ecdev) {
if (ecdev_open(np->ecdev)) {
ecdev_withdraw(np->ecdev);
goto out_error;
}
}
else {
} else {
err = register_netdev(dev);
if (err) {
printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);

View File

@ -1733,10 +1733,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&tp->lock);
// offer device to EtherCAT master module
if (ecdev_offer(dev, ec_poll, THIS_MODULE, &tp->ecdev)) {
printk(KERN_ERR PFX "Failed to offer device.\n");
goto err_out_unmap_5;
}
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
if (!tp->ecdev) {
printk(KERN_INFO "about to register device named %s (%p)...\n", dev->name, dev);

View File

@ -60,12 +60,12 @@
/*****************************************************************************/
/**
Device constructor.
\return 0 in case of success, else < 0
*/
int ec_device_init(ec_device_t *device, /**< EtherCAT device */
/** Constructor.
*
* \return 0 in case of success, else < 0
*/
int ec_device_init(
ec_device_t *device, /**< EtherCAT device */
ec_master_t *master /**< master owning the device */
)
{
@ -129,11 +129,11 @@ out_return:
/*****************************************************************************/
/**
EtherCAT device destuctor.
*/
void ec_device_clear(ec_device_t *device /**< EtherCAT device */)
/** Destuctor.
*/
void ec_device_clear(
ec_device_t *device /**< EtherCAT device */
)
{
unsigned int i;
@ -147,11 +147,10 @@ void ec_device_clear(ec_device_t *device /**< EtherCAT device */)
/*****************************************************************************/
/**
Associate with net_device.
*/
void ec_device_attach(ec_device_t *device, /**< EtherCAT device */
/** Associate with net_device.
*/
void ec_device_attach(
ec_device_t *device, /**< EtherCAT device */
struct net_device *net_dev, /**< net_device structure */
ec_pollfunc_t poll, /**< pointer to device's poll function */
struct module *module /**< the device's module */
@ -175,11 +174,11 @@ void ec_device_attach(ec_device_t *device, /**< EtherCAT device */
/*****************************************************************************/
/**
Disconnect from net_device.
*/
void ec_device_detach(ec_device_t *device /**< EtherCAT device */)
/** Disconnect from net_device.
*/
void ec_device_detach(
ec_device_t *device /**< EtherCAT device */
)
{
unsigned int i;
@ -196,12 +195,13 @@ void ec_device_detach(ec_device_t *device /**< EtherCAT device */)
/*****************************************************************************/
/**
Opens the EtherCAT device.
\return 0 in case of success, else < 0
*/
int ec_device_open(ec_device_t *device /**< EtherCAT device */)
/** Opens the EtherCAT device.
*
* \return 0 in case of success, else < 0
*/
int ec_device_open(
ec_device_t *device /**< EtherCAT device */
)
{
if (!device->dev) {
EC_ERR("No net_device to open!\n");
@ -224,12 +224,13 @@ int ec_device_open(ec_device_t *device /**< EtherCAT device */)
/*****************************************************************************/
/**
Stops the EtherCAT device.
\return 0 in case of success, else < 0
*/
int ec_device_close(ec_device_t *device /**< EtherCAT device */)
/** Stops the EtherCAT device.
*
* \return 0 in case of success, else < 0
*/
int ec_device_close(
ec_device_t *device /**< EtherCAT device */
)
{
if (!device->dev) {
EC_ERR("No device to close!\n");
@ -248,12 +249,13 @@ int ec_device_close(ec_device_t *device /**< EtherCAT device */)
/*****************************************************************************/
/**
Returns a pointer to the device's transmit memory.
\return pointer to the TX socket buffer
*/
uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT device */)
/** Returns a pointer to the device's transmit memory.
*
* \return pointer to the TX socket buffer
*/
uint8_t *ec_device_tx_data(
ec_device_t *device /**< EtherCAT device */
)
{
/* cycle through socket buffers, because otherwise there is a race
* condition, if multiple frames are sent and the DMA is not scheduled in
@ -265,15 +267,15 @@ uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT device */)
/*****************************************************************************/
/**
Sends the content of the transmit socket buffer.
Cuts the socket buffer content to the (now known) size, and calls the
start_xmit() function of the assigned net_device.
*/
void ec_device_send(ec_device_t *device, /**< EtherCAT device */
size_t size /**< number of bytes to send */
)
/** Sends the content of the transmit socket buffer.
*
* Cuts the socket buffer content to the (now known) size, and calls the
* start_xmit() function of the assigned net_device.
*/
void ec_device_send(
ec_device_t *device, /**< EtherCAT device */
size_t size /**< number of bytes to send */
)
{
struct sk_buff *skb = device->tx_skb[device->tx_ring_index];
@ -304,10 +306,8 @@ void ec_device_send(ec_device_t *device, /**< EtherCAT device */
/*****************************************************************************/
#ifdef EC_DEBUG_RING
/**
* Appends frame data to the debug ring.
/** Appends frame data to the debug ring.
*/
void ec_device_debug_ring_append(
ec_device_t *device, /**< EtherCAT device */
ec_debug_frame_dir_t dir, /**< direction */
@ -333,10 +333,8 @@ void ec_device_debug_ring_append(
/*****************************************************************************/
/**
* Outputs the debug ring.
/** Outputs the debug ring.
*/
void ec_device_debug_ring_print(
const ec_device_t *device /**< EtherCAT device */
)
@ -376,14 +374,15 @@ void ec_device_debug_ring_print(
/*****************************************************************************/
/**
Calls the poll function of the assigned net_device.
The master itself works without using interrupts. Therefore the processing
of received data and status changes of the network device has to be
done by the master calling the ISR "manually".
*/
void ec_device_poll(ec_device_t *device /**< EtherCAT device */)
/** Calls the poll function of the assigned net_device.
*
* The master itself works without using interrupts. Therefore the processing
* of received data and status changes of the network device has to be
* done by the master calling the ISR "manually".
*/
void ec_device_poll(
ec_device_t *device /**< EtherCAT device */
)
{
device->cycles_poll = get_cycles();
device->jiffies_poll = jiffies;
@ -397,17 +396,80 @@ void ec_device_poll(ec_device_t *device /**< EtherCAT device */)
* Device interface
*****************************************************************************/
/**
Accepts a received frame.
Forwards the received data to the master. The master will analyze the frame
and dispatch the received commands to the sending instances.
\ingroup DeviceInterface
*/
/** Withdraws an EtherCAT device from the master.
*
* The device is disconnected from the master and all device ressources
* are freed.
*
* \attention Before calling this function, the ecdev_stop() function has
* to be called, to be sure that the master does not use the device
* any more.
* \ingroup DeviceInterface
*/
void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */)
{
ec_master_t *master = device->master;
char str[20];
void ecdev_receive(ec_device_t *device, /**< EtherCAT device */
const void *data, /**< pointer to received data */
size_t size /**< number of bytes received */
)
ec_mac_print(device->dev->dev_addr, str);
EC_INFO("Master %u releasing main device %s.\n", master->index, str);
down(&master->device_sem);
ec_device_detach(device);
up(&master->device_sem);
}
/*****************************************************************************/
/** Opens the network device and makes the master enter IDLE mode.
*
* \return 0 on success, else < 0
* \ingroup DeviceInterface
*/
int ecdev_open(ec_device_t *device /**< EtherCAT device */)
{
if (ec_device_open(device)) {
EC_ERR("Failed to open device!\n");
return -1;
}
if (ec_master_enter_idle_mode(device->master)) {
EC_ERR("Failed to enter idle mode!\n");
return -1;
}
return 0;
}
/*****************************************************************************/
/** Makes the master leave IDLE mode and closes the network device.
*
* \return 0 on success, else < 0
* \ingroup DeviceInterface
*/
void ecdev_close(ec_device_t *device /**< EtherCAT device */)
{
ec_master_leave_idle_mode(device->master);
if (ec_device_close(device))
EC_WARN("Failed to close device!\n");
}
/*****************************************************************************/
/** Accepts a received frame.
*
* Forwards the received data to the master. The master will analyze the frame
* and dispatch the received commands to the sending instances.
*
* \ingroup DeviceInterface
*/
void ecdev_receive(
ec_device_t *device, /**< EtherCAT device */
const void *data, /**< pointer to received data */
size_t size /**< number of bytes received */
)
{
const void *ec_data = data + ETH_HLEN;
size_t ec_size = size - ETH_HLEN;
@ -430,19 +492,20 @@ void ecdev_receive(ec_device_t *device, /**< EtherCAT device */
/*****************************************************************************/
/**
Sets a new link state.
If the device notifies the master about the link being down, the master
will not try to send frames using this device.
\ingroup DeviceInterface
*/
void ecdev_set_link(ec_device_t *device, /**< EtherCAT device */
/** Sets a new link state.
*
* If the device notifies the master about the link being down, the master
* will not try to send frames using this device.
*
* \ingroup DeviceInterface
*/
void ecdev_set_link(
ec_device_t *device, /**< EtherCAT device */
uint8_t state /**< new link state */
)
{
if (unlikely(!device)) {
EC_WARN("ecdev_link_state: no device!\n");
EC_WARN("ecdev_set_link(): No device!\n");
return;
}
@ -454,15 +517,16 @@ void ecdev_set_link(ec_device_t *device, /**< EtherCAT device */
/*****************************************************************************/
/**
Reads the link state.
\ingroup DeviceInterface
*/
uint8_t ecdev_get_link(ec_device_t *device /**< EtherCAT device */)
/** Reads the link state.
*
* \ingroup DeviceInterface
*/
uint8_t ecdev_get_link(
const ec_device_t *device /**< EtherCAT device */
)
{
if (unlikely(!device)) {
EC_WARN("ecdev_link_state: no device!\n");
EC_WARN("ecdev_get_link(): No device!\n");
return 0;
}
@ -473,6 +537,9 @@ uint8_t ecdev_get_link(ec_device_t *device /**< EtherCAT device */)
/** \cond */
EXPORT_SYMBOL(ecdev_withdraw);
EXPORT_SYMBOL(ecdev_open);
EXPORT_SYMBOL(ecdev_close);
EXPORT_SYMBOL(ecdev_receive);
EXPORT_SYMBOL(ecdev_get_link);
EXPORT_SYMBOL(ecdev_set_link);

View File

@ -393,16 +393,15 @@ size_t ec_state_string(uint8_t states, /**< slave states */
* The master decides, if it wants to use the device for EtherCAT operation,
* or not. It is important, that the offered net_device is not used by the
* kernel IP stack. If the master, accepted the offer, the address of the
* newly created EtherCAT device is written to the ecdev pointer, else the
* pointer is written to zero.
* newly created EtherCAT device is returned, else \a NULL is returned.
*
* \return 0 on success, else < 0
* \return Pointer to device, if accepted, or NULL if declined.
* \ingroup DeviceInterface
*/
int ecdev_offer(struct net_device *net_dev, /**< net_device to offer */
ec_device_t *ecdev_offer(
struct net_device *net_dev, /**< net_device to offer */
ec_pollfunc_t poll, /**< device poll function */
struct module *module, /**< pointer to the module */
ec_device_t **ecdev /**< pointer to store a device on success */
struct module *module /**< pointer to the module */
)
{
ec_master_t *master;
@ -428,8 +427,7 @@ int ecdev_offer(struct net_device *net_dev, /**< net_device to offer */
up(&master->device_sem);
sprintf(net_dev->name, "ec%u", master->index);
*ecdev = &master->main_device; // offer accepted
return 0; // no error
return &master->main_device; // offer accepted
}
else {
up(&master->device_sem);
@ -441,70 +439,7 @@ int ecdev_offer(struct net_device *net_dev, /**< net_device to offer */
}
}
*ecdev = NULL; // offer declined
return 0; // no error
}
/*****************************************************************************/
/** Withdraws an EtherCAT device from the master.
*
* The device is disconnected from the master and all device ressources
* are freed.
*
* \attention Before calling this function, the ecdev_stop() function has
* to be called, to be sure that the master does not use the device
* any more.
* \ingroup DeviceInterface
*/
void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */)
{
ec_master_t *master = device->master;
char str[20];
ec_mac_print(device->dev->dev_addr, str);
EC_INFO("Master %u releasing main device %s.\n", master->index, str);
down(&master->device_sem);
ec_device_detach(device);
up(&master->device_sem);
}
/*****************************************************************************/
/** Opens the network device and makes the master enter IDLE mode.
*
* \return 0 on success, else < 0
* \ingroup DeviceInterface
*/
int ecdev_open(ec_device_t *device /**< EtherCAT device */)
{
if (ec_device_open(device)) {
EC_ERR("Failed to open device!\n");
return -1;
}
if (ec_master_enter_idle_mode(device->master)) {
EC_ERR("Failed to enter idle mode!\n");
return -1;
}
return 0;
}
/*****************************************************************************/
/** Makes the master leave IDLE mode and closes the network device.
*
* \return 0 on success, else < 0
* \ingroup DeviceInterface
*/
void ecdev_close(ec_device_t *device /**< EtherCAT device */)
{
ec_master_leave_idle_mode(device->master);
if (ec_device_close(device))
EC_WARN("Failed to close device!\n");
return NULL; // offer declined
}
/******************************************************************************
@ -598,9 +533,6 @@ module_init(ec_init_module);
module_exit(ec_cleanup_module);
EXPORT_SYMBOL(ecdev_offer);
EXPORT_SYMBOL(ecdev_withdraw);
EXPORT_SYMBOL(ecdev_open);
EXPORT_SYMBOL(ecdev_close);
EXPORT_SYMBOL(ecrt_request_master);
EXPORT_SYMBOL(ecrt_release_master);