--- a/drivers/net/ethernet/lantiq_xrx200.c 2019-01-30 02:20:35.780993746 +0100 +++ b/drivers/net/ethernet/lantiq_xrx200.c 2019-02-03 09:37:27.155082134 +0100 @@ -39,13 +39,10 @@ #define SW_POLLING #define SW_ROUTING -#ifdef SW_ROUTING -#define XRX200_MAX_DEV 2 -#else -#define XRX200_MAX_DEV 1 -#endif - #define XRX200_MAX_VLAN 64 +//pc2005 test +//#define XRX200_MAX_VLAN 8 + #define XRX200_PCE_ACTVLAN_IDX 0x01 #define XRX200_PCE_VLANMAP_IDX 0x02 @@ -207,46 +204,42 @@ int refcount; int tx_free; - struct net_device dummy_dev; - struct net_device *devs[XRX200_MAX_DEV]; - struct tasklet_struct tasklet; struct napi_struct napi; struct ltq_dma_channel dma; struct sk_buff *skb[LTQ_DESC_NUM]; + struct xrx200_priv *priv; spinlock_t lock; }; -struct xrx200_hw { - struct clk *clk; - struct mii_bus *mii_bus; - - struct xrx200_chan chan[XRX200_MAX_DMA]; - u16 vlan_vid[XRX200_MAX_VLAN]; - u16 vlan_port_map[XRX200_MAX_VLAN]; - - struct net_device *devs[XRX200_MAX_DEV]; - int num_devs; - - int port_map[XRX200_MAX_PORT]; - unsigned short wan_map; - - struct switch_dev swdev; -}; - struct xrx200_priv { struct net_device_stats stats; int id; + + struct clk *clk; + struct xrx200_chan chan_tx; + struct xrx200_chan chan_rx; + struct net_device *net_dev; + struct device *dev; + struct xrx200_port port[XRX200_MAX_PORT]; int num_port; bool wan; bool sw; - unsigned short port_map; + unsigned short d_port_map; unsigned char mac[6]; - struct xrx200_hw *hw; + struct mii_bus *mii_bus; + + u16 vlan_vid[XRX200_MAX_VLAN]; + u16 vlan_port_map[XRX200_MAX_VLAN]; + + int port_map[XRX200_MAX_PORT]; + unsigned short wan_map; + + struct switch_dev swdev; }; static __iomem void *xrx200_switch_membase; @@ -470,14 +463,14 @@ } // swconfig interface -static void xrx200_hw_init(struct xrx200_hw *hw); +static void xrx200_hw_init(struct xrx200_priv *priv); // global static int xrx200sw_reset_switch(struct switch_dev *dev) { - struct xrx200_hw *hw = container_of(dev, struct xrx200_hw, swdev); + struct xrx200_priv *priv = container_of(dev, struct xrx200_priv, swdev); - xrx200_hw_init(hw); + xrx200_hw_init(priv); return 0; } @@ -523,7 +516,7 @@ static int xrx200sw_set_vlan_vid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) { - struct xrx200_hw *hw = container_of(dev, struct xrx200_hw, swdev); + struct xrx200_priv *priv = container_of(dev, struct xrx200_priv, swdev); int i; struct xrx200_pce_table_entry tev; struct xrx200_pce_table_entry tem; @@ -538,7 +531,7 @@ return -EINVAL; } - hw->vlan_vid[val->port_vlan] = val->value.i; + priv->vlan_vid[val->port_vlan] = val->value.i; tev.index = val->port_vlan; xrx200_pce_table_entry_read(&tev); @@ -571,7 +564,7 @@ static int xrx200sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) { - struct xrx200_hw *hw = container_of(dev, struct xrx200_hw, swdev); + struct xrx200_priv *priv = container_of(dev, struct xrx200_priv, swdev); int i, portmap, tagmap, untagged; struct xrx200_pce_table_entry tem; @@ -624,7 +617,7 @@ ltq_switch_w32_mask(0, portmap, PCE_PMAP2); ltq_switch_w32_mask(0, portmap, PCE_PMAP3); - hw->vlan_port_map[val->port_vlan] = portmap; + priv->vlan_port_map[val->port_vlan] = portmap; xrx200sw_fixup_pvids(); @@ -834,19 +827,16 @@ // .get_port_stats = xrx200sw_get_port_stats, //TODO }; -static int xrx200sw_init(struct xrx200_hw *hw) +static int xrx200sw_init(struct xrx200_priv *priv) { - int netdev_num; - for (netdev_num = 0; netdev_num < hw->num_devs; netdev_num++) - { struct switch_dev *swdev; - struct net_device *dev = hw->devs[netdev_num]; - struct xrx200_priv *priv = netdev_priv(dev); - if (!priv->sw) - continue; + if (!priv->sw) { + pr_info("!!!! no switch\n"); + return -ENODEV; + } - swdev = &hw->swdev; + swdev = &priv->swdev; swdev->name = "Lantiq XRX200 Switch"; swdev->vlans = XRX200_MAX_VLAN; @@ -854,32 +844,49 @@ swdev->cpu_port = 6; swdev->ops = &xrx200sw_ops; - register_switch(swdev, dev); + register_switch(swdev, priv->net_dev); return 0; // enough switches +} + +/* drop all the packets from the DMA ring */ +static void xrx200_flush_dma(struct xrx200_chan *ch) +{ + int i; + + for (i = 0; i < LTQ_DESC_NUM; i++) { + struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc]; + + if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) != LTQ_DMA_C) + break; + + desc->ctl = LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | + XRX200_DMA_DATA_LEN; + ch->dma.desc++; + ch->dma.desc %= LTQ_DESC_NUM; } - return 0; } static int xrx200_open(struct net_device *dev) { struct xrx200_priv *priv = netdev_priv(dev); - int i; - for (i = 0; i < XRX200_MAX_DMA; i++) { - if (!priv->hw->chan[i].dma.irq) - continue; - spin_lock_bh(&priv->hw->chan[i].lock); - if (!priv->hw->chan[i].refcount) { - if (XRX200_DMA_IS_RX(i)) - napi_enable(&priv->hw->chan[i].napi); - ltq_dma_open(&priv->hw->chan[i].dma); - } - priv->hw->chan[i].refcount++; - spin_unlock_bh(&priv->hw->chan[i].lock); - } - for (i = 0; i < priv->num_port; i++) - if (priv->port[i].phydev) - phy_start(priv->port[i].phydev); + napi_enable(&priv->chan_tx.napi); + ltq_dma_open(&priv->chan_tx.dma); + ltq_dma_enable_irq(&priv->chan_tx.dma); + + napi_enable(&priv->chan_rx.napi); + ltq_dma_open(&priv->chan_rx.dma); + /* The boot loader does not always deactivate the receiving of frames + * on the ports and then some packets queue up in the PPE buffers. + * They already passed the PMAC so they do not have the tags + * configured here. Read the these packets here and drop them. + * The HW should have written them into memory after 10us + */ + usleep_range(20, 40); + xrx200_flush_dma(&priv->chan_rx); + + ltq_dma_enable_irq(&priv->chan_rx.dma); + netif_wake_queue(dev); return 0; @@ -896,19 +903,11 @@ if (priv->port[i].phydev) phy_stop(priv->port[i].phydev); - for (i = 0; i < XRX200_MAX_DMA; i++) { - if (!priv->hw->chan[i].dma.irq) - continue; + napi_disable(&priv->chan_rx.napi); + ltq_dma_close(&priv->chan_rx.dma); - priv->hw->chan[i].refcount--; - if (!priv->hw->chan[i].refcount) { - if (XRX200_DMA_IS_RX(i)) - napi_disable(&priv->hw->chan[i].napi); - spin_lock_bh(&priv->hw->chan[i].lock); - ltq_dma_close(&priv->hw->chan[XRX200_DMA_RX].dma); - spin_unlock_bh(&priv->hw->chan[i].lock); - } - } + napi_disable(&priv->chan_tx.napi); + ltq_dma_close(&priv->chan_tx.dma); return 0; } @@ -938,8 +937,8 @@ static void xrx200_hw_receive(struct xrx200_chan *ch, int id) { - struct net_device *dev = ch->devs[id]; - struct xrx200_priv *priv = netdev_priv(dev); + struct xrx200_priv *priv = ch->priv; + struct net_device *dev = priv->net_dev; struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc]; struct sk_buff *skb = ch->skb[ch->dma.desc]; int len = (desc->ctl & LTQ_DMA_SIZE_MASK); @@ -963,15 +962,15 @@ skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); netif_receive_skb(skb); - priv->stats.rx_packets++; - priv->stats.rx_bytes+=len; + dev->stats.rx_packets++; + dev->stats.rx_bytes+=len; } static int xrx200_poll_rx(struct napi_struct *napi, int budget) { struct xrx200_chan *ch = container_of(napi, struct xrx200_chan, napi); - struct xrx200_priv *priv = netdev_priv(ch->devs[0]); + struct xrx200_priv *priv = ch->priv; int rx = 0; int complete = 0; @@ -982,7 +981,7 @@ struct sk_buff *skb = ch->skb[ch->dma.desc]; u8 *special_tag = (u8*)skb->data; int port = (special_tag[7] >> SPPID_SHIFT) & SPPID_MASK; - xrx200_hw_receive(ch, priv->hw->port_map[port]); + xrx200_hw_receive(ch, priv->port_map[port]); #else xrx200_hw_receive(ch, 0); #endif @@ -993,47 +992,70 @@ } if (complete || !rx) { - napi_complete(&ch->napi); + + if (napi_complete_done(&ch->napi,rx)) { +// ltq_dma_ack_irq(&ch->dma); ltq_dma_enable_irq(&ch->dma); + } } return rx; } -static void xrx200_tx_housekeeping(unsigned long ptr) + +static struct net_device_stats *xrx200_get_stats (struct net_device *dev) { - struct xrx200_chan *ch = (struct xrx200_chan *) ptr; + struct xrx200_priv *priv = netdev_priv(dev); + + return &priv->stats; +} + + +static int xrx200_tx_housekeeping(struct napi_struct *napi, int budget) +{ + struct xrx200_chan *ch = container_of(napi, + struct xrx200_chan, napi); + struct net_device *net_dev = ch->priv->net_dev; int pkts = 0; - int i; + int bytes = 0; - spin_lock_bh(&ch->lock); - ltq_dma_ack_irq(&ch->dma); - while ((ch->dma.desc_base[ch->tx_free].ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) { - struct sk_buff *skb = ch->skb[ch->tx_free]; + while (pkts < budget) { + struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->tx_free]; - pkts++; - ch->skb[ch->tx_free] = NULL; - dev_kfree_skb(skb); - memset(&ch->dma.desc_base[ch->tx_free], 0, - sizeof(struct ltq_dma_desc)); - ch->tx_free++; - ch->tx_free %= LTQ_DESC_NUM; - } - ltq_dma_enable_irq(&ch->dma); - spin_unlock_bh(&ch->lock); + if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) { + struct sk_buff *skb = ch->skb[ch->tx_free]; - if (!pkts) - return; + pkts++; + bytes += skb->len; + ch->skb[ch->tx_free] = NULL; + consume_skb(skb); + memset(&ch->dma.desc_base[ch->tx_free], 0, + sizeof(struct ltq_dma_desc)); + ch->tx_free++; + ch->tx_free %= LTQ_DESC_NUM; + } else { + break; + } + } - for (i = 0; i < XRX200_MAX_DEV && ch->devs[i]; i++) - netif_wake_queue(ch->devs[i]); -} + net_dev->stats.tx_packets += pkts; + net_dev->stats.tx_bytes += bytes; -static struct net_device_stats *xrx200_get_stats (struct net_device *dev) -{ - struct xrx200_priv *priv = netdev_priv(dev); + if (pkts < budget) { + if (napi_complete_done(&ch->napi, pkts)) { +// ltq_dma_ack_irq(&ch->dma); + ltq_dma_enable_irq(&ch->dma); + } + } + + if (netif_queue_stopped(net_dev)) { + if (ch->dma.desc != ch->tx_free) { + netif_wake_queue(net_dev); + } + + } - return &priv->stats; + return pkts; } static void xrx200_tx_timeout(struct net_device *dev) @@ -1043,33 +1065,42 @@ printk(KERN_ERR "%s: transmit timed out, disable the dma channel irq\n", dev->name); priv->stats.tx_errors++; + + ltq_dma_enable_irq(&priv->chan_tx.dma); //TODO necessary? + netif_wake_queue(dev); } static int xrx200_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct xrx200_priv *priv = netdev_priv(dev); - struct xrx200_chan *ch; + struct xrx200_chan *ch = &priv->chan_tx; + struct ltq_dma_desc *desc; u32 byte_offset; int ret = NETDEV_TX_OK; int len; + dma_addr_t mapping; #ifdef SW_ROUTING u32 special_tag = (SPID_CPU_PORT << SPID_SHIFT) | DPID_ENABLE; #endif - if(priv->id) - ch = &priv->hw->chan[XRX200_DMA_TX_2]; - else - ch = &priv->hw->chan[XRX200_DMA_TX]; desc = &ch->dma.desc_base[ch->dma.desc]; +/* skb->dev = dev; len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; +*/ + if (skb_put_padto(skb, ETH_ZLEN)) { + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } + + len = skb->len; #ifdef SW_ROUTING if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) { - u16 port_map = priv->port_map; + u16 port_map = priv->d_port_map; if (priv->sw && skb->protocol == htons(ETH_P_8021Q)) { u16 vid; @@ -1078,9 +1109,9 @@ port_map = 0; if (!__vlan_get_tag(skb, &vid)) { for (i = 0; i < XRX200_MAX_VLAN; i++) { - if (priv->hw->vlan_vid[i] != vid) + if (priv->vlan_vid[i] != vid) continue; - port_map = priv->hw->vlan_port_map[i]; + port_map = priv->vlan_port_map[i]; break; } } @@ -1093,6 +1124,7 @@ special_tag |= (1 << DPID_SHIFT); if(skb_headroom(skb) < 4) { struct sk_buff *tmp = skb_realloc_headroom(skb, 4); +pr_info("-------fucking slow\n"); dev_kfree_skb_any(skb); skb = tmp; } @@ -1101,10 +1133,19 @@ len += 4; #endif +/* +if (skb->len > 1518) { +pr_info("lll %i\n", skb->len); +} + +if (len > 1520) { +pr_info("LLL %i\n", len); +} +*/ /* dma needs to start on a 16 byte aligned address */ byte_offset = CPHYSADDR(skb->data) % 16; - spin_lock_bh(&ch->lock); +// spin_lock_bh(&ch->lock); if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) { netdev_err(dev, "tx ring full\n"); netif_stop_queue(dev); @@ -1114,83 +1155,111 @@ ch->skb[ch->dma.desc] = skb; - netif_trans_update(dev); - - desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len, +/* + desc->addr = ((unsigned int) dma_map_single(priv->dev, skb->data, len, DMA_TO_DEVICE)) - byte_offset; +*/ + + mapping = dma_map_single(priv->dev, skb->data, len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(priv->dev, mapping))) { +pr_info("!!!!! dma mapping error\n"); + dev_kfree_skb(skb); + dev->stats.tx_dropped++; + dev->stats.tx_errors++; + ret = NETDEV_TX_OK; + goto out; + } + + /* dma needs to start on a 16 byte aligned address */ + byte_offset = mapping % 16; + + desc->addr = mapping - byte_offset; + wmb(); desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP | LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK); ch->dma.desc++; ch->dma.desc %= LTQ_DESC_NUM; - if (ch->dma.desc == ch->tx_free) + if (ch->dma.desc == ch->tx_free) { +pr_info("rx full\n"); netif_stop_queue(dev); + } - - priv->stats.tx_packets++; - priv->stats.tx_bytes+=len; - +// skb_tx_timestamp(skb); + out: - spin_unlock_bh(&ch->lock); +// spin_unlock_bh(&ch->lock); return ret; } -static irqreturn_t xrx200_dma_irq(int irq, void *priv) +static irqreturn_t xrx200_dma_irq(int irq, void *ptr) { - struct xrx200_hw *hw = priv; - int chnr = irq - XRX200_DMA_IRQ; - struct xrx200_chan *ch = &hw->chan[chnr]; + struct xrx200_chan *ch = ptr; ltq_dma_disable_irq(&ch->dma); ltq_dma_ack_irq(&ch->dma); - - if (chnr % 2) - tasklet_schedule(&ch->tasklet); - else - napi_schedule(&ch->napi); + napi_schedule(&ch->napi); return IRQ_HANDLED; } -static int xrx200_dma_init(struct xrx200_hw *hw) +static int xrx200_dma_init(struct xrx200_priv *priv) { - int i, err = 0; + int i; + struct xrx200_chan *ch_rx = &priv->chan_rx; + struct xrx200_chan *ch_tx = &priv->chan_tx; + int ret; ltq_dma_init_port(DMA_PORT_ETOP); - for (i = 0; i < 8 && !err; i++) { - int irq = XRX200_DMA_IRQ + i; - struct xrx200_chan *ch = &hw->chan[i]; - - spin_lock_init(&ch->lock); - - ch->idx = ch->dma.nr = i; - - if (i == XRX200_DMA_TX) { - ltq_dma_alloc_tx(&ch->dma); - err = request_irq(irq, xrx200_dma_irq, 0, "vrx200_tx", hw); - } else if (i == XRX200_DMA_TX_2) { - ltq_dma_alloc_tx(&ch->dma); - err = request_irq(irq, xrx200_dma_irq, 0, "vrx200_tx_2", hw); - } else if (i == XRX200_DMA_RX) { - ltq_dma_alloc_rx(&ch->dma); - for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM; - ch->dma.desc++) - if (xrx200_alloc_skb(ch)) - err = -ENOMEM; - ch->dma.desc = 0; - err = request_irq(irq, xrx200_dma_irq, 0, "vrx200_rx", hw); - } else - continue; + ch_rx->dma.nr = XRX200_DMA_RX; + ch_rx->priv = priv; + + ltq_dma_alloc_rx(&ch_rx->dma); + for (ch_rx->dma.desc = 0; ch_rx->dma.desc < LTQ_DESC_NUM; + ch_rx->dma.desc++) { + ret = xrx200_alloc_skb(ch_rx); + if (ret) + goto rx_free; + } + ch_rx->dma.desc = 0; + + ret = devm_request_irq(priv->dev, ch_rx->dma.irq, xrx200_dma_irq, 0, + "vrx200_rx", &priv->chan_rx); + if (ret) { + dev_err(priv->dev, "failed to request RX irq %d\n", + ch_rx->dma.irq); + goto rx_ring_free; + } + + ch_tx->dma.nr = XRX200_DMA_TX; + ch_tx->priv = priv; + + ltq_dma_alloc_tx(&ch_tx->dma); + ret = devm_request_irq(priv->dev, ch_tx->dma.irq, xrx200_dma_irq, 0, + "vrx200_tx", &priv->chan_tx); + if (ret) { + dev_err(priv->dev, "failed to request TX irq %d\n", + ch_tx->dma.irq); + goto tx_free; + } - if (!err) - ch->dma.irq = irq; - else - pr_err("net-xrx200: failed to request irq %d\n", irq); + return ret; + +tx_free: + ltq_dma_free(&ch_tx->dma); + +rx_ring_free: + /* free the allocated RX ring */ + for (i = 0; i < LTQ_DESC_NUM; i++) { + if (priv->chan_rx.skb[i]) + dev_kfree_skb_any(priv->chan_rx.skb[i]); } - return err; +rx_free: + ltq_dma_free(&ch_rx->dma); + return ret; } #ifdef SW_POLLING @@ -1328,11 +1397,12 @@ { struct net_device *netdev = phydev->attached_dev; - if (do_carrier) + if (do_carrier) { if (up) netif_carrier_on(netdev); else if (!xrx200_phy_has_link(netdev)) netif_carrier_off(netdev); + } phydev->adjust_link(netdev); } @@ -1343,7 +1413,7 @@ struct phy_device *phydev = NULL; unsigned val; - phydev = mdiobus_get_phy(priv->hw->mii_bus, port->phy_addr); + phydev = mdiobus_get_phy(priv->mii_bus, port->phy_addr); if (!phydev) { netdev_err(dev, "no PHY found\n"); @@ -1376,10 +1446,10 @@ #ifdef SW_POLLING phy_read_status(phydev); - val = xrx200_mdio_rd(priv->hw->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000); + val = xrx200_mdio_rd(priv->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000); val |= ADVERTIZE_MPD; - xrx200_mdio_wr(priv->hw->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000, val); - xrx200_mdio_wr(priv->hw->mii_bus, 0, 0, 0x1040); + xrx200_mdio_wr(priv->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000, val); + xrx200_mdio_wr(priv->mii_bus, 0, 0, 0x1040); phy_start_aneg(phydev); #endif @@ -1522,12 +1592,12 @@ ltq_switch_w32_mask(0, BIT(3), PCE_GCTRL_REG(0)); } -static void xrx200_hw_init(struct xrx200_hw *hw) +static void xrx200_hw_init(struct xrx200_priv *priv) { int i; /* enable clock gate */ - clk_enable(hw->clk); + clk_enable(priv->clk); ltq_switch_w32(1, 0); mdelay(100); @@ -1595,49 +1665,45 @@ xrx200sw_write_x(1, XRX200_BM_QUEUE_GCTRL_GL_MOD, 0); for (i = 0; i < XRX200_MAX_VLAN; i++) - hw->vlan_vid[i] = i; + priv->vlan_vid[i] = i; } -static void xrx200_hw_cleanup(struct xrx200_hw *hw) +static void xrx200_hw_cleanup(struct xrx200_priv *priv) { int i; /* disable the switch */ ltq_mdio_w32_mask(MDIO_GLOB_ENABLE, 0, MDIO_GLOB); - /* free the channels and IRQs */ - for (i = 0; i < 2; i++) { - ltq_dma_free(&hw->chan[i].dma); - if (hw->chan[i].dma.irq) - free_irq(hw->chan[i].dma.irq, hw); - } + ltq_dma_free(&priv->chan_tx.dma); + ltq_dma_free(&priv->chan_rx.dma); /* free the allocated RX ring */ for (i = 0; i < LTQ_DESC_NUM; i++) - dev_kfree_skb_any(hw->chan[XRX200_DMA_RX].skb[i]); + dev_kfree_skb_any(priv->chan_rx.skb[i]); /* clear the mdio bus */ - mdiobus_unregister(hw->mii_bus); - mdiobus_free(hw->mii_bus); + mdiobus_unregister(priv->mii_bus); + mdiobus_free(priv->mii_bus); /* release the clock */ - clk_disable(hw->clk); - clk_put(hw->clk); + clk_disable(priv->clk); + clk_put(priv->clk); } -static int xrx200_of_mdio(struct xrx200_hw *hw, struct device_node *np) +static int xrx200_of_mdio(struct xrx200_priv *priv, struct device_node *np) { - hw->mii_bus = mdiobus_alloc(); - if (!hw->mii_bus) + priv->mii_bus = mdiobus_alloc(); + if (!priv->mii_bus) return -ENOMEM; - hw->mii_bus->read = xrx200_mdio_rd; - hw->mii_bus->write = xrx200_mdio_wr; - hw->mii_bus->name = "lantiq,xrx200-mdio"; - snprintf(hw->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); + priv->mii_bus->read = xrx200_mdio_rd; + priv->mii_bus->write = xrx200_mdio_wr; + priv->mii_bus->name = "lantiq,xrx200-mdio"; + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); - if (of_mdiobus_register(hw->mii_bus, np)) { - mdiobus_free(hw->mii_bus); + if (of_mdiobus_register(priv->mii_bus, np)) { + mdiobus_free(priv->mii_bus); return -ENXIO; } @@ -1677,12 +1743,12 @@ } /* is this port a wan port ? */ if (priv->wan) - priv->hw->wan_map |= BIT(p->num); + priv->wan_map |= BIT(p->num); - priv->port_map |= BIT(p->num); + priv->d_port_map |= BIT(p->num); /* store the port id in the hw struct so we can map ports -> devices */ - priv->hw->port_map[p->num] = priv->hw->num_devs; + priv->port_map[p->num] = 0; } static const struct net_device_ops xrx200_netdev_ops = { @@ -1696,29 +1762,21 @@ .ndo_tx_timeout = xrx200_tx_timeout, }; -static void xrx200_of_iface(struct xrx200_hw *hw, struct device_node *iface, struct device *dev) +static void xrx200_of_iface(struct xrx200_priv *priv, struct device_node *iface, struct device *dev) { - struct xrx200_priv *priv; struct device_node *port; const __be32 *wan; const u8 *mac; - /* alloc the network device */ - hw->devs[hw->num_devs] = alloc_etherdev(sizeof(struct xrx200_priv)); - if (!hw->devs[hw->num_devs]) - return; - /* setup the network device */ - strcpy(hw->devs[hw->num_devs]->name, "eth%d"); - hw->devs[hw->num_devs]->netdev_ops = &xrx200_netdev_ops; - hw->devs[hw->num_devs]->watchdog_timeo = XRX200_TX_TIMEOUT; - hw->devs[hw->num_devs]->needed_headroom = XRX200_HEADROOM; - SET_NETDEV_DEV(hw->devs[hw->num_devs], dev); + strcpy(priv->net_dev->name, "eth%d"); + priv->net_dev->netdev_ops = &xrx200_netdev_ops; + priv->net_dev->watchdog_timeo = XRX200_TX_TIMEOUT; + priv->net_dev->needed_headroom = XRX200_HEADROOM; + SET_NETDEV_DEV(priv->net_dev, dev); /* setup our private data */ - priv = netdev_priv(hw->devs[hw->num_devs]); - priv->hw = hw; - priv->id = hw->num_devs; + priv->id = 0; mac = of_get_mac_address(iface); if (mac) @@ -1738,20 +1796,33 @@ if (of_device_is_compatible(port, "lantiq,xrx200-pdi-port")) xrx200_of_port(priv, port); - /* register the actual device */ - if (!register_netdev(hw->devs[hw->num_devs])) - hw->num_devs++; } -static struct xrx200_hw xrx200_hw; - static int xrx200_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct resource *res[4]; struct device_node *mdio_np, *iface_np, *phy_np; struct of_phandle_iterator it; int err; int i; + struct xrx200_priv *priv; + struct net_device *net_dev; + + + /* alloc the network device */ + net_dev = devm_alloc_etherdev(dev, sizeof(struct xrx200_priv)); + if (!net_dev) + return -ENOMEM; + + priv = netdev_priv(net_dev); + priv->net_dev = net_dev; + priv->dev = dev; + + net_dev->netdev_ops = &xrx200_netdev_ops; + SET_NETDEV_DEV(net_dev, dev); + net_dev->min_mtu = ETH_ZLEN; + net_dev->max_mtu = XRX200_DMA_DATA_LEN; /* load the memory ranges */ for (i = 0; i < 4; i++) { @@ -1781,85 +1852,90 @@ return -EPROBE_DEFER; } } + + priv->chan_rx.dma.irq = XRX200_DMA_IRQ + XRX200_DMA_RX; + priv->chan_tx.dma.irq = XRX200_DMA_IRQ + XRX200_DMA_TX; + priv->chan_rx.priv = priv; + priv->chan_tx.priv = priv; /* get the clock */ - xrx200_hw.clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(xrx200_hw.clk)) { + priv->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "failed to get clock\n"); - return PTR_ERR(xrx200_hw.clk); + return PTR_ERR(priv->clk); } /* bring up the dma engine and IP core */ - xrx200_dma_init(&xrx200_hw); - xrx200_hw_init(&xrx200_hw); - tasklet_init(&xrx200_hw.chan[XRX200_DMA_TX].tasklet, xrx200_tx_housekeeping, (u32) &xrx200_hw.chan[XRX200_DMA_TX]); - tasklet_init(&xrx200_hw.chan[XRX200_DMA_TX_2].tasklet, xrx200_tx_housekeeping, (u32) &xrx200_hw.chan[XRX200_DMA_TX_2]); + err = xrx200_dma_init(priv); + if (err) + return err; + + /* enable clock gate */ + err = clk_prepare_enable(priv->clk); + if (err) + goto err_uninit_dma; + + xrx200_hw_init(priv); /* bring up the mdio bus */ mdio_np = of_find_compatible_node(pdev->dev.of_node, NULL, "lantiq,xrx200-mdio"); if (mdio_np) - if (xrx200_of_mdio(&xrx200_hw, mdio_np)) + if (xrx200_of_mdio(priv, mdio_np)) dev_err(&pdev->dev, "mdio probe failed\n"); /* load the interfaces */ for_each_child_of_node(pdev->dev.of_node, iface_np) - if (of_device_is_compatible(iface_np, "lantiq,xrx200-pdi")) { - if (xrx200_hw.num_devs < XRX200_MAX_DEV) - xrx200_of_iface(&xrx200_hw, iface_np, &pdev->dev); - else - dev_err(&pdev->dev, - "only %d interfaces allowed\n", - XRX200_MAX_DEV); - } - - if (!xrx200_hw.num_devs) { - xrx200_hw_cleanup(&xrx200_hw); - dev_err(&pdev->dev, "failed to load interfaces\n"); - return -ENOENT; - } - - xrx200sw_init(&xrx200_hw); + if (of_device_is_compatible(iface_np, "lantiq,xrx200-pdi")) { + xrx200_of_iface(priv, iface_np, &pdev->dev); + break; //hack + } + + xrx200sw_init(priv); /* set wan port mask */ - ltq_pmac_w32(xrx200_hw.wan_map, PMAC_EWAN); - - for (i = 0; i < xrx200_hw.num_devs; i++) { - xrx200_hw.chan[XRX200_DMA_RX].devs[i] = xrx200_hw.devs[i]; - xrx200_hw.chan[XRX200_DMA_TX].devs[i] = xrx200_hw.devs[i]; - xrx200_hw.chan[XRX200_DMA_TX_2].devs[i] = xrx200_hw.devs[i]; - } + ltq_pmac_w32(priv->wan_map, PMAC_EWAN); /* setup NAPI */ - init_dummy_netdev(&xrx200_hw.chan[XRX200_DMA_RX].dummy_dev); - netif_napi_add(&xrx200_hw.chan[XRX200_DMA_RX].dummy_dev, - &xrx200_hw.chan[XRX200_DMA_RX].napi, xrx200_poll_rx, 32); + netif_napi_add(net_dev, &priv->chan_rx.napi, xrx200_poll_rx, 32); //32 + netif_napi_add(net_dev, &priv->chan_tx.napi, xrx200_tx_housekeeping, 32); + + platform_set_drvdata(pdev, priv); - platform_set_drvdata(pdev, &xrx200_hw); + err = register_netdev(net_dev); + if (err) + goto err_unprepare_clk; return 0; + +err_unprepare_clk: + clk_disable_unprepare(priv->clk); + +err_uninit_dma: + xrx200_hw_cleanup(priv); + + return err; } static int xrx200_remove(struct platform_device *pdev) { - struct net_device *dev = platform_get_drvdata(pdev); - struct xrx200_priv *priv; - if (!dev) - return 0; - - priv = netdev_priv(dev); + struct xrx200_priv *priv = platform_get_drvdata(pdev); + struct net_device *net_dev = priv->net_dev; /* free stack related instances */ - netif_stop_queue(dev); - netif_napi_del(&xrx200_hw.chan[XRX200_DMA_RX].napi); - - /* shut down hardware */ - xrx200_hw_cleanup(&xrx200_hw); + netif_stop_queue(net_dev); + netif_napi_del(&priv->chan_tx.napi); + netif_napi_del(&priv->chan_rx.napi); /* remove the actual device */ - unregister_netdev(dev); - free_netdev(dev); + unregister_netdev(net_dev); + + /* release the clock */ + clk_disable_unprepare(priv->clk); + + /* shut down hardware */ + xrx200_hw_cleanup(priv); return 0; }