netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Cc: jgarzik@pobox.com, netdev@vger.kernel.org,
	David Brownell <david-b@pacbell.net>
Subject: Re: [PATCHv2] net: sh_eth: Add support for Renesas SuperH Ethernet
Date: Thu, 7 Feb 2008 01:05:29 -0800	[thread overview]
Message-ID: <20080207010529.868e931b.akpm@linux-foundation.org> (raw)
In-Reply-To: <47AAC3BB.9090107@renesas.com>

On Thu, 07 Feb 2008 17:39:23 +0900 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> wrote:

> Add support for Renesas SuperH Ethernet controller.
> This driver supported SH7710 and SH7712.
> 

Nice looking driver.

Quick comments:

> ...
>
> +/*
> + * Program the hardware MAC address from dev->dev_addr.
> + */
> +static void __init update_mac_address(struct net_device *ndev)
> +{
> +	u32 ioaddr = ndev->base_addr;
> +
> +	ctrl_outl((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
> +		  (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]),
> +		  ioaddr + MAHR);
> +	ctrl_outl((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]),
> +		  ioaddr + MALR);
> +}
> +
> +/*
> + * Get MAC address from SuperH MAC address register
> + *
> + * SuperH's Ethernet device doesn't have 'ROM' to MAC address.
> + * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g).
> + * When you want use this device, you must set MAC address in bootloader.
> + *
> + */
> +static void __init read_mac_address(struct net_device *ndev)
> +{
> +	u32 ioaddr = ndev->base_addr;
> +
> +	ndev->dev_addr[0] = (ctrl_inl(ioaddr + MAHR) >> 24);
> +	ndev->dev_addr[1] = (ctrl_inl(ioaddr + MAHR) >> 16) & 0xFF;
> +	ndev->dev_addr[2] = (ctrl_inl(ioaddr + MAHR) >> 8) & 0xFF;
> +	ndev->dev_addr[3] = (ctrl_inl(ioaddr + MAHR) & 0xFF);
> +	ndev->dev_addr[4] = (ctrl_inl(ioaddr + MALR) >> 8) & 0xFF;
> +	ndev->dev_addr[5] = (ctrl_inl(ioaddr + MALR) & 0xFF);
> +}

Both the above functions are called from non-__init code and hence cannot
be __init.  sh_eth_tsu_init() is wrong too.  Please check all section
annotations in the driver.

> +struct bb_info {
> +	struct mdiobb_ctrl ctrl;
> +	u32 addr;
> +	u32 mmd_msk;/* MMD */
> +	u32 mdo_msk;
> +	u32 mdi_msk;
> +	u32 mdc_msk;
> +};

Please cc David Brownell on updates to this driver - perhaps he will find
time to review the bit-banging interface usage.

> +/* PHY bit set */
> +static void bb_set(u32 addr, u32 msk)
> +{
> +	ctrl_outl(ctrl_inl(addr) | msk, addr);
> +}
> +
> +/* PHY bit clear */
> +static void bb_clr(u32 addr, u32 msk)
> +{
> +	ctrl_outl((ctrl_inl(addr) & ~msk), addr);
> +}
> +
> +/* PHY bit read */
> +static int bb_read(u32 addr, u32 msk)
> +{
> +	return (ctrl_inl(addr) & msk) != 0;
> +}
> +
> +/* Data I/O pin control */
> +static inline void sh__mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
> +{
> +	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
> +	if (bit)
> +		bb_set(bitbang->addr, bitbang->mmd_msk);
> +	else
> +		bb_clr(bitbang->addr, bitbang->mmd_msk);
> +}
> +
> +/* Set bit data*/
> +static inline void sh__set_mdio(struct mdiobb_ctrl *ctrl, int bit)
> +{
> +	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
> +
> +	if (bit)
> +		bb_set(bitbang->addr, bitbang->mdo_msk);
> +	else
> +		bb_clr(bitbang->addr, bitbang->mdo_msk);
> +}
> +
> +/* Get bit data*/
> +static inline int sh__get_mdio(struct mdiobb_ctrl *ctrl)
> +{
> +	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
> +	return bb_read(bitbang->addr, bitbang->mdi_msk);
> +}

There seems to be a fairly random mixture of inline and non-inline here. 
I'd suggest that you just remove all the `inline's.  The compiler does a
pretty good job of working doing this for you.

> +/* MDC pin control */
> +static inline void sh__mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
> +{
> +	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
> +
> +	if (bit)
> +		bb_set(bitbang->addr, bitbang->mdc_msk);
> +	else
> +		bb_clr(bitbang->addr, bitbang->mdc_msk);
> +}
> +
> +/* mdio bus control struct */
> +static struct mdiobb_ops bb_ops = {
> +	.owner = THIS_MODULE,
> +	.set_mdc = sh__mdc_ctrl,
> +	.set_mdio_dir = sh__mmd_ctrl,
> +	.set_mdio_data = sh__set_mdio,
> +	.get_mdio_data = sh__get_mdio,
> +};

It's particularly inappropriate that sh__mdc_ctrl() was inlined - it is
only ever called via a function pointer and hence will never be inlined!

> ...
>
> +static void sh_eth_timer(unsigned long data)
> +{
> +	struct net_device *ndev = (struct net_device *)data;
> +	struct sh_eth_private *mdp = netdev_priv(ndev);
> +	int next_tick = 10 * HZ;
> +
> +	/* We could do something here... nah. */
> +	mdp->timer.expires = jiffies + next_tick;
> +	add_timer(&mdp->timer);

mod_timer() would be neater here.

> +}
>
> ...
>
> +
> +/* network device open function */
> +static int sh_eth_open(struct net_device *ndev)
> +{
> +	int ret = 0;
> +	struct sh_eth_private *mdp = netdev_priv(ndev);
> +
> +	ret = request_irq(ndev->irq, &sh_eth_interrupt, 0, ndev->name, ndev);
> +	if (ret) {
> +		printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME);
> +		return ret;
> +	}
> +
> +	/* Descriptor set */
> +	ret = sh_eth_ring_init(ndev);
> +	if (ret)
> +		goto out_free_irq;
> +
> +	/* device init */
> +	ret = sh_eth_dev_init(ndev);
> +	if (ret)
> +		goto out_free_irq;
> +
> +	/* PHY control start*/
> +	ret = sh_eth_phy_start(ndev);
> +	if (ret)
> +		goto out_free_irq;
> +
> +	/* Set the timer to check for link beat. */
> +	init_timer(&mdp->timer);
> +	mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
> +	mdp->timer.data = (u32) ndev;
> +	mdp->timer.function = sh_eth_timer;	/* timer handler */

setup_timer()

> +	add_timer(&mdp->timer);
> +
> +	return ret;
> +
> +out_free_irq:
> +	free_irq(ndev->irq, ndev);
> +	return ret;
> +}
> +
> +/* Timeout function */
> +static void sh_eth_tx_timeout(struct net_device *ndev)
> +{
> +	struct sh_eth_private *mdp = netdev_priv(ndev);
> +	u32 ioaddr = ndev->base_addr;
> +	struct sh_eth_rxdesc *rxdesc;
> +	int i;
> +
> +	netif_stop_queue(ndev);
> +
> +	/* worning message out. */
> +	printk(KERN_WARNING "%s: transmit timed out, status %8.8x,"
> +	       " resetting...\n", ndev->name, (int)ctrl_inl(ioaddr + EESR));
> +
> +	/* tx_errors count up */
> +	mdp->stats.tx_errors++;
> +
> +	/* timer off */
> +	del_timer_sync(&mdp->timer);
> +
> +	/* Free all the skbuffs in the Rx queue. */
> +	for (i = 0; i < RX_RING_SIZE; i++) {
> +		rxdesc = &mdp->rx_ring[i];
> +		rxdesc->status = 0;
> +		rxdesc->addr = 0xBADF00D0;
> +		if (mdp->rx_skbuff[i])
> +			dev_kfree_skb(mdp->rx_skbuff[i]);
> +		mdp->rx_skbuff[i] = NULL;
> +	}
> +	for (i = 0; i < TX_RING_SIZE; i++) {
> +		if (mdp->tx_skbuff[i])
> +			dev_kfree_skb(mdp->tx_skbuff[i]);
> +		mdp->tx_skbuff[i] = NULL;
> +	}
> +
> +	/* device init */
> +	sh_eth_dev_init(ndev);
> +
> +	/* timer on */
> +	mdp->timer.expires = (jiffies + (24 * HZ)) / 10;/* 2.4 sec. */
> +	add_timer(&mdp->timer);

mod_timer()

> +}
> +
>
> +#ifdef __LITTLE_ENDIAN__
> +static inline void swaps(char *src, int len)
> +{
> +	u32 *p = (u32 *)src;
> +	u32 *maxp;
> +	maxp = p + ((len + sizeof(u32) - 1) / sizeof(u32));
> +
> +	for (; p < maxp; p++)
> +		*p = swab32(*p);
> +}
> +#else
> +#define swaps(x, y)
> +#endif
> +

I'd say that the big-endian version of swaps() should be a C function
rather than a macro.  It's nicer to look at, consistent, provides typechecking,
can help avoid unused-variable warnings (an inline function provides a
reference to the arguments whereas a macro does not).

The little-endian version of this function is too large to be inlined.

This function looks fairly generic.  Are we sure there isn't some library
function which does this?


  reply	other threads:[~2008-02-07  9:05 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-07  8:39 [PATCHv2] net: sh_eth: Add support for Renesas SuperH Ethernet Yoshihiro Shimoda
2008-02-07  9:05 ` Andrew Morton [this message]
2008-02-08 10:40   ` Yoshihiro Shimoda

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=20080207010529.868e931b.akpm@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=david-b@pacbell.net \
    --cc=jgarzik@pobox.com \
    --cc=netdev@vger.kernel.org \
    --cc=shimoda.yoshihiro@renesas.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).