diff options
author | Taku Izumi <izumi.taku@jp.fujitsu.com> | 2015-08-21 04:29:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-24 17:06:34 -0400 |
commit | b772b9dc63df0ca8a750ceac9ab356376022f0b6 (patch) | |
tree | ce11cedba5d6f092c964b875f81738875953edee | |
parent | 9acf51cbf73de8952e3df75200d7a7755c16d0f6 (diff) |
fjes: raise_intr_rxdata_task
This patch add raise_intr_rxdata_task.
Extended Socket Network Device is shared memory
based, so someone's transmission denotes other's
reception. In order to notify receivers, sender
has to raise interruption of receivers.
raise_intr_rxdata_task does this work.
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/fjes/fjes.h | 4 | ||||
-rw-r--r-- | drivers/net/fjes/fjes_main.c | 63 |
2 files changed, 67 insertions, 0 deletions
diff --git a/drivers/net/fjes/fjes.h b/drivers/net/fjes/fjes.h index 7af4304f5425..8e9899ea1993 100644 --- a/drivers/net/fjes/fjes.h +++ b/drivers/net/fjes/fjes.h | |||
@@ -50,6 +50,10 @@ struct fjes_adapter { | |||
50 | 50 | ||
51 | bool irq_registered; | 51 | bool irq_registered; |
52 | 52 | ||
53 | struct workqueue_struct *txrx_wq; | ||
54 | |||
55 | struct work_struct raise_intr_rxdata_task; | ||
56 | |||
53 | struct fjes_hw hw; | 57 | struct fjes_hw hw; |
54 | }; | 58 | }; |
55 | 59 | ||
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 220ff3da4521..80e180f163f5 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c | |||
@@ -52,6 +52,7 @@ static int fjes_close(struct net_device *); | |||
52 | static int fjes_setup_resources(struct fjes_adapter *); | 52 | static int fjes_setup_resources(struct fjes_adapter *); |
53 | static void fjes_free_resources(struct fjes_adapter *); | 53 | static void fjes_free_resources(struct fjes_adapter *); |
54 | static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *); | 54 | static netdev_tx_t fjes_xmit_frame(struct sk_buff *, struct net_device *); |
55 | static void fjes_raise_intr_rxdata_task(struct work_struct *); | ||
55 | static irqreturn_t fjes_intr(int, void*); | 56 | static irqreturn_t fjes_intr(int, void*); |
56 | 57 | ||
57 | static int fjes_acpi_add(struct acpi_device *); | 58 | static int fjes_acpi_add(struct acpi_device *); |
@@ -276,6 +277,8 @@ static int fjes_close(struct net_device *netdev) | |||
276 | 277 | ||
277 | fjes_free_irq(adapter); | 278 | fjes_free_irq(adapter); |
278 | 279 | ||
280 | cancel_work_sync(&adapter->raise_intr_rxdata_task); | ||
281 | |||
279 | fjes_hw_wait_epstop(hw); | 282 | fjes_hw_wait_epstop(hw); |
280 | 283 | ||
281 | fjes_free_resources(adapter); | 284 | fjes_free_resources(adapter); |
@@ -404,6 +407,54 @@ static void fjes_free_resources(struct fjes_adapter *adapter) | |||
404 | } | 407 | } |
405 | } | 408 | } |
406 | 409 | ||
410 | static void fjes_raise_intr_rxdata_task(struct work_struct *work) | ||
411 | { | ||
412 | struct fjes_adapter *adapter = container_of(work, | ||
413 | struct fjes_adapter, raise_intr_rxdata_task); | ||
414 | struct fjes_hw *hw = &adapter->hw; | ||
415 | enum ep_partner_status pstatus; | ||
416 | int max_epid, my_epid, epid; | ||
417 | |||
418 | my_epid = hw->my_epid; | ||
419 | max_epid = hw->max_epid; | ||
420 | |||
421 | for (epid = 0; epid < max_epid; epid++) | ||
422 | hw->ep_shm_info[epid].tx_status_work = 0; | ||
423 | |||
424 | for (epid = 0; epid < max_epid; epid++) { | ||
425 | if (epid == my_epid) | ||
426 | continue; | ||
427 | |||
428 | pstatus = fjes_hw_get_partner_ep_status(hw, epid); | ||
429 | if (pstatus == EP_PARTNER_SHARED) { | ||
430 | hw->ep_shm_info[epid].tx_status_work = | ||
431 | hw->ep_shm_info[epid].tx.info->v1i.tx_status; | ||
432 | |||
433 | if (hw->ep_shm_info[epid].tx_status_work == | ||
434 | FJES_TX_DELAY_SEND_PENDING) { | ||
435 | hw->ep_shm_info[epid].tx.info->v1i.tx_status = | ||
436 | FJES_TX_DELAY_SEND_NONE; | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | |||
441 | for (epid = 0; epid < max_epid; epid++) { | ||
442 | if (epid == my_epid) | ||
443 | continue; | ||
444 | |||
445 | pstatus = fjes_hw_get_partner_ep_status(hw, epid); | ||
446 | if ((hw->ep_shm_info[epid].tx_status_work == | ||
447 | FJES_TX_DELAY_SEND_PENDING) && | ||
448 | (pstatus == EP_PARTNER_SHARED) && | ||
449 | !(hw->ep_shm_info[epid].rx.info->v1i.rx_status)) { | ||
450 | fjes_hw_raise_interrupt(hw, epid, | ||
451 | REG_ICTL_MASK_RX_DATA); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | usleep_range(500, 1000); | ||
456 | } | ||
457 | |||
407 | static int fjes_tx_send(struct fjes_adapter *adapter, int dest, | 458 | static int fjes_tx_send(struct fjes_adapter *adapter, int dest, |
408 | void *data, size_t len) | 459 | void *data, size_t len) |
409 | { | 460 | { |
@@ -416,6 +467,9 @@ static int fjes_tx_send(struct fjes_adapter *adapter, int dest, | |||
416 | 467 | ||
417 | adapter->hw.ep_shm_info[dest].tx.info->v1i.tx_status = | 468 | adapter->hw.ep_shm_info[dest].tx.info->v1i.tx_status = |
418 | FJES_TX_DELAY_SEND_PENDING; | 469 | FJES_TX_DELAY_SEND_PENDING; |
470 | if (!work_pending(&adapter->raise_intr_rxdata_task)) | ||
471 | queue_work(adapter->txrx_wq, | ||
472 | &adapter->raise_intr_rxdata_task); | ||
419 | 473 | ||
420 | retval = 0; | 474 | retval = 0; |
421 | return retval; | 475 | return retval; |
@@ -630,6 +684,11 @@ static int fjes_probe(struct platform_device *plat_dev) | |||
630 | adapter->force_reset = false; | 684 | adapter->force_reset = false; |
631 | adapter->open_guard = false; | 685 | adapter->open_guard = false; |
632 | 686 | ||
687 | adapter->txrx_wq = create_workqueue(DRV_NAME "/txrx"); | ||
688 | |||
689 | INIT_WORK(&adapter->raise_intr_rxdata_task, | ||
690 | fjes_raise_intr_rxdata_task); | ||
691 | |||
633 | res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0); | 692 | res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0); |
634 | hw->hw_res.start = res->start; | 693 | hw->hw_res.start = res->start; |
635 | hw->hw_res.size = res->end - res->start + 1; | 694 | hw->hw_res.size = res->end - res->start + 1; |
@@ -669,6 +728,10 @@ static int fjes_remove(struct platform_device *plat_dev) | |||
669 | struct fjes_adapter *adapter = netdev_priv(netdev); | 728 | struct fjes_adapter *adapter = netdev_priv(netdev); |
670 | struct fjes_hw *hw = &adapter->hw; | 729 | struct fjes_hw *hw = &adapter->hw; |
671 | 730 | ||
731 | cancel_work_sync(&adapter->raise_intr_rxdata_task); | ||
732 | if (adapter->txrx_wq) | ||
733 | destroy_workqueue(adapter->txrx_wq); | ||
734 | |||
672 | unregister_netdev(netdev); | 735 | unregister_netdev(netdev); |
673 | 736 | ||
674 | fjes_hw_exit(hw); | 737 | fjes_hw_exit(hw); |