Commit a12f801d authored by Sandeep Gopalpet's avatar Sandeep Gopalpet Committed by David S. Miller

gianfar: Add per queue structure support

This patch introduces per tx and per rx queue structures.
Earlier the members of these structures were inside the
gfar_private structure.

Moving forward if we want to support multiple queues, we need
to refactor the gfar_private structure so that introduction of
multiple queues is easier.
Signed-off-by: default avatarSandeep Gopalpet <Sandeep.Kumar@freescale.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 123b43e9
This diff is collapsed.
...@@ -7,8 +7,9 @@ ...@@ -7,8 +7,9 @@
* *
* Author: Andy Fleming * Author: Andy Fleming
* Maintainer: Kumar Gala * Maintainer: Kumar Gala
* Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
* *
* Copyright (c) 2002-2004 Freescale Semiconductor, Inc. * Copyright 2002-2009 Freescale Semiconductor, Inc.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
...@@ -699,62 +700,95 @@ struct gfar { ...@@ -699,62 +700,95 @@ struct gfar {
#define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200 #define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200
#define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400 #define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400
/* Struct stolen almost completely (and shamelessly) from the FCC enet source /**
* (Ok, that's not so true anymore, but there is a family resemblence) * struct gfar_priv_tx_q - per tx queue structure
* The GFAR buffer descriptors track the ring buffers. The rx_bd_base * @txlock: per queue tx spin lock
* and tx_bd_base always point to the currently available buffer. * @tx_skbuff:skb pointers
* The dirty_tx tracks the current buffer that is being sent by the * @skb_curtx: to be used skb pointer
* controller. The cur_tx and dirty_tx are equal under both completely * @skb_dirtytx:the last used skb pointer
* empty and completely full conditions. The empty/ready indicator in * @qindex: index of this queue
* the buffer descriptor determines the actual condition. * @dev: back pointer to the dev structure
* @grp: back pointer to the group to which this queue belongs
* @tx_bd_base: First tx buffer descriptor
* @cur_tx: Next free ring entry
* @dirty_tx: First buffer in line to be transmitted
* @tx_ring_size: Tx ring size
* @num_txbdfree: number of free TxBds
* @txcoalescing: enable/disable tx coalescing
* @txic: transmit interrupt coalescing value
* @txcount: coalescing value if based on tx frame count
* @txtime: coalescing value if based on time
*/ */
struct gfar_private { struct gfar_priv_tx_q {
/* Fields controlled by TX lock */ spinlock_t txlock __attribute__ ((aligned (SMP_CACHE_BYTES)));
spinlock_t txlock;
/* Pointer to the array of skbuffs */
struct sk_buff ** tx_skbuff; struct sk_buff ** tx_skbuff;
/* Buffer descriptor pointers */
/* next free skb in the array */ dma_addr_t tx_bd_dma_base;
struct txbd8 *tx_bd_base;
struct txbd8 *cur_tx;
struct txbd8 *dirty_tx;
struct net_device *dev;
u16 skb_curtx; u16 skb_curtx;
/* First skb in line to be transmitted */
u16 skb_dirtytx; u16 skb_dirtytx;
u16 qindex;
unsigned int tx_ring_size;
unsigned int num_txbdfree;
/* Configuration info for the coalescing features */ /* Configuration info for the coalescing features */
unsigned char txcoalescing; unsigned char txcoalescing;
unsigned long txic; unsigned long txic;
unsigned short txcount;
unsigned short txtime;
};
/* Buffer descriptor pointers */ /**
dma_addr_t tx_bd_dma_base; * struct gfar_priv_rx_q - per rx queue structure
struct txbd8 *tx_bd_base; /* First tx buffer descriptor */ * @rxlock: per queue rx spin lock
struct txbd8 *cur_tx; /* Next free ring entry */ * @napi: the napi poll function
struct txbd8 *dirty_tx; /* First buffer in line * @rx_skbuff: skb pointers
to be transmitted */ * @skb_currx: currently use skb pointer
unsigned int tx_ring_size; * @rx_bd_base: First rx buffer descriptor
unsigned int num_txbdfree; /* number of TxBDs free */ * @cur_rx: Next free rx ring entry
* @qindex: index of this queue
/* RX Locked fields */ * @dev: back pointer to the dev structure
spinlock_t rxlock; * @rx_ring_size: Rx ring size
* @rxcoalescing: enable/disable rx-coalescing
* @rxic: receive interrupt coalescing vlaue
*/
struct device_node *node; struct gfar_priv_rx_q {
struct net_device *ndev; spinlock_t rxlock __attribute__ ((aligned (SMP_CACHE_BYTES)));
struct of_device *ofdev;
struct napi_struct napi; struct napi_struct napi;
/* skb array and index */
struct sk_buff ** rx_skbuff; struct sk_buff ** rx_skbuff;
struct rxbd8 *rx_bd_base;
struct rxbd8 *cur_rx;
struct net_device *dev;
u16 skb_currx; u16 skb_currx;
u16 qindex;
unsigned int rx_ring_size;
/* RX Coalescing values */ /* RX Coalescing values */
unsigned char rxcoalescing; unsigned char rxcoalescing;
unsigned long rxic; unsigned long rxic;
};
/* Struct stolen almost completely (and shamelessly) from the FCC enet source
* (Ok, that's not so true anymore, but there is a family resemblence)
* The GFAR buffer descriptors track the ring buffers. The rx_bd_base
* and tx_bd_base always point to the currently available buffer.
* The dirty_tx tracks the current buffer that is being sent by the
* controller. The cur_tx and dirty_tx are equal under both completely
* empty and completely full conditions. The empty/ready indicator in
* the buffer descriptor determines the actual condition.
*/
struct gfar_private {
struct rxbd8 *rx_bd_base; /* First Rx buffers */ struct device_node *node;
struct rxbd8 *cur_rx; /* Next free rx ring entry */ struct net_device *ndev;
struct of_device *ofdev;
/* RX parameters */ struct gfar_priv_tx_q *tx_queue;
unsigned int rx_ring_size; struct gfar_priv_rx_q *rx_queue;
/* RX per device parameters */
unsigned int rx_buffer_size; unsigned int rx_buffer_size;
unsigned int rx_stash_size; unsigned int rx_stash_size;
unsigned int rx_stash_index; unsigned int rx_stash_index;
......
...@@ -7,8 +7,9 @@ ...@@ -7,8 +7,9 @@
* *
* Author: Andy Fleming * Author: Andy Fleming
* Maintainer: Kumar Gala * Maintainer: Kumar Gala
* Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
* *
* Copyright (c) 2003,2004 Freescale Semiconductor, Inc. * Copyright 2003-2006, 2008-2009 Freescale Semiconductor, Inc.
* *
* This software may be used and distributed according to * This software may be used and distributed according to
* the terms of the GNU Public License, Version 2, incorporated herein * the terms of the GNU Public License, Version 2, incorporated herein
...@@ -41,7 +42,7 @@ ...@@ -41,7 +42,7 @@
#include "gianfar.h" #include "gianfar.h"
extern void gfar_start(struct net_device *dev); extern void gfar_start(struct net_device *dev);
extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
#define GFAR_MAX_COAL_USECS 0xffff #define GFAR_MAX_COAL_USECS 0xffff
#define GFAR_MAX_COAL_FRAMES 0xff #define GFAR_MAX_COAL_FRAMES 0xff
...@@ -197,12 +198,16 @@ static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) ...@@ -197,12 +198,16 @@ static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct phy_device *phydev = priv->phydev; struct phy_device *phydev = priv->phydev;
struct gfar_priv_rx_q *rx_queue = NULL;
struct gfar_priv_tx_q *tx_queue = NULL;
if (NULL == phydev) if (NULL == phydev)
return -ENODEV; return -ENODEV;
tx_queue = priv->tx_queue;
rx_queue = priv->rx_queue;
cmd->maxtxpkt = get_icft_value(priv->txic); cmd->maxtxpkt = get_icft_value(tx_queue->txic);
cmd->maxrxpkt = get_icft_value(priv->rxic); cmd->maxrxpkt = get_icft_value(rx_queue->rxic);
return phy_ethtool_gset(phydev, cmd); return phy_ethtool_gset(phydev, cmd);
} }
...@@ -279,6 +284,8 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic ...@@ -279,6 +284,8 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar_priv_rx_q *rx_queue = NULL;
struct gfar_priv_tx_q *tx_queue = NULL;
unsigned long rxtime; unsigned long rxtime;
unsigned long rxcount; unsigned long rxcount;
unsigned long txtime; unsigned long txtime;
...@@ -290,10 +297,13 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals ...@@ -290,10 +297,13 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
if (NULL == priv->phydev) if (NULL == priv->phydev)
return -ENODEV; return -ENODEV;
rxtime = get_ictt_value(priv->rxic); rx_queue = priv->rx_queue;
rxcount = get_icft_value(priv->rxic); tx_queue = priv->tx_queue;
txtime = get_ictt_value(priv->txic);
txcount = get_icft_value(priv->txic); rxtime = get_ictt_value(rx_queue->rxic);
rxcount = get_icft_value(rx_queue->rxic);
txtime = get_ictt_value(tx_queue->txic);
txcount = get_icft_value(tx_queue->txic);
cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, rxtime); cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, rxtime);
cvals->rx_max_coalesced_frames = rxcount; cvals->rx_max_coalesced_frames = rxcount;
...@@ -339,16 +349,21 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals ...@@ -339,16 +349,21 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar_priv_tx_q *tx_queue = NULL;
struct gfar_priv_rx_q *rx_queue = NULL;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP; return -EOPNOTSUPP;
tx_queue = priv->tx_queue;
rx_queue = priv->rx_queue;
/* Set up rx coalescing */ /* Set up rx coalescing */
if ((cvals->rx_coalesce_usecs == 0) || if ((cvals->rx_coalesce_usecs == 0) ||
(cvals->rx_max_coalesced_frames == 0)) (cvals->rx_max_coalesced_frames == 0))
priv->rxcoalescing = 0; rx_queue->rxcoalescing = 0;
else else
priv->rxcoalescing = 1; rx_queue->rxcoalescing = 1;
if (NULL == priv->phydev) if (NULL == priv->phydev)
return -ENODEV; return -ENODEV;
...@@ -366,15 +381,15 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals ...@@ -366,15 +381,15 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
return -EINVAL; return -EINVAL;
} }
priv->rxic = mk_ic_value(cvals->rx_max_coalesced_frames, rx_queue->rxic = mk_ic_value(cvals->rx_max_coalesced_frames,
gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs)); gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs));
/* Set up tx coalescing */ /* Set up tx coalescing */
if ((cvals->tx_coalesce_usecs == 0) || if ((cvals->tx_coalesce_usecs == 0) ||
(cvals->tx_max_coalesced_frames == 0)) (cvals->tx_max_coalesced_frames == 0))
priv->txcoalescing = 0; tx_queue->txcoalescing = 0;
else else
priv->txcoalescing = 1; tx_queue->txcoalescing = 1;
/* Check the bounds of the values */ /* Check the bounds of the values */
if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
...@@ -389,16 +404,16 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals ...@@ -389,16 +404,16 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
return -EINVAL; return -EINVAL;
} }
priv->txic = mk_ic_value(cvals->tx_max_coalesced_frames, tx_queue->txic = mk_ic_value(cvals->tx_max_coalesced_frames,
gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
gfar_write(&priv->regs->rxic, 0); gfar_write(&priv->regs->rxic, 0);
if (priv->rxcoalescing) if (rx_queue->rxcoalescing)
gfar_write(&priv->regs->rxic, priv->rxic); gfar_write(&priv->regs->rxic, rx_queue->rxic);
gfar_write(&priv->regs->txic, 0); gfar_write(&priv->regs->txic, 0);
if (priv->txcoalescing) if (tx_queue->txcoalescing)
gfar_write(&priv->regs->txic, priv->txic); gfar_write(&priv->regs->txic, tx_queue->txic);
return 0; return 0;
} }
...@@ -409,6 +424,11 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals ...@@ -409,6 +424,11 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar_priv_tx_q *tx_queue = NULL;
struct gfar_priv_rx_q *rx_queue = NULL;
tx_queue = priv->tx_queue;
rx_queue = priv->rx_queue;
rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE; rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE;
rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE; rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE;
...@@ -418,10 +438,10 @@ static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rv ...@@ -418,10 +438,10 @@ static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rv
/* Values changeable by the user. The valid values are /* Values changeable by the user. The valid values are
* in the range 1 to the "*_max_pending" counterpart above. * in the range 1 to the "*_max_pending" counterpart above.
*/ */
rvals->rx_pending = priv->rx_ring_size; rvals->rx_pending = rx_queue->rx_ring_size;
rvals->rx_mini_pending = priv->rx_ring_size; rvals->rx_mini_pending = rx_queue->rx_ring_size;
rvals->rx_jumbo_pending = priv->rx_ring_size; rvals->rx_jumbo_pending = rx_queue->rx_ring_size;
rvals->tx_pending = priv->tx_ring_size; rvals->tx_pending = tx_queue->tx_ring_size;
} }
/* Change the current ring parameters, stopping the controller if /* Change the current ring parameters, stopping the controller if
...@@ -431,6 +451,8 @@ static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rv ...@@ -431,6 +451,8 @@ static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rv
static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar_priv_tx_q *tx_queue = NULL;
struct gfar_priv_rx_q *rx_queue = NULL;
int err = 0; int err = 0;
if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)
...@@ -451,29 +473,32 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva ...@@ -451,29 +473,32 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
return -EINVAL; return -EINVAL;
} }
tx_queue = priv->tx_queue;
rx_queue = priv->rx_queue;
if (dev->flags & IFF_UP) { if (dev->flags & IFF_UP) {
unsigned long flags; unsigned long flags;
/* Halt TX and RX, and process the frames which /* Halt TX and RX, and process the frames which
* have already been received */ * have already been received */
spin_lock_irqsave(&priv->txlock, flags); spin_lock_irqsave(&tx_queue->txlock, flags);
spin_lock(&priv->rxlock); spin_lock(&rx_queue->rxlock);
gfar_halt(dev); gfar_halt(dev);
spin_unlock(&priv->rxlock); spin_unlock(&rx_queue->rxlock);
spin_unlock_irqrestore(&priv->txlock, flags); spin_unlock_irqrestore(&tx_queue->txlock, flags);
gfar_clean_rx_ring(dev, priv->rx_ring_size); gfar_clean_rx_ring(rx_queue, rx_queue->rx_ring_size);
/* Now we take down the rings to rebuild them */ /* Now we take down the rings to rebuild them */
stop_gfar(dev); stop_gfar(dev);
} }
/* Change the size */ /* Change the size */
priv->rx_ring_size = rvals->rx_pending; rx_queue->rx_ring_size = rvals->rx_pending;
priv->tx_ring_size = rvals->tx_pending; tx_queue->tx_ring_size = rvals->tx_pending;
priv->num_txbdfree = priv->tx_ring_size; tx_queue->num_txbdfree = tx_queue->tx_ring_size;
/* Rebuild the rings with the new size */ /* Rebuild the rings with the new size */
if (dev->flags & IFF_UP) { if (dev->flags & IFF_UP) {
...@@ -486,24 +511,29 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva ...@@ -486,24 +511,29 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
{ {
struct gfar_private *priv = netdev_priv(dev); struct gfar_private *priv = netdev_priv(dev);
struct gfar_priv_rx_q *rx_queue = NULL;
struct gfar_priv_tx_q *tx_queue = NULL;
unsigned long flags; unsigned long flags;
int err = 0; int err = 0;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP; return -EOPNOTSUPP;
tx_queue = priv->tx_queue;
rx_queue = priv->rx_queue;
if (dev->flags & IFF_UP) { if (dev->flags & IFF_UP) {
/* Halt TX and RX, and process the frames which /* Halt TX and RX, and process the frames which
* have already been received */ * have already been received */
spin_lock_irqsave(&priv->txlock, flags); spin_lock_irqsave(&tx_queue->txlock, flags);
spin_lock(&priv->rxlock); spin_lock(&rx_queue->rxlock);
gfar_halt(dev); gfar_halt(dev);
spin_unlock(&priv->rxlock); spin_unlock(&rx_queue->rxlock);
spin_unlock_irqrestore(&priv->txlock, flags); spin_unlock_irqrestore(&tx_queue->txlock, flags);
gfar_clean_rx_ring(dev, priv->rx_ring_size); gfar_clean_rx_ring(rx_queue, rx_queue->rx_ring_size);
/* Now we take down the rings to rebuild them */ /* Now we take down the rings to rebuild them */
stop_gfar(dev); stop_gfar(dev);
......
...@@ -8,8 +8,9 @@ ...@@ -8,8 +8,9 @@
* *
* Author: Andy Fleming * Author: Andy Fleming
* Maintainer: Kumar Gala (galak@kernel.crashing.org) * Maintainer: Kumar Gala (galak@kernel.crashing.org)
* Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
* *
* Copyright (c) 2002-2005 Freescale Semiconductor, Inc. * Copyright 2002-2009 Freescale Semiconductor, Inc.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
...@@ -49,6 +50,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev, ...@@ -49,6 +50,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar_priv_rx_q *rx_queue = NULL;
int new_setting = 0; int new_setting = 0;
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -56,6 +58,8 @@ static ssize_t gfar_set_bd_stash(struct device *dev, ...@@ -56,6 +58,8 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING)) if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING))
return count; return count;
rx_queue = priv->rx_queue;
/* Find out the new setting */ /* Find out the new setting */
if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
new_setting = 1; new_setting = 1;
...@@ -65,7 +69,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev, ...@@ -65,7 +69,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
else else
return count; return count;
spin_lock_irqsave(&priv->rxlock, flags); spin_lock_irqsave(&rx_queue->rxlock, flags);
/* Set the new stashing value */ /* Set the new stashing value */
priv->bd_stash_en = new_setting; priv->bd_stash_en = new_setting;
...@@ -79,7 +83,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev, ...@@ -79,7 +83,7 @@ static ssize_t gfar_set_bd_stash(struct device *dev,
gfar_write(&priv->regs->attr, temp); gfar_write(&priv->regs->attr, temp);
spin_unlock_irqrestore(&priv->rxlock, flags); spin_unlock_irqrestore(&rx_queue->rxlock, flags);
return count; return count;
} }
...@@ -99,6 +103,7 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev, ...@@ -99,6 +103,7 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar_priv_rx_q *rx_queue = NULL;
unsigned int length = simple_strtoul(buf, NULL, 0); unsigned int length = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -106,7 +111,9 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev, ...@@ -106,7 +111,9 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev,
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
return count; return count;
spin_lock_irqsave(&priv->rxlock, flags); rx_queue = priv->rx_queue;
spin_lock_irqsave(&rx_queue->rxlock, flags);
if (length > priv->rx_buffer_size) if (length > priv->rx_buffer_size)
goto out; goto out;
...@@ -131,7 +138,7 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev, ...@@ -131,7 +138,7 @@ static ssize_t gfar_set_rx_stash_size(struct device *dev,
gfar_write(&priv->regs->attr, temp); gfar_write(&priv->regs->attr, temp);
out: out:
spin_unlock_irqrestore(&priv->rxlock, flags); spin_unlock_irqrestore(&rx_queue->rxlock, flags);
return count; return count;
} }
...@@ -154,6 +161,7 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev, ...@@ -154,6 +161,7 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar_priv_rx_q *rx_queue = NULL;
unsigned short index = simple_strtoul(buf, NULL, 0); unsigned short index = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -161,7 +169,9 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev, ...@@ -161,7 +169,9 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev,
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING)) if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
return count; return count;
spin_lock_irqsave(&priv->rxlock, flags); rx_queue = priv->rx_queue;
spin_lock_irqsave(&rx_queue->rxlock, flags);
if (index > priv->rx_stash_size) if (index > priv->rx_stash_size)
goto out; goto out;
...@@ -176,7 +186,7 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev, ...@@ -176,7 +186,7 @@ static ssize_t gfar_set_rx_stash_index(struct device *dev,
gfar_write(&priv->regs->attreli, flags); gfar_write(&priv->regs->attreli, flags);
out: out:
spin_unlock_irqrestore(&priv->rxlock, flags); spin_unlock_irqrestore(&rx_queue->rxlock, flags);
return count; return count;
} }
...@@ -198,6 +208,7 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev, ...@@ -198,6 +208,7 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar_priv_tx_q *tx_queue = NULL;
unsigned int length = simple_strtoul(buf, NULL, 0); unsigned int length = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -205,7 +216,9 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev, ...@@ -205,7 +216,9 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev,
if (length > GFAR_MAX_FIFO_THRESHOLD) if (length > GFAR_MAX_FIFO_THRESHOLD)
return count; return count;
spin_lock_irqsave(&priv->txlock, flags); tx_queue = priv->tx_queue;
spin_lock_irqsave(&tx_queue->txlock, flags);
priv->fifo_threshold = length; priv->fifo_threshold = length;
...@@ -214,7 +227,7 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev, ...@@ -214,7 +227,7 @@ static ssize_t gfar_set_fifo_threshold(struct device *dev,
temp |= length; temp |= length;
gfar_write(&priv->regs->fifo_tx_thr, temp); gfar_write(&priv->regs->fifo_tx_thr, temp);
spin_unlock_irqrestore(&priv->txlock, flags); spin_unlock_irqrestore(&tx_queue->txlock, flags);
return count; return count;
} }
...@@ -235,6 +248,7 @@ static ssize_t gfar_set_fifo_starve(struct device *dev, ...@@ -235,6 +248,7 @@ static ssize_t gfar_set_fifo_starve(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar_priv_tx_q *tx_queue = NULL;
unsigned int num = simple_strtoul(buf, NULL, 0); unsigned int num = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -242,7 +256,8 @@ static ssize_t gfar_set_fifo_starve(struct device *dev, ...@@ -242,7 +256,8 @@ static ssize_t gfar_set_fifo_starve(struct device *dev,
if (num > GFAR_MAX_FIFO_STARVE) if (num > GFAR_MAX_FIFO_STARVE)
return count; return count;
spin_lock_irqsave(&priv->txlock, flags); tx_queue = priv->tx_queue;
spin_lock_irqsave(&tx_queue->txlock, flags);
priv->fifo_starve = num; priv->fifo_starve = num;
...@@ -251,7 +266,7 @@ static ssize_t gfar_set_fifo_starve(struct device *dev, ...@@ -251,7 +266,7 @@ static ssize_t gfar_set_fifo_starve(struct device *dev,
temp |= num; temp |= num;
gfar_write(&priv->regs->fifo_tx_starve, temp); gfar_write(&priv->regs->fifo_tx_starve, temp);
spin_unlock_irqrestore(&priv->txlock, flags); spin_unlock_irqrestore(&tx_queue->txlock, flags);
return count; return count;
} }
...@@ -273,6 +288,7 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev, ...@@ -273,6 +288,7 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct gfar_private *priv = netdev_priv(to_net_dev(dev)); struct gfar_private *priv = netdev_priv(to_net_dev(dev));
struct gfar_priv_tx_q *tx_queue = NULL;
unsigned int num = simple_strtoul(buf, NULL, 0); unsigned int num = simple_strtoul(buf, NULL, 0);
u32 temp; u32 temp;
unsigned long flags; unsigned long flags;
...@@ -280,7 +296,8 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev, ...@@ -280,7 +296,8 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev,
if (num > GFAR_MAX_FIFO_STARVE_OFF) if (num > GFAR_MAX_FIFO_STARVE_OFF)
return count; return count;
spin_lock_irqsave(&priv->txlock, flags); tx_queue = priv->tx_queue;
spin_lock_irqsave(&tx_queue->txlock, flags);
priv->fifo_starve_off = num; priv->fifo_starve_off = num;
...@@ -289,7 +306,7 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev, ...@@ -289,7 +306,7 @@ static ssize_t gfar_set_fifo_starve_off(struct device *dev,
temp |= num; temp |= num;
gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);
spin_unlock_irqrestore(&priv->txlock, flags); spin_unlock_irqrestore(&tx_queue->txlock, flags);
return count; return count;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment