brintos

brintos / linux-shallow public Read only

0
0
Text · 19.3 KiB · 99d5f83 Raw
793 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * drivers/net/ethernet/ibm/emac/mal.c4 *5 * Memory Access Layer (MAL) support6 *7 * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.8 *                <benh@kernel.crashing.org>9 *10 * Based on the arch/ppc version of the driver:11 *12 * Copyright (c) 2004, 2005 Zultys Technologies.13 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>14 *15 * Based on original work by16 *      Benjamin Herrenschmidt <benh@kernel.crashing.org>,17 *      David Gibson <hermes@gibson.dropbear.id.au>,18 *19 *      Armin Kuster <akuster@mvista.com>20 *      Copyright 2002 MontaVista Softare Inc.21 */22 23#include <linux/delay.h>24#include <linux/slab.h>25#include <linux/of.h>26#include <linux/of_irq.h>27#include <linux/platform_device.h>28 29#include "core.h"30#include <asm/dcr-regs.h>31 32static int mal_count;33 34int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac)35{36	unsigned long flags;37 38	spin_lock_irqsave(&mal->lock, flags);39 40	MAL_DBG(mal, "reg(%08x, %08x)" NL,41		commac->tx_chan_mask, commac->rx_chan_mask);42 43	/* Don't let multiple commacs claim the same channel(s) */44	if ((mal->tx_chan_mask & commac->tx_chan_mask) ||45	    (mal->rx_chan_mask & commac->rx_chan_mask)) {46		spin_unlock_irqrestore(&mal->lock, flags);47		printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",48		       mal->index);49		return -EBUSY;50	}51 52	if (list_empty(&mal->list))53		napi_enable(&mal->napi);54	mal->tx_chan_mask |= commac->tx_chan_mask;55	mal->rx_chan_mask |= commac->rx_chan_mask;56	list_add(&commac->list, &mal->list);57 58	spin_unlock_irqrestore(&mal->lock, flags);59 60	return 0;61}62 63void mal_unregister_commac(struct mal_instance	*mal,64		struct mal_commac *commac)65{66	unsigned long flags;67 68	spin_lock_irqsave(&mal->lock, flags);69 70	MAL_DBG(mal, "unreg(%08x, %08x)" NL,71		commac->tx_chan_mask, commac->rx_chan_mask);72 73	mal->tx_chan_mask &= ~commac->tx_chan_mask;74	mal->rx_chan_mask &= ~commac->rx_chan_mask;75	list_del_init(&commac->list);76	if (list_empty(&mal->list))77		napi_disable(&mal->napi);78 79	spin_unlock_irqrestore(&mal->lock, flags);80}81 82int mal_set_rcbs(struct mal_instance *mal, int channel, unsigned long size)83{84	BUG_ON(channel < 0 || channel >= mal->num_rx_chans ||85	       size > MAL_MAX_RX_SIZE);86 87	MAL_DBG(mal, "set_rbcs(%d, %lu)" NL, channel, size);88 89	if (size & 0xf) {90		printk(KERN_WARNING91		       "mal%d: incorrect RX size %lu for the channel %d\n",92		       mal->index, size, channel);93		return -EINVAL;94	}95 96	set_mal_dcrn(mal, MAL_RCBS(channel), size >> 4);97	return 0;98}99 100int mal_tx_bd_offset(struct mal_instance *mal, int channel)101{102	BUG_ON(channel < 0 || channel >= mal->num_tx_chans);103 104	return channel * NUM_TX_BUFF;105}106 107int mal_rx_bd_offset(struct mal_instance *mal, int channel)108{109	BUG_ON(channel < 0 || channel >= mal->num_rx_chans);110	return mal->num_tx_chans * NUM_TX_BUFF + channel * NUM_RX_BUFF;111}112 113void mal_enable_tx_channel(struct mal_instance *mal, int channel)114{115	unsigned long flags;116 117	spin_lock_irqsave(&mal->lock, flags);118 119	MAL_DBG(mal, "enable_tx(%d)" NL, channel);120 121	set_mal_dcrn(mal, MAL_TXCASR,122		     get_mal_dcrn(mal, MAL_TXCASR) | MAL_CHAN_MASK(channel));123 124	spin_unlock_irqrestore(&mal->lock, flags);125}126 127void mal_disable_tx_channel(struct mal_instance *mal, int channel)128{129	set_mal_dcrn(mal, MAL_TXCARR, MAL_CHAN_MASK(channel));130 131	MAL_DBG(mal, "disable_tx(%d)" NL, channel);132}133 134void mal_enable_rx_channel(struct mal_instance *mal, int channel)135{136	unsigned long flags;137 138	/*139	 * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple140	 * of 8, but enabling in MAL_RXCASR needs the divided by 8 value141	 * for the bitmask142	 */143	if (!(channel % 8))144		channel >>= 3;145 146	spin_lock_irqsave(&mal->lock, flags);147 148	MAL_DBG(mal, "enable_rx(%d)" NL, channel);149 150	set_mal_dcrn(mal, MAL_RXCASR,151		     get_mal_dcrn(mal, MAL_RXCASR) | MAL_CHAN_MASK(channel));152 153	spin_unlock_irqrestore(&mal->lock, flags);154}155 156void mal_disable_rx_channel(struct mal_instance *mal, int channel)157{158	/*159	 * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple160	 * of 8, but enabling in MAL_RXCASR needs the divided by 8 value161	 * for the bitmask162	 */163	if (!(channel % 8))164		channel >>= 3;165 166	set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel));167 168	MAL_DBG(mal, "disable_rx(%d)" NL, channel);169}170 171void mal_poll_add(struct mal_instance *mal, struct mal_commac *commac)172{173	unsigned long flags;174 175	spin_lock_irqsave(&mal->lock, flags);176 177	MAL_DBG(mal, "poll_add(%p)" NL, commac);178 179	/* starts disabled */180	set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags);181 182	list_add_tail(&commac->poll_list, &mal->poll_list);183 184	spin_unlock_irqrestore(&mal->lock, flags);185}186 187void mal_poll_del(struct mal_instance *mal, struct mal_commac *commac)188{189	unsigned long flags;190 191	spin_lock_irqsave(&mal->lock, flags);192 193	MAL_DBG(mal, "poll_del(%p)" NL, commac);194 195	list_del(&commac->poll_list);196 197	spin_unlock_irqrestore(&mal->lock, flags);198}199 200/* synchronized by mal_poll() */201static inline void mal_enable_eob_irq(struct mal_instance *mal)202{203	MAL_DBG2(mal, "enable_irq" NL);204 205	// XXX might want to cache MAL_CFG as the DCR read can be slooooow206	set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) | MAL_CFG_EOPIE);207}208 209/* synchronized by NAPI state */210static inline void mal_disable_eob_irq(struct mal_instance *mal)211{212	// XXX might want to cache MAL_CFG as the DCR read can be slooooow213	set_mal_dcrn(mal, MAL_CFG, get_mal_dcrn(mal, MAL_CFG) & ~MAL_CFG_EOPIE);214 215	MAL_DBG2(mal, "disable_irq" NL);216}217 218static irqreturn_t mal_serr(int irq, void *dev_instance)219{220	struct mal_instance *mal = dev_instance;221 222	u32 esr = get_mal_dcrn(mal, MAL_ESR);223 224	/* Clear the error status register */225	set_mal_dcrn(mal, MAL_ESR, esr);226 227	MAL_DBG(mal, "SERR %08x" NL, esr);228 229	if (esr & MAL_ESR_EVB) {230		if (esr & MAL_ESR_DE) {231			/* We ignore Descriptor error,232			 * TXDE or RXDE interrupt will be generated anyway.233			 */234			return IRQ_HANDLED;235		}236 237		if (esr & MAL_ESR_PEIN) {238			/* PLB error, it's probably buggy hardware or239			 * incorrect physical address in BD (i.e. bug)240			 */241			if (net_ratelimit())242				printk(KERN_ERR243				       "mal%d: system error, "244				       "PLB (ESR = 0x%08x)\n",245				       mal->index, esr);246			return IRQ_HANDLED;247		}248 249		/* OPB error, it's probably buggy hardware or incorrect250		 * EBC setup251		 */252		if (net_ratelimit())253			printk(KERN_ERR254			       "mal%d: system error, OPB (ESR = 0x%08x)\n",255			       mal->index, esr);256	}257	return IRQ_HANDLED;258}259 260static inline void mal_schedule_poll(struct mal_instance *mal)261{262	if (likely(napi_schedule_prep(&mal->napi))) {263		MAL_DBG2(mal, "schedule_poll" NL);264		spin_lock(&mal->lock);265		mal_disable_eob_irq(mal);266		spin_unlock(&mal->lock);267		__napi_schedule(&mal->napi);268	} else269		MAL_DBG2(mal, "already in poll" NL);270}271 272static irqreturn_t mal_txeob(int irq, void *dev_instance)273{274	struct mal_instance *mal = dev_instance;275 276	u32 r = get_mal_dcrn(mal, MAL_TXEOBISR);277 278	MAL_DBG2(mal, "txeob %08x" NL, r);279 280	mal_schedule_poll(mal);281	set_mal_dcrn(mal, MAL_TXEOBISR, r);282 283#ifdef CONFIG_PPC_DCR_NATIVE284	if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))285		mtdcri(SDR0, DCRN_SDR_ICINTSTAT,286				(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));287#endif288 289	return IRQ_HANDLED;290}291 292static irqreturn_t mal_rxeob(int irq, void *dev_instance)293{294	struct mal_instance *mal = dev_instance;295 296	u32 r = get_mal_dcrn(mal, MAL_RXEOBISR);297 298	MAL_DBG2(mal, "rxeob %08x" NL, r);299 300	mal_schedule_poll(mal);301	set_mal_dcrn(mal, MAL_RXEOBISR, r);302 303#ifdef CONFIG_PPC_DCR_NATIVE304	if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))305		mtdcri(SDR0, DCRN_SDR_ICINTSTAT,306				(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));307#endif308 309	return IRQ_HANDLED;310}311 312static irqreturn_t mal_txde(int irq, void *dev_instance)313{314	struct mal_instance *mal = dev_instance;315 316	u32 deir = get_mal_dcrn(mal, MAL_TXDEIR);317	set_mal_dcrn(mal, MAL_TXDEIR, deir);318 319	MAL_DBG(mal, "txde %08x" NL, deir);320 321	if (net_ratelimit())322		printk(KERN_ERR323		       "mal%d: TX descriptor error (TXDEIR = 0x%08x)\n",324		       mal->index, deir);325 326	return IRQ_HANDLED;327}328 329static irqreturn_t mal_rxde(int irq, void *dev_instance)330{331	struct mal_instance *mal = dev_instance;332	struct list_head *l;333 334	u32 deir = get_mal_dcrn(mal, MAL_RXDEIR);335 336	MAL_DBG(mal, "rxde %08x" NL, deir);337 338	list_for_each(l, &mal->list) {339		struct mal_commac *mc = list_entry(l, struct mal_commac, list);340		if (deir & mc->rx_chan_mask) {341			set_bit(MAL_COMMAC_RX_STOPPED, &mc->flags);342			mc->ops->rxde(mc->dev);343		}344	}345 346	mal_schedule_poll(mal);347	set_mal_dcrn(mal, MAL_RXDEIR, deir);348 349	return IRQ_HANDLED;350}351 352static irqreturn_t mal_int(int irq, void *dev_instance)353{354	struct mal_instance *mal = dev_instance;355	u32 esr = get_mal_dcrn(mal, MAL_ESR);356 357	if (esr & MAL_ESR_EVB) {358		/* descriptor error */359		if (esr & MAL_ESR_DE) {360			if (esr & MAL_ESR_CIDT)361				return mal_rxde(irq, dev_instance);362			else363				return mal_txde(irq, dev_instance);364		} else { /* SERR */365			return mal_serr(irq, dev_instance);366		}367	}368	return IRQ_HANDLED;369}370 371void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)372{373	/* Spinlock-type semantics: only one caller disable poll at a time */374	while (test_and_set_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags))375		msleep(1);376 377	/* Synchronize with the MAL NAPI poller */378	napi_synchronize(&mal->napi);379}380 381void mal_poll_enable(struct mal_instance *mal, struct mal_commac *commac)382{383	smp_wmb();384	clear_bit(MAL_COMMAC_POLL_DISABLED, &commac->flags);385 386	/* Feels better to trigger a poll here to catch up with events that387	 * may have happened on this channel while disabled. It will most388	 * probably be delayed until the next interrupt but that's mostly a389	 * non-issue in the context where this is called.390	 */391	napi_schedule(&mal->napi);392}393 394static int mal_poll(struct napi_struct *napi, int budget)395{396	struct mal_instance *mal = container_of(napi, struct mal_instance, napi);397	struct list_head *l;398	int received = 0;399	unsigned long flags;400 401	MAL_DBG2(mal, "poll(%d)" NL, budget);402 403	/* Process TX skbs */404	list_for_each(l, &mal->poll_list) {405		struct mal_commac *mc =406			list_entry(l, struct mal_commac, poll_list);407		mc->ops->poll_tx(mc->dev);408	}409 410	/* Process RX skbs.411	 *412	 * We _might_ need something more smart here to enforce polling413	 * fairness.414	 */415	list_for_each(l, &mal->poll_list) {416		struct mal_commac *mc =417			list_entry(l, struct mal_commac, poll_list);418		int n;419		if (unlikely(test_bit(MAL_COMMAC_POLL_DISABLED, &mc->flags)))420			continue;421		n = mc->ops->poll_rx(mc->dev, budget - received);422		if (n) {423			received += n;424			if (received >= budget)425				return budget;426		}427	}428 429	if (napi_complete_done(napi, received)) {430		/* We need to disable IRQs to protect from RXDE IRQ here */431		spin_lock_irqsave(&mal->lock, flags);432		mal_enable_eob_irq(mal);433		spin_unlock_irqrestore(&mal->lock, flags);434	}435 436	/* Check for "rotting" packet(s) */437	list_for_each(l, &mal->poll_list) {438		struct mal_commac *mc =439			list_entry(l, struct mal_commac, poll_list);440		if (unlikely(test_bit(MAL_COMMAC_POLL_DISABLED, &mc->flags)))441			continue;442		if (unlikely(mc->ops->peek_rx(mc->dev) ||443			     test_bit(MAL_COMMAC_RX_STOPPED, &mc->flags))) {444			MAL_DBG2(mal, "rotting packet" NL);445			if (!napi_schedule(napi))446				goto more_work;447 448			spin_lock_irqsave(&mal->lock, flags);449			mal_disable_eob_irq(mal);450			spin_unlock_irqrestore(&mal->lock, flags);451		}452		mc->ops->poll_tx(mc->dev);453	}454 455 more_work:456	MAL_DBG2(mal, "poll() %d <- %d" NL, budget, received);457	return received;458}459 460static void mal_reset(struct mal_instance *mal)461{462	int n = 10;463 464	MAL_DBG(mal, "reset" NL);465 466	set_mal_dcrn(mal, MAL_CFG, MAL_CFG_SR);467 468	/* Wait for reset to complete (1 system clock) */469	while ((get_mal_dcrn(mal, MAL_CFG) & MAL_CFG_SR) && n)470		--n;471 472	if (unlikely(!n))473		printk(KERN_ERR "mal%d: reset timeout\n", mal->index);474}475 476int mal_get_regs_len(struct mal_instance *mal)477{478	return sizeof(struct emac_ethtool_regs_subhdr) +479	    sizeof(struct mal_regs);480}481 482void *mal_dump_regs(struct mal_instance *mal, void *buf)483{484	struct emac_ethtool_regs_subhdr *hdr = buf;485	struct mal_regs *regs = (struct mal_regs *)(hdr + 1);486	int i;487 488	hdr->version = mal->version;489	hdr->index = mal->index;490 491	regs->tx_count = mal->num_tx_chans;492	regs->rx_count = mal->num_rx_chans;493 494	regs->cfg = get_mal_dcrn(mal, MAL_CFG);495	regs->esr = get_mal_dcrn(mal, MAL_ESR);496	regs->ier = get_mal_dcrn(mal, MAL_IER);497	regs->tx_casr = get_mal_dcrn(mal, MAL_TXCASR);498	regs->tx_carr = get_mal_dcrn(mal, MAL_TXCARR);499	regs->tx_eobisr = get_mal_dcrn(mal, MAL_TXEOBISR);500	regs->tx_deir = get_mal_dcrn(mal, MAL_TXDEIR);501	regs->rx_casr = get_mal_dcrn(mal, MAL_RXCASR);502	regs->rx_carr = get_mal_dcrn(mal, MAL_RXCARR);503	regs->rx_eobisr = get_mal_dcrn(mal, MAL_RXEOBISR);504	regs->rx_deir = get_mal_dcrn(mal, MAL_RXDEIR);505 506	for (i = 0; i < regs->tx_count; ++i)507		regs->tx_ctpr[i] = get_mal_dcrn(mal, MAL_TXCTPR(i));508 509	for (i = 0; i < regs->rx_count; ++i) {510		regs->rx_ctpr[i] = get_mal_dcrn(mal, MAL_RXCTPR(i));511		regs->rcbs[i] = get_mal_dcrn(mal, MAL_RCBS(i));512	}513	return regs + 1;514}515 516static int mal_probe(struct platform_device *ofdev)517{518	struct mal_instance *mal;519	int err = 0, i, bd_size;520	int index = mal_count++;521	unsigned int dcr_base;522	const u32 *prop;523	u32 cfg;524	unsigned long irqflags;525	irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;526 527	mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);528	if (!mal)529		return -ENOMEM;530 531	mal->index = index;532	mal->ofdev = ofdev;533	mal->version = of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal2") ? 2 : 1;534 535	MAL_DBG(mal, "probe" NL);536 537	prop = of_get_property(ofdev->dev.of_node, "num-tx-chans", NULL);538	if (prop == NULL) {539		printk(KERN_ERR540		       "mal%d: can't find MAL num-tx-chans property!\n",541		       index);542		err = -ENODEV;543		goto fail;544	}545	mal->num_tx_chans = prop[0];546 547	prop = of_get_property(ofdev->dev.of_node, "num-rx-chans", NULL);548	if (prop == NULL) {549		printk(KERN_ERR550		       "mal%d: can't find MAL num-rx-chans property!\n",551		       index);552		err = -ENODEV;553		goto fail;554	}555	mal->num_rx_chans = prop[0];556 557	dcr_base = dcr_resource_start(ofdev->dev.of_node, 0);558	if (dcr_base == 0) {559		printk(KERN_ERR560		       "mal%d: can't find DCR resource!\n", index);561		err = -ENODEV;562		goto fail;563	}564	mal->dcr_host = dcr_map(ofdev->dev.of_node, dcr_base, 0x100);565	if (!DCR_MAP_OK(mal->dcr_host)) {566		printk(KERN_ERR567		       "mal%d: failed to map DCRs !\n", index);568		err = -ENODEV;569		goto fail;570	}571 572	if (of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal-405ez")) {573#if defined(CONFIG_IBM_EMAC_MAL_CLR_ICINTSTAT) && \574		defined(CONFIG_IBM_EMAC_MAL_COMMON_ERR)575		mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |576				MAL_FTR_COMMON_ERR_INT);577#else578		printk(KERN_ERR "%pOF: Support for 405EZ not enabled!\n",579				ofdev->dev.of_node);580		err = -ENODEV;581		goto fail_unmap;582#endif583	}584 585	mal->txeob_irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);586	mal->rxeob_irq = irq_of_parse_and_map(ofdev->dev.of_node, 1);587	mal->serr_irq = irq_of_parse_and_map(ofdev->dev.of_node, 2);588 589	if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {590		mal->txde_irq = mal->rxde_irq = mal->serr_irq;591	} else {592		mal->txde_irq = irq_of_parse_and_map(ofdev->dev.of_node, 3);593		mal->rxde_irq = irq_of_parse_and_map(ofdev->dev.of_node, 4);594	}595 596	if (!mal->txeob_irq || !mal->rxeob_irq || !mal->serr_irq ||597	    !mal->txde_irq  || !mal->rxde_irq) {598		printk(KERN_ERR599		       "mal%d: failed to map interrupts !\n", index);600		err = -ENODEV;601		goto fail_unmap;602	}603 604	INIT_LIST_HEAD(&mal->poll_list);605	INIT_LIST_HEAD(&mal->list);606	spin_lock_init(&mal->lock);607 608	mal->dummy_dev = alloc_netdev_dummy(0);609	if (!mal->dummy_dev) {610		err = -ENOMEM;611		goto fail_unmap;612	}613 614	netif_napi_add_weight(mal->dummy_dev, &mal->napi, mal_poll,615			      CONFIG_IBM_EMAC_POLL_WEIGHT);616 617	/* Load power-on reset defaults */618	mal_reset(mal);619 620	/* Set the MAL configuration register */621	cfg = (mal->version == 2) ? MAL2_CFG_DEFAULT : MAL1_CFG_DEFAULT;622	cfg |= MAL_CFG_PLBB | MAL_CFG_OPBBL | MAL_CFG_LEA;623 624	/* Current Axon is not happy with priority being non-0, it can625	 * deadlock, fix it up here626	 */627	if (of_device_is_compatible(ofdev->dev.of_node, "ibm,mcmal-axon"))628		cfg &= ~(MAL2_CFG_RPP_10 | MAL2_CFG_WPP_10);629 630	/* Apply configuration */631	set_mal_dcrn(mal, MAL_CFG, cfg);632 633	/* Allocate space for BD rings */634	BUG_ON(mal->num_tx_chans <= 0 || mal->num_tx_chans > 32);635	BUG_ON(mal->num_rx_chans <= 0 || mal->num_rx_chans > 32);636 637	bd_size = sizeof(struct mal_descriptor) *638		(NUM_TX_BUFF * mal->num_tx_chans +639		 NUM_RX_BUFF * mal->num_rx_chans);640	mal->bd_virt = dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,641					  GFP_KERNEL);642	if (mal->bd_virt == NULL) {643		err = -ENOMEM;644		goto fail_dummy;645	}646 647	for (i = 0; i < mal->num_tx_chans; ++i)648		set_mal_dcrn(mal, MAL_TXCTPR(i), mal->bd_dma +649			     sizeof(struct mal_descriptor) *650			     mal_tx_bd_offset(mal, i));651 652	for (i = 0; i < mal->num_rx_chans; ++i)653		set_mal_dcrn(mal, MAL_RXCTPR(i), mal->bd_dma +654			     sizeof(struct mal_descriptor) *655			     mal_rx_bd_offset(mal, i));656 657	if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {658		irqflags = IRQF_SHARED;659		hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;660	} else {661		irqflags = 0;662		hdlr_serr = mal_serr;663		hdlr_txde = mal_txde;664		hdlr_rxde = mal_rxde;665	}666 667	err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);668	if (err)669		goto fail2;670	err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);671	if (err)672		goto fail3;673	err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);674	if (err)675		goto fail4;676	err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);677	if (err)678		goto fail5;679	err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);680	if (err)681		goto fail6;682 683	/* Enable all MAL SERR interrupt sources */684	set_mal_dcrn(mal, MAL_IER, MAL_IER_EVENTS);685 686	/* Enable EOB interrupt */687	mal_enable_eob_irq(mal);688 689	printk(KERN_INFO690	       "MAL v%d %pOF, %d TX channels, %d RX channels\n",691	       mal->version, ofdev->dev.of_node,692	       mal->num_tx_chans, mal->num_rx_chans);693 694	/* Advertise this instance to the rest of the world */695	wmb();696	platform_set_drvdata(ofdev, mal);697 698	return 0;699 700 fail6:701	free_irq(mal->rxde_irq, mal);702 fail5:703	free_irq(mal->txeob_irq, mal);704 fail4:705	free_irq(mal->txde_irq, mal);706 fail3:707	free_irq(mal->serr_irq, mal);708 fail2:709	dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma);710 fail_dummy:711	free_netdev(mal->dummy_dev);712 fail_unmap:713	dcr_unmap(mal->dcr_host, 0x100);714 fail:715	kfree(mal);716 717	return err;718}719 720static void mal_remove(struct platform_device *ofdev)721{722	struct mal_instance *mal = platform_get_drvdata(ofdev);723 724	MAL_DBG(mal, "remove" NL);725 726	/* Synchronize with scheduled polling */727	napi_disable(&mal->napi);728 729	if (!list_empty(&mal->list))730		/* This is *very* bad */731		WARN(1, KERN_EMERG732		       "mal%d: commac list is not empty on remove!\n",733		       mal->index);734 735	free_irq(mal->serr_irq, mal);736	free_irq(mal->txde_irq, mal);737	free_irq(mal->txeob_irq, mal);738	free_irq(mal->rxde_irq, mal);739	free_irq(mal->rxeob_irq, mal);740 741	mal_reset(mal);742 743	free_netdev(mal->dummy_dev);744 745	dcr_unmap(mal->dcr_host, 0x100);746 747	dma_free_coherent(&ofdev->dev,748			  sizeof(struct mal_descriptor) *749			  (NUM_TX_BUFF * mal->num_tx_chans +750			   NUM_RX_BUFF * mal->num_rx_chans), mal->bd_virt,751			  mal->bd_dma);752	kfree(mal);753}754 755static const struct of_device_id mal_platform_match[] =756{757	{758		.compatible	= "ibm,mcmal",759	},760	{761		.compatible	= "ibm,mcmal2",762	},763	/* Backward compat */764	{765		.type		= "mcmal-dma",766		.compatible	= "ibm,mcmal",767	},768	{769		.type		= "mcmal-dma",770		.compatible	= "ibm,mcmal2",771	},772	{},773};774 775static struct platform_driver mal_of_driver = {776	.driver = {777		.name = "mcmal",778		.of_match_table = mal_platform_match,779	},780	.probe = mal_probe,781	.remove_new = mal_remove,782};783 784int __init mal_init(void)785{786	return platform_driver_register(&mal_of_driver);787}788 789void mal_exit(void)790{791	platform_driver_unregister(&mal_of_driver);792}793