aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTaku Izumi <izumi.taku@jp.fujitsu.com>2015-08-21 04:29:35 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-24 17:06:36 -0400
commit785f28e061a870eba937cb2a860cbcf631f5ebb0 (patch)
tree14476ef9ebf38cbe1a9472052c2d7f8638d7e6fe
parent8fc4cadb98c6a0f1eecde678271fcc957258af3e (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.c179
-rw-r--r--drivers/net/fjes/fjes_hw.h1
-rw-r--r--drivers/net/fjes/fjes_main.c14
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
25static void fjes_hw_update_zone_task(struct work_struct *);
26
25/* supported MTU list */ 27/* supported MTU list */
26const u32 fjes_support_mtu[] = { 28const 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
354static enum fjes_dev_command_response_e 360static 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
923static 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
822static 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
820static irqreturn_t fjes_intr(int irq, void *data) 831static 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;