1f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson/* 2f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * Copyright (C) 2006-2007 PA Semi, Inc 3f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * 4f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * Driver for the PA Semi PWRficient onchip 1G/10G Ethernet MACs 5f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * 6f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * This program is free software; you can redistribute it and/or modify 7f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * it under the terms of the GNU General Public License version 2 as 8f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * published by the Free Software Foundation. 9f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * 10f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * This program is distributed in the hope that it will be useful, 11f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * GNU General Public License for more details. 14f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * 15f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * You should have received a copy of the GNU General Public License 16f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * along with this program; if not, write to the Free Software 17f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson */ 19f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 20f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/init.h> 21f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/module.h> 22f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/pci.h> 235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 24f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/interrupt.h> 25f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/dmaengine.h> 26f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/delay.h> 27f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/netdevice.h> 281dd2d06c0459a2f1bffc56765e3cc57427818867Grant Likely#include <linux/of_mdio.h> 29f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/etherdevice.h> 30f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <asm/dma-mapping.h> 31f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/in.h> 32f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/skbuff.h> 33f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 34f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/ip.h> 35f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <linux/tcp.h> 36f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include <net/checksum.h> 3728ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson#include <linux/inet_lro.h> 3870c71606190e9115e5f8363bfcd164c582eb314aPaul Gortmaker#include <linux/prefetch.h> 39f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 40771f7404a9deca902594823d616cd7a84f827982Olof Johansson#include <asm/irq.h> 41af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson#include <asm/firmware.h> 4240afa5315823761b174926235dc38be24dc3ea63Olof Johansson#include <asm/pasemi_dma.h> 43771f7404a9deca902594823d616cd7a84f827982Olof Johansson 44f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#include "pasemi_mac.h" 45f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 468dc121a4b620090e594945fd36f878836fc5a14aOlof Johansson/* We have our own align, since ppc64 in general has it at 0 because 478dc121a4b620090e594945fd36f878836fc5a14aOlof Johansson * of design flaws in some of the server bridge chips. However, for 488dc121a4b620090e594945fd36f878836fc5a14aOlof Johansson * PWRficient doing the unaligned copies is more expensive than doing 498dc121a4b620090e594945fd36f878836fc5a14aOlof Johansson * unaligned DMA, so make sure the data is aligned instead. 508dc121a4b620090e594945fd36f878836fc5a14aOlof Johansson */ 518dc121a4b620090e594945fd36f878836fc5a14aOlof Johansson#define LOCAL_SKB_ALIGN 2 52f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 53f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson/* TODO list 54f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * 55f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * - Multicast support 56f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson * - Large MTU support 577ddeae2c6ceed7f786344731dda27d4277957780Olof Johansson * - SW LRO 587ddeae2c6ceed7f786344731dda27d4277957780Olof Johansson * - Multiqueue RX/TX 59f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson */ 60f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 6128ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson#define LRO_MAX_AGGR 64 6228ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 63ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson#define PE_MIN_MTU 64 648d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson#define PE_MAX_MTU 9000 65ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson#define PE_DEF_MTU ETH_DATA_LEN 66ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 67ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson#define DEFAULT_MSG_ENABLE \ 68ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson (NETIF_MSG_DRV | \ 69ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson NETIF_MSG_PROBE | \ 70ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson NETIF_MSG_LINK | \ 71ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson NETIF_MSG_TIMER | \ 72ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson NETIF_MSG_IFDOWN | \ 73ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson NETIF_MSG_IFUP | \ 74ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson NETIF_MSG_RX_ERR | \ 75ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson NETIF_MSG_TX_ERR) 76ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson 77ceb51361370c003e13f782edb7171a8383e5c849Olof JohanssonMODULE_LICENSE("GPL"); 78ceb51361370c003e13f782edb7171a8383e5c849Olof JohanssonMODULE_AUTHOR ("Olof Johansson <olof@lixom.net>"); 79ceb51361370c003e13f782edb7171a8383e5c849Olof JohanssonMODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver"); 80ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson 81ceb51361370c003e13f782edb7171a8383e5c849Olof Johanssonstatic int debug = -1; /* -1 == use DEFAULT_MSG_ENABLE as value */ 82ceb51361370c003e13f782edb7171a8383e5c849Olof Johanssonmodule_param(debug, int, 0); 83ceb51361370c003e13f782edb7171a8383e5c849Olof JohanssonMODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value"); 84f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 85e37c772e36a7943b2e0bd8f48312e78474c0df15Olof Johanssonextern const struct ethtool_ops pasemi_mac_ethtool_ops; 86e37c772e36a7943b2e0bd8f48312e78474c0df15Olof Johansson 87af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johanssonstatic int translation_enabled(void) 88af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson{ 89af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson#if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE) 90af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson return 1; 91af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson#else 92af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson return firmware_has_feature(FW_FEATURE_LPAR); 93af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson#endif 94af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson} 95af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson 9634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johanssonstatic void write_iob_reg(unsigned int reg, unsigned int val) 97a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson{ 9834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_write_iob_reg(reg, val); 99a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson} 100a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson 1015c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic unsigned int read_mac_reg(const struct pasemi_mac *mac, unsigned int reg) 102a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson{ 10334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson return pasemi_read_mac_reg(mac->dma_if, reg); 104a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson} 105a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson 1065c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic void write_mac_reg(const struct pasemi_mac *mac, unsigned int reg, 107a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson unsigned int val) 108a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson{ 10934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_write_mac_reg(mac->dma_if, reg, val); 110a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson} 111a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson 11234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johanssonstatic unsigned int read_dma_reg(unsigned int reg) 113a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson{ 11434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson return pasemi_read_dma_reg(reg); 115a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson} 116a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson 11734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johanssonstatic void write_dma_reg(unsigned int reg, unsigned int val) 118a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson{ 11934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_write_dma_reg(reg, val); 120a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson} 121a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson 1225c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic struct pasemi_mac_rxring *rx_ring(const struct pasemi_mac *mac) 12372b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson{ 12472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson return mac->rx; 12572b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson} 12672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson 1275c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic struct pasemi_mac_txring *tx_ring(const struct pasemi_mac *mac) 12872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson{ 12972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson return mac->tx; 13072b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson} 13172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson 1325c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic inline void prefetch_skb(const struct sk_buff *skb) 1335c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson{ 1345c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const void *d = skb; 1355c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson 1365c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson prefetch(d); 1375c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson prefetch(d+64); 1385c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson prefetch(d+128); 1395c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson prefetch(d+192); 1405c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson} 1415c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson 14234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johanssonstatic int mac_to_intf(struct pasemi_mac *mac) 14334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson{ 14434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson struct pci_dev *pdev = mac->pdev; 14534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson u32 tmp; 14634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson int nintf, off, i, j; 14734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson int devfn = pdev->devfn; 14834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 14934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson tmp = read_dma_reg(PAS_DMA_CAP_IFI); 15034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson nintf = (tmp & PAS_DMA_CAP_IFI_NIN_M) >> PAS_DMA_CAP_IFI_NIN_S; 15134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson off = (tmp & PAS_DMA_CAP_IFI_IOFF_M) >> PAS_DMA_CAP_IFI_IOFF_S; 15234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 15334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson /* IOFF contains the offset to the registers containing the 15434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson * DMA interface-to-MAC-pci-id mappings, and NIN contains number 15534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson * of total interfaces. Each register contains 4 devfns. 15634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson * Just do a linear search until we find the devfn of the MAC 15734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson * we're trying to look up. 15834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson */ 15934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 16034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson for (i = 0; i < (nintf+3)/4; i++) { 16134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson tmp = read_dma_reg(off+4*i); 16234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson for (j = 0; j < 4; j++) { 16334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (((tmp >> (8*j)) & 0xff) == devfn) 16434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson return i*4 + j; 16534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson } 16634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson } 16734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson return -1; 16834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson} 16934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 170ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johanssonstatic void pasemi_mac_intf_disable(struct pasemi_mac *mac) 171ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson{ 172ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson unsigned int flags; 173ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 174ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG); 175ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson flags &= ~PAS_MAC_CFG_PCFG_PE; 176ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags); 177ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson} 178ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 179ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johanssonstatic void pasemi_mac_intf_enable(struct pasemi_mac *mac) 180ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson{ 181ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson unsigned int flags; 182ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 183ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG); 184ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson flags |= PAS_MAC_CFG_PCFG_PE; 185ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags); 186ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson} 187ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 188f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic int pasemi_get_mac_addr(struct pasemi_mac *mac) 189f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 190f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pci_dev *pdev = mac->pdev; 191f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct device_node *dn = pci_device_to_OF_node(pdev); 1921af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net int len; 193f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson const u8 *maddr; 194f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson u8 addr[6]; 195f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 196f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (!dn) { 197f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev_dbg(&pdev->dev, 198f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson "No device node for mac, not configuring\n"); 199f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return -ENOENT; 200f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 201f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 2021af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net maddr = of_get_property(dn, "local-mac-address", &len); 2031af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net 2041af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net if (maddr && len == 6) { 2051af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net memcpy(mac->mac_addr, maddr, 6); 2061af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net return 0; 2071af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net } 2081af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net 2091af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net /* Some old versions of firmware mistakenly uses mac-address 2101af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net * (and as a string) instead of a byte array in local-mac-address. 2111af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net */ 212a5fd22ebc71eecb7b61e542d34ac50a417b3031bOlof Johansson 213a5fd22ebc71eecb7b61e542d34ac50a417b3031bOlof Johansson if (maddr == NULL) 2149028780a3e6d2c3dd940e89b377765cca008b6dfLinus Torvalds maddr = of_get_property(dn, "mac-address", NULL); 215a5fd22ebc71eecb7b61e542d34ac50a417b3031bOlof Johansson 216f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (maddr == NULL) { 217f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev_warn(&pdev->dev, 218f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson "no mac address in device tree, not configuring\n"); 219f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return -ENOENT; 220f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 221f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 222f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0], 223f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) { 224f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev_warn(&pdev->dev, 225f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson "can't parse mac address, not configuring\n"); 226f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return -EINVAL; 227f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 228f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 2291af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net memcpy(mac->mac_addr, addr, 6); 2301af7f05628fab81fdf4412d757676412ba5db660olof@lixom.net 231f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return 0; 232f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 233f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 2345cea73b0f7d4d49e276b0c4842465890d00de861Olof Johanssonstatic int pasemi_mac_set_mac_addr(struct net_device *dev, void *p) 2355cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson{ 2365cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson struct pasemi_mac *mac = netdev_priv(dev); 2375cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson struct sockaddr *addr = p; 2385cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson unsigned int adr0, adr1; 2395cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson 2405cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson if (!is_valid_ether_addr(addr->sa_data)) 241504f9b5a6bb5336ad434438d0cdd61a16db80129Danny Kukawka return -EADDRNOTAVAIL; 2425cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson 2435cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); 2445cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson 2455cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson adr0 = dev->dev_addr[2] << 24 | 2465cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson dev->dev_addr[3] << 16 | 2475cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson dev->dev_addr[4] << 8 | 2485cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson dev->dev_addr[5]; 2495cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson adr1 = read_mac_reg(mac, PAS_MAC_CFG_ADR1); 2505cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson adr1 &= ~0xffff; 2515cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson adr1 |= dev->dev_addr[0] << 8 | dev->dev_addr[1]; 2525cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson 2535cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson pasemi_mac_intf_disable(mac); 2545cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson write_mac_reg(mac, PAS_MAC_CFG_ADR0, adr0); 2555cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson write_mac_reg(mac, PAS_MAC_CFG_ADR1, adr1); 2565cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson pasemi_mac_intf_enable(mac); 2575cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson 2585cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson return 0; 2595cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson} 2605cea73b0f7d4d49e276b0c4842465890d00de861Olof Johansson 26128ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johanssonstatic int get_skb_hdr(struct sk_buff *skb, void **iphdr, 26228ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson void **tcph, u64 *hdr_flags, void *data) 26328ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson{ 26428ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson u64 macrx = (u64) data; 26528ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson unsigned int ip_len; 26628ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson struct iphdr *iph; 26728ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 26828ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson /* IPv4 header checksum failed */ 26928ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson if ((macrx & XCT_MACRX_HTY_M) != XCT_MACRX_HTY_IPV4_OK) 27028ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson return -1; 27128ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 27228ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson /* non tcp packet */ 27328ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson skb_reset_network_header(skb); 27428ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson iph = ip_hdr(skb); 27528ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson if (iph->protocol != IPPROTO_TCP) 27628ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson return -1; 27728ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 27828ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson ip_len = ip_hdrlen(skb); 27928ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson skb_set_transport_header(skb, ip_len); 28028ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson *tcph = tcp_hdr(skb); 28128ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 28228ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson /* check if ip header and tcp header are complete */ 283773212337941c5e26a05989532943877d72a2c83Roland Dreier if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb)) 28428ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson return -1; 28528ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 28628ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson *hdr_flags = LRO_IPV4 | LRO_TCP; 28728ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson *iphdr = iph; 28828ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 28928ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson return 0; 29028ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson} 29128ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 292ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johanssonstatic int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac, 2937e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson const int nfrags, 294ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson struct sk_buff *skb, 2955c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const dma_addr_t *dmas) 296ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson{ 297ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson int f; 2985c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson struct pci_dev *pdev = mac->dma_pdev; 299ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 3005c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson pci_unmap_single(pdev, dmas[0], skb_headlen(skb), PCI_DMA_TODEVICE); 301ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 302ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson for (f = 0; f < nfrags; f++) { 3039e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; 304ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 3059e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet pci_unmap_page(pdev, dmas[f+1], skb_frag_size(frag), PCI_DMA_TODEVICE); 306ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson } 307ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson dev_kfree_skb_irq(skb); 308ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 309ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson /* Freed descriptor slot + main SKB ptr + nfrags additional ptrs, 310ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson * aligned up to a power of 2 311ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson */ 312ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson return (nfrags + 3) & ~1; 313ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson} 314ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 3158d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonstatic struct pasemi_mac_csring *pasemi_mac_setup_csring(struct pasemi_mac *mac) 3168d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson{ 3178d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson struct pasemi_mac_csring *ring; 3188d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson u32 val; 3198d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson unsigned int cfg; 3208d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson int chno; 3218d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3228d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring), 3238d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson offsetof(struct pasemi_mac_csring, chan)); 3248d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3258d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (!ring) { 3268d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n"); 3278d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson goto out_chan; 3288d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 3298d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3308d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson chno = ring->chan.chno; 3318d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3328d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson ring->size = CS_RING_SIZE; 3338d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson ring->next_to_fill = 0; 3348d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3358d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* Allocate descriptors */ 3368d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE)) 3378d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson goto out_ring_desc; 3388d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3398d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno), 3408d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma)); 3418d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32); 3428d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson val |= PAS_DMA_TXCHAN_BASEU_SIZ(CS_RING_SIZE >> 3); 3438d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3448d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val); 3458d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3468d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson ring->events[0] = pasemi_dma_alloc_flag(); 3478d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson ring->events[1] = pasemi_dma_alloc_flag(); 3488d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (ring->events[0] < 0 || ring->events[1] < 0) 3498d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson goto out_flags; 3508d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3518d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_clear_flag(ring->events[0]); 3528d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_clear_flag(ring->events[1]); 3538d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3548d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson ring->fun = pasemi_dma_alloc_fun(); 3558d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (ring->fun < 0) 3568d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson goto out_fun; 3578d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3588d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson cfg = PAS_DMA_TXCHAN_CFG_TY_FUNC | PAS_DMA_TXCHAN_CFG_UP | 3598d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson PAS_DMA_TXCHAN_CFG_TATTR(ring->fun) | 3608d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson PAS_DMA_TXCHAN_CFG_LPSQ | PAS_DMA_TXCHAN_CFG_LPDQ; 3618d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3628d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (translation_enabled()) 3638d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR; 3648d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3658d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg); 3668d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3678d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* enable channel */ 3688d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_start_chan(&ring->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ | 3698d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson PAS_DMA_TXCHAN_TCMDSTA_DB | 3708d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson PAS_DMA_TXCHAN_TCMDSTA_DE | 3718d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson PAS_DMA_TXCHAN_TCMDSTA_DA); 3728d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3738d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson return ring; 3748d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3758d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonout_fun: 3768d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonout_flags: 3778d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (ring->events[0] >= 0) 3788d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_free_flag(ring->events[0]); 3798d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (ring->events[1] >= 0) 3808d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_free_flag(ring->events[1]); 3818d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_free_ring(&ring->chan); 3828d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonout_ring_desc: 3838d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_free_chan(&ring->chan); 3848d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonout_chan: 3858d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3868d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson return NULL; 3878d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson} 3888d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3898d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonstatic void pasemi_mac_setup_csrings(struct pasemi_mac *mac) 3908d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson{ 3918d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson int i; 3928d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson mac->cs[0] = pasemi_mac_setup_csring(mac); 3938d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (mac->type == MAC_TYPE_XAUI) 3948d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson mac->cs[1] = pasemi_mac_setup_csring(mac); 3958d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson else 3968d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson mac->cs[1] = 0; 3978d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 3988d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson for (i = 0; i < MAX_CS; i++) 3998d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (mac->cs[i]) 4008d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson mac->num_cs++; 4018d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson} 4028d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 4038d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonstatic void pasemi_mac_free_csring(struct pasemi_mac_csring *csring) 4048d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson{ 4058d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_stop_chan(&csring->chan); 4068d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_free_flag(csring->events[0]); 4078d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_free_flag(csring->events[1]); 4088d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_free_ring(&csring->chan); 4098d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_dma_free_chan(&csring->chan); 4101724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson pasemi_dma_free_fun(csring->fun); 4118d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson} 4128d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 4135c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic int pasemi_mac_setup_rx_resources(const struct net_device *dev) 414f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 415f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac_rxring *ring; 416f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac *mac = netdev_priv(dev); 41734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson int chno; 418af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson unsigned int cfg; 419f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 42034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson ring = pasemi_dma_alloc_chan(RXCHAN, sizeof(struct pasemi_mac_rxring), 42134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson offsetof(struct pasemi_mac_rxring, chan)); 422f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 42334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (!ring) { 42434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson dev_err(&mac->pdev->dev, "Can't allocate RX channel\n"); 42534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson goto out_chan; 42634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson } 42734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson chno = ring->chan.chno; 428f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 429f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson spin_lock_init(&ring->lock); 430f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 431021fa22e01d3d0425d3d15df48f523b69a3a11c4Olof Johansson ring->size = RX_RING_SIZE; 432fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) * 433f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson RX_RING_SIZE, GFP_KERNEL); 434f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 435fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson if (!ring->ring_info) 436fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson goto out_ring_info; 437f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 438f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* Allocate descriptors */ 43934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (pasemi_dma_alloc_ring(&ring->chan, RX_RING_SIZE)) 440fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson goto out_ring_desc; 441f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 442f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev, 443f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson RX_RING_SIZE * sizeof(u64), 444f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson &ring->buf_dma, GFP_KERNEL); 445f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (!ring->buffers) 44634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson goto out_ring_desc; 447f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 448f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson memset(ring->buffers, 0, RX_RING_SIZE * sizeof(u64)); 449f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 45034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXCHAN_BASEL(chno), 45134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXCHAN_BASEL_BRBL(ring->chan.ring_dma)); 452f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 45334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXCHAN_BASEU(chno), 45434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32) | 45534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3)); 456f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 4575c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson cfg = PAS_DMA_RXCHAN_CFG_HBU(2); 458af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson 459af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson if (translation_enabled()) 460af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson cfg |= PAS_DMA_RXCHAN_CFG_CTR; 461af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson 46234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXCHAN_CFG(chno), cfg); 463f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 46434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXINT_BASEL(mac->dma_if), 46534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXINT_BASEL_BRBL(ring->buf_dma)); 466f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 46734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXINT_BASEU(mac->dma_if), 46834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) | 46934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3)); 470f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 4715c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson cfg = PAS_DMA_RXINT_CFG_DHL(2) | PAS_DMA_RXINT_CFG_L2 | 472af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP | 473af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson PAS_DMA_RXINT_CFG_HEN; 474af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson 475af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson if (translation_enabled()) 476af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson cfg |= PAS_DMA_RXINT_CFG_ITRR | PAS_DMA_RXINT_CFG_ITR; 477af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson 47834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXINT_CFG(mac->dma_if), cfg); 479c0efd52b8b1951c20878208fdcbab0468f816804Olof Johansson 480f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson ring->next_to_fill = 0; 481f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson ring->next_to_clean = 0; 48272b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson ring->mac = mac; 483f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson mac->rx = ring; 484f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 485f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return 0; 486f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 487fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johanssonout_ring_desc: 488fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson kfree(ring->ring_info); 489fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johanssonout_ring_info: 49034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_dma_free_chan(&ring->chan); 49134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johanssonout_chan: 492f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return -ENOMEM; 493f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 494f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 49572b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johanssonstatic struct pasemi_mac_txring * 4965c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonpasemi_mac_setup_tx_resources(const struct net_device *dev) 497f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 498f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac *mac = netdev_priv(dev); 499f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson u32 val; 500f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac_txring *ring; 501af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson unsigned int cfg; 50234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson int chno; 503f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 50434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_txring), 50534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson offsetof(struct pasemi_mac_txring, chan)); 50634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 50734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (!ring) { 50834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson dev_err(&mac->pdev->dev, "Can't allocate TX channel\n"); 50934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson goto out_chan; 51034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson } 51134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 51234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson chno = ring->chan.chno; 513f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 514f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson spin_lock_init(&ring->lock); 515f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 516021fa22e01d3d0425d3d15df48f523b69a3a11c4Olof Johansson ring->size = TX_RING_SIZE; 517fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) * 518f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson TX_RING_SIZE, GFP_KERNEL); 519fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson if (!ring->ring_info) 520fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson goto out_ring_info; 521f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 522f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* Allocate descriptors */ 52334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (pasemi_dma_alloc_ring(&ring->chan, TX_RING_SIZE)) 524fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson goto out_ring_desc; 525f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 52634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno), 52734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma)); 52834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32); 529fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 3); 530f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 53134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val); 532f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 533af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE | 534af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) | 535af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson PAS_DMA_TXCHAN_CFG_UP | 5368d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson PAS_DMA_TXCHAN_CFG_WT(4); 537af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson 538af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson if (translation_enabled()) 539af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR; 540af289e803fdf2fcd19cf4a57c3c896dba146c756Olof Johansson 54134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg); 542f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 543021fa22e01d3d0425d3d15df48f523b69a3a11c4Olof Johansson ring->next_to_fill = 0; 544f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson ring->next_to_clean = 0; 54572b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson ring->mac = mac; 546f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 54772b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson return ring; 548f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 549fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johanssonout_ring_desc: 550fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson kfree(ring->ring_info); 551fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johanssonout_ring_info: 55234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_dma_free_chan(&ring->chan); 55334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johanssonout_chan: 55472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson return NULL; 555f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 556f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 55772b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johanssonstatic void pasemi_mac_free_tx_resources(struct pasemi_mac *mac) 558f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 55972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson struct pasemi_mac_txring *txring = tx_ring(mac); 560ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson unsigned int i, j; 561f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac_buffer *info; 562ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson dma_addr_t dmas[MAX_SKB_FRAGS+1]; 5637e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson int freed, nfrags; 564ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson int start, limit; 565fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson 56672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson start = txring->next_to_clean; 56772b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson limit = txring->next_to_fill; 568ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson 569ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson /* Compensate for when fill has wrapped and clean has not */ 570ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson if (start > limit) 571ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson limit += TX_RING_SIZE; 572ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson 573ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson for (i = start; i < limit; i += freed) { 57472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson info = &txring->ring_info[(i+1) & (TX_RING_SIZE-1)]; 575fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson if (info->dma && info->skb) { 5767e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson nfrags = skb_shinfo(info->skb)->nr_frags; 5777e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson for (j = 0; j <= nfrags; j++) 57872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson dmas[j] = txring->ring_info[(i+1+j) & 57972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson (TX_RING_SIZE-1)].dma; 5807e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson freed = pasemi_mac_unmap_tx_skb(mac, nfrags, 5817e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson info->skb, dmas); 582ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson } else 583ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson freed = 2; 584f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 585f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 58672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson kfree(txring->ring_info); 58734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_dma_free_chan(&txring->chan); 58834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 589f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 590f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 591ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johanssonstatic void pasemi_mac_free_rx_buffers(struct pasemi_mac *mac) 592f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 59372b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson struct pasemi_mac_rxring *rx = rx_ring(mac); 594f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson unsigned int i; 595f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac_buffer *info; 596f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 597f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson for (i = 0; i < RX_RING_SIZE; i++) { 59872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson info = &RX_DESC_INFO(rx, i); 599fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson if (info->skb && info->dma) { 600fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson pci_unmap_single(mac->dma_pdev, 601fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson info->dma, 602fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson info->skb->len, 603fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson PCI_DMA_FROMDEVICE); 604fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson dev_kfree_skb_any(info->skb); 605f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 606fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson info->dma = 0; 607fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson info->skb = NULL; 608f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 609f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 610fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson for (i = 0; i < RX_RING_SIZE; i++) 611ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson RX_BUFF(rx, i) = 0; 612ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson} 613ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 614ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johanssonstatic void pasemi_mac_free_rx_resources(struct pasemi_mac *mac) 615ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson{ 616ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_free_rx_buffers(mac); 617fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson 618f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64), 61972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson rx_ring(mac)->buffers, rx_ring(mac)->buf_dma); 620f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 62172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson kfree(rx_ring(mac)->ring_info); 62234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_dma_free_chan(&rx_ring(mac)->chan); 623f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson mac->rx = NULL; 624f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 625f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 6265c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic void pasemi_mac_replenish_rx_ring(const struct net_device *dev, 6275c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const int limit) 628f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 6295c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const struct pasemi_mac *mac = netdev_priv(dev); 63072b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson struct pasemi_mac_rxring *rx = rx_ring(mac); 631b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson int fill, count; 632f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 633cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson if (limit <= 0) 634f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return; 635f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 63672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson fill = rx_ring(mac)->next_to_fill; 637928773c23a4cf053a34ad480439448f75efa350cOlof Johansson for (count = 0; count < limit; count++) { 63872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson struct pasemi_mac_buffer *info = &RX_DESC_INFO(rx, fill); 63972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson u64 *buff = &RX_BUFF(rx, fill); 640f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct sk_buff *skb; 641f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dma_addr_t dma; 642f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 643fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson /* Entry in use? */ 644fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson WARN_ON(*buff); 645fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson 646dae2e9f430c46c29e3f771110094bd3da3625aa4Pradeep A. Dalvi skb = netdev_alloc_skb(dev, mac->bufsz); 6475d8949448b68b3b355036c8061e3282388826ec5Olof Johansson skb_reserve(skb, LOCAL_SKB_ALIGN); 648f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 6499f05cfe250498791cd24707aea3b728b52d886d5Olof Johansson if (unlikely(!skb)) 650f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson break; 651f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 6528dc121a4b620090e594945fd36f878836fc5a14aOlof Johansson dma = pci_map_single(mac->dma_pdev, skb->data, 653ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson mac->bufsz - LOCAL_SKB_ALIGN, 654f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson PCI_DMA_FROMDEVICE); 655f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 6568d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori if (unlikely(pci_dma_mapping_error(mac->dma_pdev, dma))) { 657f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev_kfree_skb_irq(info->skb); 658f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson break; 659f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 660f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 661f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson info->skb = skb; 662f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson info->dma = dma; 663ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson *buff = XCT_RXB_LEN(mac->bufsz) | XCT_RXB_ADDR(dma); 664fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson fill++; 665f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 666f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 667f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson wmb(); 668f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 66934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXINT_INCR(mac->dma_if), count); 670f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 67172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson rx_ring(mac)->next_to_fill = (rx_ring(mac)->next_to_fill + count) & 672b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson (RX_RING_SIZE - 1); 673f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 674f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 6755c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic void pasemi_mac_restart_rx_intr(const struct pasemi_mac *mac) 6761b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson{ 677906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson struct pasemi_mac_rxring *rx = rx_ring(mac); 67852a9435183f961e1bb3c146a62bfbecf93d15d58Olof Johansson unsigned int reg, pcnt; 6791b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson /* Re-enable packet count interrupts: finally 6801b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson * ack the packet count interrupt we got in rx_intr. 6811b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson */ 6821b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 683906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson pcnt = *rx->chan.status & PAS_STATUS_PCNT_M; 6841b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 68552a9435183f961e1bb3c146a62bfbecf93d15d58Olof Johansson reg = PAS_IOB_DMA_RXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_RXCH_RESET_PINTC; 6861b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 687906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson if (*rx->chan.status & PAS_STATUS_TIMER) 688906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson reg |= PAS_IOB_DMA_RXCH_RESET_TINTC; 689906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson 69034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_iob_reg(PAS_IOB_DMA_RXCH_RESET(mac->rx->chan.chno), reg); 6911b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson} 6921b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 6935c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic void pasemi_mac_restart_tx_intr(const struct pasemi_mac *mac) 6941b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson{ 69552a9435183f961e1bb3c146a62bfbecf93d15d58Olof Johansson unsigned int reg, pcnt; 6961b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 6971b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson /* Re-enable packet count interrupts */ 69834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pcnt = *tx_ring(mac)->chan.status & PAS_STATUS_PCNT_M; 6991b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 70052a9435183f961e1bb3c146a62bfbecf93d15d58Olof Johansson reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC; 7011b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 70234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_iob_reg(PAS_IOB_DMA_TXCH_RESET(tx_ring(mac)->chan.chno), reg); 7031b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson} 7041b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 7051b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson 7065c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic inline void pasemi_mac_rx_error(const struct pasemi_mac *mac, 7075c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const u64 macrx) 70869c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson{ 70969c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson unsigned int rcmdsta, ccmdsta; 71034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson struct pasemi_dmachan *chan = &rx_ring(mac)->chan; 71169c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 71269c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson if (!netif_msg_rx_err(mac)) 71369c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson return; 71469c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 71534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if)); 71634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson ccmdsta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno)); 71769c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 718fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar printk(KERN_ERR "pasemi_mac: rx error. macrx %016llx, rx status %llx\n", 71934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson macrx, *chan->status); 72069c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 72169c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n", 72269c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson rcmdsta, ccmdsta); 72369c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson} 72469c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 7255c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic inline void pasemi_mac_tx_error(const struct pasemi_mac *mac, 7265c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const u64 mactx) 72769c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson{ 72869c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson unsigned int cmdsta; 72934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson struct pasemi_dmachan *chan = &tx_ring(mac)->chan; 73069c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 73169c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson if (!netif_msg_tx_err(mac)) 73269c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson return; 73369c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 73434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson cmdsta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno)); 73569c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 736fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016llx, "\ 737fe333321e2a71f706b794d55b6a3dcb5ab240f65Ingo Molnar "tx status 0x%016llx\n", mactx, *chan->status); 73869c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 73969c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta); 74069c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson} 74169c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 7425c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johanssonstatic int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx, 7435c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const int limit) 744f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 7455c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const struct pasemi_dmachan *chan = &rx->chan; 74672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson struct pasemi_mac *mac = rx->mac; 7475c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson struct pci_dev *pdev = mac->dma_pdev; 748cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson unsigned int n; 7495c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson int count, buf_index, tot_bytes, packets; 750cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson struct pasemi_mac_buffer *info; 751cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson struct sk_buff *skb; 752b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson unsigned int len; 7535c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson u64 macrx, eval; 754cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson dma_addr_t dma; 7555c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson 7565c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson tot_bytes = 0; 7575c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson packets = 0; 758f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 75972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson spin_lock(&rx->lock); 760f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 76172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson n = rx->next_to_clean; 762f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 76372b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson prefetch(&RX_DESC(rx, n)); 764b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson 765b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson for (count = 0; count < limit; count++) { 76672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson macrx = RX_DESC(rx, n); 7675c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson prefetch(&RX_DESC(rx, n+4)); 768f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 76969c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson if ((macrx & XCT_MACRX_E) || 77034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson (*chan->status & PAS_STATUS_ERROR)) 77169c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson pasemi_mac_rx_error(mac, macrx); 77269c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 773cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson if (!(macrx & XCT_MACRX_O)) 774f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson break; 775f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 776f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson info = NULL; 777f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 778b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson BUG_ON(!(macrx & XCT_MACRX_RR_8BRES)); 779f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 78072b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson eval = (RX_DESC(rx, n+1) & XCT_RXRES_8B_EVAL_M) >> 781b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson XCT_RXRES_8B_EVAL_S; 782b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson buf_index = eval-1; 783b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson 78472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson dma = (RX_DESC(rx, n+2) & XCT_PTR_ADDR_M); 78572b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson info = &RX_DESC_INFO(rx, buf_index); 786fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson 7879f05cfe250498791cd24707aea3b728b52d886d5Olof Johansson skb = info->skb; 788f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 7895c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson prefetch_skb(skb); 790f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 791cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S; 792f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 793ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pci_unmap_single(pdev, dma, mac->bufsz - LOCAL_SKB_ALIGN, 7945c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson PCI_DMA_FROMDEVICE); 79532bee776533eea839f9499d985c1490b5ac98512Olof Johansson 79632bee776533eea839f9499d985c1490b5ac98512Olof Johansson if (macrx & XCT_MACRX_CRC) { 79732bee776533eea839f9499d985c1490b5ac98512Olof Johansson /* CRC error flagged */ 79832bee776533eea839f9499d985c1490b5ac98512Olof Johansson mac->netdev->stats.rx_errors++; 79932bee776533eea839f9499d985c1490b5ac98512Olof Johansson mac->netdev->stats.rx_crc_errors++; 8004352d82647f679fb8dd9440b34400fa49beedb2cOlof Johansson /* No need to free skb, it'll be reused */ 80132bee776533eea839f9499d985c1490b5ac98512Olof Johansson goto next; 80232bee776533eea839f9499d985c1490b5ac98512Olof Johansson } 80332bee776533eea839f9499d985c1490b5ac98512Olof Johansson 8045d8949448b68b3b355036c8061e3282388826ec5Olof Johansson info->skb = NULL; 805ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson info->dma = 0; 806fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson 80726fcfa95aef980cab4ff1ea55979c30e772dd0ddOlof Johansson if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) { 80838bf3184e8c4b8cd4285a24b6f69a300b32f0062Olof Johansson skb->ip_summed = CHECKSUM_UNNECESSARY; 809cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson skb->csum = (macrx & XCT_MACRX_CSUM_M) >> 810f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson XCT_MACRX_CSUM_S; 811f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } else 812bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet skb_checksum_none_assert(skb); 813f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 8145c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson packets++; 8155c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson tot_bytes += len; 8165c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson 8175c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson /* Don't include CRC */ 8185c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson skb_put(skb, len-4); 819f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 82026fcfa95aef980cab4ff1ea55979c30e772dd0ddOlof Johansson skb->protocol = eth_type_trans(skb, mac->netdev); 82128ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson lro_receive_skb(&mac->lro_mgr, skb, (void *)macrx); 822f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 82332bee776533eea839f9499d985c1490b5ac98512Olof Johanssonnext: 82472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson RX_DESC(rx, n) = 0; 82572b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson RX_DESC(rx, n+1) = 0; 826cd4ceb245be7926e94558e2b6cd279bfaa775908Olof Johansson 827ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson /* Need to zero it out since hardware doesn't, since the 828ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson * replenish loop uses it to tell when it's done. 829ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson */ 83072b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson RX_BUFF(rx, buf_index) = 0; 831ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson 832b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson n += 4; 833f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 834f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 8359a50bebda95745d312c69d3bb6d788067cbefb84Olof Johansson if (n > RX_RING_SIZE) { 8369a50bebda95745d312c69d3bb6d788067cbefb84Olof Johansson /* Errata 5971 workaround: L2 target of headers */ 83734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_iob_reg(PAS_IOB_COM_PKTHDRCNT, 0); 8389a50bebda95745d312c69d3bb6d788067cbefb84Olof Johansson n &= (RX_RING_SIZE-1); 8399a50bebda95745d312c69d3bb6d788067cbefb84Olof Johansson } 840b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson 84172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson rx_ring(mac)->next_to_clean = n; 842b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson 84328ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson lro_flush_all(&mac->lro_mgr); 84428ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 845b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson /* Increase is in number of 16-byte entries, and since each descriptor 846b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson * with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with 847b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson * count*2. 848b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson */ 84934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXCHAN_INCR(mac->rx->chan.chno), count << 1); 850b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson 851b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson pasemi_mac_replenish_rx_ring(mac->netdev, count); 852f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 8535c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson mac->netdev->stats.rx_bytes += tot_bytes; 8545c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson mac->netdev->stats.rx_packets += packets; 8555c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson 85672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson spin_unlock(&rx_ring(mac)->lock); 857f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 858f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return count; 859f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 860f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 861ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson/* Can't make this too large or we blow the kernel stack limits */ 862ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson#define TX_CLEAN_BATCHSIZE (128/MAX_SKB_FRAGS) 863ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 86472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johanssonstatic int pasemi_mac_clean_tx(struct pasemi_mac_txring *txring) 865f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 86634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson struct pasemi_dmachan *chan = &txring->chan; 86772b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson struct pasemi_mac *mac = txring->mac; 868ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson int i, j; 869ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson unsigned int start, descr_count, buf_count, batch_limit; 870ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson unsigned int ring_limit; 87102df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson unsigned int total_count; 872ca7e235f5eb960d83b45cef4384b490672538cd9Olof Johansson unsigned long flags; 873ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson struct sk_buff *skbs[TX_CLEAN_BATCHSIZE]; 874ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson dma_addr_t dmas[TX_CLEAN_BATCHSIZE][MAX_SKB_FRAGS+1]; 8757e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson int nf[TX_CLEAN_BATCHSIZE]; 8767e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson int nr_frags; 877f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 87802df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson total_count = 0; 879ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson batch_limit = TX_CLEAN_BATCHSIZE; 88002df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johanssonrestart: 88172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson spin_lock_irqsave(&txring->lock, flags); 882f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 88372b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson start = txring->next_to_clean; 88472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson ring_limit = txring->next_to_fill; 885ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson 8867e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson prefetch(&TX_DESC_INFO(txring, start+1).skb); 8877e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson 888ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson /* Compensate for when fill has wrapped but clean has not */ 889ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson if (start > ring_limit) 890ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson ring_limit += TX_RING_SIZE; 89102df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson 892ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson buf_count = 0; 893ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson descr_count = 0; 894f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 895ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson for (i = start; 896ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson descr_count < batch_limit && i < ring_limit; 897ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson i += buf_count) { 89872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson u64 mactx = TX_DESC(txring, i); 899ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson struct sk_buff *skb; 900ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 901fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson if ((mactx & XCT_MACTX_E) || 90234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson (*chan->status & PAS_STATUS_ERROR)) 903fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson pasemi_mac_tx_error(mac, mactx); 90469c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson 9058d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* Skip over control descriptors */ 9068d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (!(mactx & XCT_MACTX_LLEN_M)) { 9078d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson TX_DESC(txring, i) = 0; 9088d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson TX_DESC(txring, i+1) = 0; 9098d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson buf_count = 2; 9108d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson continue; 9118d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 9128d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 9138d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson skb = TX_DESC_INFO(txring, i+1).skb; 9148d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson nr_frags = TX_DESC_INFO(txring, i).dma; 9158d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 916fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson if (unlikely(mactx & XCT_MACTX_O)) 91702df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson /* Not yet transmitted */ 918f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson break; 919f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 9207e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson buf_count = 2 + nr_frags; 9217e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson /* Since we always fill with an even number of entries, make 9227e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson * sure we skip any unused one at the end as well. 9237e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson */ 9247e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson if (buf_count & 1) 9257e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson buf_count++; 926ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 9277e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson for (j = 0; j <= nr_frags; j++) 92872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson dmas[descr_count][j] = TX_DESC_INFO(txring, i+1+j).dma; 929ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 9307e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson skbs[descr_count] = skb; 9317e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson nf[descr_count] = nr_frags; 9327e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson 93372b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson TX_DESC(txring, i) = 0; 93472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson TX_DESC(txring, i+1) = 0; 935fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson 936ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson descr_count++; 937f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 93872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson txring->next_to_clean = i & (TX_RING_SIZE-1); 939ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 94072b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson spin_unlock_irqrestore(&txring->lock, flags); 9410ce68c74162ce288cfd214dd126b8d03b8b7a8edOlof Johansson netif_wake_queue(mac->netdev); 9420ce68c74162ce288cfd214dd126b8d03b8b7a8edOlof Johansson 943ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson for (i = 0; i < descr_count; i++) 9447e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson pasemi_mac_unmap_tx_skb(mac, nf[i], skbs[i], dmas[i]); 94502df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson 946ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson total_count += descr_count; 94702df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson 94802df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson /* If the batch was full, try to clean more */ 949ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson if (descr_count == batch_limit) 95002df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson goto restart; 95102df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson 95202df6cfa09c2ccebe685bfd54a708e1f50b00a81Olof Johansson return total_count; 953f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 954f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 955f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 956f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic irqreturn_t pasemi_mac_rx_intr(int irq, void *data) 957f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 9585c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const struct pasemi_mac_rxring *rxring = data; 95934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson struct pasemi_mac *mac = rxring->mac; 9605c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const struct pasemi_dmachan *chan = &rxring->chan; 961f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson unsigned int reg; 962f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 96334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (!(*chan->status & PAS_STATUS_CAUSE_M)) 964f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return IRQ_NONE; 965f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 9666dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson /* Don't reset packet count so it won't fire again but clear 9676dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson * all others. 9686dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson */ 9696dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson 9706dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson reg = 0; 97134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (*chan->status & PAS_STATUS_SOFT) 9726dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson reg |= PAS_IOB_DMA_RXCH_RESET_SINTC; 97334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (*chan->status & PAS_STATUS_ERROR) 9746dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson reg |= PAS_IOB_DMA_RXCH_RESET_DINTC; 975f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 976288379f050284087578b77e04f040b57db3db3f8Ben Hutchings napi_schedule(&mac->napi); 9776dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson 97834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_iob_reg(PAS_IOB_DMA_RXCH_RESET(chan->chno), reg); 979f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 980f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return IRQ_HANDLED; 981f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 982f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 98361cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson#define TX_CLEAN_INTERVAL HZ 98461cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 98561cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johanssonstatic void pasemi_mac_tx_timer(unsigned long data) 98661cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson{ 98761cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson struct pasemi_mac_txring *txring = (struct pasemi_mac_txring *)data; 98861cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson struct pasemi_mac *mac = txring->mac; 98961cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 99061cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson pasemi_mac_clean_tx(txring); 99161cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 99261cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson mod_timer(&txring->clean_timer, jiffies + TX_CLEAN_INTERVAL); 99361cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 99461cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson pasemi_mac_restart_tx_intr(mac); 99561cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson} 99661cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 997f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic irqreturn_t pasemi_mac_tx_intr(int irq, void *data) 998f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 99972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson struct pasemi_mac_txring *txring = data; 10005c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const struct pasemi_dmachan *chan = &txring->chan; 100161cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson struct pasemi_mac *mac = txring->mac; 100261cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson unsigned int reg; 1003f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 100434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (!(*chan->status & PAS_STATUS_CAUSE_M)) 1005f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return IRQ_NONE; 1006f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 100761cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson reg = 0; 10086dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson 100934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (*chan->status & PAS_STATUS_SOFT) 10106dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson reg |= PAS_IOB_DMA_TXCH_RESET_SINTC; 101134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (*chan->status & PAS_STATUS_ERROR) 10126dfa7522d8b08c887bf9f4cb2600b89232f132f5Olof Johansson reg |= PAS_IOB_DMA_TXCH_RESET_DINTC; 1013f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 101461cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson mod_timer(&txring->clean_timer, jiffies + (TX_CLEAN_INTERVAL)*2); 101561cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 1016288379f050284087578b77e04f040b57db3db3f8Ben Hutchings napi_schedule(&mac->napi); 101761cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 101861cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson if (reg) 101961cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg); 1020f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1021f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return IRQ_HANDLED; 1022f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1023f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1024bb6e9590792834f905a92e439a083254649c985cOlof Johanssonstatic void pasemi_adjust_link(struct net_device *dev) 1025bb6e9590792834f905a92e439a083254649c985cOlof Johansson{ 1026bb6e9590792834f905a92e439a083254649c985cOlof Johansson struct pasemi_mac *mac = netdev_priv(dev); 1027bb6e9590792834f905a92e439a083254649c985cOlof Johansson int msg; 1028bb6e9590792834f905a92e439a083254649c985cOlof Johansson unsigned int flags; 1029bb6e9590792834f905a92e439a083254649c985cOlof Johansson unsigned int new_flags; 1030bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1031bb6e9590792834f905a92e439a083254649c985cOlof Johansson if (!mac->phydev->link) { 1032bb6e9590792834f905a92e439a083254649c985cOlof Johansson /* If no link, MAC speed settings don't matter. Just report 1033bb6e9590792834f905a92e439a083254649c985cOlof Johansson * link down and return. 1034bb6e9590792834f905a92e439a083254649c985cOlof Johansson */ 1035bb6e9590792834f905a92e439a083254649c985cOlof Johansson if (mac->link && netif_msg_link(mac)) 1036bb6e9590792834f905a92e439a083254649c985cOlof Johansson printk(KERN_INFO "%s: Link is down.\n", dev->name); 1037bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1038bb6e9590792834f905a92e439a083254649c985cOlof Johansson netif_carrier_off(dev); 1039b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson pasemi_mac_intf_disable(mac); 1040bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->link = 0; 1041bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1042bb6e9590792834f905a92e439a083254649c985cOlof Johansson return; 1043b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson } else { 1044b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson pasemi_mac_intf_enable(mac); 1045bb6e9590792834f905a92e439a083254649c985cOlof Johansson netif_carrier_on(dev); 1046b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson } 1047bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1048a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG); 1049bb6e9590792834f905a92e439a083254649c985cOlof Johansson new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M | 1050bb6e9590792834f905a92e439a083254649c985cOlof Johansson PAS_MAC_CFG_PCFG_TSR_M); 1051bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1052bb6e9590792834f905a92e439a083254649c985cOlof Johansson if (!mac->phydev->duplex) 1053bb6e9590792834f905a92e439a083254649c985cOlof Johansson new_flags |= PAS_MAC_CFG_PCFG_HD; 1054bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1055bb6e9590792834f905a92e439a083254649c985cOlof Johansson switch (mac->phydev->speed) { 1056bb6e9590792834f905a92e439a083254649c985cOlof Johansson case 1000: 1057bb6e9590792834f905a92e439a083254649c985cOlof Johansson new_flags |= PAS_MAC_CFG_PCFG_SPD_1G | 1058bb6e9590792834f905a92e439a083254649c985cOlof Johansson PAS_MAC_CFG_PCFG_TSR_1G; 1059bb6e9590792834f905a92e439a083254649c985cOlof Johansson break; 1060bb6e9590792834f905a92e439a083254649c985cOlof Johansson case 100: 1061bb6e9590792834f905a92e439a083254649c985cOlof Johansson new_flags |= PAS_MAC_CFG_PCFG_SPD_100M | 1062bb6e9590792834f905a92e439a083254649c985cOlof Johansson PAS_MAC_CFG_PCFG_TSR_100M; 1063bb6e9590792834f905a92e439a083254649c985cOlof Johansson break; 1064bb6e9590792834f905a92e439a083254649c985cOlof Johansson case 10: 1065bb6e9590792834f905a92e439a083254649c985cOlof Johansson new_flags |= PAS_MAC_CFG_PCFG_SPD_10M | 1066bb6e9590792834f905a92e439a083254649c985cOlof Johansson PAS_MAC_CFG_PCFG_TSR_10M; 1067bb6e9590792834f905a92e439a083254649c985cOlof Johansson break; 1068bb6e9590792834f905a92e439a083254649c985cOlof Johansson default: 1069bb6e9590792834f905a92e439a083254649c985cOlof Johansson printk("Unsupported speed %d\n", mac->phydev->speed); 1070bb6e9590792834f905a92e439a083254649c985cOlof Johansson } 1071bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1072bb6e9590792834f905a92e439a083254649c985cOlof Johansson /* Print on link or speed/duplex change */ 1073bb6e9590792834f905a92e439a083254649c985cOlof Johansson msg = mac->link != mac->phydev->link || flags != new_flags; 1074bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1075bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->duplex = mac->phydev->duplex; 1076bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->speed = mac->phydev->speed; 1077bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->link = mac->phydev->link; 1078bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1079bb6e9590792834f905a92e439a083254649c985cOlof Johansson if (new_flags != flags) 1080a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson write_mac_reg(mac, PAS_MAC_CFG_PCFG, new_flags); 1081bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1082bb6e9590792834f905a92e439a083254649c985cOlof Johansson if (msg && netif_msg_link(mac)) 1083bb6e9590792834f905a92e439a083254649c985cOlof Johansson printk(KERN_INFO "%s: Link is up at %d Mbps, %s duplex.\n", 1084bb6e9590792834f905a92e439a083254649c985cOlof Johansson dev->name, mac->speed, mac->duplex ? "full" : "half"); 1085bb6e9590792834f905a92e439a083254649c985cOlof Johansson} 1086bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1087bb6e9590792834f905a92e439a083254649c985cOlof Johanssonstatic int pasemi_mac_phy_init(struct net_device *dev) 1088bb6e9590792834f905a92e439a083254649c985cOlof Johansson{ 1089bb6e9590792834f905a92e439a083254649c985cOlof Johansson struct pasemi_mac *mac = netdev_priv(dev); 1090bb6e9590792834f905a92e439a083254649c985cOlof Johansson struct device_node *dn, *phy_dn; 1091bb6e9590792834f905a92e439a083254649c985cOlof Johansson struct phy_device *phydev; 1092bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1093bb6e9590792834f905a92e439a083254649c985cOlof Johansson dn = pci_device_to_OF_node(mac->pdev); 10941dd2d06c0459a2f1bffc56765e3cc57427818867Grant Likely phy_dn = of_parse_phandle(dn, "phy-handle", 0); 1095bb6e9590792834f905a92e439a083254649c985cOlof Johansson of_node_put(phy_dn); 1096bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1097bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->link = 0; 1098bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->speed = 0; 1099bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->duplex = -1; 1100bb6e9590792834f905a92e439a083254649c985cOlof Johansson 11011dd2d06c0459a2f1bffc56765e3cc57427818867Grant Likely phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0, 11021dd2d06c0459a2f1bffc56765e3cc57427818867Grant Likely PHY_INTERFACE_MODE_SGMII); 1103bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1104bb6e9590792834f905a92e439a083254649c985cOlof Johansson if (IS_ERR(phydev)) { 1105bb6e9590792834f905a92e439a083254649c985cOlof Johansson printk(KERN_ERR "%s: Could not attach to phy\n", dev->name); 1106bb6e9590792834f905a92e439a083254649c985cOlof Johansson return PTR_ERR(phydev); 1107bb6e9590792834f905a92e439a083254649c985cOlof Johansson } 1108bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1109bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->phydev = phydev; 1110bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1111bb6e9590792834f905a92e439a083254649c985cOlof Johansson return 0; 1112bb6e9590792834f905a92e439a083254649c985cOlof Johansson} 1113bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1114bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1115f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic int pasemi_mac_open(struct net_device *dev) 1116f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 1117f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac *mac = netdev_priv(dev); 1118f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson unsigned int flags; 1119e37c772e36a7943b2e0bd8f48312e78474c0df15Olof Johansson int i, ret; 1120f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1121f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) | 1122f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) | 1123f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson PAS_MAC_CFG_TXP_TIFT(8) | PAS_MAC_CFG_TXP_TIFG(12); 1124f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1125a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson write_mac_reg(mac, PAS_MAC_CFG_TXP, flags); 1126f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1127f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson ret = pasemi_mac_setup_rx_resources(dev); 1128f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (ret) 1129f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson goto out_rx_resources; 1130f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 113134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson mac->tx = pasemi_mac_setup_tx_resources(dev); 113272b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson 113372b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson if (!mac->tx) 113472b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson goto out_tx_ring; 1135f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 11361724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson /* We might already have allocated rings in case mtu was changed 11371724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson * before interface was brought up. 11381724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson */ 11391724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson if (dev->mtu > 1500 && !mac->num_cs) { 11408d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_mac_setup_csrings(mac); 11418d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (!mac->num_cs) 11428d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson goto out_tx_ring; 11438d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 11448d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 1145e37c772e36a7943b2e0bd8f48312e78474c0df15Olof Johansson /* Zero out rmon counters */ 1146e37c772e36a7943b2e0bd8f48312e78474c0df15Olof Johansson for (i = 0; i < 32; i++) 1147e37c772e36a7943b2e0bd8f48312e78474c0df15Olof Johansson write_mac_reg(mac, PAS_MAC_RMON(i), 0); 1148e37c772e36a7943b2e0bd8f48312e78474c0df15Olof Johansson 1149906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson /* 0x3ff with 33MHz clock is about 31us */ 1150906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG, 1151906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff)); 1152906674abab0424b466a2db4bb6a890a8c477b10aOlof Johansson 115334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_iob_reg(PAS_IOB_DMA_RXCH_CFG(mac->rx->chan.chno), 115428ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson PAS_IOB_DMA_RXCH_CFG_CNTTH(256)); 115534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 115634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno), 115761cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson PAS_IOB_DMA_TXCH_CFG_CNTTH(32)); 115834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 1159a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson write_mac_reg(mac, PAS_MAC_IPC_CHNL, 116034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_MAC_IPC_CHNL_DCHNO(mac->rx->chan.chno) | 116134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_MAC_IPC_CHNL_BCH(mac->rx->chan.chno)); 1162f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1163f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* enable rx if */ 116434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 116534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXINT_RCMDSTA_EN | 116634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXINT_RCMDSTA_DROPS_M | 116734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXINT_RCMDSTA_BP | 116834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXINT_RCMDSTA_OO | 116934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXINT_RCMDSTA_BT); 1170f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1171f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* enable rx channel */ 117234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_dma_start_chan(&rx_ring(mac)->chan, PAS_DMA_RXCHAN_CCMDSTA_DU | 117334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXCHAN_CCMDSTA_OD | 117434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXCHAN_CCMDSTA_FD | 117534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_RXCHAN_CCMDSTA_DT); 1176f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1177f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* enable tx channel */ 117834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_dma_start_chan(&tx_ring(mac)->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ | 117934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_TXCHAN_TCMDSTA_DB | 118034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_TXCHAN_TCMDSTA_DE | 118134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson PAS_DMA_TXCHAN_TCMDSTA_DA); 1182f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1183928773c23a4cf053a34ad480439448f75efa350cOlof Johansson pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE); 1184f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 118534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_RXCHAN_INCR(rx_ring(mac)->chan.chno), 118634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson RX_RING_SIZE>>1); 1187b5254eee7994ba0a44ba7386cb66c2ce2f30fcc6Olof Johansson 118872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson /* Clear out any residual packet count state from firmware */ 118972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_restart_rx_intr(mac); 119072b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_restart_tx_intr(mac); 119172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson 1192b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE; 119336033766533176d61ba15793d8ef219775499c2fOlof Johansson 119436033766533176d61ba15793d8ef219775499c2fOlof Johansson if (mac->type == MAC_TYPE_GMAC) 119536033766533176d61ba15793d8ef219775499c2fOlof Johansson flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G; 119636033766533176d61ba15793d8ef219775499c2fOlof Johansson else 119736033766533176d61ba15793d8ef219775499c2fOlof Johansson flags |= PAS_MAC_CFG_PCFG_TSR_10G | PAS_MAC_CFG_PCFG_SPD_10G; 119836033766533176d61ba15793d8ef219775499c2fOlof Johansson 119936033766533176d61ba15793d8ef219775499c2fOlof Johansson /* Enable interface in MAC */ 120036033766533176d61ba15793d8ef219775499c2fOlof Johansson write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags); 120136033766533176d61ba15793d8ef219775499c2fOlof Johansson 1202bb6e9590792834f905a92e439a083254649c985cOlof Johansson ret = pasemi_mac_phy_init(dev); 1203b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson if (ret) { 1204b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson /* Since we won't get link notification, just enable RX */ 1205b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson pasemi_mac_intf_enable(mac); 1206b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson if (mac->type == MAC_TYPE_GMAC) { 1207b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson /* Warn for missing PHY on SGMII (1Gig) ports */ 1208b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson dev_warn(&mac->pdev->dev, 1209b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson "PHY init failed: %d.\n", ret); 1210b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson dev_warn(&mac->pdev->dev, 1211b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson "Defaulting to 1Gbit full duplex\n"); 1212b0cd2f9016f75eb8a9fdc45d32f9b41fb16d48c9Olof Johansson } 12138304b633c5e8c9ba34d3cc7f24f52434d3a3b93bOlof Johansson } 1214bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1215f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson netif_start_queue(dev); 1216bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger napi_enable(&mac->napi); 1217f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 121872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson snprintf(mac->tx_irq_name, sizeof(mac->tx_irq_name), "%s tx", 121972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson dev->name); 1220771f7404a9deca902594823d616cd7a84f827982Olof Johansson 1221a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches ret = request_irq(mac->tx->chan.irq, pasemi_mac_tx_intr, IRQF_DISABLED, 122272b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson mac->tx_irq_name, mac->tx); 1223f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (ret) { 1224f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n", 122534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson mac->tx->chan.irq, ret); 1226f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson goto out_tx_int; 1227f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 1228f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 122972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson snprintf(mac->rx_irq_name, sizeof(mac->rx_irq_name), "%s rx", 123072b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson dev->name); 123172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson 1232a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches ret = request_irq(mac->rx->chan.irq, pasemi_mac_rx_intr, IRQF_DISABLED, 123334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson mac->rx_irq_name, mac->rx); 1234f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (ret) { 1235f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n", 123634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson mac->rx->chan.irq, ret); 1237f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson goto out_rx_int; 1238f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 1239f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1240bb6e9590792834f905a92e439a083254649c985cOlof Johansson if (mac->phydev) 1241bb6e9590792834f905a92e439a083254649c985cOlof Johansson phy_start(mac->phydev); 1242bb6e9590792834f905a92e439a083254649c985cOlof Johansson 124361cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson init_timer(&mac->tx->clean_timer); 124461cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson mac->tx->clean_timer.function = pasemi_mac_tx_timer; 124561cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson mac->tx->clean_timer.data = (unsigned long)mac->tx; 124661cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson mac->tx->clean_timer.expires = jiffies+HZ; 124761cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson add_timer(&mac->tx->clean_timer); 124861cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 1249f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return 0; 1250f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1251f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonout_rx_int: 125234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson free_irq(mac->tx->chan.irq, mac->tx); 1253f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonout_tx_int: 1254bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger napi_disable(&mac->napi); 1255f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson netif_stop_queue(dev); 125672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johanssonout_tx_ring: 125772b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson if (mac->tx) 125872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_free_tx_resources(mac); 125972b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_free_rx_resources(mac); 1260f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonout_rx_resources: 1261f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1262f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return ret; 1263f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1264f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1265f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson#define MAX_RETRIES 5000 1266f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1267ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johanssonstatic void pasemi_mac_pause_txchan(struct pasemi_mac *mac) 1268ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson{ 1269ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson unsigned int sta, retries; 1270ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson int txch = tx_ring(mac)->chan.chno; 1271ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1272ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 1273ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson PAS_DMA_TXCHAN_TCMDSTA_ST); 1274ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1275ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson for (retries = 0; retries < MAX_RETRIES; retries++) { 1276ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch)); 1277ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)) 1278ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson break; 1279ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson cond_resched(); 1280ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson } 1281ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1282ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT) 1283ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson dev_err(&mac->dma_pdev->dev, 1284ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson "Failed to stop tx channel, tcmdsta %08x\n", sta); 1285ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1286ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 0); 1287ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson} 1288ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1289ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johanssonstatic void pasemi_mac_pause_rxchan(struct pasemi_mac *mac) 1290ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson{ 1291ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson unsigned int sta, retries; 1292ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson int rxch = rx_ring(mac)->chan.chno; 1293ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1294ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 1295ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson PAS_DMA_RXCHAN_CCMDSTA_ST); 1296ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson for (retries = 0; retries < MAX_RETRIES; retries++) { 1297ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch)); 1298ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)) 1299ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson break; 1300ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson cond_resched(); 1301ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson } 1302ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1303ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (sta & PAS_DMA_RXCHAN_CCMDSTA_ACT) 1304ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson dev_err(&mac->dma_pdev->dev, 1305ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson "Failed to stop rx channel, ccmdsta 08%x\n", sta); 1306ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 0); 1307ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson} 1308ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1309ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johanssonstatic void pasemi_mac_pause_rxint(struct pasemi_mac *mac) 1310ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson{ 1311ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson unsigned int sta, retries; 1312ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1313ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 1314ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson PAS_DMA_RXINT_RCMDSTA_ST); 1315ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson for (retries = 0; retries < MAX_RETRIES; retries++) { 1316ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if)); 1317ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT)) 1318ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson break; 1319ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson cond_resched(); 1320ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson } 1321ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1322ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (sta & PAS_DMA_RXINT_RCMDSTA_ACT) 1323ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson dev_err(&mac->dma_pdev->dev, 1324ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson "Failed to stop rx interface, rcmdsta %08x\n", sta); 1325ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0); 1326ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson} 1327ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1328f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic int pasemi_mac_close(struct net_device *dev) 1329f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 1330f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac *mac = netdev_priv(dev); 13319e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson unsigned int sta; 13328d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson int rxch, txch, i; 133334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 133434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson rxch = rx_ring(mac)->chan.chno; 133534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson txch = tx_ring(mac)->chan.chno; 1336f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1337bb6e9590792834f905a92e439a083254649c985cOlof Johansson if (mac->phydev) { 1338bb6e9590792834f905a92e439a083254649c985cOlof Johansson phy_stop(mac->phydev); 1339bb6e9590792834f905a92e439a083254649c985cOlof Johansson phy_disconnect(mac->phydev); 1340bb6e9590792834f905a92e439a083254649c985cOlof Johansson } 1341bb6e9590792834f905a92e439a083254649c985cOlof Johansson 134261cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson del_timer_sync(&mac->tx->clean_timer); 134361cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson 1344f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson netif_stop_queue(dev); 1345bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger napi_disable(&mac->napi); 1346f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 134734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if)); 13489e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson if (sta & (PAS_DMA_RXINT_RCMDSTA_BP | 13499e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson PAS_DMA_RXINT_RCMDSTA_OO | 13509e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson PAS_DMA_RXINT_RCMDSTA_BT)) 13519e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson printk(KERN_DEBUG "pasemi_mac: rcmdsta error: 0x%08x\n", sta); 13529e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson 135334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch)); 13549e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson if (sta & (PAS_DMA_RXCHAN_CCMDSTA_DU | 13559e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson PAS_DMA_RXCHAN_CCMDSTA_OD | 13569e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson PAS_DMA_RXCHAN_CCMDSTA_FD | 13579e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson PAS_DMA_RXCHAN_CCMDSTA_DT)) 13589e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson printk(KERN_DEBUG "pasemi_mac: ccmdsta error: 0x%08x\n", sta); 13599e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson 136034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch)); 136172b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson if (sta & (PAS_DMA_TXCHAN_TCMDSTA_SZ | PAS_DMA_TXCHAN_TCMDSTA_DB | 136272b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson PAS_DMA_TXCHAN_TCMDSTA_DE | PAS_DMA_TXCHAN_TCMDSTA_DA)) 13639e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson printk(KERN_DEBUG "pasemi_mac: tcmdsta error: 0x%08x\n", sta); 13649e81d331f2ec65695e4366ce592e14f9700bae8bOlof Johansson 1365f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* Clean out any pending buffers */ 136672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_clean_tx(tx_ring(mac)); 136772b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE); 1368f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1369ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_pause_txchan(mac); 1370ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_pause_rxint(mac); 1371ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_pause_rxchan(mac); 13721145d954a51df9362d7eaa2c68405fc226418f34Olof Johansson pasemi_mac_intf_disable(mac); 1373f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 137434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson free_irq(mac->tx->chan.irq, mac->tx); 137534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson free_irq(mac->rx->chan.irq, mac->rx); 1376f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 13771724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson for (i = 0; i < mac->num_cs; i++) { 13788d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_mac_free_csring(mac->cs[i]); 13791724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson mac->cs[i] = NULL; 13801724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson } 13811724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson 13821724ac2ef1caf5b4f764d4b86a85d552a7d7c8fbOlof Johansson mac->num_cs = 0; 13838d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 1384f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* Free resources */ 138572b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_free_rx_resources(mac); 138672b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_free_tx_resources(mac); 1387f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1388f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return 0; 1389f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1390f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 13918d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonstatic void pasemi_mac_queue_csdesc(const struct sk_buff *skb, 13928d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson const dma_addr_t *map, 13938d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson const unsigned int *map_size, 13948d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson struct pasemi_mac_txring *txring, 13958d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson struct pasemi_mac_csring *csring) 13968d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson{ 13978d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson u64 fund; 13988d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dma_addr_t cs_dest; 13998d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson const int nh_off = skb_network_offset(skb); 14008d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson const int nh_len = skb_network_header_len(skb); 14018d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson const int nfrags = skb_shinfo(skb)->nr_frags; 14028d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson int cs_size, i, fill, hdr, cpyhdr, evt; 14038d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dma_addr_t csdma; 14048d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14058d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fund = XCT_FUN_ST | XCT_FUN_RR_8BRES | 14068d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson XCT_FUN_O | XCT_FUN_FUN(csring->fun) | 14078d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson XCT_FUN_CRM_SIG | XCT_FUN_LLEN(skb->len - nh_off) | 14088d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson XCT_FUN_SHL(nh_len >> 2) | XCT_FUN_SE; 14098d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14108d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson switch (ip_hdr(skb)->protocol) { 14118d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson case IPPROTO_TCP: 14128d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fund |= XCT_FUN_SIG_TCP4; 14138d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* TCP checksum is 16 bytes into the header */ 14148d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson cs_dest = map[0] + skb_transport_offset(skb) + 16; 14158d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson break; 14168d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson case IPPROTO_UDP: 14178d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fund |= XCT_FUN_SIG_UDP4; 14188d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* UDP checksum is 6 bytes into the header */ 14198d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson cs_dest = map[0] + skb_transport_offset(skb) + 6; 14208d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson break; 14218d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson default: 14228d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson BUG(); 14238d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 14248d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14258d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* Do the checksum offloaded */ 14268d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fill = csring->next_to_fill; 14278d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson hdr = fill; 14288d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14298d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = fund; 14308d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* Room for 8BRES. Checksum result is really 2 bytes into it */ 14318d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson csdma = csring->chan.ring_dma + (fill & (CS_RING_SIZE-1)) * 8 + 2; 14328d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = 0; 14338d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14348d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill) = XCT_PTR_LEN(map_size[0]-nh_off) | XCT_PTR_ADDR(map[0]+nh_off); 14358d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson for (i = 1; i <= nfrags; i++) 14368d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill+i) = XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]); 14378d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14388d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fill += i; 14398d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (fill & 1) 14408d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fill++; 14418d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14428d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* Copy the result into the TCP packet */ 14438d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson cpyhdr = fill; 14448d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) | 14458d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson XCT_FUN_LLEN(2) | XCT_FUN_SE; 14468d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T; 14478d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(csdma); 14488d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fill++; 14498d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14508d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson evt = !csring->last_event; 14518d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson csring->last_event = evt; 14528d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14538d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* Event handshaking with MAC TX */ 14548d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O | 14558d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CTRL_CMD_ETYPE_SET | CTRL_CMD_REG(csring->events[evt]); 14568d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = 0; 14578d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O | 14588d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CTRL_CMD_ETYPE_WCLR | CTRL_CMD_REG(csring->events[!evt]); 14598d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CS_DESC(csring, fill++) = 0; 14608d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson csring->next_to_fill = fill & (CS_RING_SIZE-1); 14618d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14628d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson cs_size = fill - hdr; 14638d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1); 14648d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14658d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* TX-side event handshaking */ 14668d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fill = txring->next_to_fill; 14678d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O | 14688d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CTRL_CMD_ETYPE_WSET | CTRL_CMD_REG(csring->events[evt]); 14698d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson TX_DESC(txring, fill++) = 0; 14708d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O | 14718d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson CTRL_CMD_ETYPE_CLR | CTRL_CMD_REG(csring->events[!evt]); 14728d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson TX_DESC(txring, fill++) = 0; 14738d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson txring->next_to_fill = fill; 14748d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 14758d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2); 14768d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson} 14778d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 1478f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) 1479f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 14808d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson struct pasemi_mac * const mac = netdev_priv(dev); 14818d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson struct pasemi_mac_txring * const txring = tx_ring(mac); 14828d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson struct pasemi_mac_csring *csring; 14838d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson u64 dflags = 0; 14848d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson u64 mactx; 1485ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson dma_addr_t map[MAX_SKB_FRAGS+1]; 1486ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson unsigned int map_size[MAX_SKB_FRAGS+1]; 1487ca7e235f5eb960d83b45cef4384b490672538cd9Olof Johansson unsigned long flags; 1488ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson int i, nfrags; 14895c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson int fill; 14908d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson const int nh_off = skb_network_offset(skb); 14918d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson const int nh_len = skb_network_header_len(skb); 1492f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 14938d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson prefetch(&txring->ring_info); 1494d56f90a7c96da5187f0cdf07ee7434fe6aa78bbcArnaldo Carvalho de Melo 14958d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD; 1496f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1497ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson nfrags = skb_shinfo(skb)->nr_frags; 1498ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 1499ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson map[0] = pci_map_single(mac->dma_pdev, skb->data, skb_headlen(skb), 1500ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson PCI_DMA_TODEVICE); 1501ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson map_size[0] = skb_headlen(skb); 15028d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori if (pci_dma_mapping_error(mac->dma_pdev, map[0])) 1503ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson goto out_err_nolock; 1504ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 1505ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson for (i = 0; i < nfrags; i++) { 1506ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 1507f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 15084bb97cae662ea6e2a5aa5982d0b289a8c48d64c6Ian Campbell map[i + 1] = skb_frag_dma_map(&mac->dma_pdev->dev, frag, 0, 15099e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet skb_frag_size(frag), DMA_TO_DEVICE); 15109e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet map_size[i+1] = skb_frag_size(frag); 15115d6bcdfe38ce883946aebf751a64695471ce1ab5Ian Campbell if (dma_mapping_error(&mac->dma_pdev->dev, map[i + 1])) { 1512ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson nfrags = i; 1513ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson goto out_err_nolock; 1514ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson } 1515ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson } 1516f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 15178d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (skb->ip_summed == CHECKSUM_PARTIAL && skb->len <= 1540) { 15188d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson switch (ip_hdr(skb)->protocol) { 15198d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson case IPPROTO_TCP: 15208d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dflags |= XCT_MACTX_CSUM_TCP; 15218d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dflags |= XCT_MACTX_IPH(nh_len >> 2); 15228d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dflags |= XCT_MACTX_IPO(nh_off); 15238d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson break; 15248d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson case IPPROTO_UDP: 15258d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dflags |= XCT_MACTX_CSUM_UDP; 15268d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dflags |= XCT_MACTX_IPH(nh_len >> 2); 15278d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson dflags |= XCT_MACTX_IPO(nh_off); 15288d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson break; 15298d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson default: 15308d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson WARN_ON(1); 15318d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 15328d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 153326fcfa95aef980cab4ff1ea55979c30e772dd0ddOlof Johansson 15348d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson mactx = dflags | XCT_MACTX_LLEN(skb->len); 1535f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1536f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson spin_lock_irqsave(&txring->lock, flags); 1537f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1538ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson /* Avoid stepping on the same cache line that the DMA controller 1539ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson * is currently about to send, so leave at least 8 words available. 1540ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson * Total free space needed is mactx + fragments + 8 1541ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson */ 15428d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (RING_AVAIL(txring) < nfrags + 14) { 1543ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson /* no room -- stop the queue and wait for tx intr */ 1544ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson netif_stop_queue(dev); 1545ad5da10a64bdca1ed39b25946727a1ce2659f3d4Olof Johansson goto out_err; 1546f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 1547f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 15488d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* Queue up checksum + event descriptors, if needed */ 15498d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (mac->num_cs && skb->ip_summed == CHECKSUM_PARTIAL && skb->len > 1540) { 15508d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson csring = mac->cs[mac->last_cs]; 15518d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson mac->last_cs = (mac->last_cs + 1) % mac->num_cs; 15528d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 15538d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_mac_queue_csdesc(skb, map, map_size, txring, csring); 15548d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 15558d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 15568d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson fill = txring->next_to_fill; 15575c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson TX_DESC(txring, fill) = mactx; 15587e9916e9ddf23cd08107ed1a7fac429eea619313Olof Johansson TX_DESC_INFO(txring, fill).dma = nfrags; 15595c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson fill++; 15605c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson TX_DESC_INFO(txring, fill).skb = skb; 1561ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson for (i = 0; i <= nfrags; i++) { 15625c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson TX_DESC(txring, fill+i) = 156372b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]); 15645c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson TX_DESC_INFO(txring, fill+i).dma = map[i]; 1565ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson } 1566ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 1567ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson /* We have to add an even number of 8-byte entries to the ring 1568ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson * even if the last one is unused. That means always an odd number 1569ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson * of pointers + one mactx descriptor. 1570ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson */ 1571ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson if (nfrags & 1) 1572ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson nfrags++; 1573fc9e4d2a93dab4a995e2e75725577b9a60154cbcOlof Johansson 15745c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson txring->next_to_fill = (fill + nfrags + 1) & (TX_RING_SIZE-1); 1575f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 157609f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_packets++; 157709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_bytes += skb->len; 1578f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1579f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson spin_unlock_irqrestore(&txring->lock, flags); 1580f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 158134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), (nfrags+2) >> 1); 1582f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1583f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return NETDEV_TX_OK; 1584f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1585f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonout_err: 1586f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson spin_unlock_irqrestore(&txring->lock, flags); 1587ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johanssonout_err_nolock: 1588ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson while (nfrags--) 1589ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson pci_unmap_single(mac->dma_pdev, map[nfrags], map_size[nfrags], 1590ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson PCI_DMA_TODEVICE); 1591ad3c20d1ab586884f1815c315e3f303a8b8a7d7dOlof Johansson 1592f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return NETDEV_TX_BUSY; 1593f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1594f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1595f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic void pasemi_mac_set_rx_mode(struct net_device *dev) 1596f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 15975c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson const struct pasemi_mac *mac = netdev_priv(dev); 1598f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson unsigned int flags; 1599f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1600a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG); 1601f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1602f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* Set promiscuous */ 1603f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (dev->flags & IFF_PROMISC) 1604f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson flags |= PAS_MAC_CFG_PCFG_PR; 1605f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson else 1606f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson flags &= ~PAS_MAC_CFG_PCFG_PR; 1607f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1608a85b94222d8b95e184941183f28b06b637cc4deeOlof Johansson write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags); 1609f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1610f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1611f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1612bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int pasemi_mac_poll(struct napi_struct *napi, int budget) 1613f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 1614bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger struct pasemi_mac *mac = container_of(napi, struct pasemi_mac, napi); 1615bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger int pkts; 1616f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 161772b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pasemi_mac_clean_tx(tx_ring(mac)); 161872b05b9940f00fbfd71a1cb8ea80eb2cc1f90255Olof Johansson pkts = pasemi_mac_clean_rx(rx_ring(mac), budget); 1619bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger if (pkts < budget) { 1620f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson /* all done, no more packets present */ 1621288379f050284087578b77e04f040b57db3db3f8Ben Hutchings napi_complete(napi); 1622f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 16231b0335ea30bf85eecffd21be64b7653407d6259aOlof Johansson pasemi_mac_restart_rx_intr(mac); 162461cec3bddc79373a246e2f8eb13e5acdc106f46aOlof Johansson pasemi_mac_restart_tx_intr(mac); 1625f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 1626bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger return pkts; 1627f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1628f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 16296e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case#ifdef CONFIG_NET_POLL_CONTROLLER 16306e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case/* 16316e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case * Polling 'interrupt' - used by things like netconsole to send skbs 16326e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case * without having to re-enable interrupts. It's not called while 16336e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case * the interrupt routine is executing. 16346e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case */ 16356e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Casestatic void pasemi_mac_netpoll(struct net_device *dev) 16366e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case{ 16376e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case const struct pasemi_mac *mac = netdev_priv(dev); 16386e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case 16396e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case disable_irq(mac->tx->chan.irq); 16406e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case pasemi_mac_tx_intr(mac->tx->chan.irq, mac->tx); 16416e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case enable_irq(mac->tx->chan.irq); 16426e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case 16436e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case disable_irq(mac->rx->chan.irq); 16446e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case pasemi_mac_rx_intr(mac->rx->chan.irq, mac->rx); 16456e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case enable_irq(mac->rx->chan.irq); 16466e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case} 16476e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case#endif 16486e62040c5533a385b90fcb2e33235ad7d351d3e0Nate Case 1649ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johanssonstatic int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu) 1650ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson{ 1651ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson struct pasemi_mac *mac = netdev_priv(dev); 1652ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson unsigned int reg; 16538d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson unsigned int rcmdsta = 0; 1654ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson int running; 16558d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson int ret = 0; 1656ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1657ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU) 1658ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson return -EINVAL; 1659ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1660ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson running = netif_running(dev); 1661ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1662ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (running) { 1663ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson /* Need to stop the interface, clean out all already 1664ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson * received buffers, free all unused buffers on the RX 1665ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson * interface ring, then finally re-fill the rx ring with 1666ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson * the new-size buffers and restart. 1667ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson */ 1668ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1669ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson napi_disable(&mac->napi); 1670ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson netif_tx_disable(dev); 1671ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_intf_disable(mac); 1672ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1673ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if)); 1674ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_pause_rxint(mac); 1675ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE); 1676ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_free_rx_buffers(mac); 16778d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 16788d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 16798d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson 16808d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson /* Setup checksum channels if large MTU and none already allocated */ 16818d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (new_mtu > 1500 && !mac->num_cs) { 16828d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson pasemi_mac_setup_csrings(mac); 16838d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson if (!mac->num_cs) { 16848d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson ret = -ENOMEM; 16858d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson goto out; 16868d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson } 1687ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson } 1688ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1689ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson /* Change maxf, i.e. what size frames are accepted. 1690ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson * Need room for ethernet header and CRC word 1691ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson */ 1692ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson reg = read_mac_reg(mac, PAS_MAC_CFG_MACCFG); 1693ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson reg &= ~PAS_MAC_CFG_MACCFG_MAXF_M; 1694ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson reg |= PAS_MAC_CFG_MACCFG_MAXF(new_mtu + ETH_HLEN + 4); 1695ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_mac_reg(mac, PAS_MAC_CFG_MACCFG, reg); 1696ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1697ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson dev->mtu = new_mtu; 1698ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ 1699ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; 1700ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 17018d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johanssonout: 1702ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson if (running) { 1703ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 1704ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN); 1705ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1706ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson rx_ring(mac)->next_to_fill = 0; 1707ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE-1); 1708ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1709ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson napi_enable(&mac->napi); 1710ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson netif_start_queue(dev); 1711ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson pasemi_mac_intf_enable(mac); 1712ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson } 1713ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 17148d636d8bc5ffcdbf49c72aafcda9ddab7ccb2f41Olof Johansson return ret; 1715ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson} 1716ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 17179e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalovstatic const struct net_device_ops pasemi_netdev_ops = { 17189e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov .ndo_open = pasemi_mac_open, 17199e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov .ndo_stop = pasemi_mac_close, 17209e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov .ndo_start_xmit = pasemi_mac_start_tx, 1721afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = pasemi_mac_set_rx_mode, 17229e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov .ndo_set_mac_address = pasemi_mac_set_mac_addr, 17239e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov .ndo_change_mtu = pasemi_mac_change_mtu, 17249e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov .ndo_validate_addr = eth_validate_addr, 17259e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov#ifdef CONFIG_NET_POLL_CONTROLLER 17269e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov .ndo_poll_controller = pasemi_mac_netpoll, 17279e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov#endif 17289e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov}; 17299e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov 1730f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic int __devinit 1731f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonpasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 1732f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 1733f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct net_device *dev; 1734f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac *mac; 173515b8e19131486856373592e45793a79aefb6fbe7roel kluin int err, ret; 1736f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1737f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson err = pci_enable_device(pdev); 1738f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (err) 1739f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return err; 1740f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1741f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev = alloc_etherdev(sizeof(struct pasemi_mac)); 1742f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (dev == NULL) { 1743f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson err = -ENOMEM; 1744f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson goto out_disable_device; 1745f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 1746f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1747f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson pci_set_drvdata(pdev, dev); 1748f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson SET_NETDEV_DEV(dev, &pdev->dev); 1749f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1750f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson mac = netdev_priv(dev); 1751f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1752f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson mac->pdev = pdev; 1753f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson mac->netdev = dev; 1754f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1755bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64); 1756bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger 17575c15332bed4c59fff6423f08ef6bd6894af38a99Olof Johansson dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG | 1758251567848f2f446f4356f969329a8188faf1fe90Olof Johansson NETIF_F_HIGHDMA | NETIF_F_GSO; 1759bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger 176028ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson mac->lro_mgr.max_aggr = LRO_MAX_AGGR; 176128ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; 176228ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson mac->lro_mgr.lro_arr = mac->lro_desc; 176328ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson mac->lro_mgr.get_skb_header = get_skb_hdr; 176428ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson mac->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; 176528ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson mac->lro_mgr.dev = mac->netdev; 176628ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson mac->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; 176728ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson mac->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; 176828ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 176928ae79f531014bb3ad95b6efa0e0603069087bc5Olof Johansson 177034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL); 177134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (!mac->dma_pdev) { 177234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson dev_err(&mac->pdev->dev, "Can't find DMA Controller\n"); 177334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson err = -ENODEV; 177434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson goto out; 177534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson } 1776f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 177734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL); 177834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (!mac->iob_pdev) { 177934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson dev_err(&mac->pdev->dev, "Can't find I/O Bridge\n"); 178034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson err = -ENODEV; 178134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson goto out; 178234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson } 178334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 178434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson /* get mac addr from device tree */ 178534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (pasemi_get_mac_addr(mac) || !is_valid_ether_addr(mac->mac_addr)) { 178634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson err = -ENODEV; 178734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson goto out; 178834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson } 178934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr)); 179034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 179115b8e19131486856373592e45793a79aefb6fbe7roel kluin ret = mac_to_intf(mac); 179215b8e19131486856373592e45793a79aefb6fbe7roel kluin if (ret < 0) { 179334c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson dev_err(&mac->pdev->dev, "Can't map DMA interface\n"); 179434c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson err = -ENODEV; 179534c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson goto out; 179634c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson } 179715b8e19131486856373592e45793a79aefb6fbe7roel kluin mac->dma_if = ret; 1798f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1799f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson switch (pdev->device) { 1800f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson case 0xa005: 1801f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson mac->type = MAC_TYPE_GMAC; 1802f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson break; 1803f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson case 0xa006: 1804f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson mac->type = MAC_TYPE_XAUI; 1805f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson break; 1806f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson default: 1807f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson err = -ENODEV; 1808f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson goto out; 1809f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson } 1810f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 18119e0ac841f42df4e7acdab7dc1620de0933ed56d7Alexander Beregalov dev->netdev_ops = &pasemi_netdev_ops; 1812ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson dev->mtu = PE_DEF_MTU; 1813ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ 1814ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; 1815ef1ea0b424d09452b27f5cb1a0c108b645cb25e0Olof Johansson 1816e37c772e36a7943b2e0bd8f48312e78474c0df15Olof Johansson dev->ethtool_ops = &pasemi_mac_ethtool_ops; 1817f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1818b6e05a1b67a4b2e122d78a3f0b7ec7c779bd903cOlof Johansson if (err) 1819b6e05a1b67a4b2e122d78a3f0b7ec7c779bd903cOlof Johansson goto out; 1820f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1821ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson mac->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); 1822ceb51361370c003e13f782edb7171a8383e5c849Olof Johansson 1823bb6e9590792834f905a92e439a083254649c985cOlof Johansson /* Enable most messages by default */ 1824bb6e9590792834f905a92e439a083254649c985cOlof Johansson mac->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; 1825bb6e9590792834f905a92e439a083254649c985cOlof Johansson 1826f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson err = register_netdev(dev); 1827f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1828f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (err) { 1829f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev_err(&mac->pdev->dev, "register_netdev failed with error %d\n", 1830f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson err); 1831f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson goto out; 183269c29d89185dc1de7224f5f98588ddc061f1fad2Olof Johansson } else if netif_msg_probe(mac) 1833e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk(KERN_INFO "%s: PA Semi %s: intf %d, hw addr %pM\n", 1834f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI", 1835e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg mac->dma_if, dev->dev_addr); 1836f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1837f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return err; 1838f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1839f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonout: 1840b6e05a1b67a4b2e122d78a3f0b7ec7c779bd903cOlof Johansson if (mac->iob_pdev) 1841b6e05a1b67a4b2e122d78a3f0b7ec7c779bd903cOlof Johansson pci_dev_put(mac->iob_pdev); 1842b6e05a1b67a4b2e122d78a3f0b7ec7c779bd903cOlof Johansson if (mac->dma_pdev) 1843b6e05a1b67a4b2e122d78a3f0b7ec7c779bd903cOlof Johansson pci_dev_put(mac->dma_pdev); 1844b6e05a1b67a4b2e122d78a3f0b7ec7c779bd903cOlof Johansson 1845f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson free_netdev(dev); 1846f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonout_disable_device: 1847f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson pci_disable_device(pdev); 1848f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return err; 1849f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1850f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1851f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1852f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic void __devexit pasemi_mac_remove(struct pci_dev *pdev) 1853f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 1854f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct net_device *netdev = pci_get_drvdata(pdev); 1855f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson struct pasemi_mac *mac; 1856f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1857f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson if (!netdev) 1858f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return; 1859f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1860f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson mac = netdev_priv(netdev); 1861f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1862f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson unregister_netdev(netdev); 1863f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1864f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson pci_disable_device(pdev); 1865f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson pci_dev_put(mac->dma_pdev); 1866f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson pci_dev_put(mac->iob_pdev); 1867f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 186834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_dma_free_chan(&mac->tx->chan); 186934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson pasemi_dma_free_chan(&mac->rx->chan); 1870b6e05a1b67a4b2e122d78a3f0b7ec7c779bd903cOlof Johansson 1871f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson pci_set_drvdata(pdev, NULL); 1872f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson free_netdev(netdev); 1873f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1874f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1875a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(pasemi_mac_pci_tbl) = { 1876f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) }, 1877f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) }, 1878fd17825480b2de3076727c677f8e257623705963olof@lixom.net { }, 1879f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson}; 1880f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1881f5cd7872768d5856b1b409a33f516e5ac7798f75Olof JohanssonMODULE_DEVICE_TABLE(pci, pasemi_mac_pci_tbl); 1882f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1883f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic struct pci_driver pasemi_mac_driver = { 1884f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson .name = "pasemi_mac", 1885f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson .id_table = pasemi_mac_pci_tbl, 1886f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson .probe = pasemi_mac_probe, 1887f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson .remove = __devexit_p(pasemi_mac_remove), 1888f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson}; 1889f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1890f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonstatic void __exit pasemi_mac_cleanup_module(void) 1891f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 1892f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson pci_unregister_driver(&pasemi_mac_driver); 1893f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1894f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1895f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonint pasemi_mac_init_module(void) 1896f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson{ 189734c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson int err; 189834c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 189934c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson err = pasemi_dma_init(); 190034c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson if (err) 190134c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson return err; 190234c20624ce541f8a7ff937f474af51f9044cedd7Olof Johansson 1903f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson return pci_register_driver(&pasemi_mac_driver); 1904f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson} 1905f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johansson 1906f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonmodule_init(pasemi_mac_init_module); 1907f5cd7872768d5856b1b409a33f516e5ac7798f75Olof Johanssonmodule_exit(pasemi_mac_cleanup_module); 1908