All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wolfgang Grandegger <wg@grandegger.com>
To: Jonathan Corbet <corbet@lwn.net>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
Subject: Re: [PATCH v2 4/7] [PATCH 4/8] can: Driver for the SJA1000 CAN controller
Date: Thu, 14 May 2009 11:03:53 +0200	[thread overview]
Message-ID: <4A0BDE79.4060606@grandegger.com> (raw)
In-Reply-To: <20090513155205.4bf06c25@bike.lwn.net>

Jonathan Corbet wrote:
> [Quick drive-by review continues...]
> 
>> +
>> +static int sja1000_probe_chip(struct net_device *dev)
>> +{
>> +	struct sja1000_priv *priv = netdev_priv(dev);
> 
> Looking down toward the bottom, I see:
> 
>> +struct sja1000_priv {
>> +	struct can_priv can;
> 
> So you're still using the "put the higher-level structure at the top so we
> can treat it like either kind of pointer" trick.  I'd still recommend
> against that.  Far better to do something like:
> 
> 	struct can_priv *canpriv = netdev_priv(dev);
> 	struct sja_1000_priv *priv = container_of(canpriv, struct sja_1000_priv, can);
> 
> Of course, you can put that dance into a helper function.

There is no way to initialize the value returned by netdev_priv() as it
does not point to a member of struct net_device. I already commented here:

  http://marc.info/?l=linux-netdev&m=124120212106891&w=2

Have I missed something?

>> +	if (dev->base_addr && (priv->read_reg(dev, 0) == 0xFF)) {
>> +		printk(KERN_INFO "%s: probing @0x%lX failed\n",
>> +		       DRV_NAME, dev->base_addr);
>> +		return 0;
>> +	}
>> +	return 1;
>> +}
> 
> So zero is an error return?  That's contrary to usual practice.

OK, will fix.

>> +static int set_reset_mode(struct net_device *dev)
>> +{
>> +	struct sja1000_priv *priv = netdev_priv(dev);
>> +	unsigned char status = priv->read_reg(dev, REG_MOD);
>> +	int i;
>> +
>> +	/* disable interrupts */
>> +	priv->write_reg(dev, REG_IER, IRQ_OFF);
>> +
>> +	for (i = 0; i < 100; i++) {
>> +		/* check reset bit */
>> +		if (status & MOD_RM) {
>> +			priv->can.state = CAN_STATE_STOPPED;
>> +			return 0;
>> +		}
>> +
>> +		priv->write_reg(dev, REG_MOD, MOD_RM);	/* reset chip */
>> +		status = priv->read_reg(dev, REG_MOD);
>> +		udelay(10);
> 
> Wouldn't you want to read the new state *after* the delay?

Yes, that makes more sense.

>> +	}
>> +
>> +	dev_err(dev->dev.parent, "setting SJA1000 into reset mode failed!\n");
>> +	return 1;

Will fix this return value as well.

>> +
>> +}
>> +
>> +static int set_normal_mode(struct net_device *dev)
>> +{
>> +	struct sja1000_priv *priv = netdev_priv(dev);
>> +	unsigned char status = priv->read_reg(dev, REG_MOD);
>> +	int i;
>> +
>> +	for (i = 0; i < 100; i++) {
>> +		/* check reset bit */
>> +		if ((status & MOD_RM) == 0) {
>> +			priv->can.state = CAN_STATE_ERROR_ACTIVE;
>> +			/* enable all interrupts */
>> +			priv->write_reg(dev, REG_IER, IRQ_ALL);
>> +
>> +			return 0;
>> +		}
>> +
>> +		/* set chip to normal mode */
>> +		priv->write_reg(dev, REG_MOD, 0x00);
>> +		status = priv->read_reg(dev, REG_MOD);
>> +		udelay(10);
> 
> Here too?
> 
>> +	}
>> +
>> +	dev_err(dev->dev.parent, "setting SJA1000 into normal mode failed!\n");
>> +	return 1;
>> +
>> +}
>> +
> 
> [...]
> 
>> +irqreturn_t sja1000_interrupt(int irq, void *dev_id)
>> +{
>> +	struct net_device *dev = (struct net_device *)dev_id;
>> +	struct sja1000_priv *priv = netdev_priv(dev);
>> +	struct net_device_stats *stats = &dev->stats;
>> +	uint8_t isrc, status;
>> +	int n = 0;
>> +
>> +	/* Shared interrupts and IRQ off? */
>> +	if (priv->read_reg(dev, REG_IER) == IRQ_OFF)
>> +		return IRQ_NONE;
>> +
>> +	if (priv->pre_irq)
>> +		priv->pre_irq(dev);
>> +
>> +	while ((isrc = priv->read_reg(dev, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
>> +		n++;
>> +		status = priv->read_reg(dev, REG_SR);
>> +
>> +		if (isrc & IRQ_WUI)
>> +			dev_warn(dev->dev.parent, "wakeup interrupt\n");
> 
> How many of these might you get?  Should this be rate limited?

None, because the driver does not (yet) support the sleep mode. For that
reason it's a warning.

>> +		if (isrc & IRQ_TI) {
>> +			/* transmission complete interrupt */
>> +			stats->tx_packets++;
>> +			can_get_echo_skb(dev, 0);
>> +			netif_wake_queue(dev);
>> +		}
>> +		if (isrc & IRQ_RI) {
>> +			/* receive interrupt */
>> +			while (status & SR_RBS) {
>> +				sja1000_rx(dev);
>> +				status = priv->read_reg(dev, REG_SR);
>> +			}
>> +		}
>> +		if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
>> +			/* error interrupt */
>> +			if (sja1000_err(dev, isrc, status))
>> +				break;
>> +		}
>> +	}
>> +
>> +	if (priv->post_irq)
>> +		priv->post_irq(dev);
>> +
>> +	if (n >= SJA1000_MAX_IRQ)
>> +		dev_dbg(dev->dev.parent, "%d messages handled in ISR", n);
>> +
>> +	return (n) ? IRQ_HANDLED : IRQ_NONE;
>> +}
>> +EXPORT_SYMBOL_GPL(sja1000_interrupt);
>> +
>> +static int sja1000_open(struct net_device *dev)
>> +{
>> +	struct sja1000_priv *priv = netdev_priv(dev);
>> +	int err;
>> +
>> +	/* set chip into reset mode */
>> +	set_reset_mode(dev);
>> +
>> +	/* common open */
>> +	err = open_candev(dev);
>> +	if (err)
>> +		return err;
>> +
>> +	/* register interrupt handler, if not done by the device driver */
>> +	if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) {
>> +		err = request_irq(dev->irq, &sja1000_interrupt, IRQF_SHARED,
>> +				  dev->name, (void *)dev);
>> +		if (err)
>> +			return -EAGAIN;
> 
> If you return here you fail, but you've not undone open_candev().  Looking
> there, it seems no harm will be done - until somebody changes open_candev()
> someday. 

Right, the missing close_candev() does currently not harm but that might
change in the future. Will change.

>> +	}
>> +
>> +	/* init and start chi */
>> +	sja1000_start(dev);
>> +	priv->open_time = jiffies;
>> +
>> +	netif_start_queue(dev);
>> +
>> +	return 0;
>> +}
>> +
> 
> [...]
> 
>> +/*
>> + * SJA1000 private data structure
>> + */
>> +struct sja1000_priv {
>> +	struct can_priv can;
>> +	long open_time;
>> +	struct sk_buff *echo_skb;
>> +
>> +	u8 (*read_reg) (const struct net_device *dev, int reg);
>> +	void (*write_reg) (const struct net_device *dev, int reg, u8 val);
>> +	void (*pre_irq) (const struct net_device *dev);
>> +	void (*post_irq) (const struct net_device *dev);
> 
> What are the locking rules for functions like ->read_reg() now?  Entirely
> up to the lower level?  Would be good to document that near the structure
> definition. 

Yes, it's up to the lower level.

>> +
>> +	void *priv;		/* for board-specific data */
>> +	struct net_device *dev;
>> +
>> +	u8 ocr;
>> +	u8 cdr;
>> +	u32 flags;
> 
> The meaning of these fields is not exactly clear.

I will add a description.

Wolfgang.

  reply	other threads:[~2009-05-14  9:04 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-12  9:27 [PATCH v2 0/7] can: CAN network device driver interface and drivers Wolfgang Grandegger
2009-05-12  9:27 ` [PATCH v2 1/7] [PATCH 1/8] can: Documentation for the CAN device driver interface Wolfgang Grandegger
2009-05-12  9:27 ` [PATCH v2 2/7] [PATCH 2/8] can: Update MAINTAINERS and CREDITS file Wolfgang Grandegger
2009-05-12  9:28 ` [PATCH v2 3/7] [PATCH 3/8] can: CAN Network device driver and Netlink interface Wolfgang Grandegger
2009-05-13  6:30   ` Andrew Morton
2009-05-13  6:53     ` Andrew Morton
2009-05-13 11:37       ` Wolfgang Grandegger
2009-05-13 15:57         ` Andrew Morton
2009-05-14  9:51           ` Wolfgang Grandegger
2009-05-13 10:02     ` Oliver Hartkopp
2009-05-13 11:39       ` Wolfgang Grandegger
2009-05-13 12:08         ` Oliver Hartkopp
2009-05-13 12:23           ` Wolfgang Grandegger
2009-05-15  7:15             ` Oliver Hartkopp
2009-05-15  7:46               ` Wolfgang Grandegger
2009-05-13 21:31   ` Jonathan Corbet
2009-05-14  7:55     ` Wolfgang Grandegger
2009-05-12  9:28 ` [PATCH v2 4/7] [PATCH 4/8] can: Driver for the SJA1000 CAN controller Wolfgang Grandegger
2009-05-13 21:52   ` Jonathan Corbet
2009-05-14  9:03     ` Wolfgang Grandegger [this message]
2009-05-15 20:39       ` Jonathan Corbet
2009-05-15 21:24         ` Wolfgang Grandegger
2009-05-16  6:57           ` Wolfgang Grandegger
2009-05-20 21:31             ` Jonathan Corbet
2009-05-12  9:28 ` [PATCH v2 5/7] [PATCH 5/8] can: SJA1000 generic platform bus driver Wolfgang Grandegger
2009-05-13 22:02   ` Jonathan Corbet
2009-05-15  9:33     ` Wolfgang Grandegger
2009-05-14  6:46   ` Sascha Hauer
2009-05-15  9:35     ` Wolfgang Grandegger
2009-05-15 12:07       ` Sascha Hauer
2009-05-15 13:12         ` Wolfgang Grandegger
2009-05-12  9:28 ` [PATCH v2 6/7] [PATCH 6/8] can: SJA1000 driver for EMS PCI cards Wolfgang Grandegger
2009-05-12  9:28 ` [PATCH v2 7/7] [PATCH 7/8] can: SJA1000 driver for Kvaser " Wolfgang Grandegger
2009-05-13 22:20   ` Jonathan Corbet
2009-05-15  8:54     ` Wolfgang Grandegger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A0BDE79.4060606@grandegger.com \
    --to=wg@grandegger.com \
    --cc=corbet@lwn.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=oliver.hartkopp@volkswagen.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.