diff options
author | Taku Izumi <izumi.taku@jp.fujitsu.com> | 2015-08-21 04:29:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-24 17:06:36 -0400 |
commit | 785f28e061a870eba937cb2a860cbcf631f5ebb0 (patch) | |
tree | 14476ef9ebf38cbe1a9472052c2d7f8638d7e6fe | |
parent | 8fc4cadb98c6a0f1eecde678271fcc957258af3e (diff) |
fjes: update_zone_task
This patch adds update_zone_task.
Zoning information can be changed by user.
This task is used to monitor if zoning information is
changed or not.
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_hw.c | 179 | ||||
-rw-r--r-- | drivers/net/fjes/fjes_hw.h | 1 | ||||
-rw-r--r-- | drivers/net/fjes/fjes_main.c | 14 |
3 files changed, 194 insertions, 0 deletions
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index 4a4b750fdb9c..4525d3664ccf 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include "fjes_hw.h" | 22 | #include "fjes_hw.h" |
23 | #include "fjes.h" | 23 | #include "fjes.h" |
24 | 24 | ||
25 | static void fjes_hw_update_zone_task(struct work_struct *); | ||
26 | |||
25 | /* supported MTU list */ | 27 | /* supported MTU list */ |
26 | const u32 fjes_support_mtu[] = { | 28 | const u32 fjes_support_mtu[] = { |
27 | FJES_MTU_DEFINE(8 * 1024), | 29 | FJES_MTU_DEFINE(8 * 1024), |
@@ -322,6 +324,8 @@ int fjes_hw_init(struct fjes_hw *hw) | |||
322 | 324 | ||
323 | fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true); | 325 | fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true); |
324 | 326 | ||
327 | INIT_WORK(&hw->update_zone_task, fjes_hw_update_zone_task); | ||
328 | |||
325 | mutex_init(&hw->hw_info.lock); | 329 | mutex_init(&hw->hw_info.lock); |
326 | 330 | ||
327 | hw->max_epid = fjes_hw_get_max_epid(hw); | 331 | hw->max_epid = fjes_hw_get_max_epid(hw); |
@@ -349,6 +353,8 @@ void fjes_hw_exit(struct fjes_hw *hw) | |||
349 | } | 353 | } |
350 | 354 | ||
351 | fjes_hw_cleanup(hw); | 355 | fjes_hw_cleanup(hw); |
356 | |||
357 | cancel_work_sync(&hw->update_zone_task); | ||
352 | } | 358 | } |
353 | 359 | ||
354 | static enum fjes_dev_command_response_e | 360 | static enum fjes_dev_command_response_e |
@@ -913,3 +919,176 @@ int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh, | |||
913 | 919 | ||
914 | return 0; | 920 | return 0; |
915 | } | 921 | } |
922 | |||
923 | static void fjes_hw_update_zone_task(struct work_struct *work) | ||
924 | { | ||
925 | struct fjes_hw *hw = container_of(work, | ||
926 | struct fjes_hw, update_zone_task); | ||
927 | |||
928 | struct my_s {u8 es_status; u8 zone; } *info; | ||
929 | union fjes_device_command_res *res_buf; | ||
930 | enum ep_partner_status pstatus; | ||
931 | |||
932 | struct fjes_adapter *adapter; | ||
933 | struct net_device *netdev; | ||
934 | |||
935 | ulong unshare_bit = 0; | ||
936 | ulong share_bit = 0; | ||
937 | ulong irq_bit = 0; | ||
938 | |||
939 | int epidx; | ||
940 | int ret; | ||
941 | |||
942 | adapter = (struct fjes_adapter *)hw->back; | ||
943 | netdev = adapter->netdev; | ||
944 | res_buf = hw->hw_info.res_buf; | ||
945 | info = (struct my_s *)&res_buf->info.info; | ||
946 | |||
947 | mutex_lock(&hw->hw_info.lock); | ||
948 | |||
949 | ret = fjes_hw_request_info(hw); | ||
950 | switch (ret) { | ||
951 | case -ENOMSG: | ||
952 | case -EBUSY: | ||
953 | default: | ||
954 | if (!work_pending(&adapter->force_close_task)) { | ||
955 | adapter->force_reset = true; | ||
956 | schedule_work(&adapter->force_close_task); | ||
957 | } | ||
958 | break; | ||
959 | |||
960 | case 0: | ||
961 | |||
962 | for (epidx = 0; epidx < hw->max_epid; epidx++) { | ||
963 | if (epidx == hw->my_epid) { | ||
964 | hw->ep_shm_info[epidx].es_status = | ||
965 | info[epidx].es_status; | ||
966 | hw->ep_shm_info[epidx].zone = | ||
967 | info[epidx].zone; | ||
968 | continue; | ||
969 | } | ||
970 | |||
971 | pstatus = fjes_hw_get_partner_ep_status(hw, epidx); | ||
972 | switch (pstatus) { | ||
973 | case EP_PARTNER_UNSHARE: | ||
974 | default: | ||
975 | if ((info[epidx].zone != | ||
976 | FJES_ZONING_ZONE_TYPE_NONE) && | ||
977 | (info[epidx].es_status == | ||
978 | FJES_ZONING_STATUS_ENABLE) && | ||
979 | (info[epidx].zone == | ||
980 | info[hw->my_epid].zone)) | ||
981 | set_bit(epidx, &share_bit); | ||
982 | else | ||
983 | set_bit(epidx, &unshare_bit); | ||
984 | break; | ||
985 | |||
986 | case EP_PARTNER_COMPLETE: | ||
987 | case EP_PARTNER_WAITING: | ||
988 | if ((info[epidx].zone == | ||
989 | FJES_ZONING_ZONE_TYPE_NONE) || | ||
990 | (info[epidx].es_status != | ||
991 | FJES_ZONING_STATUS_ENABLE) || | ||
992 | (info[epidx].zone != | ||
993 | info[hw->my_epid].zone)) { | ||
994 | set_bit(epidx, | ||
995 | &adapter->unshare_watch_bitmask); | ||
996 | set_bit(epidx, | ||
997 | &hw->hw_info.buffer_unshare_reserve_bit); | ||
998 | } | ||
999 | break; | ||
1000 | |||
1001 | case EP_PARTNER_SHARED: | ||
1002 | if ((info[epidx].zone == | ||
1003 | FJES_ZONING_ZONE_TYPE_NONE) || | ||
1004 | (info[epidx].es_status != | ||
1005 | FJES_ZONING_STATUS_ENABLE) || | ||
1006 | (info[epidx].zone != | ||
1007 | info[hw->my_epid].zone)) | ||
1008 | set_bit(epidx, &irq_bit); | ||
1009 | break; | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | hw->ep_shm_info[epidx].es_status = info[epidx].es_status; | ||
1014 | hw->ep_shm_info[epidx].zone = info[epidx].zone; | ||
1015 | |||
1016 | break; | ||
1017 | } | ||
1018 | |||
1019 | mutex_unlock(&hw->hw_info.lock); | ||
1020 | |||
1021 | for (epidx = 0; epidx < hw->max_epid; epidx++) { | ||
1022 | if (epidx == hw->my_epid) | ||
1023 | continue; | ||
1024 | |||
1025 | if (test_bit(epidx, &share_bit)) { | ||
1026 | fjes_hw_setup_epbuf(&hw->ep_shm_info[epidx].tx, | ||
1027 | netdev->dev_addr, netdev->mtu); | ||
1028 | |||
1029 | mutex_lock(&hw->hw_info.lock); | ||
1030 | |||
1031 | ret = fjes_hw_register_buff_addr( | ||
1032 | hw, epidx, &hw->ep_shm_info[epidx]); | ||
1033 | |||
1034 | switch (ret) { | ||
1035 | case 0: | ||
1036 | break; | ||
1037 | case -ENOMSG: | ||
1038 | case -EBUSY: | ||
1039 | default: | ||
1040 | if (!work_pending(&adapter->force_close_task)) { | ||
1041 | adapter->force_reset = true; | ||
1042 | schedule_work( | ||
1043 | &adapter->force_close_task); | ||
1044 | } | ||
1045 | break; | ||
1046 | } | ||
1047 | mutex_unlock(&hw->hw_info.lock); | ||
1048 | } | ||
1049 | |||
1050 | if (test_bit(epidx, &unshare_bit)) { | ||
1051 | mutex_lock(&hw->hw_info.lock); | ||
1052 | |||
1053 | ret = fjes_hw_unregister_buff_addr(hw, epidx); | ||
1054 | |||
1055 | switch (ret) { | ||
1056 | case 0: | ||
1057 | break; | ||
1058 | case -ENOMSG: | ||
1059 | case -EBUSY: | ||
1060 | default: | ||
1061 | if (!work_pending(&adapter->force_close_task)) { | ||
1062 | adapter->force_reset = true; | ||
1063 | schedule_work( | ||
1064 | &adapter->force_close_task); | ||
1065 | } | ||
1066 | break; | ||
1067 | } | ||
1068 | |||
1069 | mutex_unlock(&hw->hw_info.lock); | ||
1070 | |||
1071 | if (ret == 0) | ||
1072 | fjes_hw_setup_epbuf( | ||
1073 | &hw->ep_shm_info[epidx].tx, | ||
1074 | netdev->dev_addr, netdev->mtu); | ||
1075 | } | ||
1076 | |||
1077 | if (test_bit(epidx, &irq_bit)) { | ||
1078 | fjes_hw_raise_interrupt(hw, epidx, | ||
1079 | REG_ICTL_MASK_TXRX_STOP_REQ); | ||
1080 | |||
1081 | set_bit(epidx, &hw->txrx_stop_req_bit); | ||
1082 | hw->ep_shm_info[epidx].tx. | ||
1083 | info->v1i.rx_status |= | ||
1084 | FJES_RX_STOP_REQ_REQUEST; | ||
1085 | set_bit(epidx, &hw->hw_info.buffer_unshare_reserve_bit); | ||
1086 | } | ||
1087 | } | ||
1088 | |||
1089 | if (irq_bit || adapter->unshare_watch_bitmask) { | ||
1090 | if (!work_pending(&adapter->unshare_watch_task)) | ||
1091 | queue_work(adapter->control_wq, | ||
1092 | &adapter->unshare_watch_task); | ||
1093 | } | ||
1094 | } | ||
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h index 95e632b363c1..e59b737b45e7 100644 --- a/drivers/net/fjes/fjes_hw.h +++ b/drivers/net/fjes/fjes_hw.h | |||
@@ -282,6 +282,7 @@ struct fjes_hw { | |||
282 | 282 | ||
283 | unsigned long txrx_stop_req_bit; | 283 | unsigned long txrx_stop_req_bit; |
284 | unsigned long epstop_req_bit; | 284 | unsigned long epstop_req_bit; |
285 | struct work_struct update_zone_task; | ||
285 | 286 | ||
286 | int my_epid; | 287 | int my_epid; |
287 | int max_epid; | 288 | int max_epid; |
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index c47ecf35d005..8e3a084277c0 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c | |||
@@ -315,6 +315,8 @@ static int fjes_close(struct net_device *netdev) | |||
315 | cancel_work_sync(&adapter->raise_intr_rxdata_task); | 315 | cancel_work_sync(&adapter->raise_intr_rxdata_task); |
316 | cancel_work_sync(&adapter->tx_stall_task); | 316 | cancel_work_sync(&adapter->tx_stall_task); |
317 | 317 | ||
318 | cancel_work_sync(&hw->update_zone_task); | ||
319 | |||
318 | fjes_hw_wait_epstop(hw); | 320 | fjes_hw_wait_epstop(hw); |
319 | 321 | ||
320 | fjes_free_resources(adapter); | 322 | fjes_free_resources(adapter); |
@@ -817,6 +819,15 @@ static int fjes_vlan_rx_kill_vid(struct net_device *netdev, | |||
817 | return 0; | 819 | return 0; |
818 | } | 820 | } |
819 | 821 | ||
822 | static void fjes_update_zone_irq(struct fjes_adapter *adapter, | ||
823 | int src_epid) | ||
824 | { | ||
825 | struct fjes_hw *hw = &adapter->hw; | ||
826 | |||
827 | if (!work_pending(&hw->update_zone_task)) | ||
828 | queue_work(adapter->control_wq, &hw->update_zone_task); | ||
829 | } | ||
830 | |||
820 | static irqreturn_t fjes_intr(int irq, void *data) | 831 | static irqreturn_t fjes_intr(int irq, void *data) |
821 | { | 832 | { |
822 | struct fjes_adapter *adapter = data; | 833 | struct fjes_adapter *adapter = data; |
@@ -830,6 +841,9 @@ static irqreturn_t fjes_intr(int irq, void *data) | |||
830 | if (icr & REG_ICTL_MASK_RX_DATA) | 841 | if (icr & REG_ICTL_MASK_RX_DATA) |
831 | fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID); | 842 | fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID); |
832 | 843 | ||
844 | if (icr & REG_ICTL_MASK_INFO_UPDATE) | ||
845 | fjes_update_zone_irq(adapter, icr & REG_IS_MASK_EPID); | ||
846 | |||
833 | ret = IRQ_HANDLED; | 847 | ret = IRQ_HANDLED; |
834 | } else { | 848 | } else { |
835 | ret = IRQ_NONE; | 849 | ret = IRQ_NONE; |