blob: 5fce33dec8207c91221a1b0527efbec9bb034ba4 [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*);
Taku Izumi879bc9a2015-08-21 17:29:28 +090058static struct rtnl_link_stats64 *
59fjes_get_stats64(struct net_device *, struct rtnl_link_stats64 *);
Taku Izumib9e23a62015-08-21 17:29:29 +090060static int fjes_change_mtu(struct net_device *, int);
Taku Izumi3e3fedd2015-08-21 17:29:31 +090061static int fjes_vlan_rx_add_vid(struct net_device *, __be16 proto, u16);
62static int fjes_vlan_rx_kill_vid(struct net_device *, __be16 proto, u16);
Taku Izumi4393e762015-08-21 17:29:30 +090063static void fjes_tx_retry(struct net_device *);
Taku Izumie5d486d2015-08-21 17:29:23 +090064
Taku Izumi658d4392015-08-21 17:29:17 +090065static int fjes_acpi_add(struct acpi_device *);
66static int fjes_acpi_remove(struct acpi_device *);
67static acpi_status fjes_get_acpi_resource(struct acpi_resource *, void*);
68
69static int fjes_probe(struct platform_device *);
70static int fjes_remove(struct platform_device *);
71
Taku Izumi2fcbca62015-08-21 17:29:20 +090072static int fjes_sw_init(struct fjes_adapter *);
73static void fjes_netdev_setup(struct net_device *);
Taku Izumi8edb62a2015-08-21 17:29:32 +090074static void fjes_irq_watch_task(struct work_struct *);
Taku Izumi26585932015-08-21 17:29:27 +090075static void fjes_rx_irq(struct fjes_adapter *, int);
76static int fjes_poll(struct napi_struct *, int);
77
Taku Izumi658d4392015-08-21 17:29:17 +090078static const struct acpi_device_id fjes_acpi_ids[] = {
79 {"PNP0C02", 0},
80 {"", 0},
81};
82MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids);
83
84static struct acpi_driver fjes_acpi_driver = {
85 .name = DRV_NAME,
86 .class = DRV_NAME,
87 .owner = THIS_MODULE,
88 .ids = fjes_acpi_ids,
89 .ops = {
90 .add = fjes_acpi_add,
91 .remove = fjes_acpi_remove,
92 },
93};
94
95static struct platform_driver fjes_driver = {
96 .driver = {
97 .name = DRV_NAME,
98 .owner = THIS_MODULE,
99 },
100 .probe = fjes_probe,
101 .remove = fjes_remove,
102};
103
104static struct resource fjes_resource[] = {
105 {
106 .flags = IORESOURCE_MEM,
107 .start = 0,
108 .end = 0,
109 },
110 {
111 .flags = IORESOURCE_IRQ,
112 .start = 0,
113 .end = 0,
114 },
115};
116
117static int fjes_acpi_add(struct acpi_device *device)
118{
119 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
120 char str_buf[sizeof(FJES_ACPI_SYMBOL) + 1];
121 struct platform_device *plat_dev;
122 union acpi_object *str;
123 acpi_status status;
124 int result;
125
126 status = acpi_evaluate_object(device->handle, "_STR", NULL, &buffer);
127 if (ACPI_FAILURE(status))
128 return -ENODEV;
129
130 str = buffer.pointer;
131 result = utf16s_to_utf8s((wchar_t *)str->string.pointer,
132 str->string.length, UTF16_LITTLE_ENDIAN,
133 str_buf, sizeof(str_buf) - 1);
134 str_buf[result] = 0;
135
136 if (strncmp(FJES_ACPI_SYMBOL, str_buf, strlen(FJES_ACPI_SYMBOL)) != 0) {
137 kfree(buffer.pointer);
138 return -ENODEV;
139 }
140 kfree(buffer.pointer);
141
142 status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
143 fjes_get_acpi_resource, fjes_resource);
144 if (ACPI_FAILURE(status))
145 return -ENODEV;
146
147 /* create platform_device */
148 plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource,
149 ARRAY_SIZE(fjes_resource));
150 device->driver_data = plat_dev;
151
152 return 0;
153}
154
155static int fjes_acpi_remove(struct acpi_device *device)
156{
157 struct platform_device *plat_dev;
158
159 plat_dev = (struct platform_device *)acpi_driver_data(device);
160 platform_device_unregister(plat_dev);
161
162 return 0;
163}
164
165static acpi_status
166fjes_get_acpi_resource(struct acpi_resource *acpi_res, void *data)
167{
168 struct acpi_resource_address32 *addr;
169 struct acpi_resource_irq *irq;
170 struct resource *res = data;
171
172 switch (acpi_res->type) {
173 case ACPI_RESOURCE_TYPE_ADDRESS32:
174 addr = &acpi_res->data.address32;
175 res[0].start = addr->address.minimum;
176 res[0].end = addr->address.minimum +
177 addr->address.address_length - 1;
178 break;
179
180 case ACPI_RESOURCE_TYPE_IRQ:
181 irq = &acpi_res->data.irq;
182 if (irq->interrupt_count != 1)
183 return AE_ERROR;
184 res[1].start = irq->interrupts[0];
185 res[1].end = irq->interrupts[0];
186 break;
187
188 default:
189 break;
190 }
191
192 return AE_OK;
193}
194
Taku Izumie5d486d2015-08-21 17:29:23 +0900195static int fjes_request_irq(struct fjes_adapter *adapter)
196{
197 struct net_device *netdev = adapter->netdev;
198 int result = -1;
199
Taku Izumi8edb62a2015-08-21 17:29:32 +0900200 adapter->interrupt_watch_enable = true;
201 if (!delayed_work_pending(&adapter->interrupt_watch_task)) {
202 queue_delayed_work(adapter->control_wq,
203 &adapter->interrupt_watch_task,
204 FJES_IRQ_WATCH_DELAY);
205 }
206
Taku Izumie5d486d2015-08-21 17:29:23 +0900207 if (!adapter->irq_registered) {
208 result = request_irq(adapter->hw.hw_res.irq, fjes_intr,
209 IRQF_SHARED, netdev->name, adapter);
210 if (result)
211 adapter->irq_registered = false;
212 else
213 adapter->irq_registered = true;
214 }
215
216 return result;
217}
218
219static void fjes_free_irq(struct fjes_adapter *adapter)
220{
221 struct fjes_hw *hw = &adapter->hw;
222
Taku Izumi8edb62a2015-08-21 17:29:32 +0900223 adapter->interrupt_watch_enable = false;
224 cancel_delayed_work_sync(&adapter->interrupt_watch_task);
225
Taku Izumie5d486d2015-08-21 17:29:23 +0900226 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
227
228 if (adapter->irq_registered) {
229 free_irq(adapter->hw.hw_res.irq, adapter);
230 adapter->irq_registered = false;
231 }
232}
233
Taku Izumi2fcbca62015-08-21 17:29:20 +0900234static const struct net_device_ops fjes_netdev_ops = {
Taku Izumie5d486d2015-08-21 17:29:23 +0900235 .ndo_open = fjes_open,
236 .ndo_stop = fjes_close,
Taku Izumi9acf51c2015-08-21 17:29:24 +0900237 .ndo_start_xmit = fjes_xmit_frame,
Taku Izumi879bc9a2015-08-21 17:29:28 +0900238 .ndo_get_stats64 = fjes_get_stats64,
Taku Izumib9e23a62015-08-21 17:29:29 +0900239 .ndo_change_mtu = fjes_change_mtu,
Taku Izumi4393e762015-08-21 17:29:30 +0900240 .ndo_tx_timeout = fjes_tx_retry,
Taku Izumi3e3fedd2015-08-21 17:29:31 +0900241 .ndo_vlan_rx_add_vid = fjes_vlan_rx_add_vid,
242 .ndo_vlan_rx_kill_vid = fjes_vlan_rx_kill_vid,
Taku Izumi2fcbca62015-08-21 17:29:20 +0900243};
244
Taku Izumie5d486d2015-08-21 17:29:23 +0900245/* fjes_open - Called when a network interface is made active */
246static int fjes_open(struct net_device *netdev)
247{
248 struct fjes_adapter *adapter = netdev_priv(netdev);
249 struct fjes_hw *hw = &adapter->hw;
250 int result;
251
252 if (adapter->open_guard)
253 return -ENXIO;
254
255 result = fjes_setup_resources(adapter);
256 if (result)
257 goto err_setup_res;
258
259 hw->txrx_stop_req_bit = 0;
260 hw->epstop_req_bit = 0;
261
Taku Izumi26585932015-08-21 17:29:27 +0900262 napi_enable(&adapter->napi);
263
Taku Izumie5d486d2015-08-21 17:29:23 +0900264 fjes_hw_capture_interrupt_status(hw);
265
266 result = fjes_request_irq(adapter);
267 if (result)
268 goto err_req_irq;
269
270 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, false);
271
272 netif_tx_start_all_queues(netdev);
273 netif_carrier_on(netdev);
274
275 return 0;
276
277err_req_irq:
278 fjes_free_irq(adapter);
Taku Izumi26585932015-08-21 17:29:27 +0900279 napi_disable(&adapter->napi);
Taku Izumie5d486d2015-08-21 17:29:23 +0900280
281err_setup_res:
282 fjes_free_resources(adapter);
283 return result;
284}
285
286/* fjes_close - Disables a network interface */
287static int fjes_close(struct net_device *netdev)
288{
289 struct fjes_adapter *adapter = netdev_priv(netdev);
290 struct fjes_hw *hw = &adapter->hw;
291 int epidx;
292
293 netif_tx_stop_all_queues(netdev);
294 netif_carrier_off(netdev);
295
296 fjes_hw_raise_epstop(hw);
297
Taku Izumi26585932015-08-21 17:29:27 +0900298 napi_disable(&adapter->napi);
299
Taku Izumie5d486d2015-08-21 17:29:23 +0900300 for (epidx = 0; epidx < hw->max_epid; epidx++) {
301 if (epidx == hw->my_epid)
302 continue;
303
304 adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status &=
305 ~FJES_RX_POLL_WORK;
306 }
307
308 fjes_free_irq(adapter);
309
Taku Izumi8edb62a2015-08-21 17:29:32 +0900310 cancel_delayed_work_sync(&adapter->interrupt_watch_task);
Taku Izumib772b9d2015-08-21 17:29:25 +0900311 cancel_work_sync(&adapter->raise_intr_rxdata_task);
Taku Izumiac63b942015-08-21 17:29:26 +0900312 cancel_work_sync(&adapter->tx_stall_task);
Taku Izumib772b9d2015-08-21 17:29:25 +0900313
Taku Izumie5d486d2015-08-21 17:29:23 +0900314 fjes_hw_wait_epstop(hw);
315
316 fjes_free_resources(adapter);
317
318 return 0;
319}
320
321static int fjes_setup_resources(struct fjes_adapter *adapter)
322{
323 struct net_device *netdev = adapter->netdev;
324 struct ep_share_mem_info *buf_pair;
325 struct fjes_hw *hw = &adapter->hw;
326 int result;
327 int epidx;
328
329 mutex_lock(&hw->hw_info.lock);
330 result = fjes_hw_request_info(hw);
331 switch (result) {
332 case 0:
333 for (epidx = 0; epidx < hw->max_epid; epidx++) {
334 hw->ep_shm_info[epidx].es_status =
335 hw->hw_info.res_buf->info.info[epidx].es_status;
336 hw->ep_shm_info[epidx].zone =
337 hw->hw_info.res_buf->info.info[epidx].zone;
338 }
339 break;
340 default:
341 case -ENOMSG:
342 case -EBUSY:
343 adapter->force_reset = true;
344
345 mutex_unlock(&hw->hw_info.lock);
346 return result;
347 }
348 mutex_unlock(&hw->hw_info.lock);
349
350 for (epidx = 0; epidx < (hw->max_epid); epidx++) {
351 if ((epidx != hw->my_epid) &&
352 (hw->ep_shm_info[epidx].es_status ==
353 FJES_ZONING_STATUS_ENABLE)) {
354 fjes_hw_raise_interrupt(hw, epidx,
355 REG_ICTL_MASK_INFO_UPDATE);
356 }
357 }
358
359 msleep(FJES_OPEN_ZONE_UPDATE_WAIT * hw->max_epid);
360
361 for (epidx = 0; epidx < (hw->max_epid); epidx++) {
362 if (epidx == hw->my_epid)
363 continue;
364
365 buf_pair = &hw->ep_shm_info[epidx];
366
367 fjes_hw_setup_epbuf(&buf_pair->tx, netdev->dev_addr,
368 netdev->mtu);
369
370 if (fjes_hw_epid_is_same_zone(hw, epidx)) {
371 mutex_lock(&hw->hw_info.lock);
372 result =
373 fjes_hw_register_buff_addr(hw, epidx, buf_pair);
374 mutex_unlock(&hw->hw_info.lock);
375
376 switch (result) {
377 case 0:
378 break;
379 case -ENOMSG:
380 case -EBUSY:
381 default:
382 adapter->force_reset = true;
383 return result;
384 }
385 }
386 }
387
388 return 0;
389}
390
391static void fjes_free_resources(struct fjes_adapter *adapter)
392{
393 struct net_device *netdev = adapter->netdev;
394 struct fjes_device_command_param param;
395 struct ep_share_mem_info *buf_pair;
396 struct fjes_hw *hw = &adapter->hw;
397 bool reset_flag = false;
398 int result;
399 int epidx;
400
401 for (epidx = 0; epidx < hw->max_epid; epidx++) {
402 if (epidx == hw->my_epid)
403 continue;
404
405 mutex_lock(&hw->hw_info.lock);
406 result = fjes_hw_unregister_buff_addr(hw, epidx);
407 mutex_unlock(&hw->hw_info.lock);
408
409 if (result)
410 reset_flag = true;
411
412 buf_pair = &hw->ep_shm_info[epidx];
413
414 fjes_hw_setup_epbuf(&buf_pair->tx,
415 netdev->dev_addr, netdev->mtu);
416
417 clear_bit(epidx, &hw->txrx_stop_req_bit);
418 }
419
420 if (reset_flag || adapter->force_reset) {
421 result = fjes_hw_reset(hw);
422
423 adapter->force_reset = false;
424
425 if (result)
426 adapter->open_guard = true;
427
428 hw->hw_info.buffer_share_bit = 0;
429
430 memset((void *)&param, 0, sizeof(param));
431
432 param.req_len = hw->hw_info.req_buf_size;
433 param.req_start = __pa(hw->hw_info.req_buf);
434 param.res_len = hw->hw_info.res_buf_size;
435 param.res_start = __pa(hw->hw_info.res_buf);
436 param.share_start = __pa(hw->hw_info.share->ep_status);
437
438 fjes_hw_init_command_registers(hw, &param);
439 }
440}
441
Taku Izumiac63b942015-08-21 17:29:26 +0900442static void fjes_tx_stall_task(struct work_struct *work)
443{
444 struct fjes_adapter *adapter = container_of(work,
445 struct fjes_adapter, tx_stall_task);
446 struct net_device *netdev = adapter->netdev;
447 struct fjes_hw *hw = &adapter->hw;
448 int all_queue_available, sendable;
449 enum ep_partner_status pstatus;
450 int max_epid, my_epid, epid;
451 union ep_buffer_info *info;
452 int i;
453
454 if (((long)jiffies -
455 (long)(netdev->trans_start)) > FJES_TX_TX_STALL_TIMEOUT) {
456 netif_wake_queue(netdev);
457 return;
458 }
459
460 my_epid = hw->my_epid;
461 max_epid = hw->max_epid;
462
463 for (i = 0; i < 5; i++) {
464 all_queue_available = 1;
465
466 for (epid = 0; epid < max_epid; epid++) {
467 if (my_epid == epid)
468 continue;
469
470 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
471 sendable = (pstatus == EP_PARTNER_SHARED);
472 if (!sendable)
473 continue;
474
475 info = adapter->hw.ep_shm_info[epid].tx.info;
476
477 if (EP_RING_FULL(info->v1i.head, info->v1i.tail,
478 info->v1i.count_max)) {
479 all_queue_available = 0;
480 break;
481 }
482 }
483
484 if (all_queue_available) {
485 netif_wake_queue(netdev);
486 return;
487 }
488 }
489
490 usleep_range(50, 100);
491
492 queue_work(adapter->txrx_wq, &adapter->tx_stall_task);
493}
494
Taku Izumib772b9d2015-08-21 17:29:25 +0900495static void fjes_raise_intr_rxdata_task(struct work_struct *work)
496{
497 struct fjes_adapter *adapter = container_of(work,
498 struct fjes_adapter, raise_intr_rxdata_task);
499 struct fjes_hw *hw = &adapter->hw;
500 enum ep_partner_status pstatus;
501 int max_epid, my_epid, epid;
502
503 my_epid = hw->my_epid;
504 max_epid = hw->max_epid;
505
506 for (epid = 0; epid < max_epid; epid++)
507 hw->ep_shm_info[epid].tx_status_work = 0;
508
509 for (epid = 0; epid < max_epid; epid++) {
510 if (epid == my_epid)
511 continue;
512
513 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
514 if (pstatus == EP_PARTNER_SHARED) {
515 hw->ep_shm_info[epid].tx_status_work =
516 hw->ep_shm_info[epid].tx.info->v1i.tx_status;
517
518 if (hw->ep_shm_info[epid].tx_status_work ==
519 FJES_TX_DELAY_SEND_PENDING) {
520 hw->ep_shm_info[epid].tx.info->v1i.tx_status =
521 FJES_TX_DELAY_SEND_NONE;
522 }
523 }
524 }
525
526 for (epid = 0; epid < max_epid; epid++) {
527 if (epid == my_epid)
528 continue;
529
530 pstatus = fjes_hw_get_partner_ep_status(hw, epid);
531 if ((hw->ep_shm_info[epid].tx_status_work ==
532 FJES_TX_DELAY_SEND_PENDING) &&
533 (pstatus == EP_PARTNER_SHARED) &&
534 !(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) {
535 fjes_hw_raise_interrupt(hw, epid,
536 REG_ICTL_MASK_RX_DATA);
537 }
538 }
539
540 usleep_range(500, 1000);
541}
542
Taku Izumi9acf51c2015-08-21 17:29:24 +0900543static int fjes_tx_send(struct fjes_adapter *adapter, int dest,
544 void *data, size_t len)
545{
546 int retval;
547
548 retval = fjes_hw_epbuf_tx_pkt_send(&adapter->hw.ep_shm_info[dest].tx,
549 data, len);
550 if (retval)
551 return retval;
552
553 adapter->hw.ep_shm_info[dest].tx.info->v1i.tx_status =
554 FJES_TX_DELAY_SEND_PENDING;
Taku Izumib772b9d2015-08-21 17:29:25 +0900555 if (!work_pending(&adapter->raise_intr_rxdata_task))
556 queue_work(adapter->txrx_wq,
557 &adapter->raise_intr_rxdata_task);
Taku Izumi9acf51c2015-08-21 17:29:24 +0900558
559 retval = 0;
560 return retval;
561}
562
563static netdev_tx_t
564fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
565{
566 struct fjes_adapter *adapter = netdev_priv(netdev);
567 struct fjes_hw *hw = &adapter->hw;
568
569 int max_epid, my_epid, dest_epid;
570 enum ep_partner_status pstatus;
571 struct netdev_queue *cur_queue;
572 char shortpkt[VLAN_ETH_HLEN];
573 bool is_multi, vlan;
574 struct ethhdr *eth;
575 u16 queue_no = 0;
576 u16 vlan_id = 0;
577 netdev_tx_t ret;
578 char *data;
579 int len;
580
581 ret = NETDEV_TX_OK;
582 is_multi = false;
583 cur_queue = netdev_get_tx_queue(netdev, queue_no);
584
585 eth = (struct ethhdr *)skb->data;
586 my_epid = hw->my_epid;
587
588 vlan = (vlan_get_tag(skb, &vlan_id) == 0) ? true : false;
589
590 data = skb->data;
591 len = skb->len;
592
593 if (is_multicast_ether_addr(eth->h_dest)) {
594 dest_epid = 0;
595 max_epid = hw->max_epid;
596 is_multi = true;
597 } else if (is_local_ether_addr(eth->h_dest)) {
598 dest_epid = eth->h_dest[ETH_ALEN - 1];
599 max_epid = dest_epid + 1;
600
601 if ((eth->h_dest[0] == 0x02) &&
602 (0x00 == (eth->h_dest[1] | eth->h_dest[2] |
603 eth->h_dest[3] | eth->h_dest[4])) &&
604 (dest_epid < hw->max_epid)) {
605 ;
606 } else {
607 dest_epid = 0;
608 max_epid = 0;
609 ret = NETDEV_TX_OK;
610
611 adapter->stats64.tx_packets += 1;
612 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
613 adapter->stats64.tx_bytes += len;
614 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
615 }
616 } else {
617 dest_epid = 0;
618 max_epid = 0;
619 ret = NETDEV_TX_OK;
620
621 adapter->stats64.tx_packets += 1;
622 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
623 adapter->stats64.tx_bytes += len;
624 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
625 }
626
627 for (; dest_epid < max_epid; dest_epid++) {
628 if (my_epid == dest_epid)
629 continue;
630
631 pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid);
632 if (pstatus != EP_PARTNER_SHARED) {
633 ret = NETDEV_TX_OK;
634 } else if (!fjes_hw_check_epbuf_version(
635 &adapter->hw.ep_shm_info[dest_epid].rx, 0)) {
636 /* version is NOT 0 */
637 adapter->stats64.tx_carrier_errors += 1;
638 hw->ep_shm_info[my_epid].net_stats
639 .tx_carrier_errors += 1;
640
641 ret = NETDEV_TX_OK;
642 } else if (!fjes_hw_check_mtu(
643 &adapter->hw.ep_shm_info[dest_epid].rx,
644 netdev->mtu)) {
645 adapter->stats64.tx_dropped += 1;
646 hw->ep_shm_info[my_epid].net_stats.tx_dropped += 1;
647 adapter->stats64.tx_errors += 1;
648 hw->ep_shm_info[my_epid].net_stats.tx_errors += 1;
649
650 ret = NETDEV_TX_OK;
651 } else if (vlan &&
652 !fjes_hw_check_vlan_id(
653 &adapter->hw.ep_shm_info[dest_epid].rx,
654 vlan_id)) {
655 ret = NETDEV_TX_OK;
656 } else {
657 if (len < VLAN_ETH_HLEN) {
658 memset(shortpkt, 0, VLAN_ETH_HLEN);
659 memcpy(shortpkt, skb->data, skb->len);
660 len = VLAN_ETH_HLEN;
661 data = shortpkt;
662 }
663
664 if (adapter->tx_retry_count == 0) {
665 adapter->tx_start_jiffies = jiffies;
666 adapter->tx_retry_count = 1;
667 } else {
668 adapter->tx_retry_count++;
669 }
670
671 if (fjes_tx_send(adapter, dest_epid, data, len)) {
672 if (is_multi) {
673 ret = NETDEV_TX_OK;
674 } else if (
675 ((long)jiffies -
676 (long)adapter->tx_start_jiffies) >=
677 FJES_TX_RETRY_TIMEOUT) {
678 adapter->stats64.tx_fifo_errors += 1;
679 hw->ep_shm_info[my_epid].net_stats
680 .tx_fifo_errors += 1;
681 adapter->stats64.tx_errors += 1;
682 hw->ep_shm_info[my_epid].net_stats
683 .tx_errors += 1;
684
685 ret = NETDEV_TX_OK;
686 } else {
687 netdev->trans_start = jiffies;
688 netif_tx_stop_queue(cur_queue);
689
Taku Izumiac63b942015-08-21 17:29:26 +0900690 if (!work_pending(&adapter->tx_stall_task))
691 queue_work(adapter->txrx_wq,
692 &adapter->tx_stall_task);
693
Taku Izumi9acf51c2015-08-21 17:29:24 +0900694 ret = NETDEV_TX_BUSY;
695 }
696 } else {
697 if (!is_multi) {
698 adapter->stats64.tx_packets += 1;
699 hw->ep_shm_info[my_epid].net_stats
700 .tx_packets += 1;
701 adapter->stats64.tx_bytes += len;
702 hw->ep_shm_info[my_epid].net_stats
703 .tx_bytes += len;
704 }
705
706 adapter->tx_retry_count = 0;
707 ret = NETDEV_TX_OK;
708 }
709 }
710 }
711
712 if (ret == NETDEV_TX_OK) {
713 dev_kfree_skb(skb);
714 if (is_multi) {
715 adapter->stats64.tx_packets += 1;
716 hw->ep_shm_info[my_epid].net_stats.tx_packets += 1;
717 adapter->stats64.tx_bytes += 1;
718 hw->ep_shm_info[my_epid].net_stats.tx_bytes += len;
719 }
720 }
721
722 return ret;
723}
724
Taku Izumi4393e762015-08-21 17:29:30 +0900725static void fjes_tx_retry(struct net_device *netdev)
726{
727 struct netdev_queue *queue = netdev_get_tx_queue(netdev, 0);
728
729 netif_tx_wake_queue(queue);
730}
731
Taku Izumi879bc9a2015-08-21 17:29:28 +0900732static struct rtnl_link_stats64 *
733fjes_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
734{
735 struct fjes_adapter *adapter = netdev_priv(netdev);
736
737 memcpy(stats, &adapter->stats64, sizeof(struct rtnl_link_stats64));
738
739 return stats;
740}
741
Taku Izumib9e23a62015-08-21 17:29:29 +0900742static int fjes_change_mtu(struct net_device *netdev, int new_mtu)
743{
744 bool running = netif_running(netdev);
745 int ret = 0;
746 int idx;
747
748 for (idx = 0; fjes_support_mtu[idx] != 0; idx++) {
749 if (new_mtu <= fjes_support_mtu[idx]) {
750 new_mtu = fjes_support_mtu[idx];
751 if (new_mtu == netdev->mtu)
752 return 0;
753
754 if (running)
755 fjes_close(netdev);
756
757 netdev->mtu = new_mtu;
758
759 if (running)
760 ret = fjes_open(netdev);
761
762 return ret;
763 }
764 }
765
766 return -EINVAL;
767}
768
Taku Izumi3e3fedd2015-08-21 17:29:31 +0900769static int fjes_vlan_rx_add_vid(struct net_device *netdev,
770 __be16 proto, u16 vid)
771{
772 struct fjes_adapter *adapter = netdev_priv(netdev);
773 bool ret = true;
774 int epid;
775
776 for (epid = 0; epid < adapter->hw.max_epid; epid++) {
777 if (epid == adapter->hw.my_epid)
778 continue;
779
780 if (!fjes_hw_check_vlan_id(
781 &adapter->hw.ep_shm_info[epid].tx, vid))
782 ret = fjes_hw_set_vlan_id(
783 &adapter->hw.ep_shm_info[epid].tx, vid);
784 }
785
786 return ret ? 0 : -ENOSPC;
787}
788
789static int fjes_vlan_rx_kill_vid(struct net_device *netdev,
790 __be16 proto, u16 vid)
791{
792 struct fjes_adapter *adapter = netdev_priv(netdev);
793 int epid;
794
795 for (epid = 0; epid < adapter->hw.max_epid; epid++) {
796 if (epid == adapter->hw.my_epid)
797 continue;
798
799 fjes_hw_del_vlan_id(&adapter->hw.ep_shm_info[epid].tx, vid);
800 }
801
802 return 0;
803}
804
Taku Izumie5d486d2015-08-21 17:29:23 +0900805static irqreturn_t fjes_intr(int irq, void *data)
806{
807 struct fjes_adapter *adapter = data;
808 struct fjes_hw *hw = &adapter->hw;
809 irqreturn_t ret;
810 u32 icr;
811
812 icr = fjes_hw_capture_interrupt_status(hw);
813
Taku Izumi26585932015-08-21 17:29:27 +0900814 if (icr & REG_IS_MASK_IS_ASSERT) {
815 if (icr & REG_ICTL_MASK_RX_DATA)
816 fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
817
Taku Izumie5d486d2015-08-21 17:29:23 +0900818 ret = IRQ_HANDLED;
Taku Izumi26585932015-08-21 17:29:27 +0900819 } else {
Taku Izumie5d486d2015-08-21 17:29:23 +0900820 ret = IRQ_NONE;
Taku Izumi26585932015-08-21 17:29:27 +0900821 }
Taku Izumie5d486d2015-08-21 17:29:23 +0900822
823 return ret;
824}
825
Taku Izumi26585932015-08-21 17:29:27 +0900826static int fjes_rxframe_search_exist(struct fjes_adapter *adapter,
827 int start_epid)
828{
829 struct fjes_hw *hw = &adapter->hw;
830 enum ep_partner_status pstatus;
831 int max_epid, cur_epid;
832 int i;
833
834 max_epid = hw->max_epid;
835 start_epid = (start_epid + 1 + max_epid) % max_epid;
836
837 for (i = 0; i < max_epid; i++) {
838 cur_epid = (start_epid + i) % max_epid;
839 if (cur_epid == hw->my_epid)
840 continue;
841
842 pstatus = fjes_hw_get_partner_ep_status(hw, cur_epid);
843 if (pstatus == EP_PARTNER_SHARED) {
844 if (!fjes_hw_epbuf_rx_is_empty(
845 &hw->ep_shm_info[cur_epid].rx))
846 return cur_epid;
847 }
848 }
849 return -1;
850}
851
852static void *fjes_rxframe_get(struct fjes_adapter *adapter, size_t *psize,
853 int *cur_epid)
854{
855 void *frame;
856
857 *cur_epid = fjes_rxframe_search_exist(adapter, *cur_epid);
858 if (*cur_epid < 0)
859 return NULL;
860
861 frame =
862 fjes_hw_epbuf_rx_curpkt_get_addr(
863 &adapter->hw.ep_shm_info[*cur_epid].rx, psize);
864
865 return frame;
866}
867
868static void fjes_rxframe_release(struct fjes_adapter *adapter, int cur_epid)
869{
870 fjes_hw_epbuf_rx_curpkt_drop(&adapter->hw.ep_shm_info[cur_epid].rx);
871}
872
873static void fjes_rx_irq(struct fjes_adapter *adapter, int src_epid)
874{
875 struct fjes_hw *hw = &adapter->hw;
876
877 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, true);
878
879 adapter->unset_rx_last = true;
880 napi_schedule(&adapter->napi);
881}
882
883static int fjes_poll(struct napi_struct *napi, int budget)
884{
885 struct fjes_adapter *adapter =
886 container_of(napi, struct fjes_adapter, napi);
887 struct net_device *netdev = napi->dev;
888 struct fjes_hw *hw = &adapter->hw;
889 struct sk_buff *skb;
890 int work_done = 0;
891 int cur_epid = 0;
892 int epidx;
893 size_t frame_len;
894 void *frame;
895
896 for (epidx = 0; epidx < hw->max_epid; epidx++) {
897 if (epidx == hw->my_epid)
898 continue;
899
900 adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status |=
901 FJES_RX_POLL_WORK;
902 }
903
904 while (work_done < budget) {
905 prefetch(&adapter->hw);
906 frame = fjes_rxframe_get(adapter, &frame_len, &cur_epid);
907
908 if (frame) {
909 skb = napi_alloc_skb(napi, frame_len);
910 if (!skb) {
911 adapter->stats64.rx_dropped += 1;
912 hw->ep_shm_info[cur_epid].net_stats
913 .rx_dropped += 1;
914 adapter->stats64.rx_errors += 1;
915 hw->ep_shm_info[cur_epid].net_stats
916 .rx_errors += 1;
917 } else {
918 memcpy(skb_put(skb, frame_len),
919 frame, frame_len);
920 skb->protocol = eth_type_trans(skb, netdev);
921 skb->ip_summed = CHECKSUM_UNNECESSARY;
922
923 netif_receive_skb(skb);
924
925 work_done++;
926
927 adapter->stats64.rx_packets += 1;
928 hw->ep_shm_info[cur_epid].net_stats
929 .rx_packets += 1;
930 adapter->stats64.rx_bytes += frame_len;
931 hw->ep_shm_info[cur_epid].net_stats
932 .rx_bytes += frame_len;
933
934 if (is_multicast_ether_addr(
935 ((struct ethhdr *)frame)->h_dest)) {
936 adapter->stats64.multicast += 1;
937 hw->ep_shm_info[cur_epid].net_stats
938 .multicast += 1;
939 }
940 }
941
942 fjes_rxframe_release(adapter, cur_epid);
943 adapter->unset_rx_last = true;
944 } else {
945 break;
946 }
947 }
948
949 if (work_done < budget) {
950 napi_complete(napi);
951
952 if (adapter->unset_rx_last) {
953 adapter->rx_last_jiffies = jiffies;
954 adapter->unset_rx_last = false;
955 }
956
957 if (((long)jiffies - (long)adapter->rx_last_jiffies) < 3) {
958 napi_reschedule(napi);
959 } else {
960 for (epidx = 0; epidx < hw->max_epid; epidx++) {
961 if (epidx == hw->my_epid)
962 continue;
963 adapter->hw.ep_shm_info[epidx]
964 .tx.info->v1i.rx_status &=
965 ~FJES_RX_POLL_WORK;
966 }
967
968 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, false);
969 }
970 }
971
972 return work_done;
973}
974
Taku Izumi658d4392015-08-21 17:29:17 +0900975/* fjes_probe - Device Initialization Routine */
976static int fjes_probe(struct platform_device *plat_dev)
977{
Taku Izumi2fcbca62015-08-21 17:29:20 +0900978 struct fjes_adapter *adapter;
979 struct net_device *netdev;
980 struct resource *res;
981 struct fjes_hw *hw;
982 int err;
983
984 err = -ENOMEM;
985 netdev = alloc_netdev_mq(sizeof(struct fjes_adapter), "es%d",
986 NET_NAME_UNKNOWN, fjes_netdev_setup,
987 FJES_MAX_QUEUES);
988
989 if (!netdev)
990 goto err_out;
991
992 SET_NETDEV_DEV(netdev, &plat_dev->dev);
993
994 dev_set_drvdata(&plat_dev->dev, netdev);
995 adapter = netdev_priv(netdev);
996 adapter->netdev = netdev;
997 adapter->plat_dev = plat_dev;
998 hw = &adapter->hw;
999 hw->back = adapter;
1000
1001 /* setup the private structure */
1002 err = fjes_sw_init(adapter);
1003 if (err)
1004 goto err_free_netdev;
1005
1006 adapter->force_reset = false;
1007 adapter->open_guard = false;
1008
Taku Izumib772b9d2015-08-21 17:29:25 +09001009 adapter->txrx_wq = create_workqueue(DRV_NAME "/txrx");
Taku Izumi8edb62a2015-08-21 17:29:32 +09001010 adapter->control_wq = create_workqueue(DRV_NAME "/control");
Taku Izumib772b9d2015-08-21 17:29:25 +09001011
Taku Izumiac63b942015-08-21 17:29:26 +09001012 INIT_WORK(&adapter->tx_stall_task, fjes_tx_stall_task);
Taku Izumib772b9d2015-08-21 17:29:25 +09001013 INIT_WORK(&adapter->raise_intr_rxdata_task,
1014 fjes_raise_intr_rxdata_task);
1015
Taku Izumi8edb62a2015-08-21 17:29:32 +09001016 INIT_DELAYED_WORK(&adapter->interrupt_watch_task, fjes_irq_watch_task);
1017 adapter->interrupt_watch_enable = false;
1018
Taku Izumi2fcbca62015-08-21 17:29:20 +09001019 res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
1020 hw->hw_res.start = res->start;
1021 hw->hw_res.size = res->end - res->start + 1;
1022 hw->hw_res.irq = platform_get_irq(plat_dev, 0);
1023 err = fjes_hw_init(&adapter->hw);
1024 if (err)
1025 goto err_free_netdev;
1026
1027 /* setup MAC address (02:00:00:00:00:[epid])*/
1028 netdev->dev_addr[0] = 2;
1029 netdev->dev_addr[1] = 0;
1030 netdev->dev_addr[2] = 0;
1031 netdev->dev_addr[3] = 0;
1032 netdev->dev_addr[4] = 0;
1033 netdev->dev_addr[5] = hw->my_epid; /* EPID */
1034
1035 err = register_netdev(netdev);
1036 if (err)
1037 goto err_hw_exit;
1038
1039 netif_carrier_off(netdev);
1040
Taku Izumi658d4392015-08-21 17:29:17 +09001041 return 0;
Taku Izumi2fcbca62015-08-21 17:29:20 +09001042
1043err_hw_exit:
1044 fjes_hw_exit(&adapter->hw);
1045err_free_netdev:
1046 free_netdev(netdev);
1047err_out:
1048 return err;
Taku Izumi658d4392015-08-21 17:29:17 +09001049}
1050
1051/* fjes_remove - Device Removal Routine */
1052static int fjes_remove(struct platform_device *plat_dev)
1053{
Taku Izumi2fcbca62015-08-21 17:29:20 +09001054 struct net_device *netdev = dev_get_drvdata(&plat_dev->dev);
1055 struct fjes_adapter *adapter = netdev_priv(netdev);
1056 struct fjes_hw *hw = &adapter->hw;
1057
Taku Izumi8edb62a2015-08-21 17:29:32 +09001058 cancel_delayed_work_sync(&adapter->interrupt_watch_task);
Taku Izumib772b9d2015-08-21 17:29:25 +09001059 cancel_work_sync(&adapter->raise_intr_rxdata_task);
Taku Izumiac63b942015-08-21 17:29:26 +09001060 cancel_work_sync(&adapter->tx_stall_task);
Taku Izumi8edb62a2015-08-21 17:29:32 +09001061 if (adapter->control_wq)
1062 destroy_workqueue(adapter->control_wq);
Taku Izumib772b9d2015-08-21 17:29:25 +09001063 if (adapter->txrx_wq)
1064 destroy_workqueue(adapter->txrx_wq);
1065
Taku Izumi2fcbca62015-08-21 17:29:20 +09001066 unregister_netdev(netdev);
1067
1068 fjes_hw_exit(hw);
1069
Taku Izumi26585932015-08-21 17:29:27 +09001070 netif_napi_del(&adapter->napi);
1071
Taku Izumi2fcbca62015-08-21 17:29:20 +09001072 free_netdev(netdev);
1073
Taku Izumi658d4392015-08-21 17:29:17 +09001074 return 0;
1075}
1076
Taku Izumi2fcbca62015-08-21 17:29:20 +09001077static int fjes_sw_init(struct fjes_adapter *adapter)
1078{
Taku Izumi26585932015-08-21 17:29:27 +09001079 struct net_device *netdev = adapter->netdev;
1080
1081 netif_napi_add(netdev, &adapter->napi, fjes_poll, 64);
1082
Taku Izumi2fcbca62015-08-21 17:29:20 +09001083 return 0;
1084}
1085
1086/* fjes_netdev_setup - netdevice initialization routine */
1087static void fjes_netdev_setup(struct net_device *netdev)
1088{
1089 ether_setup(netdev);
1090
1091 netdev->watchdog_timeo = FJES_TX_RETRY_INTERVAL;
1092 netdev->netdev_ops = &fjes_netdev_ops;
1093 netdev->mtu = fjes_support_mtu[0];
1094 netdev->flags |= IFF_BROADCAST;
1095 netdev->features |= NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_FILTER;
1096}
1097
Taku Izumi8edb62a2015-08-21 17:29:32 +09001098static void fjes_irq_watch_task(struct work_struct *work)
1099{
1100 struct fjes_adapter *adapter = container_of(to_delayed_work(work),
1101 struct fjes_adapter, interrupt_watch_task);
1102
1103 local_irq_disable();
1104 fjes_intr(adapter->hw.hw_res.irq, adapter);
1105 local_irq_enable();
1106
1107 if (fjes_rxframe_search_exist(adapter, 0) >= 0)
1108 napi_schedule(&adapter->napi);
1109
1110 if (adapter->interrupt_watch_enable) {
1111 if (!delayed_work_pending(&adapter->interrupt_watch_task))
1112 queue_delayed_work(adapter->control_wq,
1113 &adapter->interrupt_watch_task,
1114 FJES_IRQ_WATCH_DELAY);
1115 }
1116}
1117
Taku Izumi658d4392015-08-21 17:29:17 +09001118/* fjes_init_module - Driver Registration Routine */
1119static int __init fjes_init_module(void)
1120{
1121 int result;
1122
1123 pr_info("%s - version %s - %s\n",
1124 fjes_driver_string, fjes_driver_version, fjes_copyright);
1125
1126 result = platform_driver_register(&fjes_driver);
1127 if (result < 0)
1128 return result;
1129
1130 result = acpi_bus_register_driver(&fjes_acpi_driver);
1131 if (result < 0)
1132 goto fail_acpi_driver;
1133
1134 return 0;
1135
1136fail_acpi_driver:
1137 platform_driver_unregister(&fjes_driver);
1138 return result;
1139}
1140
1141module_init(fjes_init_module);
1142
1143/* fjes_exit_module - Driver Exit Cleanup Routine */
1144static void __exit fjes_exit_module(void)
1145{
1146 acpi_bus_unregister_driver(&fjes_acpi_driver);
1147 platform_driver_unregister(&fjes_driver);
1148}
1149
1150module_exit(fjes_exit_module);