summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-20 21:04:47 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-20 21:04:47 -0700
commit3b59bf081622b6446db77ad06c93fe23677bc533 (patch)
tree3f4bb5a27c90cc86994a1f6d3c53fbf9208003cb /drivers/net/ethernet/freescale
parente45836fafe157df137a837093037f741ad8f4c90 (diff)
parentbbdb32cb5b73597386913d052165423b9d736145 (diff)
downloadop-kernel-dev-3b59bf081622b6446db77ad06c93fe23677bc533.zip
op-kernel-dev-3b59bf081622b6446db77ad06c93fe23677bc533.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking merge from David Miller: "1) Move ixgbe driver over to purely page based buffering on receive. From Alexander Duyck. 2) Add receive packet steering support to e1000e, from Bruce Allan. 3) Convert TCP MD5 support over to RCU, from Eric Dumazet. 4) Reduce cpu usage in handling out-of-order TCP packets on modern systems, also from Eric Dumazet. 5) Support the IP{,V6}_UNICAST_IF socket options, making the wine folks happy, from Erich Hoover. 6) Support VLAN trunking from guests in hyperv driver, from Haiyang Zhang. 7) Support byte-queue-limtis in r8169, from Igor Maravic. 8) Outline code intended for IP_RECVTOS in IP_PKTOPTIONS existed but was never properly implemented, Jiri Benc fixed that. 9) 64-bit statistics support in r8169 and 8139too, from Junchang Wang. 10) Support kernel side dump filtering by ctmark in netfilter ctnetlink, from Pablo Neira Ayuso. 11) Support byte-queue-limits in gianfar driver, from Paul Gortmaker. 12) Add new peek socket options to assist with socket migration, from Pavel Emelyanov. 13) Add sch_plug packet scheduler whose queue is controlled by userland daemons using explicit freeze and release commands. From Shriram Rajagopalan. 14) Fix FCOE checksum offload handling on transmit, from Yi Zou." * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1846 commits) Fix pppol2tp getsockname() Remove printk from rds_sendmsg ipv6: fix incorrent ipv6 ipsec packet fragment cpsw: Hook up default ndo_change_mtu. net: qmi_wwan: fix build error due to cdc-wdm dependecy netdev: driver: ethernet: Add TI CPSW driver netdev: driver: ethernet: add cpsw address lookup engine support phy: add am79c874 PHY support mlx4_core: fix race on comm channel bonding: send igmp report for its master fs_enet: Add MPC5125 FEC support and PHY interface selection net: bpf_jit: fix BPF_S_LDX_B_MSH compilation net: update the usage of CHECKSUM_UNNECESSARY fcoe: use CHECKSUM_UNNECESSARY instead of CHECKSUM_PARTIAL on tx net: do not do gso for CHECKSUM_UNNECESSARY in netif_needs_gso ixgbe: Fix issues with SR-IOV loopback when flow control is disabled net/hyperv: Fix the code handling tx busy ixgbe: fix namespace issues when FCoE/DCB is not enabled rtlwifi: Remove unused ETH_ADDR_LEN defines igbvf: Use ETH_ALEN ... Fix up fairly trivial conflicts in drivers/isdn/gigaset/interface.c and drivers/net/usb/{Kconfig,qmi_wwan.c} as per David.
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r--drivers/net/ethernet/freescale/fec.c21
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.c4
-rw-r--r--drivers/net/ethernet/freescale/fec_mpc52xx.h2
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fec.h6
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c32
-rw-r--r--drivers/net/ethernet/freescale/fs_enet/mac-fec.c9
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c24
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h5
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c4
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ptp.c2
-rw-r--r--drivers/net/ethernet/freescale/gianfar_sysfs.c2
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c460
12 files changed, 322 insertions, 249 deletions
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index e92ef1b..a12b3f5 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -711,7 +711,7 @@ fec_enet_rx(struct net_device *ndev)
* include that when passing upstream as it messes up
* bridging applications.
*/
- skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN);
if (unlikely(!skb)) {
printk("%s: Memory squeeze, dropping packet.\n",
@@ -1210,7 +1210,7 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
bdp = fep->rx_bd_base;
for (i = 0; i < RX_RING_SIZE; i++) {
- skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
+ skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
if (!skb) {
fec_enet_free_buffers(ndev);
return -ENOMEM;
@@ -1739,21 +1739,6 @@ static struct platform_driver fec_driver = {
.remove = __devexit_p(fec_drv_remove),
};
-static int __init
-fec_enet_module_init(void)
-{
- printk(KERN_INFO "FEC Ethernet Driver\n");
-
- return platform_driver_register(&fec_driver);
-}
-
-static void __exit
-fec_enet_cleanup(void)
-{
- platform_driver_unregister(&fec_driver);
-}
-
-module_exit(fec_enet_cleanup);
-module_init(fec_enet_module_init);
+module_platform_driver(fec_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 30745b5..7b34d8c 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -160,7 +160,7 @@ static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task
struct sk_buff *skb;
while (!bcom_queue_full(rxtsk)) {
- skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
+ skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE);
if (!skb)
return -EAGAIN;
@@ -416,7 +416,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id)
/* skbs are allocated on open, so now we allocate a new one,
* and remove the old (with the packet) */
- skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
+ skb = netdev_alloc_skb(dev, FEC_RX_BUFFER_SIZE);
if (!skb) {
/* Can't get a new one : reuse the same & drop pkt */
dev_notice(&dev->dev, "Low memory - dropped packet.\n");
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.h b/drivers/net/ethernet/freescale/fec_mpc52xx.h
index 41d2dff..10afa54 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.h
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.h
@@ -1,5 +1,5 @@
/*
- * drivers/drivers/net/fec_mpc52xx/fec.h
+ * drivers/net/ethernet/freescale/fec_mpc52xx.h
*
* Driver for the MPC5200 Fast Ethernet Controller
*
diff --git a/drivers/net/ethernet/freescale/fs_enet/fec.h b/drivers/net/ethernet/freescale/fs_enet/fec.h
index e980527..b9fe5bd 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fec.h
+++ b/drivers/net/ethernet/freescale/fs_enet/fec.h
@@ -23,6 +23,10 @@
#define FEC_ECNTRL_ETHER_EN 0x00000002
#define FEC_ECNTRL_RESET 0x00000001
+/* RMII mode enabled only when MII_MODE bit is set too. */
+#define FEC_RCNTRL_RMII_MODE (0x00000100 | \
+ FEC_RCNTRL_MII_MODE | FEC_RCNTRL_FCE)
+#define FEC_RCNTRL_FCE 0x00000020
#define FEC_RCNTRL_BC_REJ 0x00000010
#define FEC_RCNTRL_PROM 0x00000008
#define FEC_RCNTRL_MII_MODE 0x00000004
@@ -33,8 +37,6 @@
#define FEC_TCNTRL_HBC 0x00000002
#define FEC_TCNTRL_GTS 0x00000001
-
-
/*
* Delay to wait for FEC reset command to complete (in us)
*/
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 910a8e1..e4e6cd2 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -154,7 +154,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
if (pkt_len <= fpi->rx_copybreak) {
/* +2 to make IP header L1 cache aligned */
- skbn = dev_alloc_skb(pkt_len + 2);
+ skbn = netdev_alloc_skb(dev, pkt_len + 2);
if (skbn != NULL) {
skb_reserve(skbn, 2); /* align IP header */
skb_copy_from_linear_data(skb,
@@ -165,7 +165,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
skbn = skbt;
}
} else {
- skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+ skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
if (skbn)
skb_align(skbn, ENET_RX_ALIGN);
@@ -286,7 +286,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
if (pkt_len <= fpi->rx_copybreak) {
/* +2 to make IP header L1 cache aligned */
- skbn = dev_alloc_skb(pkt_len + 2);
+ skbn = netdev_alloc_skb(dev, pkt_len + 2);
if (skbn != NULL) {
skb_reserve(skbn, 2); /* align IP header */
skb_copy_from_linear_data(skb,
@@ -297,7 +297,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev)
skbn = skbt;
}
} else {
- skbn = dev_alloc_skb(ENET_RX_FRSIZE);
+ skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
if (skbn)
skb_align(skbn, ENET_RX_ALIGN);
@@ -504,7 +504,7 @@ void fs_init_bds(struct net_device *dev)
* Initialize the receive buffer descriptors.
*/
for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
- skb = dev_alloc_skb(ENET_RX_FRSIZE);
+ skb = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
if (skb == NULL) {
dev_warn(fep->dev,
"Memory squeeze, unable to allocate skb\n");
@@ -592,7 +592,7 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
struct fs_enet_private *fep = netdev_priv(dev);
/* Alloc new skb */
- new_skb = dev_alloc_skb(skb->len + 4);
+ new_skb = netdev_alloc_skb(dev, skb->len + 4);
if (!new_skb) {
if (net_ratelimit()) {
dev_warn(fep->dev,
@@ -790,16 +790,20 @@ static int fs_init_phy(struct net_device *dev)
{
struct fs_enet_private *fep = netdev_priv(dev);
struct phy_device *phydev;
+ phy_interface_t iface;
fep->oldlink = 0;
fep->oldspeed = 0;
fep->oldduplex = -1;
+ iface = fep->fpi->use_rmii ?
+ PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII;
+
phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0,
- PHY_INTERFACE_MODE_MII);
+ iface);
if (!phydev) {
phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link,
- PHY_INTERFACE_MODE_MII);
+ iface);
}
if (!phydev) {
dev_err(&dev->dev, "Could not attach to PHY\n");
@@ -1007,6 +1011,7 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev)
struct fs_platform_info *fpi;
const u32 *data;
const u8 *mac_addr;
+ const char *phy_connection_type;
int privsize, len, ret = -ENODEV;
match = of_match_device(fs_enet_match, &ofdev->dev);
@@ -1035,6 +1040,13 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev)
NULL)))
goto out_free_fpi;
+ if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
+ phy_connection_type = of_get_property(ofdev->dev.of_node,
+ "phy-connection-type", NULL);
+ if (phy_connection_type && !strcmp("rmii", phy_connection_type))
+ fpi->use_rmii = 1;
+ }
+
privsize = sizeof(*fep) +
sizeof(struct sk_buff **) *
(fpi->rx_ring + fpi->tx_ring);
@@ -1150,6 +1162,10 @@ static struct of_device_id fs_enet_match[] = {
.compatible = "fsl,mpc5121-fec",
.data = (void *)&fs_fec_ops,
},
+ {
+ .compatible = "fsl,mpc5125-fec",
+ .data = (void *)&fs_fec_ops,
+ },
#else
{
.compatible = "fsl,pq1-fec-enet",
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
index b9fbc83..9ae6cdb 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
@@ -322,10 +322,11 @@ static void restart(struct net_device *dev)
FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
#else
/*
- * Only set MII mode - do not touch maximum frame length
+ * Only set MII/RMII mode - do not touch maximum frame length
* configured before.
*/
- FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);
+ FS(fecp, r_cntrl, fpi->use_rmii ?
+ FEC_RCNTRL_RMII_MODE : FEC_RCNTRL_MII_MODE);
#endif
/*
* adjust to duplex mode
@@ -381,7 +382,9 @@ static void stop(struct net_device *dev)
/* shut down FEC1? that's where the mii bus is */
if (fpi->has_phy) {
- FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */
+ FS(fecp, r_cntrl, fpi->use_rmii ?
+ FEC_RCNTRL_RMII_MODE :
+ FEC_RCNTRL_MII_MODE); /* MII/RMII enable */
FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
FW(fecp, ievent, FEC_ENET_MII);
FW(fecp, mii_speed, feci->mii_speed);
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 39d160d..d9428f0e 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/gianfar.c
+ * drivers/net/ethernet/freescale/gianfar.c
*
* Gianfar Ethernet Driver
* This driver is designed for the non-CPM ethernet controllers
@@ -104,10 +104,7 @@
#include "fsl_pq_mdio.h"
#define TX_TIMEOUT (1*HZ)
-#undef BRIEF_GFAR_ERRORS
-#undef VERBOSE_GFAR_ERRORS
-const char gfar_driver_name[] = "Gianfar Ethernet";
const char gfar_driver_version[] = "1.3";
static int gfar_enet_open(struct net_device *dev);
@@ -1755,9 +1752,12 @@ static void free_skb_resources(struct gfar_private *priv)
/* Go through all the buffer descriptors and free their data buffers */
for (i = 0; i < priv->num_tx_queues; i++) {
+ struct netdev_queue *txq;
tx_queue = priv->tx_queue[i];
+ txq = netdev_get_tx_queue(tx_queue->dev, tx_queue->qindex);
if(tx_queue->tx_skbuff)
free_skb_tx_queue(tx_queue);
+ netdev_tx_reset_queue(txq);
}
for (i = 0; i < priv->num_rx_queues; i++) {
@@ -2217,6 +2217,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
}
+ netdev_tx_sent_queue(txq, skb->len);
+
/*
* We can work in parallel with gfar_clean_tx_ring(), except
* when modifying num_txbdfree. Note that we didn't grab the lock
@@ -2460,6 +2462,7 @@ static void gfar_align_skb(struct sk_buff *skb)
static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
{
struct net_device *dev = tx_queue->dev;
+ struct netdev_queue *txq;
struct gfar_private *priv = netdev_priv(dev);
struct gfar_priv_rx_q *rx_queue = NULL;
struct txbd8 *bdp, *next = NULL;
@@ -2471,10 +2474,13 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
int frags = 0, nr_txbds = 0;
int i;
int howmany = 0;
+ int tqi = tx_queue->qindex;
+ unsigned int bytes_sent = 0;
u32 lstatus;
size_t buflen;
- rx_queue = priv->rx_queue[tx_queue->qindex];
+ rx_queue = priv->rx_queue[tqi];
+ txq = netdev_get_tx_queue(dev, tqi);
bdp = tx_queue->dirty_tx;
skb_dirtytx = tx_queue->skb_dirtytx;
@@ -2533,6 +2539,8 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
bdp = next_txbd(bdp, base, tx_ring_size);
}
+ bytes_sent += skb->len;
+
/*
* If there's room in the queue (limit it to rx_buffer_size)
* we add this skb back into the pool, if it's the right size
@@ -2557,13 +2565,15 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
}
/* If we freed a buffer, we can restart transmission, if necessary */
- if (__netif_subqueue_stopped(dev, tx_queue->qindex) && tx_queue->num_txbdfree)
- netif_wake_subqueue(dev, tx_queue->qindex);
+ if (netif_tx_queue_stopped(txq) && tx_queue->num_txbdfree)
+ netif_wake_subqueue(dev, tqi);
/* Update dirty indicators */
tx_queue->skb_dirtytx = skb_dirtytx;
tx_queue->dirty_tx = bdp;
+ netdev_tx_completed_queue(txq, howmany, bytes_sent);
+
return howmany;
}
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 40c33a7..fc2488a 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1,5 +1,5 @@
/*
- * drivers/net/gianfar.h
+ * drivers/net/ethernet/freescale/gianfar.h
*
* Gianfar Ethernet Driver
* Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
@@ -78,11 +78,8 @@ struct ethtool_rx_list {
#define INCREMENTAL_BUFFER_SIZE 512
#define PHY_INIT_TIMEOUT 100000
-#define GFAR_PHY_CHANGE_TIME 2
-#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.2, "
#define DRV_NAME "gfar-enet"
-extern const char gfar_driver_name[];
extern const char gfar_driver_version[];
/* MAXIMUM NUMBER OF QUEUES SUPPORTED */
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 5a3b2e5..8d74efd 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/gianfar_ethtool.c
+ * drivers/net/ethernet/freescale/gianfar_ethtool.c
*
* Gianfar Ethernet Driver
* Ethtool support for Gianfar Enet
@@ -58,7 +58,7 @@ 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 void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo);
-static char stat_gstrings[][ETH_GSTRING_LEN] = {
+static const char stat_gstrings[][ETH_GSTRING_LEN] = {
"rx-dropped-by-kernel",
"rx-large-frame-errors",
"rx-short-frame-errors",
diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c
index 83e0ed75..5fd620b 100644
--- a/drivers/net/ethernet/freescale/gianfar_ptp.c
+++ b/drivers/net/ethernet/freescale/gianfar_ptp.c
@@ -564,6 +564,6 @@ static struct platform_driver gianfar_ptp_driver = {
module_platform_driver(gianfar_ptp_driver);
-MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>");
+MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
MODULE_DESCRIPTION("PTP clock using the eTSEC");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/freescale/gianfar_sysfs.c b/drivers/net/ethernet/freescale/gianfar_sysfs.c
index 64f4094..cd14a4d 100644
--- a/drivers/net/ethernet/freescale/gianfar_sysfs.c
+++ b/drivers/net/ethernet/freescale/gianfar_sysfs.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/gianfar_sysfs.c
+ * drivers/net/ethernet/freescale/gianfar_sysfs.c
*
* Gianfar Ethernet Driver
* This driver is designed for the non-CPM ethernet controllers
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index ba2dc08..4e3cd2f 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -214,8 +214,9 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
skb = __skb_dequeue(&ugeth->rx_recycle);
if (!skb)
- skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +
- UCC_GETH_RX_DATA_BUF_ALIGNMENT);
+ skb = netdev_alloc_skb(ugeth->ndev,
+ ugeth->ug_info->uf_info.max_rx_buf_length +
+ UCC_GETH_RX_DATA_BUF_ALIGNMENT);
if (skb == NULL)
return NULL;
@@ -227,8 +228,6 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
(((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
1)));
- skb->dev = ugeth->ndev;
-
out_be32(&((struct qe_bd __iomem *)bd)->buf,
dma_map_single(ugeth->dev,
skb->data,
@@ -1857,11 +1856,93 @@ static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *uge
return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */
}
-static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
+static void ucc_geth_free_rx(struct ucc_geth_private *ugeth)
+{
+ struct ucc_geth_info *ug_info;
+ struct ucc_fast_info *uf_info;
+ u16 i, j;
+ u8 __iomem *bd;
+
+
+ ug_info = ugeth->ug_info;
+ uf_info = &ug_info->uf_info;
+
+ for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+ if (ugeth->p_rx_bd_ring[i]) {
+ /* Return existing data buffers in ring */
+ bd = ugeth->p_rx_bd_ring[i];
+ for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
+ if (ugeth->rx_skbuff[i][j]) {
+ dma_unmap_single(ugeth->dev,
+ in_be32(&((struct qe_bd __iomem *)bd)->buf),
+ ugeth->ug_info->
+ uf_info.max_rx_buf_length +
+ UCC_GETH_RX_DATA_BUF_ALIGNMENT,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_any(
+ ugeth->rx_skbuff[i][j]);
+ ugeth->rx_skbuff[i][j] = NULL;
+ }
+ bd += sizeof(struct qe_bd);
+ }
+
+ kfree(ugeth->rx_skbuff[i]);
+
+ if (ugeth->ug_info->uf_info.bd_mem_part ==
+ MEM_PART_SYSTEM)
+ kfree((void *)ugeth->rx_bd_ring_offset[i]);
+ else if (ugeth->ug_info->uf_info.bd_mem_part ==
+ MEM_PART_MURAM)
+ qe_muram_free(ugeth->rx_bd_ring_offset[i]);
+ ugeth->p_rx_bd_ring[i] = NULL;
+ }
+ }
+
+}
+
+static void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
{
+ struct ucc_geth_info *ug_info;
+ struct ucc_fast_info *uf_info;
u16 i, j;
u8 __iomem *bd;
+ ug_info = ugeth->ug_info;
+ uf_info = &ug_info->uf_info;
+
+ for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+ bd = ugeth->p_tx_bd_ring[i];
+ if (!bd)
+ continue;
+ for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
+ if (ugeth->tx_skbuff[i][j]) {
+ dma_unmap_single(ugeth->dev,
+ in_be32(&((struct qe_bd __iomem *)bd)->buf),
+ (in_be32((u32 __iomem *)bd) &
+ BD_LENGTH_MASK),
+ DMA_TO_DEVICE);
+ dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
+ ugeth->tx_skbuff[i][j] = NULL;
+ }
+ }
+
+ kfree(ugeth->tx_skbuff[i]);
+
+ if (ugeth->p_tx_bd_ring[i]) {
+ if (ugeth->ug_info->uf_info.bd_mem_part ==
+ MEM_PART_SYSTEM)
+ kfree((void *)ugeth->tx_bd_ring_offset[i]);
+ else if (ugeth->ug_info->uf_info.bd_mem_part ==
+ MEM_PART_MURAM)
+ qe_muram_free(ugeth->tx_bd_ring_offset[i]);
+ ugeth->p_tx_bd_ring[i] = NULL;
+ }
+ }
+
+}
+
+static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
+{
if (!ugeth)
return;
@@ -1928,64 +2009,8 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
kfree(ugeth->p_init_enet_param_shadow);
ugeth->p_init_enet_param_shadow = NULL;
}
- for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
- bd = ugeth->p_tx_bd_ring[i];
- if (!bd)
- continue;
- for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
- if (ugeth->tx_skbuff[i][j]) {
- dma_unmap_single(ugeth->dev,
- in_be32(&((struct qe_bd __iomem *)bd)->buf),
- (in_be32((u32 __iomem *)bd) &
- BD_LENGTH_MASK),
- DMA_TO_DEVICE);
- dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
- ugeth->tx_skbuff[i][j] = NULL;
- }
- }
-
- kfree(ugeth->tx_skbuff[i]);
-
- if (ugeth->p_tx_bd_ring[i]) {
- if (ugeth->ug_info->uf_info.bd_mem_part ==
- MEM_PART_SYSTEM)
- kfree((void *)ugeth->tx_bd_ring_offset[i]);
- else if (ugeth->ug_info->uf_info.bd_mem_part ==
- MEM_PART_MURAM)
- qe_muram_free(ugeth->tx_bd_ring_offset[i]);
- ugeth->p_tx_bd_ring[i] = NULL;
- }
- }
- for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
- if (ugeth->p_rx_bd_ring[i]) {
- /* Return existing data buffers in ring */
- bd = ugeth->p_rx_bd_ring[i];
- for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
- if (ugeth->rx_skbuff[i][j]) {
- dma_unmap_single(ugeth->dev,
- in_be32(&((struct qe_bd __iomem *)bd)->buf),
- ugeth->ug_info->
- uf_info.max_rx_buf_length +
- UCC_GETH_RX_DATA_BUF_ALIGNMENT,
- DMA_FROM_DEVICE);
- dev_kfree_skb_any(
- ugeth->rx_skbuff[i][j]);
- ugeth->rx_skbuff[i][j] = NULL;
- }
- bd += sizeof(struct qe_bd);
- }
-
- kfree(ugeth->rx_skbuff[i]);
-
- if (ugeth->ug_info->uf_info.bd_mem_part ==
- MEM_PART_SYSTEM)
- kfree((void *)ugeth->rx_bd_ring_offset[i]);
- else if (ugeth->ug_info->uf_info.bd_mem_part ==
- MEM_PART_MURAM)
- qe_muram_free(ugeth->rx_bd_ring_offset[i]);
- ugeth->p_rx_bd_ring[i] = NULL;
- }
- }
+ ucc_geth_free_tx(ugeth);
+ ucc_geth_free_rx(ugeth);
while (!list_empty(&ugeth->group_hash_q))
put_enet_addr_container(ENET_ADDR_CONT_ENTRY
(dequeue(&ugeth->group_hash_q)));
@@ -2211,6 +2236,171 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
return 0;
}
+static int ucc_geth_alloc_tx(struct ucc_geth_private *ugeth)
+{
+ struct ucc_geth_info *ug_info;
+ struct ucc_fast_info *uf_info;
+ int length;
+ u16 i, j;
+ u8 __iomem *bd;
+
+ ug_info = ugeth->ug_info;
+ uf_info = &ug_info->uf_info;
+
+ /* Allocate Tx bds */
+ for (j = 0; j < ug_info->numQueuesTx; j++) {
+ /* Allocate in multiple of
+ UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT,
+ according to spec */
+ length = ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd))
+ / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
+ * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
+ if ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) %
+ UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
+ length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
+ if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
+ u32 align = 4;
+ if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4)
+ align = UCC_GETH_TX_BD_RING_ALIGNMENT;
+ ugeth->tx_bd_ring_offset[j] =
+ (u32) kmalloc((u32) (length + align), GFP_KERNEL);
+
+ if (ugeth->tx_bd_ring_offset[j] != 0)
+ ugeth->p_tx_bd_ring[j] =
+ (u8 __iomem *)((ugeth->tx_bd_ring_offset[j] +
+ align) & ~(align - 1));
+ } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
+ ugeth->tx_bd_ring_offset[j] =
+ qe_muram_alloc(length,
+ UCC_GETH_TX_BD_RING_ALIGNMENT);
+ if (!IS_ERR_VALUE(ugeth->tx_bd_ring_offset[j]))
+ ugeth->p_tx_bd_ring[j] =
+ (u8 __iomem *) qe_muram_addr(ugeth->
+ tx_bd_ring_offset[j]);
+ }
+ if (!ugeth->p_tx_bd_ring[j]) {
+ if (netif_msg_ifup(ugeth))
+ ugeth_err
+ ("%s: Can not allocate memory for Tx bd rings.",
+ __func__);
+ return -ENOMEM;
+ }
+ /* Zero unused end of bd ring, according to spec */
+ memset_io((void __iomem *)(ugeth->p_tx_bd_ring[j] +
+ ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)), 0,
+ length - ug_info->bdRingLenTx[j] * sizeof(struct qe_bd));
+ }
+
+ /* Init Tx bds */
+ for (j = 0; j < ug_info->numQueuesTx; j++) {
+ /* Setup the skbuff rings */
+ ugeth->tx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) *
+ ugeth->ug_info->bdRingLenTx[j],
+ GFP_KERNEL);
+
+ if (ugeth->tx_skbuff[j] == NULL) {
+ if (netif_msg_ifup(ugeth))
+ ugeth_err("%s: Could not allocate tx_skbuff",
+ __func__);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++)
+ ugeth->tx_skbuff[j][i] = NULL;
+
+ ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
+ bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
+ for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
+ /* clear bd buffer */
+ out_be32(&((struct qe_bd __iomem *)bd)->buf, 0);
+ /* set bd status and length */
+ out_be32((u32 __iomem *)bd, 0);
+ bd += sizeof(struct qe_bd);
+ }
+ bd -= sizeof(struct qe_bd);
+ /* set bd status and length */
+ out_be32((u32 __iomem *)bd, T_W); /* for last BD set Wrap bit */
+ }
+
+ return 0;
+}
+
+static int ucc_geth_alloc_rx(struct ucc_geth_private *ugeth)
+{
+ struct ucc_geth_info *ug_info;
+ struct ucc_fast_info *uf_info;
+ int length;
+ u16 i, j;
+ u8 __iomem *bd;
+
+ ug_info = ugeth->ug_info;
+ uf_info = &ug_info->uf_info;
+
+ /* Allocate Rx bds */
+ for (j = 0; j < ug_info->numQueuesRx; j++) {
+ length = ug_info->bdRingLenRx[j] * sizeof(struct qe_bd);
+ if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
+ u32 align = 4;
+ if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4)
+ align = UCC_GETH_RX_BD_RING_ALIGNMENT;
+ ugeth->rx_bd_ring_offset[j] =
+ (u32) kmalloc((u32) (length + align), GFP_KERNEL);
+ if (ugeth->rx_bd_ring_offset[j] != 0)
+ ugeth->p_rx_bd_ring[j] =
+ (u8 __iomem *)((ugeth->rx_bd_ring_offset[j] +
+ align) & ~(align - 1));
+ } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
+ ugeth->rx_bd_ring_offset[j] =
+ qe_muram_alloc(length,
+ UCC_GETH_RX_BD_RING_ALIGNMENT);
+ if (!IS_ERR_VALUE(ugeth->rx_bd_ring_offset[j]))
+ ugeth->p_rx_bd_ring[j] =
+ (u8 __iomem *) qe_muram_addr(ugeth->
+ rx_bd_ring_offset[j]);
+ }
+ if (!ugeth->p_rx_bd_ring[j]) {
+ if (netif_msg_ifup(ugeth))
+ ugeth_err
+ ("%s: Can not allocate memory for Rx bd rings.",
+ __func__);
+ return -ENOMEM;
+ }
+ }
+
+ /* Init Rx bds */
+ for (j = 0; j < ug_info->numQueuesRx; j++) {
+ /* Setup the skbuff rings */
+ ugeth->rx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) *
+ ugeth->ug_info->bdRingLenRx[j],
+ GFP_KERNEL);
+
+ if (ugeth->rx_skbuff[j] == NULL) {
+ if (netif_msg_ifup(ugeth))
+ ugeth_err("%s: Could not allocate rx_skbuff",
+ __func__);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++)
+ ugeth->rx_skbuff[j][i] = NULL;
+
+ ugeth->skb_currx[j] = 0;
+ bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
+ for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
+ /* set bd status and length */
+ out_be32((u32 __iomem *)bd, R_I);
+ /* clear bd buffer */
+ out_be32(&((struct qe_bd __iomem *)bd)->buf, 0);
+ bd += sizeof(struct qe_bd);
+ }
+ bd -= sizeof(struct qe_bd);
+ /* set bd status and length */
+ out_be32((u32 __iomem *)bd, R_W); /* for last BD set Wrap bit */
+ }
+
+ return 0;
+}
+
static int ucc_geth_startup(struct ucc_geth_private *ugeth)
{
struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
@@ -2223,11 +2413,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
int ret_val = -EINVAL;
u32 remoder = UCC_GETH_REMODER_INIT;
u32 init_enet_pram_offset, cecr_subblock, command;
- u32 ifstat, i, j, size, l2qt, l3qt, length;
+ u32 ifstat, i, j, size, l2qt, l3qt;
u16 temoder = UCC_GETH_TEMODER_INIT;
u16 test;
u8 function_code = 0;
- u8 __iomem *bd;
u8 __iomem *endOfRing;
u8 numThreadsRxNumerical, numThreadsTxNumerical;
@@ -2367,142 +2556,13 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE),
0, &uf_regs->upsmr, &ug_regs->uescr);
- /* Allocate Tx bds */
- for (j = 0; j < ug_info->numQueuesTx; j++) {
- /* Allocate in multiple of
- UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT,
- according to spec */
- length = ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd))
- / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
- * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
- if ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) %
- UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
- length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
- if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
- u32 align = 4;
- if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4)
- align = UCC_GETH_TX_BD_RING_ALIGNMENT;
- ugeth->tx_bd_ring_offset[j] =
- (u32) kmalloc((u32) (length + align), GFP_KERNEL);
-
- if (ugeth->tx_bd_ring_offset[j] != 0)
- ugeth->p_tx_bd_ring[j] =
- (u8 __iomem *)((ugeth->tx_bd_ring_offset[j] +
- align) & ~(align - 1));
- } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
- ugeth->tx_bd_ring_offset[j] =
- qe_muram_alloc(length,
- UCC_GETH_TX_BD_RING_ALIGNMENT);
- if (!IS_ERR_VALUE(ugeth->tx_bd_ring_offset[j]))
- ugeth->p_tx_bd_ring[j] =
- (u8 __iomem *) qe_muram_addr(ugeth->
- tx_bd_ring_offset[j]);
- }
- if (!ugeth->p_tx_bd_ring[j]) {
- if (netif_msg_ifup(ugeth))
- ugeth_err
- ("%s: Can not allocate memory for Tx bd rings.",
- __func__);
- return -ENOMEM;
- }
- /* Zero unused end of bd ring, according to spec */
- memset_io((void __iomem *)(ugeth->p_tx_bd_ring[j] +
- ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)), 0,
- length - ug_info->bdRingLenTx[j] * sizeof(struct qe_bd));
- }
-
- /* Allocate Rx bds */
- for (j = 0; j < ug_info->numQueuesRx; j++) {
- length = ug_info->bdRingLenRx[j] * sizeof(struct qe_bd);
- if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
- u32 align = 4;
- if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4)
- align = UCC_GETH_RX_BD_RING_ALIGNMENT;
- ugeth->rx_bd_ring_offset[j] =
- (u32) kmalloc((u32) (length + align), GFP_KERNEL);
- if (ugeth->rx_bd_ring_offset[j] != 0)
- ugeth->p_rx_bd_ring[j] =
- (u8 __iomem *)((ugeth->rx_bd_ring_offset[j] +
- align) & ~(align - 1));
- } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
- ugeth->rx_bd_ring_offset[j] =
- qe_muram_alloc(length,
- UCC_GETH_RX_BD_RING_ALIGNMENT);
- if (!IS_ERR_VALUE(ugeth->rx_bd_ring_offset[j]))
- ugeth->p_rx_bd_ring[j] =
- (u8 __iomem *) qe_muram_addr(ugeth->
- rx_bd_ring_offset[j]);
- }
- if (!ugeth->p_rx_bd_ring[j]) {
- if (netif_msg_ifup(ugeth))
- ugeth_err
- ("%s: Can not allocate memory for Rx bd rings.",
- __func__);
- return -ENOMEM;
- }
- }
-
- /* Init Tx bds */
- for (j = 0; j < ug_info->numQueuesTx; j++) {
- /* Setup the skbuff rings */
- ugeth->tx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) *
- ugeth->ug_info->bdRingLenTx[j],
- GFP_KERNEL);
-
- if (ugeth->tx_skbuff[j] == NULL) {
- if (netif_msg_ifup(ugeth))
- ugeth_err("%s: Could not allocate tx_skbuff",
- __func__);
- return -ENOMEM;
- }
-
- for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++)
- ugeth->tx_skbuff[j][i] = NULL;
-
- ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
- bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
- for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
- /* clear bd buffer */
- out_be32(&((struct qe_bd __iomem *)bd)->buf, 0);
- /* set bd status and length */
- out_be32((u32 __iomem *)bd, 0);
- bd += sizeof(struct qe_bd);
- }
- bd -= sizeof(struct qe_bd);
- /* set bd status and length */
- out_be32((u32 __iomem *)bd, T_W); /* for last BD set Wrap bit */
- }
-
- /* Init Rx bds */
- for (j = 0; j < ug_info->numQueuesRx; j++) {
- /* Setup the skbuff rings */
- ugeth->rx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) *
- ugeth->ug_info->bdRingLenRx[j],
- GFP_KERNEL);
-
- if (ugeth->rx_skbuff[j] == NULL) {
- if (netif_msg_ifup(ugeth))
- ugeth_err("%s: Could not allocate rx_skbuff",
- __func__);
- return -ENOMEM;
- }
-
- for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++)
- ugeth->rx_skbuff[j][i] = NULL;
+ ret_val = ucc_geth_alloc_tx(ugeth);
+ if (ret_val != 0)
+ return ret_val;
- ugeth->skb_currx[j] = 0;
- bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
- for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
- /* set bd status and length */
- out_be32((u32 __iomem *)bd, R_I);
- /* clear bd buffer */
- out_be32(&((struct qe_bd __iomem *)bd)->buf, 0);
- bd += sizeof(struct qe_bd);
- }
- bd -= sizeof(struct qe_bd);
- /* set bd status and length */
- out_be32((u32 __iomem *)bd, R_W); /* for last BD set Wrap bit */
- }
+ ret_val = ucc_geth_alloc_rx(ugeth);
+ if (ret_val != 0)
+ return ret_val;
/*
* Global PRAM
OpenPOWER on IntegriCloud