On 2013-03-06 14:58, Jerome Poncin wrote:
> diff --git a/ksrc/drivers/cifx/cifx_pci.c b/ksrc/drivers/cifx/cifx_pci.c
> new file mode 100644
> index 0000000..e04ddb7
> --- /dev/null
> +++ b/ksrc/drivers/cifx/cifx_pci.c
> @@ -0,0 +1,634 @@
> +/*
> + * Copyright (C) 2013 Hilscher France (JP) <www.hilscher.fr>
> + *
> + * Xenomai is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * Xenomai is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with Xenomai; if not, write to the Free Software Foundation,
> + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/io.h>
> +#include <linux/mman.h>
> +
> +#include <asm-generic/xenomai/pci_ids.h>
> +
> +#include <rtdm/rtdm_driver.h>
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("RTDM board driver for CifX cards");
> +MODULE_AUTHOR("Hilscher France (JP) <www.hilscher.fr>");
> +
> +#define DPM_HOST_INT_EN0                0xfff0
> +#define DPM_HOST_INT_STAT0              0xffe0
> +#define PLX_GPIO_OFFSET                 0x15
> +#define PLX_TIMING_OFFSET               0x0a
> +
> +#define DPM_HOST_INT_MASK               0xe600ffff
> +#define DPM_HOST_INT_GLOBAL_EN          0x80000000
> +#define PLX_GPIO_DATA0_MASK             0x00000004
> +#define PLX_GPIO_DATA1_MASK             0x00000020
> +
> +#define NX_PCA_PCI_8_BIT_DPM_MODE       0x5431F962
> +#define NX_PCA_PCI_16_BIT_DPM_MODE      0x4073F8E2
> +#define NX_PCA_PCI_32_BIT_DPM_MODE      0x40824122
> +
> +/* Number of bar */
> +/* points to the DPM -> netX, netPLC, netJACK */
> +#define DPM_BAR                         0
> +/* points to the optional extended memory     */
> +#define EXT_MEM_BAR                     1
> +/* points to the DPM -> netXPLX               */
> +#define PLX_DPM_BAR                     2
> +/* timing config register                     */
> +#define PXA_PLX_BAR                     0
> +
> +/* Index of io_info structure's memory array */
> +/* first mapping describes DPM              */
> +#define DPM_INDEX                       0
> +/* second mapping describes extended memory */
> +#define EXT_MEM_INDEX                   1
> +
> +#define MAX_MAPS                        2
> +
> +#define MEM_PHYS                        1
> +
> +#define DRIVER_NAME                     "rtdm_cifx"
> +#define PERIPHERAL_NAME                 "cifx"
> +#define PROVIDER_NAME                   "Hilscher"
> +
> +/* name of a NXSB-PCA or NXPCA-PCI card */
> +#define CIFX_RTDM_PLX_CARD_NAME         "netx_plx"
> +/* name of a cifX PCI card              */
> +#define CIFX_RTDM_CARD_NAME             "netx"
> +/* name of a netPLC PCI card            */
> +#define CIFX_RTDM_NETPLC_CARD_NAME      "netplc"
> +/* name of a netJACK PCI card           */
> +#define CIFX_RTDM_NETJACK_CARD_NAME     "netjack"
> +
> +struct io_mem {
> +    uint32_t addr;

The kernel uses tabs, not 4 spaces. You can try linux/scripts/Lindent,
and then manually post-process the result so that it looks good without
violating checkpatch requirements.

> +    uint32_t size;
> +    int32_t memtype;
> +    void __iomem *internal_addr;
> +};
> +
> +struct io_info {
> +    struct io_mem mem[MAX_MAPS];
> +    int32_t irq;
> +    bool irq_enable;
> +    bool irq_registered;
> +    rtdm_irq_t irq_handle;
> +    struct ext_io_info *priv;
> +};
> +
> +struct ext_io_info {
> +    uint32_t __iomem *plx;
> +    uint8_t dpm_mode;
> +    uint32_t plx_timing;
> +};
> +
> +struct io_map_mem {
> +    uint32_t phys_addr;
> +    void **virt_addr;
> +    uint32_t length;
> +};
> +
> +static struct io_info *cifx_get_device_data(struct rtdm_device *info);
> +static struct ext_io_info *cifx_get_private(struct rtdm_device *info);
> +
> +static int cifx_set_plx_timing(struct rtdm_device *info);
> +static int cifx_get_plx_timing(struct rtdm_device *info);
> +static int cifx_get_dpm_mode(struct rtdm_device *info);
> +
> +static int cifx_pci_open(struct rtdm_dev_context *context,
> +             rtdm_user_info_t *user_info, int oflags);
> +static int cifx_pci_close(struct rtdm_dev_context *context,
> +              rtdm_user_info_t *user_info);
> +static ssize_t cifx_pci_read(struct rtdm_dev_context *context,
> +                 rtdm_user_info_t *user_info, void *buf,
> +                 size_t nbyte);
> +static ssize_t cifx_pci_write(struct rtdm_dev_context *context,
> +                  rtdm_user_info_t *user_info, const void *buf,
> +                  size_t nbyte);
> +
> +static int cifx_pci_probe(struct pci_dev *dev, const struct
> pci_device_id *id);
> +static void cifx_pci_remove(struct pci_dev *dev);
> +
> +/* Number or cifx found and open */
> +static int32_t cifx_num;
> +
> +/* RTDM Device information structure */
> +static const struct rtdm_device __initdata cifx_device_tmpl = {
> +    .struct_version = RTDM_DEVICE_STRUCT_VER,
> +
> +    .device_flags = RTDM_NAMED_DEVICE,
> +    .context_size = 0,
> +    .device_name = "",
> +
> +    .open_nrt = cifx_pci_open,
> +
> +    .ops = {
> +        .close_nrt = cifx_pci_close,
> +
> +        .read_nrt = cifx_pci_read,
> +        .write_nrt = cifx_pci_write,
> +
> +        .ioctl_rt = NULL,
> +        .ioctl_nrt = NULL,
> +
> +        .read_rt = NULL,
> +        .write_rt = NULL,

This is no RTDM driver. You provide zero real-time services, thus your
Xenomai user could simply work against the standard UIO driver.

I suppose you really want to find a box on which you can test and
finalize IRQ support now. Otherwise, this whole RTDM excercise is really
pointless.

I'm reviewing the rest nevertheless, just in case.

> +        },
> +
> +    .device_class = RTDM_CLASS_EXPERIMENTAL,
> +    .device_sub_class = RTDM_SUBCLASS_GENERIC,
> +    .profile_version = 1,
> +    .driver_name = DRIVER_NAME,
> +    .driver_version = RTDM_DRIVER_VER(1, 0, 0),
> +    .provider_name = PROVIDER_NAME,
> +};
> +
> +/* Device table */
> +static DEFINE_PCI_DEVICE_TABLE(cifx_pci_tbl) = {
> +    {PCI_VENDOR_ID_HILSCHER, PCI_DEVICE_ID_HILSCHER_NETX,
> +    0, 0},
> +    {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
> +    PCI_VENDOR_ID_PLX, PCI_SUBDEVICE_ID_NXSB_PCA},
> +    {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
> +    PCI_VENDOR_ID_PLX, PCI_SUBDEVICE_ID_NXPCA},
> +    {PCI_VENDOR_ID_HILSCHER, PCI_DEVICE_ID_HILSCHER_NETPLC,
> +    PCI_VENDOR_ID_HILSCHER, PCI_SUBDEVICE_ID_NETPLC_RAM},
> +    {PCI_VENDOR_ID_HILSCHER, PCI_DEVICE_ID_HILSCHER_NETPLC,
> +    PCI_VENDOR_ID_HILSCHER, PCI_SUBDEVICE_ID_NETPLC_FLASH},
> +    {PCI_VENDOR_ID_HILSCHER, PCI_DEVICE_ID_HILSCHER_NETJACK,
> +    PCI_VENDOR_ID_HILSCHER, PCI_SUBDEVICE_ID_NETJACK_RAM},
> +    {PCI_VENDOR_ID_HILSCHER, PCI_DEVICE_ID_HILSCHER_NETJACK,
> +    PCI_VENDOR_ID_HILSCHER, PCI_SUBDEVICE_ID_NETJACK_FLASH},
> +    { 0,}
> +};
> +
> +/* RTDM cifX Driver */
> +static struct pci_driver cifx_pci_driver = {
> +    .name = "cifx",
> +    .id_table = cifx_pci_tbl,
> +    .probe = cifx_pci_probe,
> +    .remove = cifx_pci_remove,
> +};
> +
> +/*
> + *    cifx_rtdm_device_to_device_data
> + *    Get device_data structure
> + */
> +static struct io_info *cifx_get_device_data(struct rtdm_device *info)
> +{
> +    return info->device_data;
> +}
> +
> +/*
> + *    cifx_rtdm_device_to_private
> + *    Get ext_io_info structure
> + */
> +static struct ext_io_info *cifx_get_private(struct rtdm_device *info)
> +{
> +    return ((struct io_info *)info->device_data)->priv;
> +}
> +
> +/*
> + *    cifx_set_plx_timing
> + *    Set plx timing
> + */
> +static int cifx_set_plx_timing(struct rtdm_device *info)
> +{
> +    struct ext_io_info *ext_info = cifx_get_private(info);
> +    uint32_t __iomem *plx_timing;
> +
> +    if (ext_info == NULL)

Well... you set it to non-NULL only a few lines before calling this
function.

But why calling this function with an rtdm_device pointer when it needs
ext_io_info and the caller has this reference? Needless complication.

> +        return -ENODEV;
> +
> +    plx_timing = ext_info->plx + PLX_TIMING_OFFSET;
> +    *plx_timing = ext_info->plx_timing;
> +
> +    return 0;
> +}
> +
> +/*
> + * cifx_get_plx_timing
> + * Get plx timing
> + */
> +static int cifx_get_plx_timing(struct rtdm_device *info)
> +{
> +    struct ext_io_info *ext_info = cifx_get_private(info);
> +
> +    if (ext_info == NULL)

Same here.

> +        return -ENODEV;
> +
> +    switch (ext_info->dpm_mode) {
> +    case 8:
> +        ext_info->plx_timing = NX_PCA_PCI_8_BIT_DPM_MODE;
> +        break;
> +    case 16:
> +        ext_info->plx_timing = NX_PCA_PCI_16_BIT_DPM_MODE;
> +        break;
> +    case 32:
> +        ext_info->plx_timing = NX_PCA_PCI_32_BIT_DPM_MODE;
> +        break;
> +    default:
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +/*
> + * cifx_get_dpm_mode
> + * Get dpm mode
> + */
> +static int cifx_get_dpm_mode(struct rtdm_device *info)
> +{
> +    struct ext_io_info *ext_info = cifx_get_private(info);
> +    uint32_t __iomem *plx_gpio;
> +
> +    if (ext_info == NULL)
> +        return -ENODEV;

And here.

> +
> +    plx_gpio = ext_info->plx + PLX_GPIO_OFFSET;
> +
> +    if ((*plx_gpio & PLX_GPIO_DATA0_MASK)
> +        && ~(*plx_gpio & PLX_GPIO_DATA1_MASK))
> +        ext_info->dpm_mode = 8;
> +    else if (~(*plx_gpio & PLX_GPIO_DATA0_MASK)
> +         && (*plx_gpio & PLX_GPIO_DATA1_MASK))
> +        ext_info->dpm_mode = 32;
> +    else if (~(*plx_gpio & PLX_GPIO_DATA0_MASK)
> +         && ~(*plx_gpio & PLX_GPIO_DATA1_MASK))
> +        ext_info->dpm_mode = 16;
> +    else
> +        return -EINVAL;
> +
> +    return 0;
> +}
> +
> +/*
> + * cifx_pci_open
> + * Open RTDM cifx pci driver
> + */
> +static int cifx_pci_open(struct rtdm_dev_context *context,
> +             rtdm_user_info_t *user_info, int oflags)
> +{
> +    return 0;
> +}
> +
> +/*
> + * cifx_pci_close
> + * Close RTDM cifx pci driver
> + */
> +static int cifx_pci_close(struct rtdm_dev_context *context,
> +              rtdm_user_info_t *user_info)
> +{
> +    return 0;
> +}
> +
> +/*
> + * cifx_pci_read
> + * Read
> + */
> +static ssize_t cifx_pci_read(struct rtdm_dev_context *context,
> +                 rtdm_user_info_t *user_info, void *buf,
> +                 size_t nbyte)

read() is supposed to provide read access to *stream* like data sources.
You misuse it to deliver a static (after initialization) device
descripion. Better model this with a more descriptive IOCTL. And
document the API in the header you will need for the IOCTLs. Doxgen
format, please. There are several examples in include/rtdm.

> +{
> +    struct rtdm_device *info = (struct rtdm_device *)context->device;
> +
> +    if (nbyte > sizeof(struct io_info))
> +        return 0;

Still wrong.

> +
> +    /* Copy data information for userland */
> +    if (rtdm_safe_copy_to_user(user_info, buf, info->device_data, nbyte))
> +        return 0;

Also this.

> +
> +    return nbyte;
> +}
> +
> +/*
> + * cifx_pci_write
> + * write
> + */
> +static ssize_t cifx_pci_write(struct rtdm_dev_context *context,
> +                  rtdm_user_info_t *user_info, const void *buf,
> +                  size_t nbyte)

Also here: Do not misuse write(), define an IOCTL that contains
something like "MMAP" and another one with MUNMAP in its name - that's
the purpose of this service, no?

> +{
> +    struct io_map_mem map_mem;
> +    int ret;
> +
> +    switch (nbyte) {
> +    case sizeof(map_mem):
> +        /* Copy data information for Kernel */
> +        if (rtdm_safe_copy_from_user(user_info, &map_mem, buf, nbyte))
> +            return 0;

And this is another bogus error code.

> +
> +        if (*map_mem.virt_addr == NULL) {
> +            /* Map physical on virtual memory */
> +            ret = rtdm_iomap_to_user(user_info,
> +                        map_mem.
> +                        phys_addr,
> +                        map_mem.length,
> +                        (PROT_READ | PROT_WRITE),
> +                        map_mem.virt_addr,
> +                        NULL,
> +                        NULL);
> +
> +            if (ret != 0)
> +                return 0;

And this.

> +        } else {
> +            /* Unap virtual memory */
> +            ret = rtdm_munmap(user_info,
> +                    *map_mem.virt_addr,
> +                    map_mem.length);
> +
> +            if (ret != 0)
> +                return 0;

And another bug. You make it hard for userland to discover its own bugs
by hiding proper error codes systematically.

> +        }
> +        break;
> +
> +    default:
> +        /* Error */
> +        return 0;

Since when is 0 a valid error code?

> +    }
> +
> +    return nbyte;
> +}
> +
> +static int cifx_pci_probe(struct pci_dev *dev, const struct
> pci_device_id *id)
> +{
> +    struct rtdm_device *info = NULL;
> +    struct io_info *device_data = NULL;
> +    int32_t bar;
> +    int32_t ret;
> +
> +    /* Allocate device driver structure */
> +    info = rtdm_malloc(sizeof(struct rtdm_device));

As I already told you: You are in non-RT context here, thus normal
kmalloc is sufficient. Please fix,

> +
> +    if (info == NULL)
> +        return -ENOMEM;
> +
> +    ret = pci_enable_device(dev);
> +    if (ret != 0)
> +        goto out_free;
> +
> +    ret = pci_request_regions(dev, DRIVER_NAME);
> +    if (ret != 0)
> +        goto out_disable;
> +
> +    /* Initialize structure with default values */
> +    memcpy(info, &cifx_device_tmpl, sizeof(*info));
> +
> +    info->device_id = id->device;
> +    snprintf(info->device_name, RTDM_MAX_DEVNAME_LEN, "cifx%i", cifx_num);
> +    info->proc_name = info->device_name;
> +
> +    switch (id->device) {
> +    case PCI_DEVICE_ID_HILSCHER_NETX:
> +        bar = DPM_BAR;
> +        info->peripheral_name = CIFX_RTDM_CARD_NAME;
> +        break;
> +    case PCI_DEVICE_ID_HILSCHER_NETPLC:
> +        bar = DPM_BAR;
> +        info->peripheral_name = CIFX_RTDM_NETPLC_CARD_NAME;
> +        break;
> +    case PCI_DEVICE_ID_HILSCHER_NETJACK:
> +        bar = DPM_BAR;
> +        info->peripheral_name = CIFX_RTDM_NETJACK_CARD_NAME;
> +        break;
> +    default:
> +        bar = PLX_DPM_BAR;
> +        info->peripheral_name = CIFX_RTDM_PLX_CARD_NAME;
> +        break;
> +    }
> +
> +    info->device_data = NULL;
> +
> +    /* Allocate specific data strcuture for device */
> +    device_data = rtdm_malloc(sizeof(*device_data));
> +
> +    if (device_data == NULL)
> +        goto out_release;
> +
> +    memset(device_data, 0, sizeof(*device_data));
> +
> +    /* BAR 0 or 2 points to the card's dual port memory */
> +    device_data->mem[DPM_INDEX].addr = pci_resource_start(dev, bar);
> +
> +    if (device_data->mem[DPM_INDEX].addr == 0)
> +        goto out_release;
> +
> +    device_data->mem[DPM_INDEX].internal_addr =
> +        ioremap_nocache(pci_resource_start(dev, bar),
> +                        pci_resource_len(dev, bar));
> +
> +    if (device_data->mem[DPM_INDEX].internal_addr == 0)
> +        goto out_release;
> +
> +    dev_info(&dev->dev, "DPM at %08X\n",
> device_data->mem[DPM_INDEX].addr);
> +    device_data->mem[DPM_INDEX].size = pci_resource_len(dev, bar);
> +    device_data->mem[DPM_INDEX].memtype = MEM_PHYS;
> +
> +    /* map extended mem (BAR 1 points to the extended memory) */
> +    device_data->mem[EXT_MEM_INDEX].addr =
> +                    pci_resource_start(dev, EXT_MEM_BAR);
> +
> +    /* extended memory is optional, so don't care if it is not present */
> +    if (device_data->mem[EXT_MEM_INDEX].addr != 0) {
> +        device_data->mem[EXT_MEM_INDEX].internal_addr =
> +            ioremap_nocache(pci_resource_start(dev, EXT_MEM_BAR),
> +                    pci_resource_len(dev, EXT_MEM_BAR));
> +
> +        if (device_data->mem[EXT_MEM_INDEX].internal_addr == 0)
> +            goto out_unmap;
> +
> +        dev_info(&dev->dev,
> +                "extended memory at %08X\n",
> +                device_data->mem[EXT_MEM_INDEX].addr);
> +        device_data->mem[EXT_MEM_INDEX].size =
> +                    pci_resource_len(dev, EXT_MEM_BAR);
> +        device_data->mem[EXT_MEM_INDEX].memtype = MEM_PHYS;
> +    }
> +
> +    if ((id->device == PCI_DEVICE_ID_HILSCHER_NETX)
> +        || (id->device == PCI_DEVICE_ID_HILSCHER_NETPLC)
> +        || (id->device == PCI_DEVICE_ID_HILSCHER_NETJACK)) {
> +        /* make sure all interrupts are disabled */
> +        iowrite32(0, device_data->mem[DPM_INDEX].internal_addr
> +                            + DPM_HOST_INT_EN0);
> +        device_data->priv = NULL;
> +    } else if (id->subdevice == PCI_SUBDEVICE_ID_NXPCA) {
> +        /* map PLX registers */
> +        struct ext_io_info *ext_info;
> +
> +        ext_info = rtdm_malloc(sizeof(*ext_info));
> +
> +        if (ext_info == NULL)
> +            goto out_unmap;
> +
> +        device_data->priv = ext_info;
> +
> +        /* set PXA PLX Timings */
> +        ext_info->plx = ioremap_nocache(
> +                    pci_resource_start(dev, PXA_PLX_BAR),
> +                    pci_resource_len(dev, PXA_PLX_BAR));
> +
> +        if (ext_info->plx == NULL)
> +            goto out_unmap;
> +        if (cifx_get_dpm_mode(info))
> +            goto out_unmap_plx;
> +        if (cifx_get_plx_timing(info))
> +            goto out_unmap_plx;
> +        if (cifx_set_plx_timing(info))
> +            goto out_unmap_plx;
> +    } else {
> +        struct ext_io_info *ext_info;
> +
> +        ext_info = rtdm_malloc(sizeof(*ext_info));
> +
> +        if (ext_info == NULL)
> +            goto out_free_pxa;
> +
> +        ext_info->plx = NULL;
> +        ext_info->plx_timing = 0;
> +        ext_info->dpm_mode = 0;
> +        device_data->priv = ext_info;
> +    }
> +
> +    /* Initialize irq data */
> +    device_data->irq = dev->irq;
> +    device_data->irq_enable = 0;
> +    device_data->irq_registered = 0;
> +
> +    info->device_data = device_data;
> +
> +    /* Register RTDM device driver */
> +    ret = rtdm_dev_register(info);
> +    if (ret != 0) {
> +        if (id->subdevice != PCI_SUBDEVICE_ID_NXPCA)
> +            goto out_unmap;
> +        else
> +            goto out_unmap_plx;
> +    }
> +
> +    pci_set_drvdata(dev, info);
> +
> +    if (id->device == PCI_DEVICE_ID_HILSCHER_NETX)
> +        dev_info(&dev->dev, "registered CifX card\n");
> +    else if (id->device == PCI_DEVICE_ID_HILSCHER_NETPLC)
> +        dev_info(&dev->dev, "registered netPLC card\n");
> +    else if (id->device == PCI_DEVICE_ID_HILSCHER_NETJACK)
> +        dev_info(&dev->dev, "registered netJACK card\n");
> +    else if (id->subdevice == PCI_SUBDEVICE_ID_NXSB_PCA)
> +        dev_info(&dev->dev, "registered NXSB-PCA adapter card\n");
> +    else {
> +        struct ext_io_info *ext_info = device_data->priv;
> +        dev_info(&dev->dev,
> +            "registered NXPCA-PCI adapter card in %d bit mode\n",
> +            ((struct ext_io_info *)ext_info)->dpm_mode);
> +    }
> +
> +    cifx_num++;
> +
> +    return 0;
> +
> + out_unmap_plx:
> +    iounmap((device_data->priv)->plx);
> +
> + out_free_pxa:
> +    rtdm_free(device_data->priv);
> +
> + out_unmap:
> +    iounmap(device_data->mem[DPM_INDEX].internal_addr);
> +    if (device_data->mem[EXT_MEM_INDEX].internal_addr != 0)
> +        iounmap(device_data->mem[EXT_MEM_INDEX].internal_addr);
> +
> + out_release:
> +    pci_release_regions(dev);
> +
> + out_disable:
> +    pci_disable_device(dev);
> +
> + out_free:
> +    if (info->device_data != NULL)
> +        rtdm_free(info->device_data);
> +
> +    rtdm_free(info);
> +
> +    return -ENODEV;

You throw aways what ret may contain about the error. You just need to
initialize it when the reason was "allocated_memory == NULL" to -ENOMEM.

> +}
> +
> +static void cifx_pci_remove(struct pci_dev *dev)
> +{
> +    struct rtdm_device *info = pci_get_drvdata(dev);
> +    struct io_info *device_data = cifx_get_device_data(info);
> +    struct ext_io_info *ext_info = cifx_get_private(info);
> +    int32_t ret;
> +
> +    if (info->device_data == NULL)
> +        return;
> +
> +    if (ext_info != NULL) {
> +        /* Disable all interrupts */
> +        iowrite32(0, device_data->mem[DPM_INDEX].internal_addr
> +                            + DPM_HOST_INT_EN0);
> +
> +        if (ext_info->plx != NULL)
> +            iounmap((void *)ext_info->plx);
> +
> +        rtdm_free((void *)ext_info);
> +    }
> +
> +    /* Unregister RTDM device driver */
> +    ret = rtdm_dev_unregister(info, 1000);
> +    if (ret != 0)
> +        return;

Either WARN() or ignore this (practically) impossible error.

> +
> +    pci_release_regions(dev);
> +    pci_disable_device(dev);
> +    pci_set_drvdata(dev, NULL);
> +
> +    /* Unmap memory */
> +    iounmap(device_data->mem[DPM_INDEX].internal_addr);
> +    if (device_data->mem[EXT_MEM_INDEX].internal_addr != 0)
> +        iounmap(device_data->mem[EXT_MEM_INDEX].internal_addr);
> +
> +    /* Release structure memory allocation */
> +    rtdm_free(info->device_data);
> +    rtdm_free(info);
> +
> +    if (cifx_num > 0)

Impossible.

> +        cifx_num--;
> +}
> +
> +static int __init cifx_pci_init(void)
> +{
> +    cifx_num = 0;

Unneeded, cifx_num is a global static variable, thus implicitely
intialized to 0.

> +
> +    return pci_register_driver(&cifx_pci_driver);
> +}
> +
> +static void __exit cifx_pci_exit(void)
> +{
> +    pci_unregister_driver(&cifx_pci_driver);
> +}
> +
> +module_init(cifx_pci_init);
> +module_exit(cifx_pci_exit);
> +
> +/* End of file : cifx_pci.c */

Obviously.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SDP-DE
Corporate Competence Center Embedded Linux

_______________________________________________
Xenomai mailing list
[email protected]
http://www.xenomai.org/mailman/listinfo/xenomai

Reply via email to