blob: 61949625176cc9dad7b1f6b4e811e5d5106eef5e [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 Izumi26585932015-08-21 17:29:27 +090069static void fjes_rx_irq(struct fjes_adapter *, int);
70static int fjes_poll(struct napi_struct *, int);
71
Taku Izumi658d4392015-08-21 17:29:17 +090072static const struct acpi_device_id fjes_acpi_ids[] = {
73 {"PNP0C02", 0},
74 {"", 0},
75};
76MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids);
77
78static struct acpi_driver fjes_acpi_driver = {
79 .name = DRV_NAME,
80 .class = DRV_NAME,
81 .owner = THIS_MODULE,
82 .ids = fjes_acpi_ids,
83 .ops = {
84 .add = fjes_acpi_add,
85 .remove = fjes_acpi_remove,
86 },
87};
88
89static struct platform_driver fjes_driver = {
90 .driver = {
91 .name = DRV_NAME,
92 .owner = THIS_MODULE,
93 },
94 .probe = fjes_probe,
95 .remove = fjes_remove,
96};
97
98static struct resource fjes_resource[] = {
99 {
100 .flags = IORESOURCE_MEM,
101 .start = 0,
102 .end = 0,
103 },
104 {
105 .flags = IORESOURCE_IRQ,
106 .start = 0,
107 .end = 0,
108 },
109};
110
111static int fjes_acpi_add(struct acpi_device *device)
112{
113 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
114 char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1];
115 struct platform_device *plat_dev;
116 union acpi_object *str;
117 acpi_status status;
118 int result;
119
120 status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer);
121 if (ACPI_FAILURE(status))
122 return -ENODEV;
123
124 str = buffer.pointer;
125 result = utf16s_to_utf8s((wchar_t *)str->string.pointer,
126 str->string.length, UTF16_LITTLE_ENDIAN,
127 str_buf, sizeof(str_buf) - 1);
128 str_buf[result] = 0;
129
130 if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) {
131 kfree(buffer.pointer);
132 return -ENODEV;
133 }
134 kfree(buffer.pointer);
135
136 status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
137 fjes_get_acpi_resource, fjes_resource);
138 if (ACPI_FAILURE(status))
139 return -ENODEV;
140
141 /* create platform_device */
142 plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource,
143 ARRAY_SIZE(fjes_resource));
144 device->driver_data = plat_dev;
145
146 return 0;
147}
148
149static int fjes_acpi_remove(struct acpi_device *device)
150{
151 struct platform_device *plat_dev;
152
153 plat_dev = (struct platform_device *)acpi_driver_data(device);
154 platform_device_unregister(plat_dev);
155
156 return 0;
157}
158
159static acpi_status
160fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data)
161{
162 struct acpi_resource_address32 *addr;
163 struct acpi_resource_irq *irq;
164 struct resource *res = data;
165
166 switch (acpi_res->type) {
167 case ACPI_RESOURCE_TYPE_ADDRESS32:
168 addr = &acpi_res->data.address32;
169 res[0].start = addr->address.minimum;
170 res[0].end = addr->address.minimum +
171 addr->address.address_length - 1;
172 break;
173
174 case ACPI_RESOURCE_TYPE_IRQ:
175 irq = &acpi_res->data.irq;
176 if (irq->interrupt_count != 1)
177 return AE_ERROR;
178 res[1].start = irq->interrupts[0];
179 res[1].end = irq->interrupts[0];
180 break;
181
182 default:
183 break;
184 }
185
186 return AE_OK;
187}
188
Taku Izumie5d486d2015-08-21 17:29:23 +0900189static int fjes_request_irq(struct fjes_adapter *adapter)
190{
191 struct net_device *netdev = adapter->netdev;
192 int result = -1;
193
194 if (!adapter->irq_registered) {
195 result = request_irq(adapter->hw.hw_res.irq, fjes_intr,
196 IRQF_SHARED, netdev->name, adapter);
197 if (result)
198 adapter->irq_registered = false;
199 else
200 adapter->irq_registered = true;
201 }
202
203 return result;
204}
205
206static void fjes_free_irq(struct fjes_adapter *adapter)
207{
208 struct fjes_hw *hw = &adapter->hw;
209
210 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
211
212 if (adapter->irq_registered) {
213 free_irq(adapter->hw.hw_res.irq, adapter);
214 adapter->irq_registered = false;
215 }
216}
217
Taku Izumi2fcbca62015-08-21 17:29:20 +0900218static const struct net_device_ops fjes_netdev_ops = {
Taku Izumie5d486d2015-08-21 17:29:23 +0900219 .ndo_open = fjes_open,
220 .ndo_stop = fjes_close,
Taku Izumi9acf51c2015-08-21 17:29:24 +0900221 .ndo_start_xmit = fjes_xmit_frame,
Taku Izumi2fcbca62015-08-21 17:29:20 +0900222};
223
Taku Izumie5d486d2015-08-21 17:29:23 +0900224/* fjes_open - Called when a network interface is made active */
225static int fjes_open(struct net_device *netdev)
226{
227 struct fjes_adapter *adapter = netdev_priv(netdev);
228 struct fjes_hw *hw = &adapter->hw;
229 int result;
230
231 if (adapter->open_guard)
232 return -ENXIO;
233
234 result = fjes_setup_resources(adapter);
235 if (result)
236 goto err_setup_res;
237
238 hw->txrx_stop_req_bit = 0;
239 hw->epstop_req_bit = 0;
240
Taku Izumi26585932015-08-21 17:29:27 +0900241 napi_enable(&adapter->napi);
242
Taku Izumie5d486d2015-08-21 17:29:23 +0900243 fjes_hw_capture_interrupt_status(hw);
244
245 result = fjes_request_irq(adapter);
246 if (result)
247 goto err_req_irq;
248
249 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, false);
250
251 netif_tx_start_all_queues(netdev);
252 netif_carrier_on(netdev);
253
254 return 0;
255
256err_req_irq:
257 fjes_free_irq(adapter);
Taku Izumi26585932015-08-21 17:29:27 +0900258 napi_disable(&adapter->napi);
Taku Izumie5d486d2015-08-21 17:29:23 +0900259
260err_setup_res:
261 fjes_free_resources(adapter);
262 return result;
263}
264
265/* fjes_close - Disables a network interface */
266static int fjes_close(struct net_device *netdev)
267{
268 struct fjes_adapter *adapter = netdev_priv(netdev);
269 struct fjes_hw *hw = &adapter->hw;
270 int epidx;
271
272 netif_tx_stop_all_queues(netdev);
273 netif_carrier_off(netdev);
274
275 fjes_hw_raise_epstop(hw);
276
Taku Izumi26585932015-08-21 17:29:27 +0900277 napi_disable(&adapter->napi);
278
Taku Izumie5d486d2015-08-21 17:29:23 +0900279 for (epidx = 0; epidx < hw->max_epid; epidx++) {
280 if (epidx == hw->my_epid)
281 continue;
282
283 adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &=
284 ~FJES_RX_POLL_WORK;
285 }
286
287 fjes_free_irq(adapter);
288
Taku Izumib772b9d2015-08-21 17:29:25 +0900289 cancel_work_sync(&adapter->raise_intr_rxdata_task);
Taku Izumiac63b942015-08-21 17:29:26 +0900290 cancel_work_sync(&adapter->tx_stall_task);
Taku Izumib772b9d2015-08-21 17:29:25 +0900291
Taku Izumie5d486d2015-08-21 17:29:23 +0900292 fjes_hw_wait_epstop(hw);
293
294 fjes_free_resources(adapter);
295
296 return 0;
297}
298
299static int fjes_setup_resources(struct fjes_adapter *adapter)
300{
301 struct net_device *netdev = adapter->netdev;
302 struct ep_share_mem_info *buf_pair;
303 struct fjes_hw *hw = &adapter->hw;
304 int result;
305 int epidx;
306
307 mutex_lock(&hw->hw_info.lock);
308 result = fjes_hw_request_info(hw);
309 switch (result) {
310 case 0:
311 for (epidx = 0; epidx < hw->max_epid; epidx++) {
312 hw->ep_shm_info[epidx].es_status =
313 hw->hw_info.res_buf->info.info[epidx].es_status;
314 hw->ep_shm_info[epidx].zone =
315 hw->hw_info.res_buf->info.info[epidx].zone;
316 }
317 break;
318 default:
319 case -ENOMSG:
320 case -EBUSY:
321 adapter->force_reset = true;
322
323 mutex_unlock(&hw->hw_info.lock);
324 return result;
325 }
326 mutex_unlock(&hw->hw_info.lock);
327
328 for (epidx = 0; epidx < (hw->max_epid); epidx++) {
329 if ((epidx != hw->my_epid) &&
330 (hw->ep_shm_info[epidx].es_status ==
331 FJES_ZONING_STATUS_ENABLE)) {
332 fjes_hw_raise_interrupt(hw, epidx,
333 REG_ICTL_MASK_INFO_UPDATE);
334 }
335 }
336
337 msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid);
338
339 for (epidx = 0; epidx < (hw->max_epid); epidx++) {
340 if (epidx == hw->my_epid)
341 continue;
342
343 buf_pair = &hw->ep_shm_info[epidx];
344
345 fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr,
346 netdev->mtu);
347
348 if (fjes_hw_epid_is_same_zone(hw, epidx)) {
349 mutex_lock(&hw->hw_info.lock);
350 result =
351 fjes_hw_register_buff_addr(hw, epidx, buf_pair);
352 mutex_unlock(&hw->hw_info.lock);
353
354 switch (result) {
355 case 0:
356 break;
357 case -ENOMSG:
358 case -EBUSY:
359 default:
360 adapter->force_reset = true;
361 return result;
362 }
363 }
364 }
365
366 return 0;
367}
368
369static void fjes_free_resources(struct fjes_adapter *adapter)
370{
371 struct net_device *netdev = adapter->netdev;
372 struct fjes_device_command_param param;
373 struct ep_share_mem_info *buf_pair;
374 struct fjes_hw *hw = &adapter->hw;
375 bool reset_flag = false;
376 int result;
377 int epidx;
378
379 for (epidx = 0; epidx < hw->max_epid; epidx++) {
380 if (epidx == hw->my_epid)
381 continue;
382
383 mutex_lock(&hw->hw_info.lock);
384 result = fjes_hw_unregister_buff_addr(hw, epidx);
385 mutex_unlock(&hw->hw_info.lock);
386
387 if (result)
388 reset_flag = true;
389
390 buf_pair = &hw->ep_shm_info[epidx];
391
392 fjes_hw_setup_epbuf(&buf_pair->tx,
393 netdev->dev_addr, netdev->mtu);
394
395 clear_bit(epidx, &hw->txrx_stop_req_bit);
396 }
397
398 if (reset_flag || adapter->force_reset) {
399 result = fjes_hw_reset(hw);
400
401 adapter->force_reset = false;
402
403 if (result)
404 adapter->open_guard = true;
405
406 hw->hw_info.buffer_share_bit = 0;
407
408 memset((void *)&param, 0, sizeof(param));
409
410 param.req_len = hw->hw_info.req_buf_size;
411 param.req_start = __pa(hw->hw_info.req_buf);
412 param.res_len = hw->hw_info.res_buf_size;
413 param.res_start = __pa(hw->hw_info.res_buf);
414 param.share_start = __pa(hw->hw_info.share->ep_status);
415
416 fjes_hw_init_command_registers(hw, &param);
417 }
418}
419
Taku Izumiac63b942015-08-21 17:29:26 +0900420static void fjes_tx_stall_task(struct work_struct *work)
421{
422 struct fjes_adapter *adapter = container_of(work,
423 struct fjes_adapter, tx_stall_task);
424 struct net_device *netdev = adapter->netdev;
425 struct fjes_hw *hw = &adapter->hw;
426 int all_queue_available, sendable;
427 enum ep_partner_status pstatus;
428 int max_epid, my_epid, epid;
429 union ep_buffer_info *info;
430 int i;
431
432 if (((long)jiffies -
433 (long)(netdev->trans_start)) > FJES_TX_TX_STALL_TIMEOUT) {
434 netif_wake_queue(netdev);
435 return;
436 }
437
438 my_epid = hw->my_epid;
439 max_epid = hw->max_epid;
440
441 for (i = 0; i < 5; i++) {
442 all_queue_available = 1;
443
444 for (epid = 0; epid < max_epid; epid++) {
445 if (my_epid == epid)
446 continue;
447
448 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
449 sendable = (pstatus == EP_PARTNER_SHARED);
450 if (!sendable)
451 continue;
452
453 info = adapter->hw.ep_shm_info[epid].tx.info;
454
455 if (EP_RING_FULL(info->v1i.head, info->v1i.tail,
456 info->v1i.count_max)) {
457 all_queue_available = 0;
458 break;
459 }
460 }
461
462 if (all_queue_available) {
463 netif_wake_queue(netdev);
464 return;
465 }
466 }
467
468 usleep_range(50, 100);
469
470 queue_work(adapter->txrx_wq, &adapter->tx_stall_task);
471}
472
Taku Izumib772b9d2015-08-21 17:29:25 +0900473static void fjes_raise_intr_rxdata_task(struct work_struct *work)
474{
475 struct fjes_adapter *adapter = container_of(work,
476 struct fjes_adapter, raise_intr_rxdata_task);
477 struct fjes_hw *hw = &adapter->hw;
478 enum ep_partner_status pstatus;
479 int max_epid, my_epid, epid;
480
481 my_epid = hw->my_epid;
482 max_epid = hw->max_epid;
483
484 for (epid = 0; epid < max_epid; epid++)
485 hw->ep_shm_info[epid].tx_status_work = 0;
486
487 for (epid = 0; epid < max_epid; epid++) {
488 if (epid == my_epid)
489 continue;
490
491 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
492 if (pstatus == EP_PARTNER_SHARED) {
493 hw->ep_shm_info[epid].tx_status_work =
494 hw->ep_shm_info[epid].tx.info->v1i.tx_status;
495
496 if (hw->ep_shm_info[epid].tx_status_work ==
497 FJES_TX_DELAY_SEND_PENDING) {
498 hw->ep_shm_info[epid].tx.info->v1i.tx_status =
499 FJES_TX_DELAY_SEND_NONE;
500 }
501 }
502 }
503
504 for (epid = 0; epid < max_epid; epid++) {
505 if (epid == my_epid)
506 continue;
507
508 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
509 if ((hw->ep_shm_info[epid].tx_status_work ==
510 FJES_TX_DELAY_SEND_PENDING) &&
511 (pstatus == EP_PARTNER_SHARED) &&
512 !(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) {
513 fjes_hw_raise_interrupt(hw, epid,
514 REG_ICTL_MASK_RX_DATA);
515 }
516 }
517
518 usleep_range(500, 1000);
519}
520
Taku Izumi9acf51c2015-08-21 17:29:24 +0900521static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
522 void *data, size_t len)
523{
524 int retval;
525
526 retval = fjes_hw_epbuf_tx_pkt_send(&adapter->hw.ep_shm_info[dest].tx,
527 data, len);
528 if (retval)
529 return retval;
530
531 adapter->hw.ep_shm_info[dest].tx.info->v1i.tx_status =
532 FJES_TX_DELAY_SEND_PENDING;
Taku Izumib772b9d2015-08-21 17:29:25 +0900533 if (!work_pending(&adapter->raise_intr_rxdata_task))
534 queue_work(adapter->txrx_wq,
535 &adapter->raise_intr_rxdata_task);
Taku Izumi9acf51c2015-08-21 17:29:24 +0900536
537 retval = 0;
538 return retval;
539}
540
541static netdev_tx_t
542fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
543{
544 struct fjes_adapter *adapter = netdev_priv(netdev);
545 struct fjes_hw *hw = &adapter->hw;
546
547 int max_epid, my_epid, dest_epid;
548 enum ep_partner_status pstatus;
549 struct netdev_queue *cur_queue;
550 char shortpkt[VLAN_ETH_HLEN];
551 bool is_multi, vlan;
552 struct ethhdr *eth;
553 u16 queue_no = 0;
554 u16 vlan_id = 0;
555 netdev_tx_t ret;
556 char *data;
557 int len;
558
559 ret = NETDEV_TX_OK;
560 is_multi = false;
561 cur_queue = netdev_get_tx_queue(netdev, queue_no);
562
563 eth = (struct ethhdr *)skb->data;
564 my_epid = hw->my_epid;
565
566 vlan = (vlan_get_tag(skb, &vlan_id) == 0) ? true : false;
567
568 data = skb->data;
569 len = skb->len;
570
571 if (is_multicast_ether_addr(eth->h_dest)) {
572 dest_epid = 0;
573 max_epid = hw->max_epid;
574 is_multi = true;
575 } else if (is_local_ether_addr(eth->h_dest)) {
576 dest_epid = eth->h_dest[ETH_ALEN - 1];
577 max_epid = dest_epid + 1;
578
579 if ((eth->h_dest[0] == 0x02) &&
580 (0x00 == (eth->h_dest[1] | eth->h_dest[2] |
581 eth->h_dest[3] | eth->h_dest[4])) &&
582 (dest_epid < hw->max_epid)) {
583 ;
584 } else {
585 dest_epid = 0;
586 max_epid = 0;
587 ret = NETDEV_TX_OK;
588
589 adapter->stats64.tx_packets += 1;
590 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
591 adapter->stats64.tx_bytes += len;
592 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
593 }
594 } else {
595 dest_epid = 0;
596 max_epid = 0;
597 ret = NETDEV_TX_OK;
598
599 adapter->stats64.tx_packets += 1;
600 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
601 adapter->stats64.tx_bytes += len;
602 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
603 }
604
605 for (; dest_epid < max_epid; dest_epid++) {
606 if (my_epid == dest_epid)
607 continue;
608
609 pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
610 if (pstatus != EP_PARTNER_SHARED) {
611 ret = NETDEV_TX_OK;
612 } else if (!fjes_hw_check_epbuf_version(
613 &adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
614 /* version is NOT 0 */
615 adapter->stats64.tx_carrier_errors += 1;
616 hw->ep_shm_info[my_epid].net_stats
617 .tx_carrier_errors += 1;
618
619 ret = NETDEV_TX_OK;
620 } else if (!fjes_hw_check_mtu(
621 &adapter->hw.ep_shm_info[dest_epid].rx,
622 netdev->mtu)) {
623 adapter->stats64.tx_dropped += 1;
624 hw->ep_shm_info[my_epid].net_stats.tx_dropped += 1;
625 adapter->stats64.tx_errors += 1;
626 hw->ep_shm_info[my_epid].net_stats.tx_errors += 1;
627
628 ret = NETDEV_TX_OK;
629 } else if (vlan &&
630 !fjes_hw_check_vlan_id(
631 &adapter->hw.ep_shm_info[dest_epid].rx,
632 vlan_id)) {
633 ret = NETDEV_TX_OK;
634 } else {
635 if (len < VLAN_ETH_HLEN) {
636 memset(shortpkt, 0, VLAN_ETH_HLEN);
637 memcpy(shortpkt, skb->data, skb->len);
638 len = VLAN_ETH_HLEN;
639 data = shortpkt;
640 }
641
642 if (adapter->tx_retry_count == 0) {
643 adapter->tx_start_jiffies = jiffies;
644 adapter->tx_retry_count = 1;
645 } else {
646 adapter->tx_retry_count++;
647 }
648
649 if (fjes_tx_send(adapter, dest_epid, data, len)) {
650 if (is_multi) {
651 ret = NETDEV_TX_OK;
652 } else if (
653 ((long)jiffies -
654 (long)adapter->tx_start_jiffies) >=
655 FJES_TX_RETRY_TIMEOUT) {
656 adapter->stats64.tx_fifo_errors += 1;
657 hw->ep_shm_info[my_epid].net_stats
658 .tx_fifo_errors += 1;
659 adapter->stats64.tx_errors += 1;
660 hw->ep_shm_info[my_epid].net_stats
661 .tx_errors += 1;
662
663 ret = NETDEV_TX_OK;
664 } else {
665 netdev->trans_start = jiffies;
666 netif_tx_stop_queue(cur_queue);
667
Taku Izumiac63b942015-08-21 17:29:26 +0900668 if (!work_pending(&adapter->tx_stall_task))
669 queue_work(adapter->txrx_wq,
670 &adapter->tx_stall_task);
671
Taku Izumi9acf51c2015-08-21 17:29:24 +0900672 ret = NETDEV_TX_BUSY;
673 }
674 } else {
675 if (!is_multi) {
676 adapter->stats64.tx_packets += 1;
677 hw->ep_shm_info[my_epid].net_stats
678 .tx_packets += 1;
679 adapter->stats64.tx_bytes += len;
680 hw->ep_shm_info[my_epid].net_stats
681 .tx_bytes += len;
682 }
683
684 adapter->tx_retry_count = 0;
685 ret = NETDEV_TX_OK;
686 }
687 }
688 }
689
690 if (ret == NETDEV_TX_OK) {
691 dev_kfree_skb(skb);
692 if (is_multi) {
693 adapter->stats64.tx_packets += 1;
694 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
695 adapter->stats64.tx_bytes += 1;
696 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
697 }
698 }
699
700 return ret;
701}
702
Taku Izumie5d486d2015-08-21 17:29:23 +0900703static irqreturn_t fjes_intr(int irq, void *data)
704{
705 struct fjes_adapter *adapter = data;
706 struct fjes_hw *hw = &adapter->hw;
707 irqreturn_t ret;
708 u32 icr;
709
710 icr = fjes_hw_capture_interrupt_status(hw);
711
Taku Izumi26585932015-08-21 17:29:27 +0900712 if (icr & REG_IS_MASK_IS_ASSERT) {
713 if (icr & REG_ICTL_MASK_RX_DATA)
714 fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
715
Taku Izumie5d486d2015-08-21 17:29:23 +0900716 ret = IRQ_HANDLED;
Taku Izumi26585932015-08-21 17:29:27 +0900717 } else {
Taku Izumie5d486d2015-08-21 17:29:23 +0900718 ret = IRQ_NONE;
Taku Izumi26585932015-08-21 17:29:27 +0900719 }
Taku Izumie5d486d2015-08-21 17:29:23 +0900720
721 return ret;
722}
723
Taku Izumi26585932015-08-21 17:29:27 +0900724static int fjes_rxframe_search_exist(struct fjes_adapter *adapter,
725 int start_epid)
726{
727 struct fjes_hw *hw = &adapter->hw;
728 enum ep_partner_status pstatus;
729 int max_epid, cur_epid;
730 int i;
731
732 max_epid = hw->max_epid;
733 start_epid = (start_epid + 1 + max_epid) % max_epid;
734
735 for (i = 0; i < max_epid; i++) {
736 cur_epid = (start_epid + i) % max_epid;
737 if (cur_epid == hw->my_epid)
738 continue;
739
740 pstatus = fjes_hw_get_partner_ep_status(hw, cur_epid);
741 if (pstatus == EP_PARTNER_SHARED) {
742 if (!fjes_hw_epbuf_rx_is_empty(
743 &hw->ep_shm_info[cur_epid].rx))
744 return cur_epid;
745 }
746 }
747 return -1;
748}
749
750static void *fjes_rxframe_get(struct fjes_adapter *adapter, size_t *psize,
751 int *cur_epid)
752{
753 void *frame;
754
755 *cur_epid = fjes_rxframe_search_exist(adapter, *cur_epid);
756 if (*cur_epid < 0)
757 return NULL;
758
759 frame =
760 fjes_hw_epbuf_rx_curpkt_get_addr(
761 &adapter->hw.ep_shm_info[*cur_epid].rx, psize);
762
763 return frame;
764}
765
766static void fjes_rxframe_release(struct fjes_adapter *adapter, int cur_epid)
767{
768 fjes_hw_epbuf_rx_curpkt_drop(&adapter->hw.ep_shm_info[cur_epid].rx);
769}
770
771static void fjes_rx_irq(struct fjes_adapter *adapter, int src_epid)
772{
773 struct fjes_hw *hw = &adapter->hw;
774
775 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, true);
776
777 adapter->unset_rx_last = true;
778 napi_schedule(&adapter->napi);
779}
780
781static int fjes_poll(struct napi_struct *napi, int budget)
782{
783 struct fjes_adapter *adapter =
784 container_of(napi, struct fjes_adapter, napi);
785 struct net_device *netdev = napi->dev;
786 struct fjes_hw *hw = &adapter->hw;
787 struct sk_buff *skb;
788 int work_done = 0;
789 int cur_epid = 0;
790 int epidx;
791 size_t frame_len;
792 void *frame;
793
794 for (epidx = 0; epidx < hw->max_epid; epidx++) {
795 if (epidx == hw->my_epid)
796 continue;
797
798 adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status |=
799 FJES_RX_POLL_WORK;
800 }
801
802 while (work_done < budget) {
803 prefetch(&adapter->hw);
804 frame = fjes_rxframe_get(adapter, &frame_len, &cur_epid);
805
806 if (frame) {
807 skb = napi_alloc_skb(napi, frame_len);
808 if (!skb) {
809 adapter->stats64.rx_dropped += 1;
810 hw->ep_shm_info[cur_epid].net_stats
811 .rx_dropped += 1;
812 adapter->stats64.rx_errors += 1;
813 hw->ep_shm_info[cur_epid].net_stats
814 .rx_errors += 1;
815 } else {
816 memcpy(skb_put(skb, frame_len),
817 frame, frame_len);
818 skb->protocol = eth_type_trans(skb, netdev);
819 skb->ip_summed = CHECKSUM_UNNECESSARY;
820
821 netif_receive_skb(skb);
822
823 work_done++;
824
825 adapter->stats64.rx_packets += 1;
826 hw->ep_shm_info[cur_epid].net_stats
827 .rx_packets += 1;
828 adapter->stats64.rx_bytes += frame_len;
829 hw->ep_shm_info[cur_epid].net_stats
830 .rx_bytes += frame_len;
831
832 if (is_multicast_ether_addr(
833 ((struct ethhdr *)frame)->h_dest)) {
834 adapter->stats64.multicast += 1;
835 hw->ep_shm_info[cur_epid].net_stats
836 .multicast += 1;
837 }
838 }
839
840 fjes_rxframe_release(adapter, cur_epid);
841 adapter->unset_rx_last = true;
842 } else {
843 break;
844 }
845 }
846
847 if (work_done < budget) {
848 napi_complete(napi);
849
850 if (adapter->unset_rx_last) {
851 adapter->rx_last_jiffies = jiffies;
852 adapter->unset_rx_last = false;
853 }
854
855 if (((long)jiffies - (long)adapter->rx_last_jiffies) < 3) {
856 napi_reschedule(napi);
857 } else {
858 for (epidx = 0; epidx < hw->max_epid; epidx++) {
859 if (epidx == hw->my_epid)
860 continue;
861 adapter->hw.ep_shm_info[epidx]
862 .tx.info->v1i.rx_status &=
863 ~FJES_RX_POLL_WORK;
864 }
865
866 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, false);
867 }
868 }
869
870 return work_done;
871}
872
Taku Izumi658d4392015-08-21 17:29:17 +0900873/* fjes_probe - Device Initialization Routine */
874static int fjes_probe(struct platform_device *plat_dev)
875{
Taku Izumi2fcbca62015-08-21 17:29:20 +0900876 struct fjes_adapter *adapter;
877 struct net_device *netdev;
878 struct resource *res;
879 struct fjes_hw *hw;
880 int err;
881
882 err = -ENOMEM;
883 netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), "es%d",
884 NET_NAME_UNKNOWN, fjes_netdev_setup,
885 FJES_MAX_QUEUES);
886
887 if (!netdev)
888 goto err_out;
889
890 SET_NETDEV_DEV(netdev, &plat_dev->dev);
891
892 dev_set_drvdata(&plat_dev->dev, netdev);
893 adapter = netdev_priv(netdev);
894 adapter->netdev = netdev;
895 adapter->plat_dev = plat_dev;
896 hw = &adapter->hw;
897 hw->back = adapter;
898
899 /* setup the private structure */
900 err = fjes_sw_init(adapter);
901 if (err)
902 goto err_free_netdev;
903
904 adapter->force_reset = false;
905 adapter->open_guard = false;
906
Taku Izumib772b9d2015-08-21 17:29:25 +0900907 adapter->txrx_wq = create_workqueue(DRV_NAME "/txrx");
908
Taku Izumiac63b942015-08-21 17:29:26 +0900909 INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task);
Taku Izumib772b9d2015-08-21 17:29:25 +0900910 INIT_WORK(&adapter->raise_intr_rxdata_task,
911 fjes_raise_intr_rxdata_task);
912
Taku Izumi2fcbca62015-08-21 17:29:20 +0900913 res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
914 hw->hw_res.start = res->start;
915 hw->hw_res.size = res->end - res->start + 1;
916 hw->hw_res.irq = platform_get_irq(plat_dev, 0);
917 err = fjes_hw_init(&adapter->hw);
918 if (err)
919 goto err_free_netdev;
920
921 /* setup MAC address (02:00:00:00:00:[epid])*/
922 netdev->dev_addr[0] = 2;
923 netdev->dev_addr[1] = 0;
924 netdev->dev_addr[2] = 0;
925 netdev->dev_addr[3] = 0;
926 netdev->dev_addr[4] = 0;
927 netdev->dev_addr[5] = hw->my_epid; /* EPID */
928
929 err = register_netdev(netdev);
930 if (err)
931 goto err_hw_exit;
932
933 netif_carrier_off(netdev);
934
Taku Izumi658d4392015-08-21 17:29:17 +0900935 return 0;
Taku Izumi2fcbca62015-08-21 17:29:20 +0900936
937err_hw_exit:
938 fjes_hw_exit(&adapter->hw);
939err_free_netdev:
940 free_netdev(netdev);
941err_out:
942 return err;
Taku Izumi658d4392015-08-21 17:29:17 +0900943}
944
945/* fjes_remove - Device Removal Routine */
946static int fjes_remove(struct platform_device *plat_dev)
947{
Taku Izumi2fcbca62015-08-21 17:29:20 +0900948 struct net_device *netdev = dev_get_drvdata(&plat_dev->dev);
949 struct fjes_adapter *adapter = netdev_priv(netdev);
950 struct fjes_hw *hw = &adapter->hw;
951
Taku Izumib772b9d2015-08-21 17:29:25 +0900952 cancel_work_sync(&adapter->raise_intr_rxdata_task);
Taku Izumiac63b942015-08-21 17:29:26 +0900953 cancel_work_sync(&adapter->tx_stall_task);
Taku Izumib772b9d2015-08-21 17:29:25 +0900954 if (adapter->txrx_wq)
955 destroy_workqueue(adapter->txrx_wq);
956
Taku Izumi2fcbca62015-08-21 17:29:20 +0900957 unregister_netdev(netdev);
958
959 fjes_hw_exit(hw);
960
Taku Izumi26585932015-08-21 17:29:27 +0900961 netif_napi_del(&adapter->napi);
962
Taku Izumi2fcbca62015-08-21 17:29:20 +0900963 free_netdev(netdev);
964
Taku Izumi658d4392015-08-21 17:29:17 +0900965 return 0;
966}
967
Taku Izumi2fcbca62015-08-21 17:29:20 +0900968static int fjes_sw_init(struct fjes_adapter *adapter)
969{
Taku Izumi26585932015-08-21 17:29:27 +0900970 struct net_device *netdev = adapter->netdev;
971
972 netif_napi_add(netdev, &adapter->napi, fjes_poll, 64);
973
Taku Izumi2fcbca62015-08-21 17:29:20 +0900974 return 0;
975}
976
977/* fjes_netdev_setup - netdevice initialization routine */
978static void fjes_netdev_setup(struct net_device *netdev)
979{
980 ether_setup(netdev);
981
982 netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
983 netdev->netdev_ops = &fjes_netdev_ops;
984 netdev->mtu = fjes_support_mtu[0];
985 netdev->flags |= IFF_BROADCAST;
986 netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
987}
988
Taku Izumi658d4392015-08-21 17:29:17 +0900989/* fjes_init_module - Driver Registration Routine */
990static int __init fjes_init_module(void)
991{
992 int result;
993
994 pr_info("%s - version %s - %s\n",
995 fjes_driver_string, fjes_driver_version, fjes_copyright);
996
997 result = platform_driver_register(&fjes_driver);
998 if (result < 0)
999 return result;
1000
1001 result = acpi_bus_register_driver(&fjes_acpi_driver);
1002 if (result < 0)
1003 goto fail_acpi_driver;
1004
1005 return 0;
1006
1007fail_acpi_driver:
1008 platform_driver_unregister(&fjes_driver);
1009 return result;
1010}
1011
1012module_init(fjes_init_module);
1013
1014/* fjes_exit_module - Driver Exit Cleanup Routine */
1015static void __exit fjes_exit_module(void)
1016{
1017 acpi_bus_unregister_driver(&fjes_acpi_driver);
1018 platform_driver_unregister(&fjes_driver);
1019}
1020
1021module_exit(fjes_exit_module);