diff options
Diffstat (limited to 'drivers/net/ethernet/pasemi/pasemi_mac.c')
| -rw-r--r-- | drivers/net/ethernet/pasemi/pasemi_mac.c | 221 |
1 files changed, 80 insertions, 141 deletions
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index a5f0b5da6149..fe58024b5901 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -1,23 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2006-2007 PA Semi, Inc * * Driver for the PA Semi PWRficient onchip 1G/10G Ethernet MACs - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/init.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/slab.h> @@ -32,9 +19,7 @@ #include <linux/skbuff.h> #include <linux/ip.h> -#include <linux/tcp.h> #include <net/checksum.h> -#include <linux/inet_lro.h> #include <linux/prefetch.h> #include <asm/irq.h> @@ -54,13 +39,10 @@ * * - Multicast support * - Large MTU support - * - SW LRO * - Multiqueue RX/TX */ -#define LRO_MAX_AGGR 64 - -#define PE_MIN_MTU 64 +#define PE_MIN_MTU (ETH_ZLEN + ETH_HLEN) #define PE_MAX_MTU 9000 #define PE_DEF_MTU ETH_DATA_LEN @@ -191,7 +173,7 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac) struct device_node *dn = pci_device_to_OF_node(pdev); int len; const u8 *maddr; - u8 addr[6]; + u8 addr[ETH_ALEN]; if (!dn) { dev_dbg(&pdev->dev, @@ -201,8 +183,8 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac) maddr = of_get_property(dn, "local-mac-address", &len); - if (maddr && len == 6) { - memcpy(mac->mac_addr, maddr, 6); + if (maddr && len == ETH_ALEN) { + memcpy(mac->mac_addr, maddr, ETH_ALEN); return 0; } @@ -219,14 +201,13 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac) return -ENOENT; } - if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0], - &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) { + if (!mac_pton(maddr, addr)) { dev_warn(&pdev->dev, "can't parse mac address, not configuring\n"); return -EINVAL; } - memcpy(mac->mac_addr, addr, 6); + memcpy(mac->mac_addr, addr, ETH_ALEN); return 0; } @@ -240,7 +221,7 @@ static int pasemi_mac_set_mac_addr(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + eth_hw_addr_set(dev, addr->sa_data); adr0 = dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 | @@ -258,37 +239,6 @@ static int pasemi_mac_set_mac_addr(struct net_device *dev, void *p) return 0; } -static int get_skb_hdr(struct sk_buff *skb, void **iphdr, - void **tcph, u64 *hdr_flags, void *data) -{ - u64 macrx = (u64) data; - unsigned int ip_len; - struct iphdr *iph; - - /* IPv4 header checksum failed */ - if ((macrx & XCT_MACRX_HTY_M) != XCT_MACRX_HTY_IPV4_OK) - return -1; - - /* non tcp packet */ - skb_reset_network_header(skb); - iph = ip_hdr(skb); - if (iph->protocol != IPPROTO_TCP) - return -1; - - ip_len = ip_hdrlen(skb); - skb_set_transport_header(skb, ip_len); - *tcph = tcp_hdr(skb); - - /* check if ip header and tcp header are complete */ - if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb)) - return -1; - - *hdr_flags = LRO_IPV4 | LRO_TCP; - *iphdr = iph; - - return 0; -} - static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac, const int nfrags, struct sk_buff *skb, @@ -297,12 +247,13 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac, int f; struct pci_dev *pdev = mac->dma_pdev; - pci_unmap_single(pdev, dmas[0], skb_headlen(skb), PCI_DMA_TODEVICE); + dma_unmap_single(&pdev->dev, dmas[0], skb_headlen(skb), DMA_TO_DEVICE); for (f = 0; f < nfrags; f++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; - pci_unmap_page(pdev, dmas[f+1], skb_frag_size(frag), PCI_DMA_TODEVICE); + dma_unmap_page(&pdev->dev, dmas[f + 1], skb_frag_size(frag), + DMA_TO_DEVICE); } dev_kfree_skb_irq(skb); @@ -429,8 +380,9 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev) spin_lock_init(&ring->lock); ring->size = RX_RING_SIZE; - ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) * - RX_RING_SIZE, GFP_KERNEL); + ring->ring_info = kcalloc(RX_RING_SIZE, + sizeof(struct pasemi_mac_buffer), + GFP_KERNEL); if (!ring->ring_info) goto out_ring_info; @@ -441,8 +393,7 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev) ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64), - &ring->buf_dma, - GFP_KERNEL | __GFP_ZERO); + &ring->buf_dma, GFP_KERNEL); if (!ring->buffers) goto out_ring_desc; @@ -513,8 +464,9 @@ pasemi_mac_setup_tx_resources(const struct net_device *dev) spin_lock_init(&ring->lock); ring->size = TX_RING_SIZE; - ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) * - TX_RING_SIZE, GFP_KERNEL); + ring->ring_info = kcalloc(TX_RING_SIZE, + sizeof(struct pasemi_mac_buffer), + GFP_KERNEL); if (!ring->ring_info) goto out_ring_info; @@ -597,10 +549,8 @@ static void pasemi_mac_free_rx_buffers(struct pasemi_mac *mac) for (i = 0; i < RX_RING_SIZE; i++) { info = &RX_DESC_INFO(rx, i); if (info->skb && info->dma) { - pci_unmap_single(mac->dma_pdev, - info->dma, - info->skb->len, - PCI_DMA_FROMDEVICE); + dma_unmap_single(&mac->dma_pdev->dev, info->dma, + info->skb->len, DMA_FROM_DEVICE); dev_kfree_skb_any(info->skb); } info->dma = 0; @@ -649,11 +599,11 @@ static void pasemi_mac_replenish_rx_ring(struct net_device *dev, if (unlikely(!skb)) break; - dma = pci_map_single(mac->dma_pdev, skb->data, + dma = dma_map_single(&mac->dma_pdev->dev, skb->data, mac->bufsz - LOCAL_SKB_ALIGN, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); - if (unlikely(pci_dma_mapping_error(mac->dma_pdev, dma))) { + if (dma_mapping_error(&mac->dma_pdev->dev, dma)) { dev_kfree_skb_irq(info->skb); break; } @@ -790,8 +740,9 @@ static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx, len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S; - pci_unmap_single(pdev, dma, mac->bufsz - LOCAL_SKB_ALIGN, - PCI_DMA_FROMDEVICE); + dma_unmap_single(&pdev->dev, dma, + mac->bufsz - LOCAL_SKB_ALIGN, + DMA_FROM_DEVICE); if (macrx & XCT_MACRX_CRC) { /* CRC error flagged */ @@ -819,7 +770,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx, skb_put(skb, len-4); skb->protocol = eth_type_trans(skb, mac->netdev); - lro_receive_skb(&mac->lro_mgr, skb, (void *)macrx); + napi_gro_receive(&mac->napi, skb); next: RX_DESC(rx, n) = 0; @@ -841,8 +792,6 @@ next: rx_ring(mac)->next_to_clean = n; - lro_flush_all(&mac->lro_mgr); - /* Increase is in number of 16-byte entries, and since each descriptor * with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with * count*2. @@ -983,9 +932,10 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data) #define TX_CLEAN_INTERVAL HZ -static void pasemi_mac_tx_timer(unsigned long data) +static void pasemi_mac_tx_timer(struct timer_list *t) { - struct pasemi_mac_txring *txring = (struct pasemi_mac_txring *)data; + struct pasemi_mac_txring *txring = timer_container_of(txring, t, + clean_timer); struct pasemi_mac *mac = txring->mac; pasemi_mac_clean_tx(txring); @@ -1029,7 +979,7 @@ static void pasemi_adjust_link(struct net_device *dev) unsigned int flags; unsigned int new_flags; - if (!mac->phydev->link) { + if (!dev->phydev->link) { /* If no link, MAC speed settings don't matter. Just report * link down and return. */ @@ -1050,10 +1000,10 @@ static void pasemi_adjust_link(struct net_device *dev) new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M | PAS_MAC_CFG_PCFG_TSR_M); - if (!mac->phydev->duplex) + if (!dev->phydev->duplex) new_flags |= PAS_MAC_CFG_PCFG_HD; - switch (mac->phydev->speed) { + switch (dev->phydev->speed) { case 1000: new_flags |= PAS_MAC_CFG_PCFG_SPD_1G | PAS_MAC_CFG_PCFG_TSR_1G; @@ -1067,15 +1017,15 @@ static void pasemi_adjust_link(struct net_device *dev) PAS_MAC_CFG_PCFG_TSR_10M; break; default: - printk("Unsupported speed %d\n", mac->phydev->speed); + printk("Unsupported speed %d\n", dev->phydev->speed); } /* Print on link or speed/duplex change */ - msg = mac->link != mac->phydev->link || flags != new_flags; + msg = mac->link != dev->phydev->link || flags != new_flags; - mac->duplex = mac->phydev->duplex; - mac->speed = mac->phydev->speed; - mac->link = mac->phydev->link; + mac->duplex = dev->phydev->duplex; + mac->speed = dev->phydev->speed; + mac->link = dev->phydev->link; if (new_flags != flags) write_mac_reg(mac, PAS_MAC_CFG_PCFG, new_flags); @@ -1093,7 +1043,6 @@ static int pasemi_mac_phy_init(struct net_device *dev) dn = pci_device_to_OF_node(mac->pdev); phy_dn = of_parse_phandle(dn, "phy-handle", 0); - of_node_put(phy_dn); mac->link = 0; mac->speed = 0; @@ -1102,13 +1051,12 @@ static int pasemi_mac_phy_init(struct net_device *dev) phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII); + of_node_put(phy_dn); if (!phydev) { printk(KERN_ERR "%s: Could not attach to phy\n", dev->name); return -ENODEV; } - mac->phydev = phydev; - return 0; } @@ -1131,16 +1079,20 @@ static int pasemi_mac_open(struct net_device *dev) mac->tx = pasemi_mac_setup_tx_resources(dev); - if (!mac->tx) + if (!mac->tx) { + ret = -ENOMEM; goto out_tx_ring; + } /* We might already have allocated rings in case mtu was changed * before interface was brought up. */ if (dev->mtu > 1500 && !mac->num_cs) { pasemi_mac_setup_csrings(mac); - if (!mac->num_cs) + if (!mac->num_cs) { + ret = -ENOMEM; goto out_tx_ring; + } } /* Zero out rmon counters */ @@ -1219,7 +1171,7 @@ static int pasemi_mac_open(struct net_device *dev) snprintf(mac->tx_irq_name, sizeof(mac->tx_irq_name), "%s tx", dev->name); - ret = request_irq(mac->tx->chan.irq, pasemi_mac_tx_intr, IRQF_DISABLED, + ret = request_irq(mac->tx->chan.irq, pasemi_mac_tx_intr, 0, mac->tx_irq_name, mac->tx); if (ret) { dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n", @@ -1230,7 +1182,7 @@ static int pasemi_mac_open(struct net_device *dev) snprintf(mac->rx_irq_name, sizeof(mac->rx_irq_name), "%s rx", dev->name); - ret = request_irq(mac->rx->chan.irq, pasemi_mac_rx_intr, IRQF_DISABLED, + ret = request_irq(mac->rx->chan.irq, pasemi_mac_rx_intr, 0, mac->rx_irq_name, mac->rx); if (ret) { dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n", @@ -1238,14 +1190,11 @@ static int pasemi_mac_open(struct net_device *dev) goto out_rx_int; } - if (mac->phydev) - phy_start(mac->phydev); + if (dev->phydev) + phy_start(dev->phydev); - init_timer(&mac->tx->clean_timer); - mac->tx->clean_timer.function = pasemi_mac_tx_timer; - mac->tx->clean_timer.data = (unsigned long)mac->tx; - mac->tx->clean_timer.expires = jiffies+HZ; - add_timer(&mac->tx->clean_timer); + timer_setup(&mac->tx->clean_timer, pasemi_mac_tx_timer, 0); + mod_timer(&mac->tx->clean_timer, jiffies + HZ); return 0; @@ -1335,12 +1284,12 @@ static int pasemi_mac_close(struct net_device *dev) rxch = rx_ring(mac)->chan.chno; txch = tx_ring(mac)->chan.chno; - if (mac->phydev) { - phy_stop(mac->phydev); - phy_disconnect(mac->phydev); + if (dev->phydev) { + phy_stop(dev->phydev); + phy_disconnect(dev->phydev); } - del_timer_sync(&mac->tx->clean_timer); + timer_delete_sync(&mac->tx->clean_timer); netif_stop_queue(dev); napi_disable(&mac->napi); @@ -1400,7 +1349,7 @@ static void pasemi_mac_queue_csdesc(const struct sk_buff *skb, const int nh_off = skb_network_offset(skb); const int nh_len = skb_network_header_len(skb); const int nfrags = skb_shinfo(skb)->nr_frags; - int cs_size, i, fill, hdr, cpyhdr, evt; + int cs_size, i, fill, hdr, evt; dma_addr_t csdma; fund = XCT_FUN_ST | XCT_FUN_RR_8BRES | @@ -1441,7 +1390,6 @@ static void pasemi_mac_queue_csdesc(const struct sk_buff *skb, fill++; /* Copy the result into the TCP packet */ - cpyhdr = fill; CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) | XCT_FUN_LLEN(2) | XCT_FUN_SE; CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T; @@ -1476,7 +1424,7 @@ static void pasemi_mac_queue_csdesc(const struct sk_buff *skb, write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2); } -static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) { struct pasemi_mac * const mac = netdev_priv(dev); struct pasemi_mac_txring * const txring = tx_ring(mac); @@ -1497,10 +1445,10 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) nfrags = skb_shinfo(skb)->nr_frags; - map[0] = pci_map_single(mac->dma_pdev, skb->data, skb_headlen(skb), - PCI_DMA_TODEVICE); + map[0] = dma_map_single(&mac->dma_pdev->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); map_size[0] = skb_headlen(skb); - if (pci_dma_mapping_error(mac->dma_pdev, map[0])) + if (dma_mapping_error(&mac->dma_pdev->dev, map[0])) goto out_err_nolock; for (i = 0; i < nfrags; i++) { @@ -1587,8 +1535,8 @@ out_err: spin_unlock_irqrestore(&txring->lock, flags); out_err_nolock: while (nfrags--) - pci_unmap_single(mac->dma_pdev, map[nfrags], map_size[nfrags], - PCI_DMA_TODEVICE); + dma_unmap_single(&mac->dma_pdev->dev, map[nfrags], + map_size[nfrags], DMA_TO_DEVICE); return NETDEV_TX_BUSY; } @@ -1619,7 +1567,7 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget) pkts = pasemi_mac_clean_rx(rx_ring(mac), budget); if (pkts < budget) { /* all done, no more packets present */ - napi_complete(napi); + napi_complete_done(napi, pkts); pasemi_mac_restart_rx_intr(mac); pasemi_mac_restart_tx_intr(mac); @@ -1655,9 +1603,6 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) int running; int ret = 0; - if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU) - return -EINVAL; - running = netif_running(dev); if (running) { @@ -1679,7 +1624,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) } /* Setup checksum channels if large MTU and none already allocated */ - if (new_mtu > 1500 && !mac->num_cs) { + if (new_mtu > PE_DEF_MTU && !mac->num_cs) { pasemi_mac_setup_csrings(mac); if (!mac->num_cs) { ret = -ENOMEM; @@ -1695,7 +1640,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) reg |= PAS_MAC_CFG_MACCFG_MAXF(new_mtu + ETH_HLEN + 4); write_mac_reg(mac, PAS_MAC_CFG_MACCFG, reg); - dev->mtu = new_mtu; + WRITE_ONCE(dev->mtu, new_mtu); /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; @@ -1753,20 +1698,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mac->pdev = pdev; mac->netdev = dev; - netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64); - - dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_GSO; - - mac->lro_mgr.max_aggr = LRO_MAX_AGGR; - mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; - mac->lro_mgr.lro_arr = mac->lro_desc; - mac->lro_mgr.get_skb_header = get_skb_hdr; - mac->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; - mac->lro_mgr.dev = mac->netdev; - mac->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; - mac->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; + netif_napi_add(dev, &mac->napi, pasemi_mac_poll); + dev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA | + NETIF_F_GSO; + dev->lltx = true; mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL); if (!mac->dma_pdev) { @@ -1774,6 +1710,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = -ENODEV; goto out; } + dma_set_mask(&mac->dma_pdev->dev, DMA_BIT_MASK(64)); mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL); if (!mac->iob_pdev) { @@ -1787,7 +1724,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = -ENODEV; goto out; } - memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr)); + eth_hw_addr_set(dev, mac->mac_addr); ret = mac_to_intf(mac); if (ret < 0) { @@ -1811,6 +1748,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev->netdev_ops = &pasemi_netdev_ops; dev->mtu = PE_DEF_MTU; + + /* MTU range: 64 - 9000 */ + dev->min_mtu = PE_MIN_MTU; + dev->max_mtu = PE_MAX_MTU; + /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; @@ -1839,10 +1781,8 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return err; out: - if (mac->iob_pdev) - pci_dev_put(mac->iob_pdev); - if (mac->dma_pdev) - pci_dev_put(mac->dma_pdev); + pci_dev_put(mac->iob_pdev); + pci_dev_put(mac->dma_pdev); free_netdev(dev); out_disable_device: @@ -1870,11 +1810,10 @@ static void pasemi_mac_remove(struct pci_dev *pdev) pasemi_dma_free_chan(&mac->tx->chan); pasemi_dma_free_chan(&mac->rx->chan); - pci_set_drvdata(pdev, NULL); free_netdev(netdev); } -static DEFINE_PCI_DEVICE_TABLE(pasemi_mac_pci_tbl) = { +static const struct pci_device_id pasemi_mac_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) }, { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) }, { }, @@ -1894,7 +1833,7 @@ static void __exit pasemi_mac_cleanup_module(void) pci_unregister_driver(&pasemi_mac_driver); } -int pasemi_mac_init_module(void) +static int pasemi_mac_init_module(void) { int err; |
