On 09/13/11 09:56, Marc Kleine-Budde wrote:

> On 09/12/2011 08:44 PM, Oliver Hartkopp wrote:

>> +static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id)
>> +{
>> +    struct ems_pcmcia_card *card = dev_id;
>> +    struct net_device *dev;
>> +    irqreturn_t retval = IRQ_NONE;
>> +    int i, again;
>> +
>> +    /* Card not present */
>> +    if (readw(card->base_addr) != 0xAA55)
>> +            return IRQ_HANDLED;
> 
> this looks fishy. Is it possible, that there is no card here? Why return
> IRQ_HANDLED in this case?
> 


This has been introduced to handle PCMCIA card ejects under heavy load.
Probably IRQ_NONE could be returned here also - but if we come to this point
everything is removed anyway.

>> +
>> +    do {
>> +            again = 0;
>> +
>> +            /* Check interrupt for each channel */
>> +            for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) {
> 
> If I understand the code correct, you can use card->channels...
> 
>> +                    dev = card->net_dev[i];
>> +                    if (!dev)
>> +                            continue;
> 
> ...and drop the if (!dev) here.


I don't know if all the initialization stuff in ems_pcmcia_add_card() and the
interrupt handler is completely irq-save.

Therefore i would keep this untouched - especially as EMS_PCMCIA_MAX_CHAN is 2
and not 20 ...

Maybe Markus or Sebastian would like to change it.

> 
>> +
>> +                    if (sja1000_interrupt(irq, dev) == IRQ_HANDLED)
>> +                            again = 1;
>> +            }
>> +            /* At least one channel handled the interrupt */
>> +            if (again)
>> +                    retval = IRQ_HANDLED;
>> +
>> +    } while (again);
>> +
>> +    return retval;
>> +}
>> +
>> +/*
>> + * Check if a CAN controller is present at the specified location
>> + * by trying to set 'em into the PeliCAN mode
>> + */
>> +static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv)
>> +{
>> +    /* Make sure SJA1000 is in reset mode */
>> +    ems_pcmcia_write_reg(priv, REG_MOD, 1);
>> +    ems_pcmcia_write_reg(priv, REG_CDR, CDR_PELICAN);
>> +
>> +    /* read reset-values */
>> +    if (ems_pcmcia_read_reg(priv, REG_CDR) == CDR_PELICAN)
>> +            return 1;
>> +
>> +    return 0;
>> +}
>> +
>> +static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
>> +{car
>> +    struct ems_pcmcia_card *card = pdev->priv;
>> +    struct net_device *dev;
>> +    int i;
>> +
>> +    if (!card)
>> +            return;
> 
> can this happen?


Don't know.

> 
>> +
>> +    free_irq(pdev->irq, card);
>> +
>> +    for (i = 0; i < card->channels; i++) {
>> +            dev = card->net_dev[i];
>> +            if (!dev)
>> +                    continue;
> 
> can this happen?


See above comment about the card setup.

> 
>> +
>> +            printk(KERN_INFO "%s: removing %s on channel #%d\n",
>> +                   DRV_NAME, dev->name, i);
> 
> here you have a pcmcia_device, so you can use:
> dev_info(&pdev->dev, "");


This looks a bit broken then:

can0: removing can0 on channel #1

Now it is

ems_pcmcia: removing can0 on channel #1

> 
>> +            unregister_sja1000dev(dev);
>> +            free_sja1000dev(dev);
>> +    }
>> +
>> +    writeb(EMS_CMD_UMAP, card->base_addr);
>> +    iounmap(card->base_addr);
>> +    kfree(card);
>> +
>> +    pdev->priv = NULL;
>> +}
>> +
>> +/*
>> + * Probe PCI device for EMS CAN signature and register each available
>> + * CAN channel to SJA1000 Socket-CAN subsystem.
>> + */
>> +static int __devinit ems_pcmcia_add_card(struct pcmcia_device *pdev,
>> +                                     unsigned long base)
>> +{
>> +    struct sja1000_priv *priv;
>> +    struct net_device *dev;
>> +    struct ems_pcmcia_card *card;
>> +    int err, i;
>> +
>> +    /* Allocating card structures to hold addresses, ... */
>> +    card = kzalloc(sizeof(struct ems_pcmcia_card), GFP_KERNEL);
>> +    if (!card) {
>> +            printk(KERN_ERR "%s: unable to allocate memory\n", DRV_NAME);
> 
> dev_err()


Is there a &pdev->dev ?? IMHO no.

> 
>> +            return -ENOMEM;
>> +    }
>> +
>> +    pdev->priv = card;
>> +    card->channels = 0;
>> +
>> +    card->base_addr = ioremap(base, EMS_PCMCIA_MEM_SIZE);
>> +    if (!card->base_addr) {
>> +            err = -ENOMEM;
>> +            goto failure_cleanup;
>> +    }
>> +
>> +    /* Check for unique EMS CAN signature */
>> +    if (readw(card->base_addr) != 0xAA55) {
>> +            printk(KERN_ERR "%s: No EMS CPC Card hardware found.\n",
>> +                   DRV_NAME);
> 
> dev_err();
> 
>> +            err = -ENODEV;
>> +            goto failure_cleanup;
>> +    }
>> +
>> +    /* Request board reset */
>> +    writeb(EMS_CMD_RESET, card->base_addr);
>> +
>> +    /* Make sure CAN controllers are mapped into card's memory space */
>> +    writeb(EMS_CMD_MAP, card->base_addr);
>> +
>> +    /* Detect available channels */
>> +    for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) {
> 
> i < ARRAY_SIZE(card->net_dev)


Does not look more readable to me.

> 
>> +            dev = alloc_sja1000dev(0);
>> +            if (!dev) {
>> +                    err = -ENOMEM;
>> +                    goto failure_cleanup;
>> +            }
>> +
>> +            card->net_dev[i] = dev;
>> +            priv = netdev_priv(dev);
>> +            priv->priv = card;
>> +            SET_NETDEV_DEV(dev, &pdev->dev);
>> +
>> +            priv->irq_flags = IRQF_SHARED;
>> +            dev->irq = pdev->irq;
>> +            priv->reg_base = card->base_addr + EMS_PCMCIA_CAN_BASE_OFFSET +
>> +                    (i * EMS_PCMCIA_CAN_CTRL_SIZE);
>> +
>> +            /* Check if channel is present */
>> +            if (ems_pcmcia_check_chan(priv)) {
>> +                    priv->read_reg  = ems_pcmcia_read_reg;
>> +                    priv->write_reg = ems_pcmcia_write_reg;
>> +                    priv->can.clock.freq = EMS_PCMCIA_CAN_CLOCK;
>> +                    priv->ocr = EMS_PCMCIA_OCR;
>> +                    priv->cdr = EMS_PCMCIA_CDR;
>> +                    priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER;
>> +
>> +                    /* Register SJA1000 device */
>> +                    err = register_sja1000dev(dev);
>> +                    if (err) {
>> +                            printk(KERN_INFO "%s: registering device "
>> +                                   "failed (err=%d)\n", DRV_NAME, err);
> 
> dev_err (not info)


Yes. Will change in final post.

> 
>> +                            free_sja1000dev(dev);
>> +                            goto failure_cleanup;
>> +                    }
>> +
>> +                    card->channels++;
>> +
>> +                    printk(KERN_INFO "%s: registered %s on channel "
>> +                           "#%d at 0x%p, irq %d\n", DRV_NAME, dev->name,
>> +                           i, priv->reg_base, dev->irq);
> 
> dev_info
> 
>> +            } else
>> +                    free_sja1000dev(dev);
>> +    }
>> +
>> +    err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
>> +                      DRV_NAME, card);
>> +    if (err) {
>> +            printk(KERN_INFO "Registering device failed (err=%d)\n", err);
> 
> dev_err (not info)


Will change in next post.

> 
>> +            goto failure_cleanup;
>> +    }
>> +
>> +    return 0;
>> +
>> +failure_cleanup:
>> +    printk(KERN_ERR "Error: %d. Cleaning Up.\n", err);
> 
> dev_err()
> 
>> +    ems_pcmcia_del_card(pdev);
>> +
>> +    return err;
>> +}
>> +
>> +/*
>> + * Setup PCMCIA socket and probe for EMS CPC-CARD
>> + */
>> +static int __devinit ems_pcmcia_probe(struct pcmcia_device *dev)
>> +{
>> +    int csval;
>> +
>> +    /* General socket configuration */
>> +    dev->config_flags |= CONF_ENABLE_IRQ;
>> +    dev->config_index = 1;
>> +    dev->config_regs = PRESENT_OPTION;
>> +
>> +    /* The io structure describes IO port mapping */
>> +    dev->resource[0]->end = 16;
>> +    dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
>> +    dev->resource[1]->end = 16;
>> +    dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
>> +    dev->io_lines = 5;
>> +
>> +    /* Allocate a memory window */
>> +    dev->resource[2]->flags =
>> +            (WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE);
>> +    dev->resource[2]->start = dev->resource[2]->end = 0;
>> +
>> +    csval = pcmcia_request_window(dev, dev->resource[2], 0);
>> +    if (csval) {
>> +            dev_err(&dev->dev, "pcmcia_request_window failed (err=%d)\n",
>> +                    csval);
>> +            return 0;
>> +    }
>> +
>> +    csval = pcmcia_map_mem_page(dev, dev->resource[2], dev->config_base);
>> +    if (csval) {
>> +            dev_err(&dev->dev, "pcmcia_map_mem_page failed (err=%d)\n",
>> +                    csval);
>> +            return 0;
>> +    }
>> +
>> +    csval = pcmcia_enable_device(dev);
>> +    if (csval) {
>> +            dev_err(&dev->dev, "pcmcia_enable_device failed (err=%d)\n",
>> +                    csval);
>> +            return 0;
>> +    }
>> +
>> +    ems_pcmcia_add_card(dev, dev->resource[2]->start);
>> +    return 0;
>> +}
>> +
>> +/*
>> + * Release claimed resources
>> + */
>> +static void ems_pcmcia_remove(struct pcmcia_device *dev)
>> +{
>> +    ems_pcmcia_del_card(dev);
>> +    pcmcia_disable_device(dev);
>> +}
>> +
>> +static struct pcmcia_driver ems_pcmcia_driver = {
>> +    .name = DRV_NAME,
>> +    .probe = ems_pcmcia_probe,
>> +    .remove = ems_pcmcia_remove,
>> +    .id_table = ems_pcmcia_tbl,
>> +};
>> +
>> +static int __init ems_pcmcia_init(void)
>> +{
>> +    return pcmcia_register_driver(&ems_pcmcia_driver);
>> +}
>> +module_init(ems_pcmcia_init);
>> +
>> +static void __exit ems_pcmcia_exit(void)
>> +{
>> +    pcmcia_unregister_driver(&ems_pcmcia_driver);
>> +}
>> +module_exit(ems_pcmcia_exit);
>>
> 
> cheers, Marc


Finally i'm still unsure about the dev_??? stuff. Maybe it's best, we let the
Markus/Sebastian look over the code fist.

Thanks for the review!

Cheers, Oliver
_______________________________________________
Socketcan-core mailing list
Socketcan-core@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to