From 47dd7a540b8a0cdc028914b7351fca0cf0a1d305 Mon Sep 17 00:00:00 2001 From: Giuseppe Cavallaro Date: Wed, 14 Oct 2009 15:13:45 -0700 Subject: net: add support for STMicroelectronics Ethernet controllers. This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers (Synopsys IP blocks). Driver documentation: o http://stlinux.com/drupal/kernel/network/stmmac Revisions: o http://stlinux.com/drupal/kernel/network/stmmac-driver-revisions Performances: o http://stlinux.com/drupal/benchmarks/networking/stmmac Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_timer.h | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 drivers/net/stmmac/stmmac_timer.h (limited to 'drivers/net/stmmac/stmmac_timer.h') diff --git a/drivers/net/stmmac/stmmac_timer.h b/drivers/net/stmmac/stmmac_timer.h new file mode 100644 index 000000000000..f795cae33725 --- /dev/null +++ b/drivers/net/stmmac/stmmac_timer.h @@ -0,0 +1,41 @@ +/******************************************************************************* + STMMAC external timer Header File. + + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope 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 + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +struct stmmac_timer { + void (*timer_start) (unsigned int new_freq); + void (*timer_stop) (void); + unsigned int freq; +}; + +/* Open the HW timer device and return 0 in case of success */ +int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm); +/* Stop the timer and release it */ +int stmmac_close_ext_timer(void); +/* Function used for scheduling task within the stmmac */ +void stmmac_schedule(struct net_device *dev); + +#if defined(CONFIG_STMMAC_TMU_TIMER) +extern int tmu2_register_user(void *fnt, void *data); +extern void tmu2_unregister_user(void); +#endif -- cgit v1.2.3 From 73cfe264c27fb50d4592ef1580486bea319443ac Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Sun, 22 Nov 2009 22:59:56 +0000 Subject: stmmac: do not fail when the timer cannot be used. If the external timer cannot be used the driver will continue to work without mitigation. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_main.c | 50 ++++++++++++++++++++++----------------- drivers/net/stmmac/stmmac_timer.h | 1 + 2 files changed, 29 insertions(+), 22 deletions(-) (limited to 'drivers/net/stmmac/stmmac_timer.h') diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index c2f14dc9ba28..9542995ba667 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -416,13 +416,8 @@ static void init_dma_desc_rings(struct net_device *dev) unsigned int txsize = priv->dma_tx_size; unsigned int rxsize = priv->dma_rx_size; unsigned int bfsize = priv->dma_buf_sz; - int buff2_needed = 0; - int dis_ic = 0; + int buff2_needed = 0, dis_ic = 0; -#ifdef CONFIG_STMMAC_TIMER - /* Using Timers disable interrupts on completion for the reception */ - dis_ic = 1; -#endif /* Set the Buffer size according to the MTU; * indeed, in case of jumbo we need to bump-up the buffer sizes. */ @@ -437,6 +432,11 @@ static void init_dma_desc_rings(struct net_device *dev) else bfsize = DMA_BUFFER_SIZE; +#ifdef CONFIG_STMMAC_TIMER + /* Disable interrupts on completion for the reception if timer is on */ + if (likely(priv->tm->enable)) + dis_ic = 1; +#endif /* If the MTU exceeds 8k so use the second buffer in the chain */ if (bfsize >= BUF_SIZE_8KiB) buff2_needed = 1; @@ -809,20 +809,22 @@ static void stmmac_tx(struct stmmac_priv *priv) static inline void stmmac_enable_irq(struct stmmac_priv *priv) { -#ifndef CONFIG_STMMAC_TIMER - writel(DMA_INTR_DEFAULT_MASK, priv->dev->base_addr + DMA_INTR_ENA); -#else - priv->tm->timer_start(tmrate); +#ifdef CONFIG_STMMAC_TIMER + if (likely(priv->tm->enable)) + priv->tm->timer_start(tmrate); + else #endif + writel(DMA_INTR_DEFAULT_MASK, priv->dev->base_addr + DMA_INTR_ENA); } static inline void stmmac_disable_irq(struct stmmac_priv *priv) { -#ifndef CONFIG_STMMAC_TIMER - writel(0, priv->dev->base_addr + DMA_INTR_ENA); -#else - priv->tm->timer_stop(); +#ifdef CONFIG_STMMAC_TIMER + if (likely(priv->tm->enable)) + priv->tm->timer_stop(); + else #endif + writel(0, priv->dev->base_addr + DMA_INTR_ENA); } static int stmmac_has_work(struct stmmac_priv *priv) @@ -1031,22 +1033,23 @@ static int stmmac_open(struct net_device *dev) } #ifdef CONFIG_STMMAC_TIMER - priv->tm = kmalloc(sizeof(struct stmmac_timer *), GFP_KERNEL); + priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL); if (unlikely(priv->tm == NULL)) { pr_err("%s: ERROR: timer memory alloc failed \n", __func__); return -ENOMEM; } priv->tm->freq = tmrate; - /* Test if the HW timer can be actually used. - * In case of failure continue with no timer. */ + /* Test if the external timer can be actually used. + * In case of failure continue without timer. */ if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) { - pr_warning("stmmaceth: cannot attach the HW timer\n"); + pr_warning("stmmaceth: cannot attach the external timer.\n"); tmrate = 0; priv->tm->freq = 0; priv->tm->timer_start = stmmac_no_timer_started; priv->tm->timer_stop = stmmac_no_timer_stopped; - } + } else + priv->tm->enable = 1; #endif /* Create and initialize the TX/RX descriptors chains. */ @@ -1322,9 +1325,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) /* Interrupt on completition only for the latest segment */ priv->mac_type->ops->close_tx_desc(desc); + #ifdef CONFIG_STMMAC_TIMER - /* Clean IC while using timers */ - priv->mac_type->ops->clear_tx_ic(desc); + /* Clean IC while using timer */ + if (likely(priv->tm->enable)) + priv->mac_type->ops->clear_tx_ic(desc); #endif /* To avoid raise condition */ priv->mac_type->ops->set_tx_owner(first); @@ -2028,7 +2033,8 @@ static int stmmac_suspend(struct platform_device *pdev, pm_message_t state) #ifdef CONFIG_STMMAC_TIMER priv->tm->timer_stop(); - dis_ic = 1; + if (likely(priv->tm->enable)) + dis_ic = 1; #endif napi_disable(&priv->napi); diff --git a/drivers/net/stmmac/stmmac_timer.h b/drivers/net/stmmac/stmmac_timer.h index f795cae33725..6863590d184b 100644 --- a/drivers/net/stmmac/stmmac_timer.h +++ b/drivers/net/stmmac/stmmac_timer.h @@ -26,6 +26,7 @@ struct stmmac_timer { void (*timer_start) (unsigned int new_freq); void (*timer_stop) (void); unsigned int freq; + unsigned int enable; }; /* Open the HW timer device and return 0 in case of success */ -- cgit v1.2.3