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