From 61c7a080a5a061c976988fd4b844dfb468dda255 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 13 Apr 2010 16:12:29 -0700 Subject: of: Always use 'struct device.of_node' to get device node pointer. The following structure elements duplicate the information in 'struct device.of_node' and so are being eliminated. This patch makes all readers of these elements use device.of_node instead. (struct of_device *)->node (struct dev_archdata *)->prom_node (sparc) (struct dev_archdata *)->of_node (powerpc & microblaze) Signed-off-by: Grant Likely --- drivers/net/ll_temac_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/ll_temac_main.c') diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index ba617e3cf1bb..9c7395c10e44 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -858,14 +858,14 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) mutex_init(&lp->indirect_mutex); /* map device registers */ - lp->regs = of_iomap(op->node, 0); + lp->regs = of_iomap(op->dev.of_node, 0); if (!lp->regs) { dev_err(&op->dev, "could not map temac regs.\n"); goto nodev; } /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ - np = of_parse_phandle(op->node, "llink-connected", 0); + np = of_parse_phandle(op->dev.of_node, "llink-connected", 0); if (!np) { dev_err(&op->dev, "could not find DMA node\n"); goto nodev; @@ -890,7 +890,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) of_node_put(np); /* Finished with the DMA node; drop the reference */ /* Retrieve the MAC address */ - addr = of_get_property(op->node, "local-mac-address", &size); + addr = of_get_property(op->dev.of_node, "local-mac-address", &size); if ((!addr) || (size != 6)) { dev_err(&op->dev, "could not find MAC address\n"); rc = -ENODEV; @@ -898,11 +898,11 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) } temac_set_mac_address(ndev, (void *)addr); - rc = temac_mdio_setup(lp, op->node); + rc = temac_mdio_setup(lp, op->dev.of_node); if (rc) dev_warn(&op->dev, "error registering MDIO bus\n"); - lp->phy_node = of_parse_phandle(op->node, "phy-handle", 0); + lp->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0); if (lp->phy_node) dev_dbg(lp->dev, "using PHY node %s (%p)\n", np->full_name, np); -- cgit v1.2.3 From 4018294b53d1dae026880e45f174c1cc63b5d435 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 13 Apr 2010 16:13:02 -0700 Subject: of: Remove duplicate fields from of_platform_driver .name, .match_table and .owner are duplicated in both of_platform_driver and device_driver. This patch is a removes the extra copies from struct of_platform_driver and converts all users to the device_driver members. This patch is a pretty mechanical change. The usage model doesn't change and if any drivers have been missed, or if anything has been fixed up incorrectly, then it will fail with a compile time error, and the fixup will be trivial. This patch looks big and scary because it touches so many files, but it should be pretty safe. Signed-off-by: Grant Likely Acked-by: Sean MacLennan --- drivers/net/ll_temac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ll_temac_main.c') diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 9c7395c10e44..dc318330ec79 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -955,12 +955,12 @@ static struct of_device_id temac_of_match[] __devinitdata = { MODULE_DEVICE_TABLE(of, temac_of_match); static struct of_platform_driver temac_of_driver = { - .match_table = temac_of_match, .probe = temac_of_probe, .remove = __devexit_p(temac_of_remove), .driver = { .owner = THIS_MODULE, .name = "xilinx_temac", + .of_match_table = temac_of_match, }, }; -- cgit v1.2.3 From 755fae0ac41672523a3ac00d41fe9bac226b0578 Mon Sep 17 00:00:00 2001 From: Brian Hill Date: Wed, 26 May 2010 20:42:18 -0700 Subject: net: ll_temac: fix interrupt bug when interrupt 0 is used The code is not checking the interrupt for DMA correctly so that an interrupt number of 0 will cause a false error. Signed-off-by: Brian Hill Signed-off-by: John Linn Signed-off-by: David S. Miller --- drivers/net/ll_temac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ll_temac_main.c') diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index b59b24d667f0..1bb6e605f64f 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -950,7 +950,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) lp->rx_irq = irq_of_parse_and_map(np, 0); lp->tx_irq = irq_of_parse_and_map(np, 1); - if (!lp->rx_irq || !lp->tx_irq) { + if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) { dev_err(&op->dev, "could not determine irqs\n"); rc = -ENOMEM; goto nodev; -- cgit v1.2.3 From 23ecc4bde21f0ccb38f4b53cadde7fc5d67d68e3 Mon Sep 17 00:00:00 2001 From: Brian Hill Date: Wed, 26 May 2010 20:44:30 -0700 Subject: net: ll_temac: fix checksum offload logic The current checksum offload code does not work and this corrects that functionality. It also updates the interrupt coallescing initialization so than there are fewer interrupts and performance is increased. Signed-off-by: Brian Hill Signed-off-by: John Linn Signed-off-by: David S. Miller --- drivers/net/ll_temac_main.c | 82 ++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 24 deletions(-) (limited to 'drivers/net/ll_temac_main.c') diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 1bb6e605f64f..fbd07de2e088 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -245,7 +245,7 @@ static int temac_dma_bd_init(struct net_device *ndev) CHNL_CTRL_IRQ_COAL_EN); /* 0x10220483 */ /* 0x00100483 */ - lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 | + lp->dma_out(lp, RX_CHNL_CTRL, 0xff070000 | CHNL_CTRL_IRQ_EN | CHNL_CTRL_IRQ_DLY_EN | CHNL_CTRL_IRQ_COAL_EN | @@ -574,6 +574,10 @@ static void temac_start_xmit_done(struct net_device *ndev) if (cur_p->app4) dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); cur_p->app0 = 0; + cur_p->app1 = 0; + cur_p->app2 = 0; + cur_p->app3 = 0; + cur_p->app4 = 0; ndev->stats.tx_packets++; ndev->stats.tx_bytes += cur_p->len; @@ -589,6 +593,29 @@ static void temac_start_xmit_done(struct net_device *ndev) netif_wake_queue(ndev); } +static inline int temac_check_tx_bd_space(struct temac_local *lp, int num_frag) +{ + struct cdmac_bd *cur_p; + int tail; + + tail = lp->tx_bd_tail; + cur_p = &lp->tx_bd_v[tail]; + + do { + if (cur_p->app0) + return NETDEV_TX_BUSY; + + tail++; + if (tail >= TX_BD_NUM) + tail = 0; + + cur_p = &lp->tx_bd_v[tail]; + num_frag--; + } while (num_frag >= 0); + + return 0; +} + static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct temac_local *lp = netdev_priv(ndev); @@ -603,7 +630,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; - if (cur_p->app0 & STS_CTRL_APP0_CMPLT) { + if (temac_check_tx_bd_space(lp, num_frag)) { if (!netif_queue_stopped(ndev)) { netif_stop_queue(ndev); return NETDEV_TX_BUSY; @@ -613,29 +640,14 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) cur_p->app0 = 0; if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - int length = 0, start = 0, insert = 0; - - switch (ip->protocol) { - case IPPROTO_TCP: - start = sizeof(struct iphdr) + ETH_HLEN; - insert = sizeof(struct iphdr) + ETH_HLEN + 16; - length = ip->tot_len - sizeof(struct iphdr); - break; - case IPPROTO_UDP: - start = sizeof(struct iphdr) + ETH_HLEN; - insert = sizeof(struct iphdr) + ETH_HLEN + 6; - length = ip->tot_len - sizeof(struct iphdr); - break; - default: - break; - } - cur_p->app1 = ((start << 16) | insert); - cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr, - length, ip->protocol, 0); - skb->data[insert] = 0; - skb->data[insert + 1] = 0; + unsigned int csum_start_off = skb_transport_offset(skb); + unsigned int csum_index_off = csum_start_off + skb->csum_offset; + + cur_p->app0 |= 1; /* TX Checksum Enabled */ + cur_p->app1 = (csum_start_off << 16) | csum_index_off; + cur_p->app2 = 0; /* initial checksum seed */ } + cur_p->app0 |= STS_CTRL_APP0_SOP; cur_p->len = skb_headlen(skb); cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len, @@ -699,6 +711,15 @@ static void ll_temac_recv(struct net_device *ndev) skb->protocol = eth_type_trans(skb, ndev); skb->ip_summed = CHECKSUM_NONE; + /* if we're doing rx csum offload, set it up */ + if (((lp->temac_features & TEMAC_FEATURE_RX_CSUM) != 0) && + (skb->protocol == __constant_htons(ETH_P_IP)) && + (skb->len > 64)) { + + skb->csum = cur_p->app3 & 0xFFFF; + skb->ip_summed = CHECKSUM_COMPLETE; + } + netif_rx(skb); ndev->stats.rx_packets++; @@ -883,6 +904,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) struct temac_local *lp; struct net_device *ndev; const void *addr; + __be32 *p; int size, rc = 0; /* Init network device structure */ @@ -926,6 +948,18 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) goto nodev; } + /* Setup checksum offload, but default to off if not specified */ + lp->temac_features = 0; + p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,txcsum", NULL); + if (p && be32_to_cpu(*p)) { + lp->temac_features |= TEMAC_FEATURE_TX_CSUM; + /* Can checksum TCP/UDP over IPv4. */ + ndev->features |= NETIF_F_IP_CSUM; + } + p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL); + if (p && be32_to_cpu(*p)) + lp->temac_features |= TEMAC_FEATURE_RX_CSUM; + /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ np = of_parse_phandle(op->node, "llink-connected", 0); if (!np) { -- cgit v1.2.3