blob: ac1e076366621dd52d8ace88e4ecdfff9668df46 [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 Izumib772b9d2015-08-21 17:29:25 +090055static void fjes_raise_intr_rxdata_task(struct work_struct *);
Taku Izumiac63b942015-08-21 17:29:26 +090056static void fjes_tx_stall_task(struct work_struct *);
Taku Izumie5d486d2015-08-21 17:29:23 +090057static irqreturn_t fjes_intr(int, void*);
58
Taku Izumi658d4392015-08-21 17:29:17 +090059static int fjes_acpi_add(struct acpi_device *);
60static int fjes_acpi_remove(struct acpi_device *);
61static acpi_status fjes_get_acpi_resource(struct acpi_resource *, void*);
62
63static int fjes_probe(struct platform_device *);
64static int fjes_remove(struct platform_device *);
65
Taku Izumi2fcbca62015-08-21 17:29:20 +090066static int fjes_sw_init(struct fjes_adapter *);
67static void fjes_netdev_setup(struct net_device *);
68
Taku Izumi658d4392015-08-21 17:29:17 +090069static const struct acpi_device_id fjes_acpi_ids[] = {
70 {"PNP0C02", 0},
71 {"", 0},
72};
73MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids);
74
75static struct acpi_driver fjes_acpi_driver = {
76 .name = DRV_NAME,
77 .class = DRV_NAME,
78 .owner = THIS_MODULE,
79 .ids = fjes_acpi_ids,
80 .ops = {
81 .add = fjes_acpi_add,
82 .remove = fjes_acpi_remove,
83 },
84};
85
86static struct platform_driver fjes_driver = {
87 .driver = {
88 .name = DRV_NAME,
89 .owner = THIS_MODULE,
90 },
91 .probe = fjes_probe,
92 .remove = fjes_remove,
93};
94
95static struct resource fjes_resource[] = {
96 {
97 .flags = IORESOURCE_MEM,
98 .start = 0,
99 .end = 0,
100 },
101 {
102 .flags = IORESOURCE_IRQ,
103 .start = 0,
104 .end = 0,
105 },
106};
107
108static int fjes_acpi_add(struct acpi_device *device)
109{
110 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
111 char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1];
112 struct platform_device *plat_dev;
113 union acpi_object *str;
114 acpi_status status;
115 int result;
116
117 status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer);
118 if (ACPI_FAILURE(status))
119 return -ENODEV;
120
121 str = buffer.pointer;
122 result = utf16s_to_utf8s((wchar_t *)str->string.pointer,
123 str->string.length, UTF16_LITTLE_ENDIAN,
124 str_buf, sizeof(str_buf) - 1);
125 str_buf[result] = 0;
126
127 if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) {
128 kfree(buffer.pointer);
129 return -ENODEV;
130 }
131 kfree(buffer.pointer);
132
133 status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
134 fjes_get_acpi_resource, fjes_resource);
135 if (ACPI_FAILURE(status))
136 return -ENODEV;
137
138 /* create platform_device */
139 plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource,
140 ARRAY_SIZE(fjes_resource));
141 device->driver_data = plat_dev;
142
143 return 0;
144}
145
146static int fjes_acpi_remove(struct acpi_device *device)
147{
148 struct platform_device *plat_dev;
149
150 plat_dev = (struct platform_device *)acpi_driver_data(device);
151 platform_device_unregister(plat_dev);
152
153 return 0;
154}
155
156static acpi_status
157fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data)
158{
159 struct acpi_resource_address32 *addr;
160 struct acpi_resource_irq *irq;
161 struct resource *res = data;
162
163 switch (acpi_res->type) {
164 case ACPI_RESOURCE_TYPE_ADDRESS32:
165 addr = &acpi_res->data.address32;
166 res[0].start = addr->address.minimum;
167 res[0].end = addr->address.minimum +
168 addr->address.address_length - 1;
169 break;
170
171 case ACPI_RESOURCE_TYPE_IRQ:
172 irq = &acpi_res->data.irq;
173 if (irq->interrupt_count != 1)
174 return AE_ERROR;
175 res[1].start = irq->interrupts[0];
176 res[1].end = irq->interrupts[0];
177 break;
178
179 default:
180 break;
181 }
182
183 return AE_OK;
184}
185
Taku Izumie5d486d2015-08-21 17:29:23 +0900186static int fjes_request_irq(struct fjes_adapter *adapter)
187{
188 struct net_device *netdev = adapter->netdev;
189 int result = -1;
190
191 if (!adapter->irq_registered) {
192 result = request_irq(adapter->hw.hw_res.irq, fjes_intr,
193 IRQF_SHARED, netdev->name, adapter);
194 if (result)
195 adapter->irq_registered = false;
196 else
197 adapter->irq_registered = true;
198 }
199
200 return result;
201}
202
203static void fjes_free_irq(struct fjes_adapter *adapter)
204{
205 struct fjes_hw *hw = &adapter->hw;
206
207 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
208
209 if (adapter->irq_registered) {
210 free_irq(adapter->hw.hw_res.irq, adapter);
211 adapter->irq_registered = false;
212 }
213}
214
Taku Izumi2fcbca62015-08-21 17:29:20 +0900215static const struct net_device_ops fjes_netdev_ops = {
Taku Izumie5d486d2015-08-21 17:29:23 +0900216 .ndo_open = fjes_open,
217 .ndo_stop = fjes_close,
Taku Izumi9acf51c2015-08-21 17:29:24 +0900218 .ndo_start_xmit = fjes_xmit_frame,
Taku Izumi2fcbca62015-08-21 17:29:20 +0900219};
220
Taku Izumie5d486d2015-08-21 17:29:23 +0900221/* fjes_open - Called when a network interface is made active */
222static int fjes_open(struct net_device *netdev)
223{
224 struct fjes_adapter *adapter = netdev_priv(netdev);
225 struct fjes_hw *hw = &adapter->hw;
226 int result;
227
228 if (adapter->open_guard)
229 return -ENXIO;
230
231 result = fjes_setup_resources(adapter);
232 if (result)
233 goto err_setup_res;
234
235 hw->txrx_stop_req_bit = 0;
236 hw->epstop_req_bit = 0;
237
238 fjes_hw_capture_interrupt_status(hw);
239
240 result = fjes_request_irq(adapter);
241 if (result)
242 goto err_req_irq;
243
244 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, false);
245
246 netif_tx_start_all_queues(netdev);
247 netif_carrier_on(netdev);
248
249 return 0;
250
251err_req_irq:
252 fjes_free_irq(adapter);
253
254err_setup_res:
255 fjes_free_resources(adapter);
256 return result;
257}
258
259/* fjes_close - Disables a network interface */
260static int fjes_close(struct net_device *netdev)
261{
262 struct fjes_adapter *adapter = netdev_priv(netdev);
263 struct fjes_hw *hw = &adapter->hw;
264 int epidx;
265
266 netif_tx_stop_all_queues(netdev);
267 netif_carrier_off(netdev);
268
269 fjes_hw_raise_epstop(hw);
270
271 for (epidx = 0; epidx < hw->max_epid; epidx++) {
272 if (epidx == hw->my_epid)
273 continue;
274
275 adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &=
276 ~FJES_RX_POLL_WORK;
277 }
278
279 fjes_free_irq(adapter);
280
Taku Izumib772b9d2015-08-21 17:29:25 +0900281 cancel_work_sync(&adapter->raise_intr_rxdata_task);
Taku Izumiac63b942015-08-21 17:29:26 +0900282 cancel_work_sync(&adapter->tx_stall_task);
Taku Izumib772b9d2015-08-21 17:29:25 +0900283
Taku Izumie5d486d2015-08-21 17:29:23 +0900284 fjes_hw_wait_epstop(hw);
285
286 fjes_free_resources(adapter);
287
288 return 0;
289}
290
291static int fjes_setup_resources(struct fjes_adapter *adapter)
292{
293 struct net_device *netdev = adapter->netdev;
294 struct ep_share_mem_info *buf_pair;
295 struct fjes_hw *hw = &adapter->hw;
296 int result;
297 int epidx;
298
299 mutex_lock(&hw->hw_info.lock);
300 result = fjes_hw_request_info(hw);
301 switch (result) {
302 case 0:
303 for (epidx = 0; epidx < hw->max_epid; epidx++) {
304 hw->ep_shm_info[epidx].es_status =
305 hw->hw_info.res_buf->info.info[epidx].es_status;
306 hw->ep_shm_info[epidx].zone =
307 hw->hw_info.res_buf->info.info[epidx].zone;
308 }
309 break;
310 default:
311 case -ENOMSG:
312 case -EBUSY:
313 adapter->force_reset = true;
314
315 mutex_unlock(&hw->hw_info.lock);
316 return result;
317 }
318 mutex_unlock(&hw->hw_info.lock);
319
320 for (epidx = 0; epidx < (hw->max_epid); epidx++) {
321 if ((epidx != hw->my_epid) &&
322 (hw->ep_shm_info[epidx].es_status ==
323 FJES_ZONING_STATUS_ENABLE)) {
324 fjes_hw_raise_interrupt(hw, epidx,
325 REG_ICTL_MASK_INFO_UPDATE);
326 }
327 }
328
329 msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid);
330
331 for (epidx = 0; epidx < (hw->max_epid); epidx++) {
332 if (epidx == hw->my_epid)
333 continue;
334
335 buf_pair = &hw->ep_shm_info[epidx];
336
337 fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr,
338 netdev->mtu);
339
340 if (fjes_hw_epid_is_same_zone(hw, epidx)) {
341 mutex_lock(&hw->hw_info.lock);
342 result =
343 fjes_hw_register_buff_addr(hw, epidx, buf_pair);
344 mutex_unlock(&hw->hw_info.lock);
345
346 switch (result) {
347 case 0:
348 break;
349 case -ENOMSG:
350 case -EBUSY:
351 default:
352 adapter->force_reset = true;
353 return result;
354 }
355 }
356 }
357
358 return 0;
359}
360
361static void fjes_free_resources(struct fjes_adapter *adapter)
362{
363 struct net_device *netdev = adapter->netdev;
364 struct fjes_device_command_param param;
365 struct ep_share_mem_info *buf_pair;
366 struct fjes_hw *hw = &adapter->hw;
367 bool reset_flag = false;
368 int result;
369 int epidx;
370
371 for (epidx = 0; epidx < hw->max_epid; epidx++) {
372 if (epidx == hw->my_epid)
373 continue;
374
375 mutex_lock(&hw->hw_info.lock);
376 result = fjes_hw_unregister_buff_addr(hw, epidx);
377 mutex_unlock(&hw->hw_info.lock);
378
379 if (result)
380 reset_flag = true;
381
382 buf_pair = &hw->ep_shm_info[epidx];
383
384 fjes_hw_setup_epbuf(&buf_pair->tx,
385 netdev->dev_addr, netdev->mtu);
386
387 clear_bit(epidx, &hw->txrx_stop_req_bit);
388 }
389
390 if (reset_flag || adapter->force_reset) {
391 result = fjes_hw_reset(hw);
392
393 adapter->force_reset = false;
394
395 if (result)
396 adapter->open_guard = true;
397
398 hw->hw_info.buffer_share_bit = 0;
399
400 memset((void *)&param, 0, sizeof(param));
401
402 param.req_len = hw->hw_info.req_buf_size;
403 param.req_start = __pa(hw->hw_info.req_buf);
404 param.res_len = hw->hw_info.res_buf_size;
405 param.res_start = __pa(hw->hw_info.res_buf);
406 param.share_start = __pa(hw->hw_info.share->ep_status);
407
408 fjes_hw_init_command_registers(hw, &param);
409 }
410}
411
Taku Izumiac63b942015-08-21 17:29:26 +0900412static void fjes_tx_stall_task(struct work_struct *work)
413{
414 struct fjes_adapter *adapter = container_of(work,
415 struct fjes_adapter, tx_stall_task);
416 struct net_device *netdev = adapter->netdev;
417 struct fjes_hw *hw = &adapter->hw;
418 int all_queue_available, sendable;
419 enum ep_partner_status pstatus;
420 int max_epid, my_epid, epid;
421 union ep_buffer_info *info;
422 int i;
423
424 if (((long)jiffies -
425 (long)(netdev->trans_start)) > FJES_TX_TX_STALL_TIMEOUT) {
426 netif_wake_queue(netdev);
427 return;
428 }
429
430 my_epid = hw->my_epid;
431 max_epid = hw->max_epid;
432
433 for (i = 0; i < 5; i++) {
434 all_queue_available = 1;
435
436 for (epid = 0; epid < max_epid; epid++) {
437 if (my_epid == epid)
438 continue;
439
440 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
441 sendable = (pstatus == EP_PARTNER_SHARED);
442 if (!sendable)
443 continue;
444
445 info = adapter->hw.ep_shm_info[epid].tx.info;
446
447 if (EP_RING_FULL(info->v1i.head, info->v1i.tail,
448 info->v1i.count_max)) {
449 all_queue_available = 0;
450 break;
451 }
452 }
453
454 if (all_queue_available) {
455 netif_wake_queue(netdev);
456 return;
457 }
458 }
459
460 usleep_range(50, 100);
461
462 queue_work(adapter->txrx_wq, &adapter->tx_stall_task);
463}
464
Taku Izumib772b9d2015-08-21 17:29:25 +0900465static void fjes_raise_intr_rxdata_task(struct work_struct *work)
466{
467 struct fjes_adapter *adapter = container_of(work,
468 struct fjes_adapter, raise_intr_rxdata_task);
469 struct fjes_hw *hw = &adapter->hw;
470 enum ep_partner_status pstatus;
471 int max_epid, my_epid, epid;
472
473 my_epid = hw->my_epid;
474 max_epid = hw->max_epid;
475
476 for (epid = 0; epid < max_epid; epid++)
477 hw->ep_shm_info[epid].tx_status_work = 0;
478
479 for (epid = 0; epid < max_epid; epid++) {
480 if (epid == my_epid)
481 continue;
482
483 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
484 if (pstatus == EP_PARTNER_SHARED) {
485 hw->ep_shm_info[epid].tx_status_work =
486 hw->ep_shm_info[epid].tx.info->v1i.tx_status;
487
488 if (hw->ep_shm_info[epid].tx_status_work ==
489 FJES_TX_DELAY_SEND_PENDING) {
490 hw->ep_shm_info[epid].tx.info->v1i.tx_status =
491 FJES_TX_DELAY_SEND_NONE;
492 }
493 }
494 }
495
496 for (epid = 0; epid < max_epid; epid++) {
497 if (epid == my_epid)
498 continue;
499
500 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
501 if ((hw->ep_shm_info[epid].tx_status_work ==
502 FJES_TX_DELAY_SEND_PENDING) &&
503 (pstatus == EP_PARTNER_SHARED) &&
504 !(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) {
505 fjes_hw_raise_interrupt(hw, epid,
506 REG_ICTL_MASK_RX_DATA);
507 }
508 }
509
510 usleep_range(500, 1000);
511}
512
Taku Izumi9acf51c2015-08-21 17:29:24 +0900513static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
514 void *data, size_t len)
515{
516 int retval;
517
518 retval = fjes_hw_epbuf_tx_pkt_send(&adapter->hw.ep_shm_info[dest].tx,
519 data, len);
520 if (retval)
521 return retval;
522
523 adapter->hw.ep_shm_info[dest].tx.info->v1i.tx_status =
524 FJES_TX_DELAY_SEND_PENDING;
Taku Izumib772b9d2015-08-21 17:29:25 +0900525 if (!work_pending(&adapter->raise_intr_rxdata_task))
526 queue_work(adapter->txrx_wq,
527 &adapter->raise_intr_rxdata_task);
Taku Izumi9acf51c2015-08-21 17:29:24 +0900528
529 retval = 0;
530 return retval;
531}
532
533static netdev_tx_t
534fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
535{
536 struct fjes_adapter *adapter = netdev_priv(netdev);
537 struct fjes_hw *hw = &adapter->hw;
538
539 int max_epid, my_epid, dest_epid;
540 enum ep_partner_status pstatus;
541 struct netdev_queue *cur_queue;
542 char shortpkt[VLAN_ETH_HLEN];
543 bool is_multi, vlan;
544 struct ethhdr *eth;
545 u16 queue_no = 0;
546 u16 vlan_id = 0;
547 netdev_tx_t ret;
548 char *data;
549 int len;
550
551 ret = NETDEV_TX_OK;
552 is_multi = false;
553 cur_queue = netdev_get_tx_queue(netdev, queue_no);
554
555 eth = (struct ethhdr *)skb->data;
556 my_epid = hw->my_epid;
557
558 vlan = (vlan_get_tag(skb, &vlan_id) == 0) ? true : false;
559
560 data = skb->data;
561 len = skb->len;
562
563 if (is_multicast_ether_addr(eth->h_dest)) {
564 dest_epid = 0;
565 max_epid = hw->max_epid;
566 is_multi = true;
567 } else if (is_local_ether_addr(eth->h_dest)) {
568 dest_epid = eth->h_dest[ETH_ALEN - 1];
569 max_epid = dest_epid + 1;
570
571 if ((eth->h_dest[0] == 0x02) &&
572 (0x00 == (eth->h_dest[1] | eth->h_dest[2] |
573 eth->h_dest[3] | eth->h_dest[4])) &&
574 (dest_epid < hw->max_epid)) {
575 ;
576 } else {
577 dest_epid = 0;
578 max_epid = 0;
579 ret = NETDEV_TX_OK;
580
581 adapter->stats64.tx_packets += 1;
582 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
583 adapter->stats64.tx_bytes += len;
584 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
585 }
586 } else {
587 dest_epid = 0;
588 max_epid = 0;
589 ret = NETDEV_TX_OK;
590
591 adapter->stats64.tx_packets += 1;
592 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
593 adapter->stats64.tx_bytes += len;
594 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
595 }
596
597 for (; dest_epid < max_epid; dest_epid++) {
598 if (my_epid == dest_epid)
599 continue;
600
601 pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
602 if (pstatus != EP_PARTNER_SHARED) {
603 ret = NETDEV_TX_OK;
604 } else if (!fjes_hw_check_epbuf_version(
605 &adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
606 /* version is NOT 0 */
607 adapter->stats64.tx_carrier_errors += 1;
608 hw->ep_shm_info[my_epid].net_stats
609 .tx_carrier_errors += 1;
610
611 ret = NETDEV_TX_OK;
612 } else if (!fjes_hw_check_mtu(
613 &adapter->hw.ep_shm_info[dest_epid].rx,
614 netdev->mtu)) {
615 adapter->stats64.tx_dropped += 1;
616 hw->ep_shm_info[my_epid].net_stats.tx_dropped += 1;
617 adapter->stats64.tx_errors += 1;
618 hw->ep_shm_info[my_epid].net_stats.tx_errors += 1;
619
620 ret = NETDEV_TX_OK;
621 } else if (vlan &&
622 !fjes_hw_check_vlan_id(
623 &adapter->hw.ep_shm_info[dest_epid].rx,
624 vlan_id)) {
625 ret = NETDEV_TX_OK;
626 } else {
627 if (len < VLAN_ETH_HLEN) {
628 memset(shortpkt, 0, VLAN_ETH_HLEN);
629 memcpy(shortpkt, skb->data, skb->len);
630 len = VLAN_ETH_HLEN;
631 data = shortpkt;
632 }
633
634 if (adapter->tx_retry_count == 0) {
635 adapter->tx_start_jiffies = jiffies;
636 adapter->tx_retry_count = 1;
637 } else {
638 adapter->tx_retry_count++;
639 }
640
641 if (fjes_tx_send(adapter, dest_epid, data, len)) {
642 if (is_multi) {
643 ret = NETDEV_TX_OK;
644 } else if (
645 ((long)jiffies -
646 (long)adapter->tx_start_jiffies) >=
647 FJES_TX_RETRY_TIMEOUT) {
648 adapter->stats64.tx_fifo_errors += 1;
649 hw->ep_shm_info[my_epid].net_stats
650 .tx_fifo_errors += 1;
651 adapter->stats64.tx_errors += 1;
652 hw->ep_shm_info[my_epid].net_stats
653 .tx_errors += 1;
654
655 ret = NETDEV_TX_OK;
656 } else {
657 netdev->trans_start = jiffies;
658 netif_tx_stop_queue(cur_queue);
659
Taku Izumiac63b942015-08-21 17:29:26 +0900660 if (!work_pending(&adapter->tx_stall_task))
661 queue_work(adapter->txrx_wq,
662 &adapter->tx_stall_task);
663
Taku Izumi9acf51c2015-08-21 17:29:24 +0900664 ret = NETDEV_TX_BUSY;
665 }
666 } else {
667 if (!is_multi) {
668 adapter->stats64.tx_packets += 1;
669 hw->ep_shm_info[my_epid].net_stats
670 .tx_packets += 1;
671 adapter->stats64.tx_bytes += len;
672 hw->ep_shm_info[my_epid].net_stats
673 .tx_bytes += len;
674 }
675
676 adapter->tx_retry_count = 0;
677 ret = NETDEV_TX_OK;
678 }
679 }
680 }
681
682 if (ret == NETDEV_TX_OK) {
683 dev_kfree_skb(skb);
684 if (is_multi) {
685 adapter->stats64.tx_packets += 1;
686 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
687 adapter->stats64.tx_bytes += 1;
688 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
689 }
690 }
691
692 return ret;
693}
694
Taku Izumie5d486d2015-08-21 17:29:23 +0900695static irqreturn_t fjes_intr(int irq, void *data)
696{
697 struct fjes_adapter *adapter = data;
698 struct fjes_hw *hw = &adapter->hw;
699 irqreturn_t ret;
700 u32 icr;
701
702 icr = fjes_hw_capture_interrupt_status(hw);
703
704 if (icr & REG_IS_MASK_IS_ASSERT)
705 ret = IRQ_HANDLED;
706 else
707 ret = IRQ_NONE;
708
709 return ret;
710}
711
Taku Izumi658d4392015-08-21 17:29:17 +0900712/* fjes_probe - Device Initialization Routine */
713static int fjes_probe(struct platform_device *plat_dev)
714{
Taku Izumi2fcbca62015-08-21 17:29:20 +0900715 struct fjes_adapter *adapter;
716 struct net_device *netdev;
717 struct resource *res;
718 struct fjes_hw *hw;
719 int err;
720
721 err = -ENOMEM;
722 netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), "es%d",
723 NET_NAME_UNKNOWN, fjes_netdev_setup,
724 FJES_MAX_QUEUES);
725
726 if (!netdev)
727 goto err_out;
728
729 SET_NETDEV_DEV(netdev, &plat_dev->dev);
730
731 dev_set_drvdata(&plat_dev->dev, netdev);
732 adapter = netdev_priv(netdev);
733 adapter->netdev = netdev;
734 adapter->plat_dev = plat_dev;
735 hw = &adapter->hw;
736 hw->back = adapter;
737
738 /* setup the private structure */
739 err = fjes_sw_init(adapter);
740 if (err)
741 goto err_free_netdev;
742
743 adapter->force_reset = false;
744 adapter->open_guard = false;
745
Taku Izumib772b9d2015-08-21 17:29:25 +0900746 adapter->txrx_wq = create_workqueue(DRV_NAME "/txrx");
747
Taku Izumiac63b942015-08-21 17:29:26 +0900748 INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task);
Taku Izumib772b9d2015-08-21 17:29:25 +0900749 INIT_WORK(&adapter->raise_intr_rxdata_task,
750 fjes_raise_intr_rxdata_task);
751
Taku Izumi2fcbca62015-08-21 17:29:20 +0900752 res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
753 hw->hw_res.start = res->start;
754 hw->hw_res.size = res->end - res->start + 1;
755 hw->hw_res.irq = platform_get_irq(plat_dev, 0);
756 err = fjes_hw_init(&adapter->hw);
757 if (err)
758 goto err_free_netdev;
759
760 /* setup MAC address (02:00:00:00:00:[epid])*/
761 netdev->dev_addr[0] = 2;
762 netdev->dev_addr[1] = 0;
763 netdev->dev_addr[2] = 0;
764 netdev->dev_addr[3] = 0;
765 netdev->dev_addr[4] = 0;
766 netdev->dev_addr[5] = hw->my_epid; /* EPID */
767
768 err = register_netdev(netdev);
769 if (err)
770 goto err_hw_exit;
771
772 netif_carrier_off(netdev);
773
Taku Izumi658d4392015-08-21 17:29:17 +0900774 return 0;
Taku Izumi2fcbca62015-08-21 17:29:20 +0900775
776err_hw_exit:
777 fjes_hw_exit(&adapter->hw);
778err_free_netdev:
779 free_netdev(netdev);
780err_out:
781 return err;
Taku Izumi658d4392015-08-21 17:29:17 +0900782}
783
784/* fjes_remove - Device Removal Routine */
785static int fjes_remove(struct platform_device *plat_dev)
786{
Taku Izumi2fcbca62015-08-21 17:29:20 +0900787 struct net_device *netdev = dev_get_drvdata(&plat_dev->dev);
788 struct fjes_adapter *adapter = netdev_priv(netdev);
789 struct fjes_hw *hw = &adapter->hw;
790
Taku Izumib772b9d2015-08-21 17:29:25 +0900791 cancel_work_sync(&adapter->raise_intr_rxdata_task);
Taku Izumiac63b942015-08-21 17:29:26 +0900792 cancel_work_sync(&adapter->tx_stall_task);
Taku Izumib772b9d2015-08-21 17:29:25 +0900793 if (adapter->txrx_wq)
794 destroy_workqueue(adapter->txrx_wq);
795
Taku Izumi2fcbca62015-08-21 17:29:20 +0900796 unregister_netdev(netdev);
797
798 fjes_hw_exit(hw);
799
800 free_netdev(netdev);
801
Taku Izumi658d4392015-08-21 17:29:17 +0900802 return 0;
803}
804
Taku Izumi2fcbca62015-08-21 17:29:20 +0900805static int fjes_sw_init(struct fjes_adapter *adapter)
806{
807 return 0;
808}
809
810/* fjes_netdev_setup - netdevice initialization routine */
811static void fjes_netdev_setup(struct net_device *netdev)
812{
813 ether_setup(netdev);
814
815 netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
816 netdev->netdev_ops = &fjes_netdev_ops;
817 netdev->mtu = fjes_support_mtu[0];
818 netdev->flags |= IFF_BROADCAST;
819 netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
820}
821
Taku Izumi658d4392015-08-21 17:29:17 +0900822/* fjes_init_module - Driver Registration Routine */
823static int __init fjes_init_module(void)
824{
825 int result;
826
827 pr_info("%s - version %s - %s\n",
828 fjes_driver_string, fjes_driver_version, fjes_copyright);
829
830 result = platform_driver_register(&fjes_driver);
831 if (result < 0)
832 return result;
833
834 result = acpi_bus_register_driver(&fjes_acpi_driver);
835 if (result < 0)
836 goto fail_acpi_driver;
837
838 return 0;
839
840fail_acpi_driver:
841 platform_driver_unregister(&fjes_driver);
842 return result;
843}
844
845module_init(fjes_init_module);
846
847/* fjes_exit_module - Driver Exit Cleanup Routine */
848static void __exit fjes_exit_module(void)
849{
850 acpi_bus_unregister_driver(&fjes_acpi_driver);
851 platform_driver_unregister(&fjes_driver);
852}
853
854module_exit(fjes_exit_module);