1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29aa32835SJeff Kirsher /* 33396c782SPaul Gortmaker * drivers/net/ethernet/ibm/emac/mal.c 49aa32835SJeff Kirsher * 59aa32835SJeff Kirsher * Memory Access Layer (MAL) support 69aa32835SJeff Kirsher * 79aa32835SJeff Kirsher * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. 89aa32835SJeff Kirsher * <benh@kernel.crashing.org> 99aa32835SJeff Kirsher * 109aa32835SJeff Kirsher * Based on the arch/ppc version of the driver: 119aa32835SJeff Kirsher * 129aa32835SJeff Kirsher * Copyright (c) 2004, 2005 Zultys Technologies. 139aa32835SJeff Kirsher * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> 149aa32835SJeff Kirsher * 159aa32835SJeff Kirsher * Based on original work by 169aa32835SJeff Kirsher * Benjamin Herrenschmidt <benh@kernel.crashing.org>, 179aa32835SJeff Kirsher * David Gibson <hermes@gibson.dropbear.id.au>, 189aa32835SJeff Kirsher * 199aa32835SJeff Kirsher * Armin Kuster <akuster@mvista.com> 209aa32835SJeff Kirsher * Copyright 2002 MontaVista Softare Inc. 219aa32835SJeff Kirsher */ 229aa32835SJeff Kirsher 239aa32835SJeff Kirsher #include <linux/delay.h> 249aa32835SJeff Kirsher #include <linux/slab.h> 255af50730SRob Herring #include <linux/of_irq.h> 269aa32835SJeff Kirsher 279aa32835SJeff Kirsher #include "core.h" 289aa32835SJeff Kirsher #include <asm/dcr-regs.h> 299aa32835SJeff Kirsher 309aa32835SJeff Kirsher static int mal_count; 319aa32835SJeff Kirsher 321dd06ae8SGreg Kroah-Hartman int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac) 339aa32835SJeff Kirsher { 349aa32835SJeff Kirsher unsigned long flags; 359aa32835SJeff Kirsher 369aa32835SJeff Kirsher spin_lock_irqsave(&mal->lock, flags); 379aa32835SJeff Kirsher 389aa32835SJeff Kirsher MAL_DBG(mal, "reg(%08x, %08x)" NL, 399aa32835SJeff Kirsher commac->tx_chan_mask, commac->rx_chan_mask); 409aa32835SJeff Kirsher 419aa32835SJeff Kirsher /* Don't let multiple commacs claim the same channel(s) */ 429aa32835SJeff Kirsher if ((mal->tx_chan_mask & commac->tx_chan_mask) || 439aa32835SJeff Kirsher (mal->rx_chan_mask & commac->rx_chan_mask)) { 449aa32835SJeff Kirsher spin_unlock_irqrestore(&mal->lock, flags); 459aa32835SJeff Kirsher printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n", 469aa32835SJeff Kirsher mal->index); 479aa32835SJeff Kirsher return -EBUSY; 489aa32835SJeff Kirsher } 499aa32835SJeff Kirsher 509aa32835SJeff Kirsher if (list_empty(&mal->list)) 519aa32835SJeff Kirsher napi_enable(&mal->napi); 529aa32835SJeff Kirsher mal->tx_chan_mask |= commac->tx_chan_mask; 539aa32835SJeff Kirsher mal->rx_chan_mask |= commac->rx_chan_mask; 549aa32835SJeff Kirsher list_add(&commac->list, &mal->list); 559aa32835SJeff Kirsher 569aa32835SJeff Kirsher spin_unlock_irqrestore(&mal->lock, flags); 579aa32835SJeff Kirsher 589aa32835SJeff Kirsher return 0; 599aa32835SJeff Kirsher } 609aa32835SJeff Kirsher 619aa32835SJeff Kirsher void mal_unregister_commac(struct mal_instance *mal, 629aa32835SJeff Kirsher struct mal_commac *commac) 639aa32835SJeff Kirsher { 649aa32835SJeff Kirsher unsigned long flags; 659aa32835SJeff Kirsher 669aa32835SJeff Kirsher spin_lock_irqsave(&mal->lock, flags); 679aa32835SJeff Kirsher 689aa32835SJeff Kirsher MAL_DBG(mal, "unreg(%08x, %08x)" NL, 699aa32835SJeff Kirsher commac->tx_chan_mask, commac->rx_chan_mask); 709aa32835SJeff Kirsher 719aa32835SJeff Kirsher mal->tx_chan_mask &= ~commac->tx_chan_mask; 729aa32835SJeff Kirsher mal->rx_chan_mask &= ~commac->rx_chan_mask; 739aa32835SJeff Kirsher list_del_init(&commac->list); 749aa32835SJeff Kirsher if (list_empty(&mal->list)) 759aa32835SJeff Kirsher napi_disable(&mal->napi); 769aa32835SJeff Kirsher 779aa32835SJeff Kirsher spin_unlock_irqrestore(&mal->lock, flags); 789aa32835SJeff Kirsher } 799aa32835SJeff Kirsher 809aa32835SJeff Kirsher int mal_set_rcbs(struct mal_instance *mal, int channel, unsigned long size) 819aa32835SJeff Kirsher { 829aa32835SJeff Kirsher BUG_ON(channel < 0 || channel >= mal->num_rx_chans || 839aa32835SJeff Kirsher size > MAL_MAX_RX_SIZE); 849aa32835SJeff Kirsher 859aa32835SJeff Kirsher MAL_DBG(mal, "set_rbcs(%d, %lu)" NL, channel, size); 869aa32835SJeff Kirsher 879aa32835SJeff Kirsher if (size & 0xf) { 889aa32835SJeff Kirsher printk(KERN_WARNING 899aa32835SJeff Kirsher "mal%d: incorrect RX size %lu for the channel %d\n", 909aa32835SJeff Kirsher mal->index, size, channel); 919aa32835SJeff Kirsher return -EINVAL; 929aa32835SJeff Kirsher } 939aa32835SJeff Kirsher 949aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_RCBS(channel), size >> 4); 959aa32835SJeff Kirsher return 0; 969aa32835SJeff Kirsher } 979aa32835SJeff Kirsher 989aa32835SJeff Kirsher int mal_tx_bd_offset(struct mal_instance *mal, int channel) 999aa32835SJeff Kirsher { 1009aa32835SJeff Kirsher BUG_ON(channel < 0 || channel >= mal->num_tx_chans); 1019aa32835SJeff Kirsher 1029aa32835SJeff Kirsher return channel * NUM_TX_BUFF; 1039aa32835SJeff Kirsher } 1049aa32835SJeff Kirsher 1059aa32835SJeff Kirsher int mal_rx_bd_offset(struct mal_instance *mal, int channel) 1069aa32835SJeff Kirsher { 1079aa32835SJeff Kirsher BUG_ON(channel < 0 || channel >= mal->num_rx_chans); 1089aa32835SJeff Kirsher return mal->num_tx_chans * NUM_TX_BUFF + channel * NUM_RX_BUFF; 1099aa32835SJeff Kirsher } 1109aa32835SJeff Kirsher 1119aa32835SJeff Kirsher void mal_enable_tx_channel(struct mal_instance *mal, int channel) 1129aa32835SJeff Kirsher { 1139aa32835SJeff Kirsher unsigned long flags; 1149aa32835SJeff Kirsher 1159aa32835SJeff Kirsher spin_lock_irqsave(&mal->lock, flags); 1169aa32835SJeff Kirsher 1179aa32835SJeff Kirsher MAL_DBG(mal, "enable_tx(%d)" NL, channel); 1189aa32835SJeff Kirsher 1199aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_TXCASR, 1209aa32835SJeff Kirsher get_mal_dcrn(mal, MAL_TXCASR) | MAL_CHAN_MASK(channel)); 1219aa32835SJeff Kirsher 1229aa32835SJeff Kirsher spin_unlock_irqrestore(&mal->lock, flags); 1239aa32835SJeff Kirsher } 1249aa32835SJeff Kirsher 1259aa32835SJeff Kirsher void mal_disable_tx_channel(struct mal_instance *mal, int channel) 1269aa32835SJeff Kirsher { 1279aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_TXCARR, MAL_CHAN_MASK(channel)); 1289aa32835SJeff Kirsher 1299aa32835SJeff Kirsher MAL_DBG(mal, "disable_tx(%d)" NL, channel); 1309aa32835SJeff Kirsher } 1319aa32835SJeff Kirsher 1329aa32835SJeff Kirsher void mal_enable_rx_channel(struct mal_instance *mal, int channel) 1339aa32835SJeff Kirsher { 1349aa32835SJeff Kirsher unsigned long flags; 1359aa32835SJeff Kirsher 1369aa32835SJeff Kirsher /* 1379aa32835SJeff Kirsher * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple 1389aa32835SJeff Kirsher * of 8, but enabling in MAL_RXCASR needs the divided by 8 value 1399aa32835SJeff Kirsher * for the bitmask 1409aa32835SJeff Kirsher */ 1419aa32835SJeff Kirsher if (!(channel % 8)) 1429aa32835SJeff Kirsher channel >>= 3; 1439aa32835SJeff Kirsher 1449aa32835SJeff Kirsher spin_lock_irqsave(&mal->lock, flags); 1459aa32835SJeff Kirsher 1469aa32835SJeff Kirsher MAL_DBG(mal, "enable_rx(%d)" NL, channel); 1479aa32835SJeff Kirsher 1489aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_RXCASR, 1499aa32835SJeff Kirsher get_mal_dcrn(mal, MAL_RXCASR) | MAL_CHAN_MASK(channel)); 1509aa32835SJeff Kirsher 1519aa32835SJeff Kirsher spin_unlock_irqrestore(&mal->lock, flags); 1529aa32835SJeff Kirsher } 1539aa32835SJeff Kirsher 1549aa32835SJeff Kirsher void mal_disable_rx_channel(struct mal_instance *mal, int channel) 1559aa32835SJeff Kirsher { 1569aa32835SJeff Kirsher /* 1579aa32835SJeff Kirsher * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple 1589aa32835SJeff Kirsher * of 8, but enabling in MAL_RXCASR needs the divided by 8 value 1599aa32835SJeff Kirsher * for the bitmask 1609aa32835SJeff Kirsher */ 1619aa32835SJeff Kirsher if (!(channel % 8)) 1629aa32835SJeff Kirsher channel >>= 3; 1639aa32835SJeff Kirsher 1649aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel)); 1659aa32835SJeff Kirsher 1669aa32835SJeff Kirsher MAL_DBG(mal, "disable_rx(%d)" NL, channel); 1679aa32835SJeff Kirsher } 1689aa32835SJeff Kirsher 1699aa32835SJeff Kirsher void mal_poll_add(struct mal_instance *mal, struct mal_commac *commac) 1709aa32835SJeff Kirsher { 1719aa32835SJeff Kirsher unsigned long flags; 1729aa32835SJeff Kirsher 1739aa32835SJeff Kirsher spin_lock_irqsave(&mal->lock, flags); 1749aa32835SJeff Kirsher 1759aa32835SJeff Kirsher MAL_DBG(mal, "poll_add(%p)" NL, commac); 1769aa32835SJeff Kirsher 1779aa32835SJeff Kirsher /* starts disabled */ 1789aa32835SJeff Kirsher set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags); 1799aa32835SJeff Kirsher 1809aa32835SJeff Kirsher list_add_tail(&commac->poll_list, &mal->poll_list); 1819aa32835SJeff Kirsher 1829aa32835SJeff Kirsher spin_unlock_irqrestore(&mal->lock, flags); 1839aa32835SJeff Kirsher } 1849aa32835SJeff Kirsher 1859aa32835SJeff Kirsher void mal_poll_del(struct mal_instance *mal, struct mal_commac *commac) 1869aa32835SJeff Kirsher { 1879aa32835SJeff Kirsher unsigned long flags; 1889aa32835SJeff Kirsher 1899aa32835SJeff Kirsher spin_lock_irqsave(&mal->lock, flags); 1909aa32835SJeff Kirsher 1919aa32835SJeff Kirsher MAL_DBG(mal, "poll_del(%p)" NL, commac); 1929aa32835SJeff Kirsher 1939aa32835SJeff Kirsher list_del(&commac->poll_list); 1949aa32835SJeff Kirsher 1959aa32835SJeff Kirsher spin_unlock_irqrestore(&mal->lock, flags); 1969aa32835SJeff Kirsher } 1979aa32835SJeff Kirsher 1989aa32835SJeff Kirsher /* synchronized by mal_poll() */ 1999aa32835SJeff Kirsher static inline void mal_enable_eob_irq(struct mal_instance *mal) 2009aa32835SJeff Kirsher { 2019aa32835SJeff Kirsher MAL_DBG2(mal, "enable_irq" NL); 2029aa32835SJeff Kirsher 2039aa32835SJeff Kirsher // XXX might want to cache MAL_CFG as the DCR read can be slooooow 2049aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) | MAL_CFG_EOPIE); 2059aa32835SJeff Kirsher } 2069aa32835SJeff Kirsher 2079aa32835SJeff Kirsher /* synchronized by NAPI state */ 2089aa32835SJeff Kirsher static inline void mal_disable_eob_irq(struct mal_instance *mal) 2099aa32835SJeff Kirsher { 2109aa32835SJeff Kirsher // XXX might want to cache MAL_CFG as the DCR read can be slooooow 2119aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) & ~MAL_CFG_EOPIE); 2129aa32835SJeff Kirsher 2139aa32835SJeff Kirsher MAL_DBG2(mal, "disable_irq" NL); 2149aa32835SJeff Kirsher } 2159aa32835SJeff Kirsher 2169aa32835SJeff Kirsher static irqreturn_t mal_serr(int irq, void *dev_instance) 2179aa32835SJeff Kirsher { 2189aa32835SJeff Kirsher struct mal_instance *mal = dev_instance; 2199aa32835SJeff Kirsher 2209aa32835SJeff Kirsher u32 esr = get_mal_dcrn(mal, MAL_ESR); 2219aa32835SJeff Kirsher 2229aa32835SJeff Kirsher /* Clear the error status register */ 2239aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_ESR, esr); 2249aa32835SJeff Kirsher 2259aa32835SJeff Kirsher MAL_DBG(mal, "SERR %08x" NL, esr); 2269aa32835SJeff Kirsher 2279aa32835SJeff Kirsher if (esr & MAL_ESR_EVB) { 2289aa32835SJeff Kirsher if (esr & MAL_ESR_DE) { 2299aa32835SJeff Kirsher /* We ignore Descriptor error, 2309aa32835SJeff Kirsher * TXDE or RXDE interrupt will be generated anyway. 2319aa32835SJeff Kirsher */ 2329aa32835SJeff Kirsher return IRQ_HANDLED; 2339aa32835SJeff Kirsher } 2349aa32835SJeff Kirsher 2359aa32835SJeff Kirsher if (esr & MAL_ESR_PEIN) { 2369aa32835SJeff Kirsher /* PLB error, it's probably buggy hardware or 2379aa32835SJeff Kirsher * incorrect physical address in BD (i.e. bug) 2389aa32835SJeff Kirsher */ 2399aa32835SJeff Kirsher if (net_ratelimit()) 2409aa32835SJeff Kirsher printk(KERN_ERR 2419aa32835SJeff Kirsher "mal%d: system error, " 2429aa32835SJeff Kirsher "PLB (ESR = 0x%08x)\n", 2439aa32835SJeff Kirsher mal->index, esr); 2449aa32835SJeff Kirsher return IRQ_HANDLED; 2459aa32835SJeff Kirsher } 2469aa32835SJeff Kirsher 2479aa32835SJeff Kirsher /* OPB error, it's probably buggy hardware or incorrect 2489aa32835SJeff Kirsher * EBC setup 2499aa32835SJeff Kirsher */ 2509aa32835SJeff Kirsher if (net_ratelimit()) 2519aa32835SJeff Kirsher printk(KERN_ERR 2529aa32835SJeff Kirsher "mal%d: system error, OPB (ESR = 0x%08x)\n", 2539aa32835SJeff Kirsher mal->index, esr); 2549aa32835SJeff Kirsher } 2559aa32835SJeff Kirsher return IRQ_HANDLED; 2569aa32835SJeff Kirsher } 2579aa32835SJeff Kirsher 2589aa32835SJeff Kirsher static inline void mal_schedule_poll(struct mal_instance *mal) 2599aa32835SJeff Kirsher { 2609aa32835SJeff Kirsher if (likely(napi_schedule_prep(&mal->napi))) { 2619aa32835SJeff Kirsher MAL_DBG2(mal, "schedule_poll" NL); 26232663b8bSAlistair Popple spin_lock(&mal->lock); 2639aa32835SJeff Kirsher mal_disable_eob_irq(mal); 26432663b8bSAlistair Popple spin_unlock(&mal->lock); 2659aa32835SJeff Kirsher __napi_schedule(&mal->napi); 2669aa32835SJeff Kirsher } else 2679aa32835SJeff Kirsher MAL_DBG2(mal, "already in poll" NL); 2689aa32835SJeff Kirsher } 2699aa32835SJeff Kirsher 2709aa32835SJeff Kirsher static irqreturn_t mal_txeob(int irq, void *dev_instance) 2719aa32835SJeff Kirsher { 2729aa32835SJeff Kirsher struct mal_instance *mal = dev_instance; 2739aa32835SJeff Kirsher 2749aa32835SJeff Kirsher u32 r = get_mal_dcrn(mal, MAL_TXEOBISR); 2759aa32835SJeff Kirsher 2769aa32835SJeff Kirsher MAL_DBG2(mal, "txeob %08x" NL, r); 2779aa32835SJeff Kirsher 2789aa32835SJeff Kirsher mal_schedule_poll(mal); 2799aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_TXEOBISR, r); 2809aa32835SJeff Kirsher 2819aa32835SJeff Kirsher #ifdef CONFIG_PPC_DCR_NATIVE 2829aa32835SJeff Kirsher if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT)) 2839aa32835SJeff Kirsher mtdcri(SDR0, DCRN_SDR_ICINTSTAT, 2849aa32835SJeff Kirsher (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX)); 2859aa32835SJeff Kirsher #endif 2869aa32835SJeff Kirsher 2879aa32835SJeff Kirsher return IRQ_HANDLED; 2889aa32835SJeff Kirsher } 2899aa32835SJeff Kirsher 2909aa32835SJeff Kirsher static irqreturn_t mal_rxeob(int irq, void *dev_instance) 2919aa32835SJeff Kirsher { 2929aa32835SJeff Kirsher struct mal_instance *mal = dev_instance; 2939aa32835SJeff Kirsher 2949aa32835SJeff Kirsher u32 r = get_mal_dcrn(mal, MAL_RXEOBISR); 2959aa32835SJeff Kirsher 2969aa32835SJeff Kirsher MAL_DBG2(mal, "rxeob %08x" NL, r); 2979aa32835SJeff Kirsher 2989aa32835SJeff Kirsher mal_schedule_poll(mal); 2999aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_RXEOBISR, r); 3009aa32835SJeff Kirsher 3019aa32835SJeff Kirsher #ifdef CONFIG_PPC_DCR_NATIVE 3029aa32835SJeff Kirsher if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT)) 3039aa32835SJeff Kirsher mtdcri(SDR0, DCRN_SDR_ICINTSTAT, 3049aa32835SJeff Kirsher (mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX)); 3059aa32835SJeff Kirsher #endif 3069aa32835SJeff Kirsher 3079aa32835SJeff Kirsher return IRQ_HANDLED; 3089aa32835SJeff Kirsher } 3099aa32835SJeff Kirsher 3109aa32835SJeff Kirsher static irqreturn_t mal_txde(int irq, void *dev_instance) 3119aa32835SJeff Kirsher { 3129aa32835SJeff Kirsher struct mal_instance *mal = dev_instance; 3139aa32835SJeff Kirsher 3149aa32835SJeff Kirsher u32 deir = get_mal_dcrn(mal, MAL_TXDEIR); 3159aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_TXDEIR, deir); 3169aa32835SJeff Kirsher 3179aa32835SJeff Kirsher MAL_DBG(mal, "txde %08x" NL, deir); 3189aa32835SJeff Kirsher 3199aa32835SJeff Kirsher if (net_ratelimit()) 3209aa32835SJeff Kirsher printk(KERN_ERR 3219aa32835SJeff Kirsher "mal%d: TX descriptor error (TXDEIR = 0x%08x)\n", 3229aa32835SJeff Kirsher mal->index, deir); 3239aa32835SJeff Kirsher 3249aa32835SJeff Kirsher return IRQ_HANDLED; 3259aa32835SJeff Kirsher } 3269aa32835SJeff Kirsher 3279aa32835SJeff Kirsher static irqreturn_t mal_rxde(int irq, void *dev_instance) 3289aa32835SJeff Kirsher { 3299aa32835SJeff Kirsher struct mal_instance *mal = dev_instance; 3309aa32835SJeff Kirsher struct list_head *l; 3319aa32835SJeff Kirsher 3329aa32835SJeff Kirsher u32 deir = get_mal_dcrn(mal, MAL_RXDEIR); 3339aa32835SJeff Kirsher 3349aa32835SJeff Kirsher MAL_DBG(mal, "rxde %08x" NL, deir); 3359aa32835SJeff Kirsher 3369aa32835SJeff Kirsher list_for_each(l, &mal->list) { 3379aa32835SJeff Kirsher struct mal_commac *mc = list_entry(l, struct mal_commac, list); 3389aa32835SJeff Kirsher if (deir & mc->rx_chan_mask) { 3399aa32835SJeff Kirsher set_bit(MAL_COMMAC_RX_STOPPED, &mc->flags); 3409aa32835SJeff Kirsher mc->ops->rxde(mc->dev); 3419aa32835SJeff Kirsher } 3429aa32835SJeff Kirsher } 3439aa32835SJeff Kirsher 3449aa32835SJeff Kirsher mal_schedule_poll(mal); 3459aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_RXDEIR, deir); 3469aa32835SJeff Kirsher 3479aa32835SJeff Kirsher return IRQ_HANDLED; 3489aa32835SJeff Kirsher } 3499aa32835SJeff Kirsher 3509aa32835SJeff Kirsher static irqreturn_t mal_int(int irq, void *dev_instance) 3519aa32835SJeff Kirsher { 3529aa32835SJeff Kirsher struct mal_instance *mal = dev_instance; 3539aa32835SJeff Kirsher u32 esr = get_mal_dcrn(mal, MAL_ESR); 3549aa32835SJeff Kirsher 3559aa32835SJeff Kirsher if (esr & MAL_ESR_EVB) { 3569aa32835SJeff Kirsher /* descriptor error */ 3579aa32835SJeff Kirsher if (esr & MAL_ESR_DE) { 3589aa32835SJeff Kirsher if (esr & MAL_ESR_CIDT) 3599aa32835SJeff Kirsher return mal_rxde(irq, dev_instance); 3609aa32835SJeff Kirsher else 3619aa32835SJeff Kirsher return mal_txde(irq, dev_instance); 3629aa32835SJeff Kirsher } else { /* SERR */ 3639aa32835SJeff Kirsher return mal_serr(irq, dev_instance); 3649aa32835SJeff Kirsher } 3659aa32835SJeff Kirsher } 3669aa32835SJeff Kirsher return IRQ_HANDLED; 3679aa32835SJeff Kirsher } 3689aa32835SJeff Kirsher 3699aa32835SJeff Kirsher void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac) 3709aa32835SJeff Kirsher { 3719aa32835SJeff Kirsher /* Spinlock-type semantics: only one caller disable poll at a time */ 3729aa32835SJeff Kirsher while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags)) 3739aa32835SJeff Kirsher msleep(1); 3749aa32835SJeff Kirsher 3759aa32835SJeff Kirsher /* Synchronize with the MAL NAPI poller */ 3769aa32835SJeff Kirsher napi_synchronize(&mal->napi); 3779aa32835SJeff Kirsher } 3789aa32835SJeff Kirsher 3799aa32835SJeff Kirsher void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac) 3809aa32835SJeff Kirsher { 3819aa32835SJeff Kirsher smp_wmb(); 3829aa32835SJeff Kirsher clear_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags); 3839aa32835SJeff Kirsher 3849aa32835SJeff Kirsher /* Feels better to trigger a poll here to catch up with events that 3859aa32835SJeff Kirsher * may have happened on this channel while disabled. It will most 3869aa32835SJeff Kirsher * probably be delayed until the next interrupt but that's mostly a 3879aa32835SJeff Kirsher * non-issue in the context where this is called. 3889aa32835SJeff Kirsher */ 3899aa32835SJeff Kirsher napi_schedule(&mal->napi); 3909aa32835SJeff Kirsher } 3919aa32835SJeff Kirsher 3929aa32835SJeff Kirsher static int mal_poll(struct napi_struct *napi, int budget) 3939aa32835SJeff Kirsher { 3949aa32835SJeff Kirsher struct mal_instance *mal = container_of(napi, struct mal_instance, napi); 3959aa32835SJeff Kirsher struct list_head *l; 3969aa32835SJeff Kirsher int received = 0; 3979aa32835SJeff Kirsher unsigned long flags; 3989aa32835SJeff Kirsher 3999aa32835SJeff Kirsher MAL_DBG2(mal, "poll(%d)" NL, budget); 400f5595606SChristian Lamparter 4019aa32835SJeff Kirsher /* Process TX skbs */ 4029aa32835SJeff Kirsher list_for_each(l, &mal->poll_list) { 4039aa32835SJeff Kirsher struct mal_commac *mc = 4049aa32835SJeff Kirsher list_entry(l, struct mal_commac, poll_list); 4059aa32835SJeff Kirsher mc->ops->poll_tx(mc->dev); 4069aa32835SJeff Kirsher } 4079aa32835SJeff Kirsher 4089aa32835SJeff Kirsher /* Process RX skbs. 4099aa32835SJeff Kirsher * 4109aa32835SJeff Kirsher * We _might_ need something more smart here to enforce polling 4119aa32835SJeff Kirsher * fairness. 4129aa32835SJeff Kirsher */ 4139aa32835SJeff Kirsher list_for_each(l, &mal->poll_list) { 4149aa32835SJeff Kirsher struct mal_commac *mc = 4159aa32835SJeff Kirsher list_entry(l, struct mal_commac, poll_list); 4169aa32835SJeff Kirsher int n; 4179aa32835SJeff Kirsher if (unlikely(test_bit(MAL_COMMAC_POLL_DISABLED, &mc->flags))) 4189aa32835SJeff Kirsher continue; 4193d1a6333SEric Dumazet n = mc->ops->poll_rx(mc->dev, budget - received); 4209aa32835SJeff Kirsher if (n) { 4219aa32835SJeff Kirsher received += n; 4223d1a6333SEric Dumazet if (received >= budget) 4233d1a6333SEric Dumazet return budget; 4249aa32835SJeff Kirsher } 4259aa32835SJeff Kirsher } 4269aa32835SJeff Kirsher 4273d1a6333SEric Dumazet if (napi_complete_done(napi, received)) { 4289aa32835SJeff Kirsher /* We need to disable IRQs to protect from RXDE IRQ here */ 4299aa32835SJeff Kirsher spin_lock_irqsave(&mal->lock, flags); 4309aa32835SJeff Kirsher mal_enable_eob_irq(mal); 4319aa32835SJeff Kirsher spin_unlock_irqrestore(&mal->lock, flags); 4323d1a6333SEric Dumazet } 4339aa32835SJeff Kirsher 4349aa32835SJeff Kirsher /* Check for "rotting" packet(s) */ 4359aa32835SJeff Kirsher list_for_each(l, &mal->poll_list) { 4369aa32835SJeff Kirsher struct mal_commac *mc = 4379aa32835SJeff Kirsher list_entry(l, struct mal_commac, poll_list); 4389aa32835SJeff Kirsher if (unlikely(test_bit(MAL_COMMAC_POLL_DISABLED, &mc->flags))) 4399aa32835SJeff Kirsher continue; 4409aa32835SJeff Kirsher if (unlikely(mc->ops->peek_rx(mc->dev) || 4419aa32835SJeff Kirsher test_bit(MAL_COMMAC_RX_STOPPED, &mc->flags))) { 4429aa32835SJeff Kirsher MAL_DBG2(mal, "rotting packet" NL); 443b4dfd326SAlistair Popple if (!napi_reschedule(napi)) 4449aa32835SJeff Kirsher goto more_work; 445b4dfd326SAlistair Popple 44632663b8bSAlistair Popple spin_lock_irqsave(&mal->lock, flags); 447b4dfd326SAlistair Popple mal_disable_eob_irq(mal); 44832663b8bSAlistair Popple spin_unlock_irqrestore(&mal->lock, flags); 4499aa32835SJeff Kirsher } 4509aa32835SJeff Kirsher mc->ops->poll_tx(mc->dev); 4519aa32835SJeff Kirsher } 4529aa32835SJeff Kirsher 4539aa32835SJeff Kirsher more_work: 4549aa32835SJeff Kirsher MAL_DBG2(mal, "poll() %d <- %d" NL, budget, received); 4559aa32835SJeff Kirsher return received; 4569aa32835SJeff Kirsher } 4579aa32835SJeff Kirsher 4589aa32835SJeff Kirsher static void mal_reset(struct mal_instance *mal) 4599aa32835SJeff Kirsher { 4609aa32835SJeff Kirsher int n = 10; 4619aa32835SJeff Kirsher 4629aa32835SJeff Kirsher MAL_DBG(mal, "reset" NL); 4639aa32835SJeff Kirsher 4649aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_CFG, MAL_CFG_SR); 4659aa32835SJeff Kirsher 4669aa32835SJeff Kirsher /* Wait for reset to complete (1 system clock) */ 4679aa32835SJeff Kirsher while ((get_mal_dcrn(mal, MAL_CFG) & MAL_CFG_SR) && n) 4689aa32835SJeff Kirsher --n; 4699aa32835SJeff Kirsher 4709aa32835SJeff Kirsher if (unlikely(!n)) 4719aa32835SJeff Kirsher printk(KERN_ERR "mal%d: reset timeout\n", mal->index); 4729aa32835SJeff Kirsher } 4739aa32835SJeff Kirsher 4749aa32835SJeff Kirsher int mal_get_regs_len(struct mal_instance *mal) 4759aa32835SJeff Kirsher { 4769aa32835SJeff Kirsher return sizeof(struct emac_ethtool_regs_subhdr) + 4779aa32835SJeff Kirsher sizeof(struct mal_regs); 4789aa32835SJeff Kirsher } 4799aa32835SJeff Kirsher 4809aa32835SJeff Kirsher void *mal_dump_regs(struct mal_instance *mal, void *buf) 4819aa32835SJeff Kirsher { 4829aa32835SJeff Kirsher struct emac_ethtool_regs_subhdr *hdr = buf; 4839aa32835SJeff Kirsher struct mal_regs *regs = (struct mal_regs *)(hdr + 1); 4849aa32835SJeff Kirsher int i; 4859aa32835SJeff Kirsher 4869aa32835SJeff Kirsher hdr->version = mal->version; 4879aa32835SJeff Kirsher hdr->index = mal->index; 4889aa32835SJeff Kirsher 4899aa32835SJeff Kirsher regs->tx_count = mal->num_tx_chans; 4909aa32835SJeff Kirsher regs->rx_count = mal->num_rx_chans; 4919aa32835SJeff Kirsher 4929aa32835SJeff Kirsher regs->cfg = get_mal_dcrn(mal, MAL_CFG); 4939aa32835SJeff Kirsher regs->esr = get_mal_dcrn(mal, MAL_ESR); 4949aa32835SJeff Kirsher regs->ier = get_mal_dcrn(mal, MAL_IER); 4959aa32835SJeff Kirsher regs->tx_casr = get_mal_dcrn(mal, MAL_TXCASR); 4969aa32835SJeff Kirsher regs->tx_carr = get_mal_dcrn(mal, MAL_TXCARR); 4979aa32835SJeff Kirsher regs->tx_eobisr = get_mal_dcrn(mal, MAL_TXEOBISR); 4989aa32835SJeff Kirsher regs->tx_deir = get_mal_dcrn(mal, MAL_TXDEIR); 4999aa32835SJeff Kirsher regs->rx_casr = get_mal_dcrn(mal, MAL_RXCASR); 5009aa32835SJeff Kirsher regs->rx_carr = get_mal_dcrn(mal, MAL_RXCARR); 5019aa32835SJeff Kirsher regs->rx_eobisr = get_mal_dcrn(mal, MAL_RXEOBISR); 5029aa32835SJeff Kirsher regs->rx_deir = get_mal_dcrn(mal, MAL_RXDEIR); 5039aa32835SJeff Kirsher 5049aa32835SJeff Kirsher for (i = 0; i < regs->tx_count; ++i) 5059aa32835SJeff Kirsher regs->tx_ctpr[i] = get_mal_dcrn(mal, MAL_TXCTPR(i)); 5069aa32835SJeff Kirsher 5079aa32835SJeff Kirsher for (i = 0; i < regs->rx_count; ++i) { 5089aa32835SJeff Kirsher regs->rx_ctpr[i] = get_mal_dcrn(mal, MAL_RXCTPR(i)); 5099aa32835SJeff Kirsher regs->rcbs[i] = get_mal_dcrn(mal, MAL_RCBS(i)); 5109aa32835SJeff Kirsher } 5119aa32835SJeff Kirsher return regs + 1; 5129aa32835SJeff Kirsher } 5139aa32835SJeff Kirsher 514fe17dc1eSBill Pemberton static int mal_probe(struct platform_device *ofdev) 5159aa32835SJeff Kirsher { 5169aa32835SJeff Kirsher struct mal_instance *mal; 5179aa32835SJeff Kirsher int err = 0, i, bd_size; 5189aa32835SJeff Kirsher int index = mal_count++; 5199aa32835SJeff Kirsher unsigned int dcr_base; 5209aa32835SJeff Kirsher const u32 *prop; 5219aa32835SJeff Kirsher u32 cfg; 5229aa32835SJeff Kirsher unsigned long irqflags; 5239aa32835SJeff Kirsher irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde; 5249aa32835SJeff Kirsher 5259aa32835SJeff Kirsher mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL); 526b2adaca9SJoe Perches if (!mal) 5279aa32835SJeff Kirsher return -ENOMEM; 528b2adaca9SJoe Perches 5299aa32835SJeff Kirsher mal->index = index; 5309aa32835SJeff Kirsher mal->ofdev = ofdev; 5319aa32835SJeff Kirsher mal->version = of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal2") ? 2 : 1; 5329aa32835SJeff Kirsher 5339aa32835SJeff Kirsher MAL_DBG(mal, "probe" NL); 5349aa32835SJeff Kirsher 5359aa32835SJeff Kirsher prop = of_get_property(ofdev->dev.of_node, "num-tx-chans", NULL); 5369aa32835SJeff Kirsher if (prop == NULL) { 5379aa32835SJeff Kirsher printk(KERN_ERR 5389aa32835SJeff Kirsher "mal%d: can't find MAL num-tx-chans property!\n", 5399aa32835SJeff Kirsher index); 5409aa32835SJeff Kirsher err = -ENODEV; 5419aa32835SJeff Kirsher goto fail; 5429aa32835SJeff Kirsher } 5439aa32835SJeff Kirsher mal->num_tx_chans = prop[0]; 5449aa32835SJeff Kirsher 5459aa32835SJeff Kirsher prop = of_get_property(ofdev->dev.of_node, "num-rx-chans", NULL); 5469aa32835SJeff Kirsher if (prop == NULL) { 5479aa32835SJeff Kirsher printk(KERN_ERR 5489aa32835SJeff Kirsher "mal%d: can't find MAL num-rx-chans property!\n", 5499aa32835SJeff Kirsher index); 5509aa32835SJeff Kirsher err = -ENODEV; 5519aa32835SJeff Kirsher goto fail; 5529aa32835SJeff Kirsher } 5539aa32835SJeff Kirsher mal->num_rx_chans = prop[0]; 5549aa32835SJeff Kirsher 5559aa32835SJeff Kirsher dcr_base = dcr_resource_start(ofdev->dev.of_node, 0); 5569aa32835SJeff Kirsher if (dcr_base == 0) { 5579aa32835SJeff Kirsher printk(KERN_ERR 5589aa32835SJeff Kirsher "mal%d: can't find DCR resource!\n", index); 5599aa32835SJeff Kirsher err = -ENODEV; 5609aa32835SJeff Kirsher goto fail; 5619aa32835SJeff Kirsher } 5629aa32835SJeff Kirsher mal->dcr_host = dcr_map(ofdev->dev.of_node, dcr_base, 0x100); 5639aa32835SJeff Kirsher if (!DCR_MAP_OK(mal->dcr_host)) { 5649aa32835SJeff Kirsher printk(KERN_ERR 5659aa32835SJeff Kirsher "mal%d: failed to map DCRs !\n", index); 5669aa32835SJeff Kirsher err = -ENODEV; 5679aa32835SJeff Kirsher goto fail; 5689aa32835SJeff Kirsher } 5699aa32835SJeff Kirsher 5709aa32835SJeff Kirsher if (of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal-405ez")) { 5713b3bceefSTony Breeds #if defined(CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT) && \ 5723b3bceefSTony Breeds defined(CONFIG_IBM_EMAC_MAL_COMMON_ERR) 5739aa32835SJeff Kirsher mal->features |= (MAL_FTR_CLEAR_ICINTSTAT | 5749aa32835SJeff Kirsher MAL_FTR_COMMON_ERR_INT); 5759aa32835SJeff Kirsher #else 576f7ce9103SRob Herring printk(KERN_ERR "%pOF: Support for 405EZ not enabled!\n", 577f7ce9103SRob Herring ofdev->dev.of_node); 5789aa32835SJeff Kirsher err = -ENODEV; 5799aa32835SJeff Kirsher goto fail; 5809aa32835SJeff Kirsher #endif 5819aa32835SJeff Kirsher } 5829aa32835SJeff Kirsher 5839aa32835SJeff Kirsher mal->txeob_irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); 5849aa32835SJeff Kirsher mal->rxeob_irq = irq_of_parse_and_map(ofdev->dev.of_node, 1); 5859aa32835SJeff Kirsher mal->serr_irq = irq_of_parse_and_map(ofdev->dev.of_node, 2); 5869aa32835SJeff Kirsher 5879aa32835SJeff Kirsher if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) { 5889aa32835SJeff Kirsher mal->txde_irq = mal->rxde_irq = mal->serr_irq; 5899aa32835SJeff Kirsher } else { 5909aa32835SJeff Kirsher mal->txde_irq = irq_of_parse_and_map(ofdev->dev.of_node, 3); 5919aa32835SJeff Kirsher mal->rxde_irq = irq_of_parse_and_map(ofdev->dev.of_node, 4); 5929aa32835SJeff Kirsher } 5939aa32835SJeff Kirsher 59499c1790eSMichael Ellerman if (!mal->txeob_irq || !mal->rxeob_irq || !mal->serr_irq || 59599c1790eSMichael Ellerman !mal->txde_irq || !mal->rxde_irq) { 5969aa32835SJeff Kirsher printk(KERN_ERR 5979aa32835SJeff Kirsher "mal%d: failed to map interrupts !\n", index); 5989aa32835SJeff Kirsher err = -ENODEV; 5999aa32835SJeff Kirsher goto fail_unmap; 6009aa32835SJeff Kirsher } 6019aa32835SJeff Kirsher 6029aa32835SJeff Kirsher INIT_LIST_HEAD(&mal->poll_list); 6039aa32835SJeff Kirsher INIT_LIST_HEAD(&mal->list); 6049aa32835SJeff Kirsher spin_lock_init(&mal->lock); 6059aa32835SJeff Kirsher 6069aa32835SJeff Kirsher init_dummy_netdev(&mal->dummy_dev); 6079aa32835SJeff Kirsher 6089aa32835SJeff Kirsher netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll, 6093b3bceefSTony Breeds CONFIG_IBM_EMAC_POLL_WEIGHT); 6109aa32835SJeff Kirsher 6119aa32835SJeff Kirsher /* Load power-on reset defaults */ 6129aa32835SJeff Kirsher mal_reset(mal); 6139aa32835SJeff Kirsher 6149aa32835SJeff Kirsher /* Set the MAL configuration register */ 6159aa32835SJeff Kirsher cfg = (mal->version == 2) ? MAL2_CFG_DEFAULT : MAL1_CFG_DEFAULT; 6169aa32835SJeff Kirsher cfg |= MAL_CFG_PLBB | MAL_CFG_OPBBL | MAL_CFG_LEA; 6179aa32835SJeff Kirsher 6189aa32835SJeff Kirsher /* Current Axon is not happy with priority being non-0, it can 6199aa32835SJeff Kirsher * deadlock, fix it up here 6209aa32835SJeff Kirsher */ 6219aa32835SJeff Kirsher if (of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal-axon")) 6229aa32835SJeff Kirsher cfg &= ~(MAL2_CFG_RPP_10 | MAL2_CFG_WPP_10); 6239aa32835SJeff Kirsher 6249aa32835SJeff Kirsher /* Apply configuration */ 6259aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_CFG, cfg); 6269aa32835SJeff Kirsher 6279aa32835SJeff Kirsher /* Allocate space for BD rings */ 6289aa32835SJeff Kirsher BUG_ON(mal->num_tx_chans <= 0 || mal->num_tx_chans > 32); 6299aa32835SJeff Kirsher BUG_ON(mal->num_rx_chans <= 0 || mal->num_rx_chans > 32); 6309aa32835SJeff Kirsher 6319aa32835SJeff Kirsher bd_size = sizeof(struct mal_descriptor) * 6329aa32835SJeff Kirsher (NUM_TX_BUFF * mal->num_tx_chans + 6339aa32835SJeff Kirsher NUM_RX_BUFF * mal->num_rx_chans); 634750afb08SLuis Chamberlain mal->bd_virt = dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma, 635ede23fa8SJoe Perches GFP_KERNEL); 6369aa32835SJeff Kirsher if (mal->bd_virt == NULL) { 6379aa32835SJeff Kirsher err = -ENOMEM; 6389aa32835SJeff Kirsher goto fail_unmap; 6399aa32835SJeff Kirsher } 6409aa32835SJeff Kirsher 6419aa32835SJeff Kirsher for (i = 0; i < mal->num_tx_chans; ++i) 6429aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_TXCTPR(i), mal->bd_dma + 6439aa32835SJeff Kirsher sizeof(struct mal_descriptor) * 6449aa32835SJeff Kirsher mal_tx_bd_offset(mal, i)); 6459aa32835SJeff Kirsher 6469aa32835SJeff Kirsher for (i = 0; i < mal->num_rx_chans; ++i) 6479aa32835SJeff Kirsher set_mal_dcrn(mal, MAL_RXCTPR(i), mal->bd_dma + 6489aa32835SJeff Kirsher sizeof(struct mal_descriptor) * 6499aa32835SJeff Kirsher mal_rx_bd_offset(mal, i)); 6509aa32835SJeff Kirsher 6519aa32835SJeff Kirsher if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) { 6529aa32835SJeff Kirsher irqflags = IRQF_SHARED; 6539aa32835SJeff Kirsher hdlr_serr = hdlr_txde = hdlr_rxde = mal_int; 6549aa32835SJeff Kirsher } else { 6559aa32835SJeff Kirsher irqflags = 0; 6569aa32835SJeff Kirsher hdlr_serr = mal_serr; 6579aa32835SJeff Kirsher hdlr_txde = mal_txde; 6589aa32835SJeff Kirsher hdlr_rxde = mal_rxde; 6599aa32835SJeff Kirsher } 6609aa32835SJeff Kirsher 6619aa32835SJeff Kirsher err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal); 6629aa32835SJeff Kirsher if (err) 6639aa32835SJeff Kirsher goto fail2; 6649aa32835SJeff Kirsher err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal); 6659aa32835SJeff Kirsher if (err) 6669aa32835SJeff Kirsher goto fail3; 6679aa32835SJeff Kirsher err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal); 6689aa32835SJeff Kirsher if (err) 6699aa32835SJeff Kirsher goto fail4; 6709aa32835SJeff Kirsher err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal); 6719aa32835SJeff Kirsher if (err) 6729aa32835SJeff Kirsher goto fail5; 6739aa32835SJeff Kirsher err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal); 6749aa32835SJeff Kirsher if (err) 6759aa32835SJeff Kirsher goto fail6; 6769aa32835SJeff Kirsher 6779aa32835SJeff Kirsher /* Enable all MAL SERR interrupt sources */ 67809271db6SIvan Mikhaylov set_mal_dcrn(mal, MAL_IER, MAL_IER_EVENTS); 6799aa32835SJeff Kirsher 6809aa32835SJeff Kirsher /* Enable EOB interrupt */ 6819aa32835SJeff Kirsher mal_enable_eob_irq(mal); 6829aa32835SJeff Kirsher 6839aa32835SJeff Kirsher printk(KERN_INFO 684f7ce9103SRob Herring "MAL v%d %pOF, %d TX channels, %d RX channels\n", 685f7ce9103SRob Herring mal->version, ofdev->dev.of_node, 6869aa32835SJeff Kirsher mal->num_tx_chans, mal->num_rx_chans); 6879aa32835SJeff Kirsher 6889aa32835SJeff Kirsher /* Advertise this instance to the rest of the world */ 6899aa32835SJeff Kirsher wmb(); 6908513fbd8SJingoo Han platform_set_drvdata(ofdev, mal); 6919aa32835SJeff Kirsher 6929aa32835SJeff Kirsher return 0; 6939aa32835SJeff Kirsher 6949aa32835SJeff Kirsher fail6: 6959aa32835SJeff Kirsher free_irq(mal->rxde_irq, mal); 6969aa32835SJeff Kirsher fail5: 6979aa32835SJeff Kirsher free_irq(mal->txeob_irq, mal); 6989aa32835SJeff Kirsher fail4: 6999aa32835SJeff Kirsher free_irq(mal->txde_irq, mal); 7009aa32835SJeff Kirsher fail3: 7019aa32835SJeff Kirsher free_irq(mal->serr_irq, mal); 7029aa32835SJeff Kirsher fail2: 7039aa32835SJeff Kirsher dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma); 7049aa32835SJeff Kirsher fail_unmap: 7059aa32835SJeff Kirsher dcr_unmap(mal->dcr_host, 0x100); 7069aa32835SJeff Kirsher fail: 7079aa32835SJeff Kirsher kfree(mal); 7089aa32835SJeff Kirsher 7099aa32835SJeff Kirsher return err; 7109aa32835SJeff Kirsher } 7119aa32835SJeff Kirsher 712fe17dc1eSBill Pemberton static int mal_remove(struct platform_device *ofdev) 7139aa32835SJeff Kirsher { 7148513fbd8SJingoo Han struct mal_instance *mal = platform_get_drvdata(ofdev); 7159aa32835SJeff Kirsher 7169aa32835SJeff Kirsher MAL_DBG(mal, "remove" NL); 7179aa32835SJeff Kirsher 7189aa32835SJeff Kirsher /* Synchronize with scheduled polling */ 7199aa32835SJeff Kirsher napi_disable(&mal->napi); 7209aa32835SJeff Kirsher 721f7c3f96aSJulia Lawall if (!list_empty(&mal->list)) 7229aa32835SJeff Kirsher /* This is *very* bad */ 723f7c3f96aSJulia Lawall WARN(1, KERN_EMERG 7249aa32835SJeff Kirsher "mal%d: commac list is not empty on remove!\n", 7259aa32835SJeff Kirsher mal->index); 7269aa32835SJeff Kirsher 7279aa32835SJeff Kirsher free_irq(mal->serr_irq, mal); 7289aa32835SJeff Kirsher free_irq(mal->txde_irq, mal); 7299aa32835SJeff Kirsher free_irq(mal->txeob_irq, mal); 7309aa32835SJeff Kirsher free_irq(mal->rxde_irq, mal); 7319aa32835SJeff Kirsher free_irq(mal->rxeob_irq, mal); 7329aa32835SJeff Kirsher 7339aa32835SJeff Kirsher mal_reset(mal); 7349aa32835SJeff Kirsher 7359aa32835SJeff Kirsher dma_free_coherent(&ofdev->dev, 7369aa32835SJeff Kirsher sizeof(struct mal_descriptor) * 7379aa32835SJeff Kirsher (NUM_TX_BUFF * mal->num_tx_chans + 7389aa32835SJeff Kirsher NUM_RX_BUFF * mal->num_rx_chans), mal->bd_virt, 7399aa32835SJeff Kirsher mal->bd_dma); 7409aa32835SJeff Kirsher kfree(mal); 7419aa32835SJeff Kirsher 7429aa32835SJeff Kirsher return 0; 7439aa32835SJeff Kirsher } 7449aa32835SJeff Kirsher 74547b61667SFabian Frederick static const struct of_device_id mal_platform_match[] = 7469aa32835SJeff Kirsher { 7479aa32835SJeff Kirsher { 7489aa32835SJeff Kirsher .compatible = "ibm,mcmal", 7499aa32835SJeff Kirsher }, 7509aa32835SJeff Kirsher { 7519aa32835SJeff Kirsher .compatible = "ibm,mcmal2", 7529aa32835SJeff Kirsher }, 7539aa32835SJeff Kirsher /* Backward compat */ 7549aa32835SJeff Kirsher { 7559aa32835SJeff Kirsher .type = "mcmal-dma", 7569aa32835SJeff Kirsher .compatible = "ibm,mcmal", 7579aa32835SJeff Kirsher }, 7589aa32835SJeff Kirsher { 7599aa32835SJeff Kirsher .type = "mcmal-dma", 7609aa32835SJeff Kirsher .compatible = "ibm,mcmal2", 7619aa32835SJeff Kirsher }, 7629aa32835SJeff Kirsher {}, 7639aa32835SJeff Kirsher }; 7649aa32835SJeff Kirsher 7659aa32835SJeff Kirsher static struct platform_driver mal_of_driver = { 7669aa32835SJeff Kirsher .driver = { 7679aa32835SJeff Kirsher .name = "mcmal", 7689aa32835SJeff Kirsher .of_match_table = mal_platform_match, 7699aa32835SJeff Kirsher }, 7709aa32835SJeff Kirsher .probe = mal_probe, 7719aa32835SJeff Kirsher .remove = mal_remove, 7729aa32835SJeff Kirsher }; 7739aa32835SJeff Kirsher 7749aa32835SJeff Kirsher int __init mal_init(void) 7759aa32835SJeff Kirsher { 7769aa32835SJeff Kirsher return platform_driver_register(&mal_of_driver); 7779aa32835SJeff Kirsher } 7789aa32835SJeff Kirsher 7799aa32835SJeff Kirsher void mal_exit(void) 7809aa32835SJeff Kirsher { 7819aa32835SJeff Kirsher platform_driver_unregister(&mal_of_driver); 7829aa32835SJeff Kirsher } 783