summaryrefslogtreecommitdiff
path: root/drivers/net/ibm_emac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ibm_emac')
-rw-r--r--drivers/net/ibm_emac/Kconfig70
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c29
-rw-r--r--drivers/net/ibm_emac/ibm_emac_debug.c8
-rw-r--r--drivers/net/ibm_emac/ibm_emac_mal.c48
-rw-r--r--drivers/net/ibm_emac/ibm_emac_mal.h2
5 files changed, 106 insertions, 51 deletions
diff --git a/drivers/net/ibm_emac/Kconfig b/drivers/net/ibm_emac/Kconfig
new file mode 100644
index 000000000000..f61c48047dc0
--- /dev/null
+++ b/drivers/net/ibm_emac/Kconfig
@@ -0,0 +1,70 @@
+config IBM_EMAC
+ tristate "PowerPC 4xx on-chip Ethernet support"
+ depends on 4xx && !PPC_MERGE
+ help
+ This driver supports the PowerPC 4xx EMAC family of on-chip
+ Ethernet controllers.
+
+config IBM_EMAC_RXB
+ int "Number of receive buffers"
+ depends on IBM_EMAC
+ default "128"
+
+config IBM_EMAC_TXB
+ int "Number of transmit buffers"
+ depends on IBM_EMAC
+ default "64"
+
+config IBM_EMAC_POLL_WEIGHT
+ int "MAL NAPI polling weight"
+ depends on IBM_EMAC
+ default "32"
+
+config IBM_EMAC_RX_COPY_THRESHOLD
+ int "RX skb copy threshold (bytes)"
+ depends on IBM_EMAC
+ default "256"
+
+config IBM_EMAC_RX_SKB_HEADROOM
+ int "Additional RX skb headroom (bytes)"
+ depends on IBM_EMAC
+ default "0"
+ help
+ Additional receive skb headroom. Note, that driver
+ will always reserve at least 2 bytes to make IP header
+ aligned, so usually there is no need to add any additional
+ headroom.
+
+ If unsure, set to 0.
+
+config IBM_EMAC_PHY_RX_CLK_FIX
+ bool "PHY Rx clock workaround"
+ depends on IBM_EMAC && (405EP || 440GX || 440EP || 440GR)
+ help
+ Enable this if EMAC attached to a PHY which doesn't generate
+ RX clock if there is no link, if this is the case, you will
+ see "TX disable timeout" or "RX disable timeout" in the system
+ log.
+
+ If unsure, say N.
+
+config IBM_EMAC_DEBUG
+ bool "Debugging"
+ depends on IBM_EMAC
+ default n
+
+config IBM_EMAC_ZMII
+ bool
+ depends on IBM_EMAC && (NP405H || NP405L || 44x)
+ default y
+
+config IBM_EMAC_RGMII
+ bool
+ depends on IBM_EMAC && 440GX
+ default y
+
+config IBM_EMAC_TAH
+ bool
+ depends on IBM_EMAC && 440GX
+ default y
+
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index f752e5fc65ba..73664f226f32 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -353,10 +353,9 @@ static void emac_hash_mc(struct ocp_enet_private *dev)
for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
int bit;
- DBG2("%d: mc %02x:%02x:%02x:%02x:%02x:%02x" NL,
- dev->def->index,
- dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
- dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
+ DECLARE_MAC_BUF(mac);
+ DBG2("%d: mc %s" NL,
+ dev->def->index, print_mac(mac, dmi->dmi_addr));
bit = 63 - (ether_crc(ETH_ALEN, dmi->dmi_addr) >> 26);
gaht[bit >> 4] |= 0x8000 >> (bit & 0x0f);
@@ -1843,9 +1842,14 @@ static int emac_ethtool_nway_reset(struct net_device *ndev)
return res;
}
-static int emac_ethtool_get_stats_count(struct net_device *ndev)
+static int emac_get_sset_count(struct net_device *ndev, int sset)
{
- return EMAC_ETHTOOL_STATS_COUNT;
+ switch (sset) {
+ case ETH_SS_STATS:
+ return EMAC_ETHTOOL_STATS_COUNT;
+ default:
+ return -EOPNOTSUPP;
+ }
}
static void emac_ethtool_get_strings(struct net_device *ndev, u32 stringset,
@@ -1876,7 +1880,6 @@ static void emac_ethtool_get_drvinfo(struct net_device *ndev,
strcpy(info->version, DRV_VERSION);
info->fw_version[0] = '\0';
sprintf(info->bus_info, "PPC 4xx EMAC %d", dev->def->index);
- info->n_stats = emac_ethtool_get_stats_count(ndev);
info->regdump_len = emac_ethtool_get_regs_len(ndev);
}
@@ -1896,12 +1899,10 @@ static const struct ethtool_ops emac_ethtool_ops = {
.get_rx_csum = emac_ethtool_get_rx_csum,
.get_strings = emac_ethtool_get_strings,
- .get_stats_count = emac_ethtool_get_stats_count,
+ .get_sset_count = emac_get_sset_count,
.get_ethtool_stats = emac_ethtool_get_ethtool_stats,
.get_link = ethtool_op_get_link,
- .get_tx_csum = ethtool_op_get_tx_csum,
- .get_sg = ethtool_op_get_sg,
};
static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
@@ -1942,6 +1943,7 @@ static int __init emac_probe(struct ocp_device *ocpdev)
struct ocp_device *maldev;
struct ocp_enet_private *dev;
int err, i;
+ DECLARE_MAC_BUF(mac);
DBG("%d: probe" NL, ocpdev->def->index);
@@ -1962,7 +1964,6 @@ static int __init emac_probe(struct ocp_device *ocpdev)
dev->ndev = ndev;
dev->ldev = &ocpdev->dev;
dev->def = ocpdev->def;
- SET_MODULE_OWNER(ndev);
/* Find MAL device we are connected to */
maldev =
@@ -2191,10 +2192,8 @@ static int __init emac_probe(struct ocp_device *ocpdev)
ocp_set_drvdata(ocpdev, dev);
- printk("%s: emac%d, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- ndev->name, dev->def->index,
- ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
- ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+ printk("%s: emac%d, MAC %s\n",
+ ndev->name, dev->def->index, print_mac(mac, ndev->dev_addr));
if (dev->phy.address >= 0)
printk("%s: found %s PHY (0x%02x)\n", ndev->name,
diff --git a/drivers/net/ibm_emac/ibm_emac_debug.c b/drivers/net/ibm_emac/ibm_emac_debug.c
index 92f970d402df..1f70906cfb98 100644
--- a/drivers/net/ibm_emac/ibm_emac_debug.c
+++ b/drivers/net/ibm_emac/ibm_emac_debug.c
@@ -132,7 +132,7 @@ void emac_dbg_register(int idx, struct ocp_enet_private *dev)
{
unsigned long flags;
- if (idx >= sizeof(__emacs) / sizeof(__emacs[0])) {
+ if (idx >= ARRAY_SIZE(__emacs)) {
printk(KERN_WARNING
"invalid index %d when registering EMAC for debugging\n",
idx);
@@ -148,7 +148,7 @@ void mal_dbg_register(int idx, struct ibm_ocp_mal *mal)
{
unsigned long flags;
- if (idx >= sizeof(__mals) / sizeof(__mals[0])) {
+ if (idx >= ARRAY_SIZE(__mals)) {
printk(KERN_WARNING
"invalid index %d when registering MAL for debugging\n",
idx);
@@ -167,11 +167,11 @@ void emac_dbg_dump_all(void)
local_irq_save(flags);
- for (i = 0; i < sizeof(__mals) / sizeof(__mals[0]); ++i)
+ for (i = 0; i < ARRAY_SIZE(__mals); ++i)
if (__mals[i])
emac_mal_dump(__mals[i]);
- for (i = 0; i < sizeof(__emacs) / sizeof(__emacs[0]); ++i)
+ for (i = 0; i < ARRAY_SIZE(__emacs); ++i)
if (__emacs[i])
emac_mac_dump(i, __emacs[i]);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index cabd9846a5ee..4e49e8c4f871 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -207,10 +207,10 @@ static irqreturn_t mal_serr(int irq, void *dev_instance)
static inline void mal_schedule_poll(struct ibm_ocp_mal *mal)
{
- if (likely(netif_rx_schedule_prep(&mal->poll_dev))) {
+ if (likely(napi_schedule_prep(&mal->napi))) {
MAL_DBG2("%d: schedule_poll" NL, mal->def->index);
mal_disable_eob_irq(mal);
- __netif_rx_schedule(&mal->poll_dev);
+ __napi_schedule(&mal->napi);
} else
MAL_DBG2("%d: already in poll" NL, mal->def->index);
}
@@ -273,11 +273,11 @@ static irqreturn_t mal_rxde(int irq, void *dev_instance)
return IRQ_HANDLED;
}
-static int mal_poll(struct net_device *ndev, int *budget)
+static int mal_poll(struct napi_struct *napi, int budget)
{
- struct ibm_ocp_mal *mal = ndev->priv;
+ struct ibm_ocp_mal *mal = container_of(napi, struct ibm_ocp_mal, napi);
struct list_head *l;
- int rx_work_limit = min(ndev->quota, *budget), received = 0, done;
+ int received = 0;
MAL_DBG2("%d: poll(%d) %d ->" NL, mal->def->index, *budget,
rx_work_limit);
@@ -295,38 +295,34 @@ static int mal_poll(struct net_device *ndev, int *budget)
list_for_each(l, &mal->poll_list) {
struct mal_commac *mc =
list_entry(l, struct mal_commac, poll_list);
- int n = mc->ops->poll_rx(mc->dev, rx_work_limit);
+ int n = mc->ops->poll_rx(mc->dev, budget);
if (n) {
received += n;
- rx_work_limit -= n;
- if (rx_work_limit <= 0) {
- done = 0;
+ budget -= n;
+ if (budget <= 0)
goto more_work; // XXX What if this is the last one ?
- }
}
}
/* We need to disable IRQs to protect from RXDE IRQ here */
local_irq_disable();
- __netif_rx_complete(ndev);
+ __napi_complete(napi);
mal_enable_eob_irq(mal);
local_irq_enable();
- done = 1;
-
/* Check for "rotting" packet(s) */
list_for_each(l, &mal->poll_list) {
struct mal_commac *mc =
list_entry(l, struct mal_commac, poll_list);
if (unlikely(mc->ops->peek_rx(mc->dev) || mc->rx_stopped)) {
MAL_DBG2("%d: rotting packet" NL, mal->def->index);
- if (netif_rx_reschedule(ndev, received))
+ if (napi_reschedule(napi))
mal_disable_eob_irq(mal);
else
MAL_DBG2("%d: already in poll list" NL,
mal->def->index);
- if (rx_work_limit > 0)
+ if (budget > 0)
goto again;
else
goto more_work;
@@ -335,12 +331,8 @@ static int mal_poll(struct net_device *ndev, int *budget)
}
more_work:
- ndev->quota -= received;
- *budget -= received;
-
- MAL_DBG2("%d: poll() %d <- %d" NL, mal->def->index, *budget,
- done ? 0 : 1);
- return done ? 0 : 1;
+ MAL_DBG2("%d: poll() %d <- %d" NL, mal->def->index, budget, received);
+ return received;
}
static void mal_reset(struct ibm_ocp_mal *mal)
@@ -425,11 +417,8 @@ static int __init mal_probe(struct ocp_device *ocpdev)
mal->def = ocpdev->def;
INIT_LIST_HEAD(&mal->poll_list);
- set_bit(__LINK_STATE_START, &mal->poll_dev.state);
- mal->poll_dev.weight = CONFIG_IBM_EMAC_POLL_WEIGHT;
- mal->poll_dev.poll = mal_poll;
- mal->poll_dev.priv = mal;
- atomic_set(&mal->poll_dev.refcnt, 1);
+ mal->napi.weight = CONFIG_IBM_EMAC_POLL_WEIGHT;
+ mal->napi.poll = mal_poll;
INIT_LIST_HEAD(&mal->list);
@@ -520,11 +509,8 @@ static void __exit mal_remove(struct ocp_device *ocpdev)
MAL_DBG("%d: remove" NL, mal->def->index);
- /* Syncronize with scheduled polling,
- stolen from net/core/dev.c:dev_close()
- */
- clear_bit(__LINK_STATE_START, &mal->poll_dev.state);
- netif_poll_disable(&mal->poll_dev);
+ /* Synchronize with scheduled polling */
+ napi_disable(&mal->napi);
if (!list_empty(&mal->list)) {
/* This is *very* bad */
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index 64bc338acc6c..8f54d621994d 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -195,7 +195,7 @@ struct ibm_ocp_mal {
dcr_host_t dcrhost;
struct list_head poll_list;
- struct net_device poll_dev;
+ struct napi_struct napi;
struct list_head list;
u32 tx_chan_mask;