blob: 220ff3da4521211ed8307ae7d37be84cbcfaf632 [file] [log] [blame]
Taku Izumi658d4392015-08-21 17:29:17 +09001/*
2 * FUJITSU Extended Socket Network Device driver
3 * Copyright (c) 2015 FUJITSU LIMITED
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * The full GNU General Public License is included in this distribution in
18 * the file called "COPYING".
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/types.h>
24#include <linux/nls.h>
25#include <linux/platform_device.h>
Taku Izumi2fcbca62015-08-21 17:29:20 +090026#include <linux/netdevice.h>
Taku Izumie5d486d2015-08-21 17:29:23 +090027#include <linux/interrupt.h>
Taku Izumi658d4392015-08-21 17:29:17 +090028
29#include "fjes.h"
30
31#define MAJ 1
32#define MIN 0
33#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
34#define DRV_NAME "fjes"
35char fjes_driver_name[] = DRV_NAME;
36char fjes_driver_version[] = DRV_VERSION;
37static const char fjes_driver_string[] =
38 "FUJITSU Extended Socket Network Device Driver";
39static const char fjes_copyright[] =
40 "Copyright (c) 2015 FUJITSU LIMITED";
41
42MODULE_AUTHOR("Taku Izumi <izumi.taku@jp.fujitsu.com>");
43MODULE_DESCRIPTION("FUJITSU Extended Socket Network Device Driver");
44MODULE_LICENSE("GPL");
45MODULE_VERSION(DRV_VERSION);
46
Taku Izumie5d486d2015-08-21 17:29:23 +090047static int fjes_request_irq(struct fjes_adapter *);
48static void fjes_free_irq(struct fjes_adapter *);
49
50static int fjes_open(struct net_device *);
51static int fjes_close(struct net_device *);
52static int fjes_setup_resources(struct fjes_adapter *);
53static void fjes_free_resources(struct fjes_adapter *);
Taku Izumi9acf51c2015-08-21 17:29:24 +090054static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *);
Taku Izumie5d486d2015-08-21 17:29:23 +090055static irqreturn_t fjes_intr(int, void*);
56
Taku Izumi658d4392015-08-21 17:29:17 +090057static int fjes_acpi_add(struct acpi_device *);
58static int fjes_acpi_remove(struct acpi_device *);
59static acpi_status fjes_get_acpi_resource(struct acpi_resource *, void*);
60
61static int fjes_probe(struct platform_device *);
62static int fjes_remove(struct platform_device *);
63
Taku Izumi2fcbca62015-08-21 17:29:20 +090064static int fjes_sw_init(struct fjes_adapter *);
65static void fjes_netdev_setup(struct net_device *);
66
Taku Izumi658d4392015-08-21 17:29:17 +090067static const struct acpi_device_id fjes_acpi_ids[] = {
68 {"PNP0C02", 0},
69 {"", 0},
70};
71MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids);
72
73static struct acpi_driver fjes_acpi_driver = {
74 .name = DRV_NAME,
75 .class = DRV_NAME,
76 .owner = THIS_MODULE,
77 .ids = fjes_acpi_ids,
78 .ops = {
79 .add = fjes_acpi_add,
80 .remove = fjes_acpi_remove,
81 },
82};
83
84static struct platform_driver fjes_driver = {
85 .driver = {
86 .name = DRV_NAME,
87 .owner = THIS_MODULE,
88 },
89 .probe = fjes_probe,
90 .remove = fjes_remove,
91};
92
93static struct resource fjes_resource[] = {
94 {
95 .flags = IORESOURCE_MEM,
96 .start = 0,
97 .end = 0,
98 },
99 {
100 .flags = IORESOURCE_IRQ,
101 .start = 0,
102 .end = 0,
103 },
104};
105
106static int fjes_acpi_add(struct acpi_device *device)
107{
108 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
109 char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1];
110 struct platform_device *plat_dev;
111 union acpi_object *str;
112 acpi_status status;
113 int result;
114
115 status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer);
116 if (ACPI_FAILURE(status))
117 return -ENODEV;
118
119 str = buffer.pointer;
120 result = utf16s_to_utf8s((wchar_t *)str->string.pointer,
121 str->string.length, UTF16_LITTLE_ENDIAN,
122 str_buf, sizeof(str_buf) - 1);
123 str_buf[result] = 0;
124
125 if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) {
126 kfree(buffer.pointer);
127 return -ENODEV;
128 }
129 kfree(buffer.pointer);
130
131 status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
132 fjes_get_acpi_resource, fjes_resource);
133 if (ACPI_FAILURE(status))
134 return -ENODEV;
135
136 /* create platform_device */
137 plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource,
138 ARRAY_SIZE(fjes_resource));
139 device->driver_data = plat_dev;
140
141 return 0;
142}
143
144static int fjes_acpi_remove(struct acpi_device *device)
145{
146 struct platform_device *plat_dev;
147
148 plat_dev = (struct platform_device *)acpi_driver_data(device);
149 platform_device_unregister(plat_dev);
150
151 return 0;
152}
153
154static acpi_status
155fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data)
156{
157 struct acpi_resource_address32 *addr;
158 struct acpi_resource_irq *irq;
159 struct resource *res = data;
160
161 switch (acpi_res->type) {
162 case ACPI_RESOURCE_TYPE_ADDRESS32:
163 addr = &acpi_res->data.address32;
164 res[0].start = addr->address.minimum;
165 res[0].end = addr->address.minimum +
166 addr->address.address_length - 1;
167 break;
168
169 case ACPI_RESOURCE_TYPE_IRQ:
170 irq = &acpi_res->data.irq;
171 if (irq->interrupt_count != 1)
172 return AE_ERROR;
173 res[1].start = irq->interrupts[0];
174 res[1].end = irq->interrupts[0];
175 break;
176
177 default:
178 break;
179 }
180
181 return AE_OK;
182}
183
Taku Izumie5d486d2015-08-21 17:29:23 +0900184static int fjes_request_irq(struct fjes_adapter *adapter)
185{
186 struct net_device *netdev = adapter->netdev;
187 int result = -1;
188
189 if (!adapter->irq_registered) {
190 result = request_irq(adapter->hw.hw_res.irq, fjes_intr,
191 IRQF_SHARED, netdev->name, adapter);
192 if (result)
193 adapter->irq_registered = false;
194 else
195 adapter->irq_registered = true;
196 }
197
198 return result;
199}
200
201static void fjes_free_irq(struct fjes_adapter *adapter)
202{
203 struct fjes_hw *hw = &adapter->hw;
204
205 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
206
207 if (adapter->irq_registered) {
208 free_irq(adapter->hw.hw_res.irq, adapter);
209 adapter->irq_registered = false;
210 }
211}
212
Taku Izumi2fcbca62015-08-21 17:29:20 +0900213static const struct net_device_ops fjes_netdev_ops = {
Taku Izumie5d486d2015-08-21 17:29:23 +0900214 .ndo_open = fjes_open,
215 .ndo_stop = fjes_close,
Taku Izumi9acf51c2015-08-21 17:29:24 +0900216 .ndo_start_xmit = fjes_xmit_frame,
Taku Izumi2fcbca62015-08-21 17:29:20 +0900217};
218
Taku Izumie5d486d2015-08-21 17:29:23 +0900219/* fjes_open - Called when a network interface is made active */
220static int fjes_open(struct net_device *netdev)
221{
222 struct fjes_adapter *adapter = netdev_priv(netdev);
223 struct fjes_hw *hw = &adapter->hw;
224 int result;
225
226 if (adapter->open_guard)
227 return -ENXIO;
228
229 result = fjes_setup_resources(adapter);
230 if (result)
231 goto err_setup_res;
232
233 hw->txrx_stop_req_bit = 0;
234 hw->epstop_req_bit = 0;
235
236 fjes_hw_capture_interrupt_status(hw);
237
238 result = fjes_request_irq(adapter);
239 if (result)
240 goto err_req_irq;
241
242 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, false);
243
244 netif_tx_start_all_queues(netdev);
245 netif_carrier_on(netdev);
246
247 return 0;
248
249err_req_irq:
250 fjes_free_irq(adapter);
251
252err_setup_res:
253 fjes_free_resources(adapter);
254 return result;
255}
256
257/* fjes_close - Disables a network interface */
258static int fjes_close(struct net_device *netdev)
259{
260 struct fjes_adapter *adapter = netdev_priv(netdev);
261 struct fjes_hw *hw = &adapter->hw;
262 int epidx;
263
264 netif_tx_stop_all_queues(netdev);
265 netif_carrier_off(netdev);
266
267 fjes_hw_raise_epstop(hw);
268
269 for (epidx = 0; epidx < hw->max_epid; epidx++) {
270 if (epidx == hw->my_epid)
271 continue;
272
273 adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &=
274 ~FJES_RX_POLL_WORK;
275 }
276
277 fjes_free_irq(adapter);
278
279 fjes_hw_wait_epstop(hw);
280
281 fjes_free_resources(adapter);
282
283 return 0;
284}
285
286static int fjes_setup_resources(struct fjes_adapter *adapter)
287{
288 struct net_device *netdev = adapter->netdev;
289 struct ep_share_mem_info *buf_pair;
290 struct fjes_hw *hw = &adapter->hw;
291 int result;
292 int epidx;
293
294 mutex_lock(&hw->hw_info.lock);
295 result = fjes_hw_request_info(hw);
296 switch (result) {
297 case 0:
298 for (epidx = 0; epidx < hw->max_epid; epidx++) {
299 hw->ep_shm_info[epidx].es_status =
300 hw->hw_info.res_buf->info.info[epidx].es_status;
301 hw->ep_shm_info[epidx].zone =
302 hw->hw_info.res_buf->info.info[epidx].zone;
303 }
304 break;
305 default:
306 case -ENOMSG:
307 case -EBUSY:
308 adapter->force_reset = true;
309
310 mutex_unlock(&hw->hw_info.lock);
311 return result;
312 }
313 mutex_unlock(&hw->hw_info.lock);
314
315 for (epidx = 0; epidx < (hw->max_epid); epidx++) {
316 if ((epidx != hw->my_epid) &&
317 (hw->ep_shm_info[epidx].es_status ==
318 FJES_ZONING_STATUS_ENABLE)) {
319 fjes_hw_raise_interrupt(hw, epidx,
320 REG_ICTL_MASK_INFO_UPDATE);
321 }
322 }
323
324 msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid);
325
326 for (epidx = 0; epidx < (hw->max_epid); epidx++) {
327 if (epidx == hw->my_epid)
328 continue;
329
330 buf_pair = &hw->ep_shm_info[epidx];
331
332 fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr,
333 netdev->mtu);
334
335 if (fjes_hw_epid_is_same_zone(hw, epidx)) {
336 mutex_lock(&hw->hw_info.lock);
337 result =
338 fjes_hw_register_buff_addr(hw, epidx, buf_pair);
339 mutex_unlock(&hw->hw_info.lock);
340
341 switch (result) {
342 case 0:
343 break;
344 case -ENOMSG:
345 case -EBUSY:
346 default:
347 adapter->force_reset = true;
348 return result;
349 }
350 }
351 }
352
353 return 0;
354}
355
356static void fjes_free_resources(struct fjes_adapter *adapter)
357{
358 struct net_device *netdev = adapter->netdev;
359 struct fjes_device_command_param param;
360 struct ep_share_mem_info *buf_pair;
361 struct fjes_hw *hw = &adapter->hw;
362 bool reset_flag = false;
363 int result;
364 int epidx;
365
366 for (epidx = 0; epidx < hw->max_epid; epidx++) {
367 if (epidx == hw->my_epid)
368 continue;
369
370 mutex_lock(&hw->hw_info.lock);
371 result = fjes_hw_unregister_buff_addr(hw, epidx);
372 mutex_unlock(&hw->hw_info.lock);
373
374 if (result)
375 reset_flag = true;
376
377 buf_pair = &hw->ep_shm_info[epidx];
378
379 fjes_hw_setup_epbuf(&buf_pair->tx,
380 netdev->dev_addr, netdev->mtu);
381
382 clear_bit(epidx, &hw->txrx_stop_req_bit);
383 }
384
385 if (reset_flag || adapter->force_reset) {
386 result = fjes_hw_reset(hw);
387
388 adapter->force_reset = false;
389
390 if (result)
391 adapter->open_guard = true;
392
393 hw->hw_info.buffer_share_bit = 0;
394
395 memset((void *)&param, 0, sizeof(param));
396
397 param.req_len = hw->hw_info.req_buf_size;
398 param.req_start = __pa(hw->hw_info.req_buf);
399 param.res_len = hw->hw_info.res_buf_size;
400 param.res_start = __pa(hw->hw_info.res_buf);
401 param.share_start = __pa(hw->hw_info.share->ep_status);
402
403 fjes_hw_init_command_registers(hw, &param);
404 }
405}
406
Taku Izumi9acf51c2015-08-21 17:29:24 +0900407static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
408 void *data, size_t len)
409{
410 int retval;
411
412 retval = fjes_hw_epbuf_tx_pkt_send(&adapter->hw.ep_shm_info[dest].tx,
413 data, len);
414 if (retval)
415 return retval;
416
417 adapter->hw.ep_shm_info[dest].tx.info->v1i.tx_status =
418 FJES_TX_DELAY_SEND_PENDING;
419
420 retval = 0;
421 return retval;
422}
423
424static netdev_tx_t
425fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
426{
427 struct fjes_adapter *adapter = netdev_priv(netdev);
428 struct fjes_hw *hw = &adapter->hw;
429
430 int max_epid, my_epid, dest_epid;
431 enum ep_partner_status pstatus;
432 struct netdev_queue *cur_queue;
433 char shortpkt[VLAN_ETH_HLEN];
434 bool is_multi, vlan;
435 struct ethhdr *eth;
436 u16 queue_no = 0;
437 u16 vlan_id = 0;
438 netdev_tx_t ret;
439 char *data;
440 int len;
441
442 ret = NETDEV_TX_OK;
443 is_multi = false;
444 cur_queue = netdev_get_tx_queue(netdev, queue_no);
445
446 eth = (struct ethhdr *)skb->data;
447 my_epid = hw->my_epid;
448
449 vlan = (vlan_get_tag(skb, &vlan_id) == 0) ? true : false;
450
451 data = skb->data;
452 len = skb->len;
453
454 if (is_multicast_ether_addr(eth->h_dest)) {
455 dest_epid = 0;
456 max_epid = hw->max_epid;
457 is_multi = true;
458 } else if (is_local_ether_addr(eth->h_dest)) {
459 dest_epid = eth->h_dest[ETH_ALEN - 1];
460 max_epid = dest_epid + 1;
461
462 if ((eth->h_dest[0] == 0x02) &&
463 (0x00 == (eth->h_dest[1] | eth->h_dest[2] |
464 eth->h_dest[3] | eth->h_dest[4])) &&
465 (dest_epid < hw->max_epid)) {
466 ;
467 } else {
468 dest_epid = 0;
469 max_epid = 0;
470 ret = NETDEV_TX_OK;
471
472 adapter->stats64.tx_packets += 1;
473 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
474 adapter->stats64.tx_bytes += len;
475 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
476 }
477 } else {
478 dest_epid = 0;
479 max_epid = 0;
480 ret = NETDEV_TX_OK;
481
482 adapter->stats64.tx_packets += 1;
483 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
484 adapter->stats64.tx_bytes += len;
485 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
486 }
487
488 for (; dest_epid < max_epid; dest_epid++) {
489 if (my_epid == dest_epid)
490 continue;
491
492 pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
493 if (pstatus != EP_PARTNER_SHARED) {
494 ret = NETDEV_TX_OK;
495 } else if (!fjes_hw_check_epbuf_version(
496 &adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
497 /* version is NOT 0 */
498 adapter->stats64.tx_carrier_errors += 1;
499 hw->ep_shm_info[my_epid].net_stats
500 .tx_carrier_errors += 1;
501
502 ret = NETDEV_TX_OK;
503 } else if (!fjes_hw_check_mtu(
504 &adapter->hw.ep_shm_info[dest_epid].rx,
505 netdev->mtu)) {
506 adapter->stats64.tx_dropped += 1;
507 hw->ep_shm_info[my_epid].net_stats.tx_dropped += 1;
508 adapter->stats64.tx_errors += 1;
509 hw->ep_shm_info[my_epid].net_stats.tx_errors += 1;
510
511 ret = NETDEV_TX_OK;
512 } else if (vlan &&
513 !fjes_hw_check_vlan_id(
514 &adapter->hw.ep_shm_info[dest_epid].rx,
515 vlan_id)) {
516 ret = NETDEV_TX_OK;
517 } else {
518 if (len < VLAN_ETH_HLEN) {
519 memset(shortpkt, 0, VLAN_ETH_HLEN);
520 memcpy(shortpkt, skb->data, skb->len);
521 len = VLAN_ETH_HLEN;
522 data = shortpkt;
523 }
524
525 if (adapter->tx_retry_count == 0) {
526 adapter->tx_start_jiffies = jiffies;
527 adapter->tx_retry_count = 1;
528 } else {
529 adapter->tx_retry_count++;
530 }
531
532 if (fjes_tx_send(adapter, dest_epid, data, len)) {
533 if (is_multi) {
534 ret = NETDEV_TX_OK;
535 } else if (
536 ((long)jiffies -
537 (long)adapter->tx_start_jiffies) >=
538 FJES_TX_RETRY_TIMEOUT) {
539 adapter->stats64.tx_fifo_errors += 1;
540 hw->ep_shm_info[my_epid].net_stats
541 .tx_fifo_errors += 1;
542 adapter->stats64.tx_errors += 1;
543 hw->ep_shm_info[my_epid].net_stats
544 .tx_errors += 1;
545
546 ret = NETDEV_TX_OK;
547 } else {
548 netdev->trans_start = jiffies;
549 netif_tx_stop_queue(cur_queue);
550
551 ret = NETDEV_TX_BUSY;
552 }
553 } else {
554 if (!is_multi) {
555 adapter->stats64.tx_packets += 1;
556 hw->ep_shm_info[my_epid].net_stats
557 .tx_packets += 1;
558 adapter->stats64.tx_bytes += len;
559 hw->ep_shm_info[my_epid].net_stats
560 .tx_bytes += len;
561 }
562
563 adapter->tx_retry_count = 0;
564 ret = NETDEV_TX_OK;
565 }
566 }
567 }
568
569 if (ret == NETDEV_TX_OK) {
570 dev_kfree_skb(skb);
571 if (is_multi) {
572 adapter->stats64.tx_packets += 1;
573 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
574 adapter->stats64.tx_bytes += 1;
575 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
576 }
577 }
578
579 return ret;
580}
581
Taku Izumie5d486d2015-08-21 17:29:23 +0900582static irqreturn_t fjes_intr(int irq, void *data)
583{
584 struct fjes_adapter *adapter = data;
585 struct fjes_hw *hw = &adapter->hw;
586 irqreturn_t ret;
587 u32 icr;
588
589 icr = fjes_hw_capture_interrupt_status(hw);
590
591 if (icr & REG_IS_MASK_IS_ASSERT)
592 ret = IRQ_HANDLED;
593 else
594 ret = IRQ_NONE;
595
596 return ret;
597}
598
Taku Izumi658d4392015-08-21 17:29:17 +0900599/* fjes_probe - Device Initialization Routine */
600static int fjes_probe(struct platform_device *plat_dev)
601{
Taku Izumi2fcbca62015-08-21 17:29:20 +0900602 struct fjes_adapter *adapter;
603 struct net_device *netdev;
604 struct resource *res;
605 struct fjes_hw *hw;
606 int err;
607
608 err = -ENOMEM;
609 netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), "es%d",
610 NET_NAME_UNKNOWN, fjes_netdev_setup,
611 FJES_MAX_QUEUES);
612
613 if (!netdev)
614 goto err_out;
615
616 SET_NETDEV_DEV(netdev, &plat_dev->dev);
617
618 dev_set_drvdata(&plat_dev->dev, netdev);
619 adapter = netdev_priv(netdev);
620 adapter->netdev = netdev;
621 adapter->plat_dev = plat_dev;
622 hw = &adapter->hw;
623 hw->back = adapter;
624
625 /* setup the private structure */
626 err = fjes_sw_init(adapter);
627 if (err)
628 goto err_free_netdev;
629
630 adapter->force_reset = false;
631 adapter->open_guard = false;
632
633 res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
634 hw->hw_res.start = res->start;
635 hw->hw_res.size = res->end - res->start + 1;
636 hw->hw_res.irq = platform_get_irq(plat_dev, 0);
637 err = fjes_hw_init(&adapter->hw);
638 if (err)
639 goto err_free_netdev;
640
641 /* setup MAC address (02:00:00:00:00:[epid])*/
642 netdev->dev_addr[0] = 2;
643 netdev->dev_addr[1] = 0;
644 netdev->dev_addr[2] = 0;
645 netdev->dev_addr[3] = 0;
646 netdev->dev_addr[4] = 0;
647 netdev->dev_addr[5] = hw->my_epid; /* EPID */
648
649 err = register_netdev(netdev);
650 if (err)
651 goto err_hw_exit;
652
653 netif_carrier_off(netdev);
654
Taku Izumi658d4392015-08-21 17:29:17 +0900655 return 0;
Taku Izumi2fcbca62015-08-21 17:29:20 +0900656
657err_hw_exit:
658 fjes_hw_exit(&adapter->hw);
659err_free_netdev:
660 free_netdev(netdev);
661err_out:
662 return err;
Taku Izumi658d4392015-08-21 17:29:17 +0900663}
664
665/* fjes_remove - Device Removal Routine */
666static int fjes_remove(struct platform_device *plat_dev)
667{
Taku Izumi2fcbca62015-08-21 17:29:20 +0900668 struct net_device *netdev = dev_get_drvdata(&plat_dev->dev);
669 struct fjes_adapter *adapter = netdev_priv(netdev);
670 struct fjes_hw *hw = &adapter->hw;
671
672 unregister_netdev(netdev);
673
674 fjes_hw_exit(hw);
675
676 free_netdev(netdev);
677
Taku Izumi658d4392015-08-21 17:29:17 +0900678 return 0;
679}
680
Taku Izumi2fcbca62015-08-21 17:29:20 +0900681static int fjes_sw_init(struct fjes_adapter *adapter)
682{
683 return 0;
684}
685
686/* fjes_netdev_setup - netdevice initialization routine */
687static void fjes_netdev_setup(struct net_device *netdev)
688{
689 ether_setup(netdev);
690
691 netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
692 netdev->netdev_ops = &fjes_netdev_ops;
693 netdev->mtu = fjes_support_mtu[0];
694 netdev->flags |= IFF_BROADCAST;
695 netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
696}
697
Taku Izumi658d4392015-08-21 17:29:17 +0900698/* fjes_init_module - Driver Registration Routine */
699static int __init fjes_init_module(void)
700{
701 int result;
702
703 pr_info("%s - version %s - %s\n",
704 fjes_driver_string, fjes_driver_version, fjes_copyright);
705
706 result = platform_driver_register(&fjes_driver);
707 if (result < 0)
708 return result;
709
710 result = acpi_bus_register_driver(&fjes_acpi_driver);
711 if (result < 0)
712 goto fail_acpi_driver;
713
714 return 0;
715
716fail_acpi_driver:
717 platform_driver_unregister(&fjes_driver);
718 return result;
719}
720
721module_init(fjes_init_module);
722
723/* fjes_exit_module - Driver Exit Cleanup Routine */
724static void __exit fjes_exit_module(void)
725{
726 acpi_bus_unregister_driver(&fjes_acpi_driver);
727 platform_driver_unregister(&fjes_driver);
728}
729
730module_exit(fjes_exit_module);