devices/ccat/netdev.c
changeset 2589 2b9c78543663
equal deleted inserted replaced
2415:af21f0bdc7c9 2589:2b9c78543663
       
     1 /**
       
     2     Network Driver for Beckhoff CCAT communication controller
       
     3     Copyright (C) 2014  Beckhoff Automation GmbH
       
     4     Author: Patrick Bruenn <p.bruenn@beckhoff.com>
       
     5 
       
     6     This program is free software; you can redistribute it and/or modify
       
     7     it under the terms of the GNU General Public License as published by
       
     8     the Free Software Foundation; either version 2 of the License, or
       
     9     (at your option) any later version.
       
    10 
       
    11     This program is distributed in the hope that it will be useful,
       
    12     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    14     GNU General Public License for more details.
       
    15 
       
    16     You should have received a copy of the GNU General Public License along
       
    17     with this program; if not, write to the Free Software Foundation, Inc.,
       
    18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19 */
       
    20 
       
    21 #include <linux/etherdevice.h>
       
    22 #include <linux/kernel.h>
       
    23 #include <linux/module.h>
       
    24 #include <linux/netdevice.h>
       
    25 
       
    26 #include "module.h"
       
    27 #include "netdev.h"
       
    28 
       
    29 /**
       
    30  * EtherCAT frame to enable forwarding on EtherCAT Terminals
       
    31  */
       
    32 static const u8 frameForwardEthernetFrames[] = {
       
    33 	0x01, 0x01, 0x05, 0x01, 0x00, 0x00,
       
    34 	0x00, 0x1b, 0x21, 0x36, 0x1b, 0xce,
       
    35 	0x88, 0xa4, 0x0e, 0x10,
       
    36 	0x08,
       
    37 	0x00,
       
    38 	0x00, 0x00,
       
    39 	0x00, 0x01,
       
    40 	0x02, 0x00,
       
    41 	0x00, 0x00,
       
    42 	0x00, 0x00,
       
    43 	0x00, 0x00
       
    44 };
       
    45 
       
    46 #define FIFO_LENGTH 64
       
    47 #define POLL_TIME ktime_set(0, 100 * NSEC_PER_USEC)
       
    48 
       
    49 /**
       
    50  * Helper to check if frame in tx dma memory was already marked as sent by CCAT
       
    51  */
       
    52 static inline bool ccat_eth_frame_sent(const struct ccat_eth_frame *const frame)
       
    53 {
       
    54 	return le32_to_cpu(frame->tx_flags) & CCAT_FRAME_SENT;
       
    55 }
       
    56 
       
    57 /**
       
    58  * Helper to check if frame in tx dma memory was already marked as sent by CCAT
       
    59  */
       
    60 static inline bool ccat_eth_frame_received(const struct ccat_eth_frame *const
       
    61 					   frame)
       
    62 {
       
    63 	return le32_to_cpu(frame->rx_flags) & CCAT_FRAME_RECEIVED;
       
    64 }
       
    65 
       
    66 static void ecdev_kfree_skb_any(struct sk_buff *skb)
       
    67 {
       
    68 	/* never release a skb in EtherCAT mode */
       
    69 }
       
    70 
       
    71 static bool ecdev_carrier_ok(const struct net_device *const netdev)
       
    72 {
       
    73 	struct ccat_eth_priv *const priv = netdev_priv(netdev);
       
    74 	return ecdev_get_link(priv->ecdev);
       
    75 }
       
    76 
       
    77 static void ecdev_carrier_on(struct net_device *const netdev)
       
    78 {
       
    79 	struct ccat_eth_priv *const priv = netdev_priv(netdev);
       
    80 	ecdev_set_link(priv->ecdev, 1);
       
    81 }
       
    82 
       
    83 static void ecdev_carrier_off(struct net_device *const netdev)
       
    84 {
       
    85 	struct ccat_eth_priv *const priv = netdev_priv(netdev);
       
    86 	ecdev_set_link(priv->ecdev, 0);
       
    87 }
       
    88 
       
    89 static void ecdev_nop(struct net_device *const netdev)
       
    90 {
       
    91 	/* dummy called if nothing has to be done in EtherCAT operation mode */
       
    92 }
       
    93 
       
    94 static void unregister_ecdev(struct net_device *const netdev)
       
    95 {
       
    96 	struct ccat_eth_priv *const priv = netdev_priv(netdev);
       
    97 	ecdev_close(priv->ecdev);
       
    98 	ecdev_withdraw(priv->ecdev);
       
    99 }
       
   100 
       
   101 static void ccat_eth_fifo_inc(struct ccat_eth_dma_fifo *fifo)
       
   102 {
       
   103 	if (++fifo->next >= fifo->end)
       
   104 		fifo->next = fifo->dma.virt;
       
   105 }
       
   106 
       
   107 typedef void (*fifo_add_function) (struct ccat_eth_dma_fifo *,
       
   108 				   struct ccat_eth_frame *);
       
   109 
       
   110 static void ccat_eth_rx_fifo_add(struct ccat_eth_dma_fifo *fifo,
       
   111 				 struct ccat_eth_frame *frame)
       
   112 {
       
   113 	const size_t offset = ((void *)(frame) - fifo->dma.virt);
       
   114 	const u32 addr_and_length = (1 << 31) | offset;
       
   115 
       
   116 	frame->rx_flags = cpu_to_le32(0);
       
   117 	iowrite32(addr_and_length, fifo->reg);
       
   118 }
       
   119 
       
   120 static void ccat_eth_tx_fifo_add_free(struct ccat_eth_dma_fifo *fifo,
       
   121 				      struct ccat_eth_frame *frame)
       
   122 {
       
   123 	/* mark frame as ready to use for tx */
       
   124 	frame->tx_flags = cpu_to_le32(CCAT_FRAME_SENT);
       
   125 }
       
   126 
       
   127 static void ccat_eth_dma_fifo_reset(struct ccat_eth_dma_fifo *fifo)
       
   128 {
       
   129 	/* reset hw fifo */
       
   130 	iowrite32(0, fifo->reg + 0x8);
       
   131 	wmb();
       
   132 
       
   133 	if (fifo->add) {
       
   134 		fifo->next = fifo->dma.virt;
       
   135 		do {
       
   136 			fifo->add(fifo, fifo->next);
       
   137 			ccat_eth_fifo_inc(fifo);
       
   138 		} while (fifo->next != fifo->dma.virt);
       
   139 	}
       
   140 }
       
   141 
       
   142 static int ccat_eth_dma_fifo_init(struct ccat_eth_dma_fifo *fifo,
       
   143 				  void __iomem * const fifo_reg,
       
   144 				  fifo_add_function add, size_t channel,
       
   145 				  struct ccat_eth_priv *const priv)
       
   146 {
       
   147 	if (0 !=
       
   148 	    ccat_dma_init(&fifo->dma, channel, priv->ccatdev->bar[2].ioaddr,
       
   149 			  &priv->ccatdev->pdev->dev)) {
       
   150 		pr_info("init DMA%llu memory failed.\n", (u64) channel);
       
   151 		return -1;
       
   152 	}
       
   153 	fifo->add = add;
       
   154 	fifo->end = ((struct ccat_eth_frame *)fifo->dma.virt) + FIFO_LENGTH;
       
   155 	fifo->reg = fifo_reg;
       
   156 	return 0;
       
   157 }
       
   158 
       
   159 /**
       
   160  * Stop both (Rx/Tx) DMA fifo's and free related management structures
       
   161  */
       
   162 static void ccat_eth_priv_free_dma(struct ccat_eth_priv *priv)
       
   163 {
       
   164 	/* reset hw fifo's */
       
   165 	iowrite32(0, priv->rx_fifo.reg + 0x8);
       
   166 	iowrite32(0, priv->tx_fifo.reg + 0x8);
       
   167 	wmb();
       
   168 
       
   169 	/* release dma */
       
   170 	ccat_dma_free(&priv->rx_fifo.dma);
       
   171 	ccat_dma_free(&priv->tx_fifo.dma);
       
   172 }
       
   173 
       
   174 /**
       
   175  * Initalizes both (Rx/Tx) DMA fifo's and related management structures
       
   176  */
       
   177 static int ccat_eth_priv_init_dma(struct ccat_eth_priv *priv)
       
   178 {
       
   179 	if (ccat_eth_dma_fifo_init
       
   180 	    (&priv->rx_fifo, priv->reg.rx_fifo, ccat_eth_rx_fifo_add,
       
   181 	     priv->info.rx_dma_chan, priv)) {
       
   182 		pr_warn("init Rx DMA fifo failed.\n");
       
   183 		return -1;
       
   184 	}
       
   185 
       
   186 	if (ccat_eth_dma_fifo_init
       
   187 	    (&priv->tx_fifo, priv->reg.tx_fifo, ccat_eth_tx_fifo_add_free,
       
   188 	     priv->info.tx_dma_chan, priv)) {
       
   189 		pr_warn("init Tx DMA fifo failed.\n");
       
   190 		ccat_dma_free(&priv->rx_fifo.dma);
       
   191 		return -1;
       
   192 	}
       
   193 
       
   194 	/* disable MAC filter */
       
   195 	iowrite8(0, priv->reg.mii + 0x8 + 6);
       
   196 	wmb();
       
   197 	return 0;
       
   198 }
       
   199 
       
   200 /**
       
   201  * Initializes the CCat... members of the ccat_eth_priv structure.
       
   202  * Call this function only if info and ioaddr are already initialized!
       
   203  */
       
   204 static void ccat_eth_priv_init_mappings(struct ccat_eth_priv *priv)
       
   205 {
       
   206 	struct ccat_mac_infoblock offsets;
       
   207 	void __iomem *const func_base =
       
   208 	    priv->ccatdev->bar[0].ioaddr + priv->info.addr;
       
   209 
       
   210 	memcpy_fromio(&offsets, func_base, sizeof(offsets));
       
   211 	priv->reg.mii = func_base + offsets.mii;
       
   212 	priv->reg.tx_fifo = func_base + offsets.tx_fifo;
       
   213 	priv->reg.rx_fifo = func_base + offsets.tx_fifo + 0x10;
       
   214 	priv->reg.mac = func_base + offsets.mac;
       
   215 	priv->reg.rx_mem = func_base + offsets.rx_mem;
       
   216 	priv->reg.tx_mem = func_base + offsets.tx_mem;
       
   217 	priv->reg.misc = func_base + offsets.misc;
       
   218 }
       
   219 
       
   220 static netdev_tx_t ccat_eth_start_xmit(struct sk_buff *skb,
       
   221 				       struct net_device *dev)
       
   222 {
       
   223 	struct ccat_eth_priv *const priv = netdev_priv(dev);
       
   224 	struct ccat_eth_dma_fifo *const fifo = &priv->tx_fifo;
       
   225 	u32 addr_and_length;
       
   226 
       
   227 	if (skb_is_nonlinear(skb)) {
       
   228 		pr_warn("Non linear skb not supported -> drop frame.\n");
       
   229 		atomic64_inc(&priv->tx_dropped);
       
   230 		priv->kfree_skb_any(skb);
       
   231 		return NETDEV_TX_OK;
       
   232 	}
       
   233 
       
   234 	if (skb->len > sizeof(fifo->next->data)) {
       
   235 		pr_warn("skb.len %llu exceeds dma buffer %llu -> drop frame.\n",
       
   236 			(u64) skb->len, (u64) sizeof(fifo->next->data));
       
   237 		atomic64_inc(&priv->tx_dropped);
       
   238 		priv->kfree_skb_any(skb);
       
   239 		return NETDEV_TX_OK;
       
   240 	}
       
   241 
       
   242 	if (!ccat_eth_frame_sent(fifo->next)) {
       
   243 		netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
       
   244 		priv->stop_queue(priv->netdev);
       
   245 		return NETDEV_TX_BUSY;
       
   246 	}
       
   247 
       
   248 	/* prepare frame in DMA memory */
       
   249 	fifo->next->tx_flags = cpu_to_le32(0);
       
   250 	fifo->next->length = cpu_to_le16(skb->len);
       
   251 	memcpy(fifo->next->data, skb->data, skb->len);
       
   252 
       
   253 	/* Queue frame into CCAT TX-FIFO, CCAT ignores the first 8 bytes of the tx descriptor */
       
   254 	addr_and_length = offsetof(struct ccat_eth_frame, length);
       
   255 	addr_and_length += ((void *)fifo->next - fifo->dma.virt);
       
   256 	addr_and_length += ((skb->len + CCAT_ETH_FRAME_HEAD_LEN) / 8) << 24;
       
   257 	iowrite32(addr_and_length, priv->reg.tx_fifo);
       
   258 
       
   259 	/* update stats */
       
   260 	atomic64_add(skb->len, &priv->tx_bytes);
       
   261 
       
   262 	priv->kfree_skb_any(skb);
       
   263 
       
   264 	ccat_eth_fifo_inc(fifo);
       
   265 	/* stop queue if tx ring is full */
       
   266 	if (!ccat_eth_frame_sent(fifo->next)) {
       
   267 		priv->stop_queue(priv->netdev);
       
   268 	}
       
   269 	return NETDEV_TX_OK;
       
   270 }
       
   271 
       
   272 /**
       
   273  * Function to transmit a raw buffer to the network (f.e. frameForwardEthernetFrames)
       
   274  * @dev a valid net_device
       
   275  * @data pointer to your raw buffer
       
   276  * @len number of bytes in the raw buffer to transmit
       
   277  */
       
   278 static void ccat_eth_xmit_raw(struct net_device *dev, const char *const data,
       
   279 			      size_t len)
       
   280 {
       
   281 	struct sk_buff *skb = dev_alloc_skb(len);
       
   282 
       
   283 	skb->dev = dev;
       
   284 	skb_copy_to_linear_data(skb, data, len);
       
   285 	skb_put(skb, len);
       
   286 	ccat_eth_start_xmit(skb, dev);
       
   287 }
       
   288 
       
   289 static void ccat_eth_receive(struct net_device *const dev,
       
   290 			     const void *const data, const size_t len)
       
   291 {
       
   292 	struct sk_buff *const skb = dev_alloc_skb(len + NET_IP_ALIGN);
       
   293 	struct ccat_eth_priv *const priv = netdev_priv(dev);
       
   294 
       
   295 	if (!skb) {
       
   296 		pr_info("%s() out of memory :-(\n", __FUNCTION__);
       
   297 		atomic64_inc(&priv->rx_dropped);
       
   298 		return;
       
   299 	}
       
   300 	skb->dev = dev;
       
   301 	skb_reserve(skb, NET_IP_ALIGN);
       
   302 	skb_copy_to_linear_data(skb, data, len);
       
   303 	skb_put(skb, len);
       
   304 	skb->protocol = eth_type_trans(skb, dev);
       
   305 	skb->ip_summed = CHECKSUM_UNNECESSARY;
       
   306 	atomic64_add(len, &priv->rx_bytes);
       
   307 	netif_rx(skb);
       
   308 }
       
   309 
       
   310 static void ccat_eth_link_down(struct net_device *const dev)
       
   311 {
       
   312 	struct ccat_eth_priv *const priv = netdev_priv(dev);
       
   313 
       
   314 	priv->stop_queue(dev);
       
   315 	priv->carrier_off(dev);
       
   316 	netdev_info(dev, "NIC Link is Down\n");
       
   317 }
       
   318 
       
   319 static void ccat_eth_link_up(struct net_device *const dev)
       
   320 {
       
   321 	struct ccat_eth_priv *const priv = netdev_priv(dev);
       
   322 
       
   323 	netdev_info(dev, "NIC Link is Up\n");
       
   324 	/* TODO netdev_info(dev, "NIC Link is Up %u Mbps %s Duplex\n",
       
   325 	   speed == SPEED_100 ? 100 : 10,
       
   326 	   cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); */
       
   327 
       
   328 	ccat_eth_dma_fifo_reset(&priv->rx_fifo);
       
   329 	ccat_eth_dma_fifo_reset(&priv->tx_fifo);
       
   330 
       
   331 	/* TODO reset CCAT MAC register */
       
   332 
       
   333 	ccat_eth_xmit_raw(dev, frameForwardEthernetFrames,
       
   334 			  sizeof(frameForwardEthernetFrames));
       
   335 	priv->carrier_on(dev);
       
   336 	priv->start_queue(dev);
       
   337 }
       
   338 
       
   339 /**
       
   340  * Read link state from CCAT hardware
       
   341  * @return 1 if link is up, 0 if not
       
   342  */
       
   343 inline static size_t ccat_eth_priv_read_link_state(const struct ccat_eth_priv
       
   344 						   *const priv)
       
   345 {
       
   346 	return (1 << 24) == (ioread32(priv->reg.mii + 0x8 + 4) & (1 << 24));
       
   347 }
       
   348 
       
   349 /**
       
   350  * Poll for link state changes
       
   351  */
       
   352 static void poll_link(struct ccat_eth_priv *const priv)
       
   353 {
       
   354 	const size_t link = ccat_eth_priv_read_link_state(priv);
       
   355 
       
   356 	if (link != priv->carrier_ok(priv->netdev)) {
       
   357 		if (link)
       
   358 			ccat_eth_link_up(priv->netdev);
       
   359 		else
       
   360 			ccat_eth_link_down(priv->netdev);
       
   361 	}
       
   362 }
       
   363 
       
   364 /**
       
   365  * Poll for available rx dma descriptors in ethernet operating mode
       
   366  */
       
   367 static void poll_rx(struct ccat_eth_priv *const priv)
       
   368 {
       
   369 	static const size_t overhead = CCAT_ETH_FRAME_HEAD_LEN - 4;
       
   370 	struct ccat_eth_dma_fifo *const fifo = &priv->rx_fifo;
       
   371 
       
   372 	/* TODO omit possible deadlock in situations with heavy traffic */
       
   373 	while (ccat_eth_frame_received(fifo->next)) {
       
   374 		const size_t len = le16_to_cpu(fifo->next->length) - overhead;
       
   375 		if (priv->ecdev) {
       
   376 			ecdev_receive(priv->ecdev, fifo->next->data, len);
       
   377 		} else {
       
   378 			ccat_eth_receive(priv->netdev, fifo->next->data, len);
       
   379 		}
       
   380 		ccat_eth_rx_fifo_add(fifo, fifo->next);
       
   381 		ccat_eth_fifo_inc(fifo);
       
   382 	}
       
   383 }
       
   384 
       
   385 static void ec_poll_rx(struct net_device *dev)
       
   386 {
       
   387 	struct ccat_eth_priv *const priv = netdev_priv(dev);
       
   388 	poll_rx(priv);
       
   389 }
       
   390 
       
   391 /**
       
   392  * Poll for available tx dma descriptors in ethernet operating mode
       
   393  */
       
   394 static void poll_tx(struct ccat_eth_priv *const priv)
       
   395 {
       
   396 	if (ccat_eth_frame_sent(priv->tx_fifo.next)) {
       
   397 		netif_wake_queue(priv->netdev);
       
   398 	}
       
   399 }
       
   400 
       
   401 /**
       
   402  * Since CCAT doesn't support interrupts until now, we have to poll
       
   403  * some status bits to recognize things like link change etc.
       
   404  */
       
   405 static enum hrtimer_restart poll_timer_callback(struct hrtimer *timer)
       
   406 {
       
   407 	struct ccat_eth_priv *const priv =
       
   408 	    container_of(timer, struct ccat_eth_priv, poll_timer);
       
   409 
       
   410 	poll_link(priv);
       
   411 	if(!priv->ecdev) {
       
   412 		poll_rx(priv);
       
   413 		poll_tx(priv);
       
   414 	}
       
   415 	hrtimer_forward_now(timer, POLL_TIME);
       
   416 	return HRTIMER_RESTART;
       
   417 }
       
   418 
       
   419 static struct rtnl_link_stats64 *ccat_eth_get_stats64(struct net_device *dev, struct rtnl_link_stats64
       
   420 						      *storage)
       
   421 {
       
   422 	struct ccat_eth_priv *const priv = netdev_priv(dev);
       
   423 	struct ccat_mac_register mac;
       
   424 	memcpy_fromio(&mac, priv->reg.mac, sizeof(mac));
       
   425 	storage->rx_packets = mac.rx_frames;	/* total packets received       */
       
   426 	storage->tx_packets = mac.tx_frames;	/* total packets transmitted    */
       
   427 	storage->rx_bytes = atomic64_read(&priv->rx_bytes);	/* total bytes received         */
       
   428 	storage->tx_bytes = atomic64_read(&priv->tx_bytes);	/* total bytes transmitted      */
       
   429 	storage->rx_errors = mac.frame_len_err + mac.rx_mem_full + mac.crc_err + mac.rx_err;	/* bad packets received         */
       
   430 	storage->tx_errors = mac.tx_mem_full;	/* packet transmit problems     */
       
   431 	storage->rx_dropped = atomic64_read(&priv->rx_dropped);	/* no space in linux buffers    */
       
   432 	storage->tx_dropped = atomic64_read(&priv->tx_dropped);	/* no space available in linux  */
       
   433 	//TODO __u64    multicast;              /* multicast packets received   */
       
   434 	//TODO __u64    collisions;
       
   435 
       
   436 	/* detailed rx_errors: */
       
   437 	storage->rx_length_errors = mac.frame_len_err;
       
   438 	storage->rx_over_errors = mac.rx_mem_full;	/* receiver ring buff overflow  */
       
   439 	storage->rx_crc_errors = mac.crc_err;	/* recved pkt with crc error    */
       
   440 	storage->rx_frame_errors = mac.rx_err;	/* recv'd frame alignment error */
       
   441 	storage->rx_fifo_errors = mac.rx_mem_full;	/* recv'r fifo overrun          */
       
   442 	//TODO __u64    rx_missed_errors;       /* receiver missed packet       */
       
   443 
       
   444 	/* detailed tx_errors */
       
   445 	//TODO __u64    tx_aborted_errors;
       
   446 	//TODO __u64    tx_carrier_errors;
       
   447 	//TODO __u64    tx_fifo_errors;
       
   448 	//TODO __u64    tx_heartbeat_errors;
       
   449 	//TODO __u64    tx_window_errors;
       
   450 
       
   451 	/* for cslip etc */
       
   452 	//TODO __u64    rx_compressed;
       
   453 	//TODO __u64    tx_compressed;
       
   454 	return storage;
       
   455 }
       
   456 
       
   457 static int ccat_eth_open(struct net_device *dev)
       
   458 {
       
   459 	struct ccat_eth_priv *const priv = netdev_priv(dev);
       
   460 
       
   461 	hrtimer_init(&priv->poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
       
   462 	priv->poll_timer.function = poll_timer_callback;
       
   463 	hrtimer_start(&priv->poll_timer, POLL_TIME, HRTIMER_MODE_REL);
       
   464 	return 0;
       
   465 }
       
   466 
       
   467 static int ccat_eth_stop(struct net_device *dev)
       
   468 {
       
   469 	struct ccat_eth_priv *const priv = netdev_priv(dev);
       
   470 
       
   471 	priv->stop_queue(dev);
       
   472 	hrtimer_cancel(&priv->poll_timer);
       
   473 	return 0;
       
   474 }
       
   475 
       
   476 static const struct net_device_ops ccat_eth_netdev_ops = {
       
   477 	.ndo_get_stats64 = ccat_eth_get_stats64,
       
   478 	.ndo_open = ccat_eth_open,
       
   479 	.ndo_start_xmit = ccat_eth_start_xmit,
       
   480 	.ndo_stop = ccat_eth_stop,
       
   481 };
       
   482 
       
   483 struct ccat_eth_priv *ccat_eth_init(const struct ccat_device *const ccatdev,
       
   484 				    const void __iomem * const addr)
       
   485 {
       
   486 	struct ccat_eth_priv *priv;
       
   487 	struct net_device *const netdev = alloc_etherdev(sizeof(*priv));
       
   488 
       
   489 	priv = netdev_priv(netdev);
       
   490 	priv->netdev = netdev;
       
   491 	priv->ccatdev = ccatdev;
       
   492 
       
   493 	/* ccat register mappings */
       
   494 	memcpy_fromio(&priv->info, addr, sizeof(priv->info));
       
   495 	ccat_eth_priv_init_mappings(priv);
       
   496 
       
   497 	if (ccat_eth_priv_init_dma(priv)) {
       
   498 		pr_warn("%s(): DMA initialization failed.\n", __FUNCTION__);
       
   499 		free_netdev(netdev);
       
   500 		return NULL;
       
   501 	}
       
   502 
       
   503 	/* init netdev with MAC and stack callbacks */
       
   504 	memcpy_fromio(netdev->dev_addr, priv->reg.mii + 8, netdev->addr_len);
       
   505 	netdev->netdev_ops = &ccat_eth_netdev_ops;
       
   506 
       
   507 	/* use as EtherCAT device? */
       
   508 	priv->ecdev = ecdev_offer(netdev, ec_poll_rx, THIS_MODULE);
       
   509 	if (priv->ecdev) {
       
   510 		priv->carrier_off = ecdev_carrier_off;
       
   511 		priv->carrier_ok = ecdev_carrier_ok;
       
   512 		priv->carrier_on = ecdev_carrier_on;
       
   513 		priv->kfree_skb_any = ecdev_kfree_skb_any;
       
   514 		priv->start_queue = ecdev_nop;
       
   515 		priv->stop_queue = ecdev_nop;
       
   516 		priv->unregister = unregister_ecdev;
       
   517 
       
   518 		priv->carrier_off(netdev);
       
   519 		if (ecdev_open(priv->ecdev)) {
       
   520 			pr_info("unable to register network device.\n");
       
   521 			ecdev_withdraw(priv->ecdev);
       
   522 			ccat_eth_priv_free_dma(priv);
       
   523 			free_netdev(netdev);
       
   524 			return NULL;
       
   525 		}
       
   526 		return priv;
       
   527 	}
       
   528 
       
   529 	/* EtherCAT disabled -> prepare normal ethernet mode */
       
   530 	priv->carrier_off = netif_carrier_off;
       
   531 	priv->carrier_ok = netif_carrier_ok;
       
   532 	priv->carrier_on = netif_carrier_on;
       
   533 	priv->kfree_skb_any = dev_kfree_skb_any;
       
   534 	priv->start_queue = netif_start_queue;
       
   535 	priv->stop_queue = netif_stop_queue;
       
   536 	priv->unregister = unregister_netdev;
       
   537 
       
   538 	priv->carrier_off(netdev);
       
   539 	if (register_netdev(netdev)) {
       
   540 		pr_info("unable to register network device.\n");
       
   541 		ccat_eth_priv_free_dma(priv);
       
   542 		free_netdev(netdev);
       
   543 		return NULL;
       
   544 	}
       
   545 	pr_info("registered %s as network device.\n", netdev->name);
       
   546 	return priv;
       
   547 }
       
   548 
       
   549 void ccat_eth_remove(struct ccat_eth_priv *const priv)
       
   550 {
       
   551 	priv->unregister(priv->netdev);
       
   552 	ccat_eth_priv_free_dma(priv);
       
   553 	free_netdev(priv->netdev);
       
   554 }