diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers.json.j2 b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers.json.j2 new file mode 100644 index 000000000000..0b1cb2c541b6 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t0.j2 b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t0.j2 new file mode 100644 index 000000000000..3e39d411e8bf --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t0.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '5m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,128,4) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "11213696", + "type": "ingress", + "mode": "dynamic", + "xoff": "3855488" + }, + "egress_lossy_pool": { + "size": "9532224", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t1.j2 b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t1.j2 new file mode 100644 index 000000000000..d9f562f95624 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/buffers_defaults_t1.j2 @@ -0,0 +1,47 @@ + +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {%- for port_idx in range(0,128,4) %} + {%- if PORT_ALL.append("Ethernet%d" % (port_idx)) %}{%- endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10443264", + "type": "ingress", + "mode": "dynamic", + "xoff": "4625920" + }, + "egress_lossy_pool": { + "size": "8877440", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/pg_profile_lookup.ini b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/pg_profile_lookup.ini new file mode 100644 index 000000000000..3b2a417cebcd --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -4 2288 + 25000 5m 1248 2288 53248 -4 2288 + 40000 5m 1248 2288 66560 -4 2288 + 50000 5m 1248 2288 90272 -4 2288 + 100000 5m 1248 2288 165568 -4 2288 + 10000 40m 1248 2288 37024 -4 2288 + 25000 40m 1248 2288 53248 -4 2288 + 40000 40m 1248 2288 71552 -4 2288 + 50000 40m 1248 2288 96096 -4 2288 + 100000 40m 1248 2288 177632 -4 2288 + 10000 300m 1248 2288 46176 -4 2288 + 25000 300m 1248 2288 79040 -4 2288 + 40000 300m 1248 2288 108160 -4 2288 + 50000 300m 1248 2288 141856 -4 2288 + 100000 300m 1248 2288 268736 -4 2288 diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/qos.json.j2 b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/qos.json.j2 new file mode 100644 index 000000000000..b724b48c2c23 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/MiTAC-LY1200-B32H0-C3/qos.json.j2 @@ -0,0 +1,167 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSY" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"512000", + "red_min_threshold":"512000", + "yellow_max_threshold":"512000", + "yellow_min_threshold":"512000", + "green_max_threshold": "184320", + "green_min_threshold": "184320" + }, + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"512000", + "red_min_threshold":"512000", + "yellow_max_threshold":"512000", + "yellow_min_threshold":"512000", + "green_max_threshold": "184320", + "green_min_threshold": "184320" + } + }, + "QUEUE": { + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0-1" : { + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSY]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf index 8d4683add468..cda2e2810cbf 100644 --- a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/installer.conf @@ -1,4 +1,4 @@ CONSOLE_PORT=0x3f8 CONSOLE_DEV=0 CONSOLE_SPEED=115200 -ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax pcie_aspm=off irqpoll" +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="acpi_enforce_resources=lax pcie_aspm=off irqpoll modprobe.blacklist=i2c_ismt" diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/minigraph.xml b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/minigraph.xml deleted file mode 100644 index 210eac2fd620..000000000000 --- a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/minigraph.xml +++ /dev/null @@ -1,1074 +0,0 @@ - - - - - - ARISTA01T0 - 10.0.0.33 - sonic - 10.0.0.32 - 1 - 180 - 60 - - - sonic - 10.0.0.0 - ARISTA01T2 - 10.0.0.1 - 1 - 180 - 60 - - - ARISTA02T0 - 10.0.0.35 - sonic - 10.0.0.34 - 1 - 180 - 60 - - - sonic - 10.0.0.2 - ARISTA02T2 - 10.0.0.3 - 1 - 180 - 60 - - - ARISTA03T0 - 10.0.0.37 - sonic - 10.0.0.36 - 1 - 180 - 60 - - - sonic - 10.0.0.4 - ARISTA03T2 - 10.0.0.5 - 1 - 180 - 60 - - - ARISTA04T0 - 10.0.0.39 - sonic - 10.0.0.38 - 1 - 180 - 60 - - - sonic - 10.0.0.6 - ARISTA04T2 - 10.0.0.7 - 1 - 180 - 60 - - - ARISTA05T0 - 10.0.0.41 - sonic - 10.0.0.40 - 1 - 180 - 60 - - - sonic - 10.0.0.8 - ARISTA05T2 - 10.0.0.9 - 1 - 180 - 60 - - - ARISTA06T0 - 10.0.0.43 - sonic - 10.0.0.42 - 1 - 180 - 60 - - - sonic - 10.0.0.10 - ARISTA06T2 - 10.0.0.11 - 1 - 180 - 60 - - - ARISTA07T0 - 10.0.0.45 - sonic - 10.0.0.44 - 1 - 180 - 60 - - - sonic - 10.0.0.12 - ARISTA07T2 - 10.0.0.13 - 1 - 180 - 60 - - - ARISTA08T0 - 10.0.0.47 - sonic - 10.0.0.46 - 1 - 180 - 60 - - - sonic - 10.0.0.14 - ARISTA08T2 - 10.0.0.15 - 1 - 180 - 60 - - - ARISTA09T0 - 10.0.0.49 - sonic - 10.0.0.48 - 1 - 180 - 60 - - - sonic - 10.0.0.16 - ARISTA09T2 - 10.0.0.17 - 1 - 180 - 60 - - - ARISTA10T0 - 10.0.0.51 - sonic - 10.0.0.50 - 1 - 180 - 60 - - - sonic - 10.0.0.18 - ARISTA10T2 - 10.0.0.19 - 1 - 180 - 60 - - - ARISTA11T0 - 10.0.0.53 - sonic - 10.0.0.52 - 1 - 180 - 60 - - - sonic - 10.0.0.20 - ARISTA11T2 - 10.0.0.21 - 1 - 180 - 60 - - - ARISTA12T0 - 10.0.0.55 - sonic - 10.0.0.54 - 1 - 180 - 60 - - - sonic - 10.0.0.22 - ARISTA12T2 - 10.0.0.23 - 1 - 180 - 60 - - - ARISTA13T0 - 10.0.0.57 - sonic - 10.0.0.56 - 1 - 180 - 60 - - - sonic - 10.0.0.24 - ARISTA13T2 - 10.0.0.25 - 1 - 180 - 60 - - - ARISTA14T0 - 10.0.0.59 - sonic - 10.0.0.58 - 1 - 180 - 60 - - - sonic - 10.0.0.26 - ARISTA14T2 - 10.0.0.27 - 1 - 180 - 60 - - - ARISTA15T0 - 10.0.0.61 - sonic - 10.0.0.60 - 1 - 180 - 60 - - - sonic - 10.0.0.28 - ARISTA15T2 - 10.0.0.29 - 1 - 180 - 60 - - - ARISTA16T0 - 10.0.0.63 - sonic - 10.0.0.62 - 1 - 180 - 60 - - - sonic - 10.0.0.30 - ARISTA16T2 - 10.0.0.31 - 1 - 180 - 60 - - - - - 65100 - sonic - - -
10.0.0.33
- - -
- -
10.0.0.1
- - -
- -
10.0.0.35
- - -
- -
10.0.0.3
- - -
- -
10.0.0.37
- - -
- -
10.0.0.5
- - -
- -
10.0.0.39
- - -
- -
10.0.0.7
- - -
- -
10.0.0.41
- - -
- -
10.0.0.9
- - -
- -
10.0.0.43
- - -
- -
10.0.0.11
- - -
- -
10.0.0.45
- - -
- -
10.0.0.13
- - -
- -
10.0.0.47
- - -
- -
10.0.0.15
- - -
- -
10.0.0.49
- - -
- -
10.0.0.17
- - -
- -
10.0.0.51
- - -
- -
10.0.0.19
- - -
- -
10.0.0.53
- - -
- -
10.0.0.21
- - -
- -
10.0.0.55
- - -
- -
10.0.0.23
- - -
- -
10.0.0.57
- - -
- -
10.0.0.25
- - -
- -
10.0.0.59
- - -
- -
10.0.0.27
- - -
- -
10.0.0.61
- - -
- -
10.0.0.29
- - -
- -
10.0.0.63
- - -
- -
10.0.0.31
- - -
-
- -
- - 64001 - ARISTA01T0 - - - - 65200 - ARISTA01T2 - - - - 64002 - ARISTA02T0 - - - - 65200 - ARISTA02T2 - - - - 64003 - ARISTA03T0 - - - - 65200 - ARISTA03T2 - - - - 64004 - ARISTA04T0 - - - - 65200 - ARISTA04T2 - - - - 64005 - ARISTA05T0 - - - - 65200 - ARISTA05T2 - - - - 64006 - ARISTA06T0 - - - - 65200 - ARISTA06T2 - - - - 64007 - ARISTA07T0 - - - - 65200 - ARISTA07T2 - - - - 64008 - ARISTA08T0 - - - - 65200 - ARISTA08T2 - - - - 64009 - ARISTA09T0 - - - - 65200 - ARISTA09T2 - - - - 64010 - ARISTA10T0 - - - - 65200 - ARISTA10T2 - - - - 64011 - ARISTA11T0 - - - - 65200 - ARISTA11T2 - - - - 64012 - ARISTA12T0 - - - - 65200 - ARISTA12T2 - - - - 64013 - ARISTA13T0 - - - - 65200 - ARISTA13T2 - - - - 64014 - ARISTA14T0 - - - - 65200 - ARISTA14T2 - - - - 64015 - ARISTA15T0 - - - - 65200 - ARISTA15T2 - - - - 64016 - ARISTA16T0 - - - - 65200 - ARISTA16T2 - - -
-
- - - - - - HostIP - Loopback0 - - 10.1.0.32/32 - - 10.1.0.32/32 - - - - - - - - sonic - - - - - - Ethernet0 - 10.0.0.0/31 - - - - Ethernet4 - 10.0.0.2/31 - - - - Ethernet8 - 10.0.0.4/31 - - - - Ethernet12 - 10.0.0.6/31 - - - - Ethernet16 - 10.0.0.8/31 - - - - Ethernet20 - 10.0.0.10/31 - - - - Ethernet24 - 10.0.0.12/31 - - - - Ethernet28 - 10.0.0.14/31 - - - - Ethernet32 - 10.0.0.16/31 - - - - Ethernet36 - 10.0.0.18/31 - - - - Ethernet40 - 10.0.0.20/31 - - - - Ethernet44 - 10.0.0.22/31 - - - - Ethernet48 - 10.0.0.24/31 - - - - Ethernet52 - 10.0.0.26/31 - - - - Ethernet56 - 10.0.0.28/31 - - - - Ethernet60 - 10.0.0.30/31 - - - - Ethernet64 - 10.0.0.32/31 - - - - Ethernet68 - 10.0.0.34/31 - - - - Ethernet72 - 10.0.0.36/31 - - - - Ethernet76 - 10.0.0.38/31 - - - - Ethernet80 - 10.0.0.40/31 - - - - Ethernet84 - 10.0.0.42/31 - - - - Ethernet88 - 10.0.0.44/31 - - - - Ethernet92 - 10.0.0.46/31 - - - - Ethernet96 - 10.0.0.48/31 - - - - Ethernet100 - 10.0.0.50/31 - - - - Ethernet104 - 10.0.0.52/31 - - - - Ethernet108 - 10.0.0.54/31 - - - - Ethernet112 - 10.0.0.56/31 - - - - Ethernet116 - 10.0.0.58/31 - - - - Ethernet120 - 10.0.0.60/31 - - - - Ethernet124 - 10.0.0.62/31 - - - - - - - - - - - - DeviceInterfaceLink - sonic - Ethernet0 - ARISTA01T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet4 - ARISTA02T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet8 - ARISTA03T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet12 - ARISTA04T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet16 - ARISTA05T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet20 - ARISTA06T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet24 - ARISTA07T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet28 - ARISTA08T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet32 - ARISTA09T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet36 - ARISTA10T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet40 - ARISTA11T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet44 - ARISTA12T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet48 - ARISTA13T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet52 - ARISTA14T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet56 - ARISTA15T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet60 - ARISTA16T2 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet64 - ARISTA01T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet68 - ARISTA02T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet72 - ARISTA03T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet76 - ARISTA04T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet80 - ARISTA05T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet84 - ARISTA06T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet88 - ARISTA07T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet92 - ARISTA08T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet96 - ARISTA09T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet100 - ARISTA10T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet104 - ARISTA11T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet108 - ARISTA12T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet112 - ARISTA13T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet116 - ARISTA14T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet120 - ARISTA15T0 - Ethernet1 - - - DeviceInterfaceLink - sonic - Ethernet124 - ARISTA16T0 - Ethernet1 - - - - - sonic - MiTAC-LY1200-B32H0-C3 - - - - - - - sonic - - - DhcpResources - - - - - NtpResources - - 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org - - - SyslogResources - - - - - - - - - sonic - MiTAC-LY1200-B32H0-C3 -
diff --git a/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/psuutil.py b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/psuutil.py new file mode 100644 index 000000000000..8fd9d3b1f349 --- /dev/null +++ b/device/mitac/x86_64-mitac_ly1200_b32h0_c3-r0/plugins/psuutil.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +############################################################################# +# MiTAC +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +import os.path + +try: + from sonic_psu.psu_base import PsuBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class PsuUtil(PsuBase): + """Platform-specific PSUutil class""" + + def __init__(self): + PsuBase.__init__(self) + + self.psu_nums = 2 + self.psu_path = "/sys/bus/i2c/devices/1-0032/" + self.psu_presence = "ps{}_ps" + self.psu_oper_status = "ps{}_pg" + + def get_num_psus(self): + """ + Retrieves the number of PSUs available on the device + :return: An integer, the number of PSUs available on the device + """ + return self.psu_nums + + def get_psu_status(self, index): + """ + Retrieves the oprational status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is operating properly, False if PSU is faulty + """ + if index is None: + return False + + status = 1 + try: + with open(self.psu_path + self.psu_oper_status.format(index), 'r') as power_status: + status = int(power_status.read(), 0) + except IOError: + return False + + return status == 0 + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 1-based index + :param index: An integer, 1-based index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + if index is None: + return False + + status = 1 + try: + with open(self.psu_path + self.psu_presence.format(index), 'r') as presence_status: + status = int(presence_status.read(), 0) + except IOError: + return False + + return status == 0 diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk index c7fa0f7aa80e..5bef3b467e26 100755 --- a/platform/broadcom/rules.mk +++ b/platform/broadcom/rules.mk @@ -9,7 +9,7 @@ include $(PLATFORM_PATH)/platform-modules-inventec.mk include $(PLATFORM_PATH)/platform-modules-cel.mk include $(PLATFORM_PATH)/platform-modules-delta.mk include $(PLATFORM_PATH)/platform-modules-quanta.mk -#include $(PLATFORM_PATH)/platform-modules-mitac.mk +include $(PLATFORM_PATH)/platform-modules-mitac.mk include $(PLATFORM_PATH)/docker-orchagent-brcm.mk include $(PLATFORM_PATH)/docker-syncd-brcm.mk include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk diff --git a/platform/broadcom/sonic-platform-modules-mitac/.gitignore b/platform/broadcom/sonic-platform-modules-mitac/.gitignore index 38e72f05332d..ae5cd673e9ad 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/.gitignore +++ b/platform/broadcom/sonic-platform-modules-mitac/.gitignore @@ -7,6 +7,10 @@ ly1200-32x/modules/*.cmd ly1200-32x/modules/Module.symvers ly1200-32x/modules/modules.order ly1200-32x/modules/.tmp_versions +ly1200-32x/opt/xcvr-serv/*.o +ly1200-32x/opt/sys-serv/*.o +ly1200-32x/opt/xcvr-serv/xcvr-servd +ly1200-32x/opt/sys-serv/sys-servd debian/sonic-platform-mitac-ly1200-32x/ debian/sonic-platform-mitac-ly1200-32x.debhelper.log @@ -15,3 +19,5 @@ debian/sonic-platform-mitac-ly1200-32x.postrm.debhelper debian/sonic-platform-mitac-ly1200-32x.prerm.debhelper debian/sonic-platform-mitac-ly1200-32x.substvars debian/files +debian/.debhelper +debian/debhelper-build-stamp diff --git a/platform/broadcom/sonic-platform-modules-mitac/README.md b/platform/broadcom/sonic-platform-modules-mitac/README.md index d7d47a58debf..ff88d76910f1 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/README.md +++ b/platform/broadcom/sonic-platform-modules-mitac/README.md @@ -1 +1,2 @@ -platform drivers of MiTAC products for the SONiC project +# sonic-platform-modules-mitac_stretch +platform drivers of MiTAC products for the SONiC project of Debian 9 diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/control b/platform/broadcom/sonic-platform-modules-mitac/debian/control index 8e20f8524d74..86dc337af8d9 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/debian/control +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/control @@ -7,6 +7,5 @@ Standards-Version: 3.9.3 Package: sonic-platform-mitac-ly1200-32x Architecture: amd64 -Depends: linux-image-3.16.0-5-amd64 -Description: kernel modules for platform devices such as fan, led, sfp - +Depends: linux-image-4.9.0-7-amd64, bc +Description: kernel modules for platform devices such as fan, led, sfp \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/rules b/platform/broadcom/sonic-platform-modules-mitac/debian/rules index 7f9f99827d21..1ccafeb62127 100755 --- a/platform/broadcom/sonic-platform-modules-mitac/debian/rules +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/rules @@ -1,4 +1,6 @@ #!/usr/bin/make -f +# Uncomment this to turn on verbose mode. +export DH_VERBOSE=1 export INSTALL_MOD_DIR:=extra @@ -7,16 +9,27 @@ KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) MODULE_DIRS:= ly1200-32x +SERVICE_DIR := service %: - dh $@ + dh $@ --with systemd override_dh_auto_build: (for mod in $(MODULE_DIRS); do \ make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + make -C $(MOD_SRC_DIR)/$${mod}/opt/xcvr-serv; \ + make -C $(MOD_SRC_DIR)/$${mod}/opt/sys-serv; \ done) -override_dh_auto_install: +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +binary-indep: + dh_testdir + dh_installdirs (for mod in $(MODULE_DIRS); do \ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}\ $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ @@ -29,13 +42,24 @@ override_dh_auto_install: mkdir -p debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/init.d; \ cp -rfL $(MOD_SRC_DIR)/$${mod}/etc/* \ debian/$(PACKAGE_PRE_NAME)-$${mod}/etc; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + (cd debian/$(PACKAGE_PRE_NAME)-$${mod}/opt/xcvr-serv; rm -f *.[cho]; rm -f Makefile); \ + (cd debian/$(PACKAGE_PRE_NAME)-$${mod}/opt/sys-serv; rm -f *.[cho]; rm -f Makefile); \ done) - -override_dh_usrlocal: - -override_dh_clean: - dh_clean - (for mod in $(MODULE_DIRS); do \ - make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules clean; \ - done) - + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb diff --git a/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init index d2f7dbf610ab..ed988b683542 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init +++ b/platform/broadcom/sonic-platform-modules-mitac/debian/sonic-platform-mitac-ly1200-32x.init @@ -6,8 +6,8 @@ # Required-Stop: # Should-Start: # Should-Stop: -# Default-Start: S -# Default-Stop: 0 6 +# Default-Start: +# Default-Stop: # Short-Description: Setup ly1200-32x board. ### END INIT INFO @@ -16,26 +16,24 @@ start) echo -n "Setting up board... " echo 0 > /proc/sys/kernel/perf_cpu_time_max_percent - - /etc/init.d/gpe start /etc/init.d/i2c_init start /etc/init.d/sys_polld start - /opt/script/start_watchdog.sh & - /opt/script/start_service.sh & + /etc/init.d/xcvr_servd start + /etc/init.d/sys_servd start + echo 0 > /sys/bus/i2c/devices/1-0031/wd_en + echo "done." ;; stop) echo -n "cleaning... " - /etc/init.d/gpe stop /etc/init.d/i2c_init stop /etc/init.d/xcvr_servd stop /etc/init.d/sys_servd stop /etc/init.d/sys_polld stop echo "done." - ;; force-reload|restart) @@ -43,7 +41,7 @@ force-reload|restart) ;; *) - echo "Usage: /etc/init.d/sonic-platform-mitac-ly1200-32x.init {start|stop}" + echo "Usage: /etc/init.d/sonic-platform-mitac-ly1200-32x {start|stop}" exit 1 ;; esac diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld index 936f01e8b640..a7ae13ecee8b 100755 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/fan-ctrld @@ -3,7 +3,7 @@ # Provides: fan-ctrld # Required-Start: # Required-Stop: -# Default-Start: rc.local +# Default-Start: # Default-Stop: # Short-Description: Daemon fan-ctrld ### END INIT INFO diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe deleted file mode 100755 index c326442db047..000000000000 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/gpe +++ /dev/null @@ -1,39 +0,0 @@ -#! /bin/bash -### BEGIN INIT INFO -# Provides: gpe -# Required-Start: -# Required-Stop: -# Default-Start: rc.local -# Default-Stop: -# Short-Description: Daemon gpe -### END INIT INFO - -# Load kernel modules -load_module () { - if [ `lsmod | grep -c "gpe "` -eq 0 ]; then - insmod /lib/modules/`uname -r`/extra/mitac_ly1200_32x_gpe.ko - fi -} - -remove_module () { - rmmod mitac-ly1200-32x_gpe -} - -case "$1" in - start) - load_module - ;; - stop) - remove_module - ;; - reload|restart|force-reload) - remove_module - load_module - ;; - *) - echo "Usage: $N {start|stop|reload|restart|force-reload}" >&2 - exit 1 - ;; -esac - -exit 0 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init index caddfce3325d..4281cc00c1e0 100755 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/i2c_init @@ -1,16 +1,17 @@ #!/bin/bash ### BEGIN INIT INFO -# Provides: setup-board +# Provides: setup-board-i2c # Required-Start: # Required-Stop: # Should-Start: # Should-Stop: -# Default-Start: S -# Default-Stop: 0 6 +# Default-Start: +# Default-Stop: # Short-Description: Setup ly1200-32x board. ### END INIT INFO +I2C_BUS_RM_ALL=0 I2C_I801_RM_PRINT=0 I2C_ISMT_RM_PRINT=0 I2C_I801_INS_PRINT=0 @@ -47,90 +48,9 @@ function log_msg() { # Load kernel modules load_modules () { - #----------remove i801 start--------------------- - if [ `lsmod | grep -c "i2c_i801 "` -eq 1 ]; then - rmmod i2c_i801 - while [ `lsmod | grep -c "i2c_i801 "` -eq 1 ] - do - if [ $I2C_I801_RM_PRINT -eq 0 ]; then - I2C_I801_RM_PRINT=1 - log_msg "Wait for i2c_i801 remove." - fi - if [ $I2C_I801_RM_RETRY -lt $RETRY ];then - I2C_I801_RM_RETRY=$((I2C_I801_RM_RETRY + 1)) - else - break - fi - sleep 1 - done - if [ $I2C_I801_RM_PRINT -eq 1 ]; then - log_msg "i2c_i801 remove success." - fi - fi - #----------remove i801 end------------------------ - - - #----------remove ismt start---------------------- - if [ `lsmod | grep -c "i2c_ismt "` -eq 1 ]; then - rmmod i2c_ismt - while [ `lsmod | grep -c "i2c_ismt "` -eq 1 ] - do - if [ $I2C_ISMT_RM_PRINT -eq 0 ]; then - I2C_ISMT_RM_PRINT=1 - log_msg "Wait for i2c_ismt remove." - fi - if [ $I2C_ISMT_RM_RETRY -lt $RETRY ];then - I2C_ISMT_RM_RETRY=$((I2C_ISMT_RM_RETRY + 1)) - else - break - fi - sleep 1 - done - if [ $I2C_ISMT_RM_PRINT -eq 1 ]; then - log_msg "i2c_ismt remove success." - fi - fi - #----------remove ismt end------------------------ - - #----------insert i801 start---------------------- - insmod /lib/modules/`uname -r`/kernel/drivers/i2c/busses/i2c-i801.ko - while [ `lsmod | grep -c "i2c_i801 "` -eq 0 ] - do - if [ $I2C_I801_INS_PRINT -eq 0 ]; then - I2C_I801_INS_PRINT=1 - log_msg "Wait for i2c_i801 insert." - fi - if [ $I2C_I801_INS_RETRY -lt $RETRY ];then - I2C_I801_INS_RETRY=$((I2C_I801_INS_RETRY + 1)) - else - break - fi - sleep 1 - done - if [ $I2C_I801_INS_PRINT -eq 1 ]; then - log_msg "i2c_i801 insert success." - fi - #----------insert i801 end------------------------ - - #----------insert ismt start---------------------- - insmod /lib/modules/`uname -r`/kernel/drivers/i2c/busses/i2c-ismt.ko - while [ `lsmod | grep -c "i2c_ismt "` -eq 0 ] - do - if [ $I2C_ISMT_INS_PRINT -eq 0 ]; then - I2C_ISMT_INS_PRINT=1 - log_msg "Wait for i2c_ismt insert." - fi - if [ $I2C_ISMT_INS_RETRY -lt $RETRY ];then - I2C_ISMT_INS_RETRY=$((I2C_ISMT_INS_RETRY + 1)) - else - break - fi - sleep 1 - done - if [ $I2C_ISMT_INS_PRINT -eq 1 ]; then - log_msg "i2c_ismt insert success." - fi - #----------insert ismt start------------------------ + modprobe i2c_i801 + modprobe i2c_ismt + if [ `lsmod | grep -c "at24 "` -eq 0 ]; then insmod /lib/modules/`uname -r`/kernel/drivers/misc/eeprom/at24.ko fi @@ -185,18 +105,24 @@ load_i2c_dev_modules () { fi } +# Load nvmem_core modules +load_nvmem_core_modules () { + if [ `lsmod | grep -c "nvmem_core "` -eq 0 ]; then + modprobe nvmem_core + fi +} + case "$1" in start) - echo -n "Setting up board... " + echo -n "Loading modules for board... " load_i2c_dev_modules + load_nvmem_core_modules load_modules echo "done." ;; stop) echo -n "cleaning... " - - echo "done." ;; diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld index 1df43346f257..7918c836c628 100755 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_polld @@ -3,7 +3,7 @@ # Provides: sys-polld # Required-Start: # Required-Stop: -# Default-Start: rc.local +# Default-Start: # Default-Stop: # Short-Description: Daemon sys-polld ### END INIT INFO diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd index 09ee087d5db0..2737f8fb5507 100755 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/sys_servd @@ -3,8 +3,8 @@ # Provides: sys-servd # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog -# Default-Start: rc.local -# Default-Stop: 0 1 6 +# Default-Start: +# Default-Stop: # Short-Description: Daemon sys-servd ### END INIT INFO diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd index 1558614fd43c..4eed58457a33 100755 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/init.d/xcvr_servd @@ -3,8 +3,8 @@ # Provides: xcvr-servd # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog -# Default-Start: rc.local -# Default-Stop: 0 1 6 +# Default-Start: +# Default-Stop: # Short-Description: Daemon xcvr-servd ### END INIT INFO diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd deleted file mode 120000 index d71f756d3deb..000000000000 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc0.d/K02xcvr_servd +++ /dev/null @@ -1 +0,0 @@ -../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd deleted file mode 120000 index d71f756d3deb..000000000000 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc1.d/K02xcvr_servd +++ /dev/null @@ -1 +0,0 @@ -../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd deleted file mode 120000 index d71f756d3deb..000000000000 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/etc/rc6.d/K02xcvr_servd +++ /dev/null @@ -1 +0,0 @@ -../init.d/xcvr_servd \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h index e851ca5fb487..cc256db58c9d 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/master_cpld_sysfs.h @@ -8,7 +8,7 @@ struct device_attribute field \ #define SYSFS_RAW_RW_ATTR_DEF(field) \ struct device_attribute field \ - = __ATTR(field, S_IRUGO | S_IWUGO, master_cpld_##field##_raw_read, master_cpld_##field##_raw_write); + = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, master_cpld_##field##_raw_read, master_cpld_##field##_raw_write); #define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ struct device_attribute field \ @@ -16,7 +16,7 @@ struct device_attribute field \ #define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ struct device_attribute field \ - = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, _read, _write); #define SYSFS_ATTR_PTR(field) \ &field.attr diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c index e5af8b70bf9a..0900070a8d07 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/mitac_ly1200_32x_system_cpld.c @@ -5,7 +5,12 @@ #include "system_cpld_reg.h" #include "system_cpld_sysfs.h" -#ifdef CONFIG_DRV_SYSCPLD_WDT + +#define MIC_DEBUG_TAG " [mitac] " +#define MITAC_WDT_MINOR 135 +#define MITAC_WDT_NAME "watchdog5" + +#if CONFIG_DRV_SYSCPLD_WDT #include #include #include @@ -33,7 +38,6 @@ MODULE_DEVICE_TABLE(i2c, system_cpld_ids); static int system_cpld_raw_read(struct device *dev, struct device_attribute *attr, char *buf, int reg_offset, int reg_width, int fld_shift, int fld_width, int fld_mask, char* reg_name){ unsigned int reg_val = 0, fld_val; - static int debug_flag; struct system_cpld_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; int err; @@ -64,7 +68,6 @@ static int system_cpld_raw_write(struct device *dev, struct device_attribute *at int ret_code; unsigned int reg_val, fld_val; unsigned long val; - static int debug_flag; struct system_cpld_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; if (reg_width != 8){ @@ -192,7 +195,7 @@ static const struct attribute_group system_cpld_group_misc = { .attrs = misc_attributes, }; -#ifdef CONFIG_DRV_SYSCPLD_WDT +#if CONFIG_DRV_SYSCPLD_WDT /* ***************************************************************************** * @@ -276,9 +279,9 @@ static void wdt_set_timeout(int index) { struct device *dev = &system_cpld->client->dev; struct device_attribute *fake_attr=NULL; - char buf[1]; + char buf[16]; if ( WD_TIMO_MAX_NUM == 16 ) { - sprintf(buf,"%x",index); + snprintf(buf, 16, "%x",index); system_cpld_wd_timer_raw_write(dev, fake_attr, buf, (size_t)0); } else @@ -390,7 +393,7 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd, */ static int wdt_open(struct inode *inode, struct file *file) { - if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) { + if (MINOR(inode->i_rdev) == MITAC_WDT_MINOR) { if (test_and_set_bit(0, &wdt_is_open)) { return -EBUSY; } @@ -412,7 +415,7 @@ static int wdt_open(struct inode *inode, struct file *file) */ static int wdt_release(struct inode *inode, struct file *file) { - if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) + if (MINOR(inode->i_rdev) == MITAC_WDT_MINOR) clear_bit(0, &wdt_is_open); return 0; } @@ -447,8 +450,8 @@ static const struct file_operations wdt_fops = { }; static struct miscdevice wdt_dev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", + .minor = MITAC_WDT_MINOR, + .name = MITAC_WDT_NAME, .fops = &wdt_fops, }; @@ -459,6 +462,8 @@ static struct miscdevice wdt_dev = { static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; +static struct notifier_block *p_wdt_notifier = NULL; + #endif /* CONFIG_DRV_SYSCPLD_WDT */ static int system_cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -483,14 +488,22 @@ static int system_cpld_probe(struct i2c_client *client, const struct i2c_device_ printk(KERN_INFO "%s: System CPLD LCMXO3LF created.\n", __FUNCTION__); -#ifdef CONFIG_DRV_SYSCPLD_WDT +#if CONFIG_DRV_SYSCPLD_WDT + wdt_dev.minor = MITAC_WDT_MINOR; err = misc_register(&wdt_dev); - if (err) - return err; - err = register_reboot_notifier(&wdt_notifier); if (err) { - misc_deregister(&wdt_dev); - return err; + printk(MIC_DEBUG_TAG"%s-%d misc_register register watchdog (%s : %d) fail err=%d \n", __FUNCTION__, __LINE__, wdt_dev.name, wdt_dev.minor, err); + wdt_dev.minor = 0; + } + else { + p_wdt_notifier = &wdt_notifier; + err = register_reboot_notifier(p_wdt_notifier); + if (err) { + printk(MIC_DEBUG_TAG"%s-%d register_reboot_notifier fail err:%d \n", __FUNCTION__, __LINE__, err); + misc_deregister(&wdt_dev); + p_wdt_notifier = NULL; + wdt_dev.minor = 0; + } } printk(KERN_INFO "%s: System CPLD watchdog created.\n", __FUNCTION__); #endif @@ -501,9 +514,9 @@ static int system_cpld_probe(struct i2c_client *client, const struct i2c_device_ static int system_cpld_remove(struct i2c_client *client) { -#ifdef CONFIG_DRV_SYSCPLD_WDT - misc_deregister(&wdt_dev); - unregister_reboot_notifier(&wdt_notifier); +#if CONFIG_DRV_SYSCPLD_WDT + if(p_wdt_notifier) unregister_reboot_notifier(p_wdt_notifier); + if(wdt_dev.minor) misc_deregister(&wdt_dev); #endif sysfs_remove_group(&client->dev.kobj, &system_cpld_group_misc); diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h index 92d00d29d493..a619f45388cb 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/slave_cpld_sysfs.h @@ -8,7 +8,7 @@ struct device_attribute field \ #define SYSFS_RAW_RW_ATTR_DEF(field) \ struct device_attribute field \ - = __ATTR(field, S_IRUGO | S_IWUGO, slave_cpld_##field##_raw_read, slave_cpld_##field##_raw_write); + = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, slave_cpld_##field##_raw_read, slave_cpld_##field##_raw_write); #define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ struct device_attribute field \ @@ -16,7 +16,7 @@ struct device_attribute field \ #define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ struct device_attribute field \ - = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, _read, _write); #define SYSFS_ATTR_PTR(field) \ &field.attr diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h index e6b03bd1bd0d..1dbe9b2819f9 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/modules/system_cpld_sysfs.h @@ -8,7 +8,7 @@ struct device_attribute field \ #define SYSFS_RAW_RW_ATTR_DEF(field) \ struct device_attribute field \ - = __ATTR(field, S_IRUGO | S_IWUGO, system_cpld_##field##_raw_read, system_cpld_##field##_raw_write); + = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, system_cpld_##field##_raw_read, system_cpld_##field##_raw_write); #define SYSFS_MISC_RO_ATTR_DEF(field, _read) \ struct device_attribute field \ @@ -16,7 +16,7 @@ struct device_attribute field \ #define SYSFS_MISC_RW_ATTR_DEF(field, _read, _write) \ struct device_attribute field \ - = __ATTR(field, S_IRUGO | S_IWUGO, _read, _write); + = __ATTR(field, S_IRUGO | S_IWUSR | S_IWGRP, _read, _write); #define SYSFS_ATTR_PTR(field) \ &field.attr diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf index 56409f5c3e30..fc37dda47f47 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_B2F.conf @@ -1,12 +1,13 @@ ##### Temperature vs Fan table ##### ## FORMAT: "PWM" fan speed(range from 0 to 255) -# Duty Cycle 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85% 90% 95% 100% -PWM 64 77 89 102 115 128 140 153 166 179 191 204 217 230 242 255 +# Duty Cycle 30% 32.5% 35% 37.5% 40% 45% 50% 55% 60% 65% 70% 75% 80% 90% 100% +PWM 77 83 89 95 102 114 128 141 153 166 179 192 204 230 255 ## FORMAT: sensor name(TEMP_XXX) with asserted temperature by each levels -TEMP_CPU 52 55 58 61 64 67 70 73 76 79 82 85 88 91 94 97 -TEMP_SWITCH 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120 +TEMP_CPU 46 48 50 52 54 57 60 63 66 69 72 75 78 81 84 +TEMP_SWITCH 72 74 76 78 80 83 86 89 92 95 98 101 104 107 110 #TEMP_HDD 25 #TEMP_TMP75_CPU 25 #TEMP_TMP75_CENTER 25 -#TEMP_TMP75_RIGHT 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 -TEMP_TMP75_FAN 26.5 31.5 36.5 41.5 46.5 51.5 56.5 61.5 66.5 71.5 76.5 81.5 86.5 91.5 96.5 101.5 +#TEMP_TMP75_RIGHT 33 37 45 53 61 69 77 85 93 +TEMP_TMP75_FAN 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 +TEMP_XCVR 36 38 40 42 44 46 48 50 52 54 56 58 60 63 66 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf index 6c459d874feb..ee316c66bd06 100644 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/fan-ctrl/fan-zone-thermal_F2B.conf @@ -1,12 +1,12 @@ ##### Temperature vs Fan table ##### ## FORMAT: "PWM" fan speed(range from 0 to 255) -# Duty Cycle 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85% 90% 95% 100% -PWM 64 77 89 102 115 128 140 153 166 179 191 204 217 230 242 255 +# Duty Cycle 29% 31% 33% 35% 37.5% 40% 45% 50% 55% 60% 65% 70% 75% 80% 90% 100% +PWM 74 79 84 89 96 102 115 128 140 153 166 179 191 204 230 255 ## FORMAT: sensor name(TEMP_XXX) with asserted temperature by each levels -TEMP_CPU 60 65 70 73 76 79 82 85 88 91 94 97 100 103 106 109 -TEMP_SWITCH 73 76 79 82 85 88 91 94 97 100 103 106 109 112 115 118 +TEMP_CPU 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 +TEMP_SWITCH 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 #TEMP_HDD 25 #TEMP_TMP75_CPU 25 #TEMP_TMP75_CENTER 25 -TEMP_TMP75_RIGHT 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 +TEMP_TMP75_RIGHT 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 #TEMP_TMP75_FAN 25 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh deleted file mode 100755 index 4b0c4c35471f..000000000000 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/funcs.sh +++ /dev/null @@ -1,23 +0,0 @@ -#/bin/bash - -# process name/id -DAEMON_NAME=`basename $0` -DAEMON_PID="$$" - -DEF_SEVERITY="INFO" - -#/* -#* FEATURE: -#* log_msg -#* PURPOSE: -#* log message -#* PARAMETERS: -#* msg (IN) message -#* RETURNS: -#* -#*/ -function log_msg() { - local msg=$1 - - `logger -t $DAEMON_NAME -p $DEF_SEVERITY $msg` -} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh deleted file mode 100755 index 2bc9589738d0..000000000000 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_service.sh +++ /dev/null @@ -1,99 +0,0 @@ -#/bin/bash - -DIR=$(dirname $0) - -# include files -source ${DIR}/funcs.sh - -ACPI_INSTALL_PRINT=0 -ACPID_INSTALL_PRINT=0 -BC_INSTALL_PRINT=0 -ACPID_SOCKET_PRINT=0 -ACPI_PRINT=0 - - -while [ 1 ] -do - if [ `dpkg -l |grep -c "acpi "` -eq "0" ]; then - dpkg -i /opt/debs/acpi_1.7-1_amd64.deb - if [ "$?" -ne "0" ]; then - if [ $ACPI_INSTALL_PRINT -eq 0 ]; then - ACPI_INSTALL_PRINT=1 - log_msg "Wait for acpi package install." - fi - sleep 1 - continue - else - log_msg "Install acpi package success." - fi - fi - break -done - -while [ 1 ] -do - if [ `dpkg -l |grep -c "acpid "` -eq "0" ]; then - dpkg -i /opt/debs/acpid_2.0.23-2_amd64.deb - if [ "$?" -ne "0" ]; then - if [ $ACPID_INSTALL_PRINT -eq 0 ]; then - ACPID_INSTALL_PRINT=1 - log_msg "Wait for acpid package install." - fi - sleep 1 - continue - else - log_msg "Install acpid package success." - fi - fi - break -done - -while [ 1 ] -do - if [ `dpkg -l |grep -c " bc "` -eq "0" ]; then - dpkg -i /opt/debs/bc_1.06.95-9_amd64.deb - if [ "$?" -ne "0" ]; then - if [ $BC_INSTALL_PRINT -eq 0 ]; then - BC_INSTALL_PRINT=1 - log_msg "Wait for bc package install." - fi - sleep 1 - continue - else - log_msg "Install bc package success." - fi - fi - break -done - -while [ 1 ] -do - if [ ! -e "/sys/firmware/acpi/interrupts/gpe01" ]; then - if [ $ACPI_PRINT -eq 0 ]; then - ACPI_PRINT=1 - log_msg "Wait for acpi daemon start." - fi - sleep 1 - continue - fi - log_msg "The acpi daemon start." - break -done - -while [ 1 ] -do - if [ ! -e "/var/run/acpid.socket" ]; then - if [ $ACPID_SOCKET_PRINT -eq 0 ]; then - ACPID_SOCKET_PRINT=1 - log_msg "Wait for acipd daemon start." - fi - sleep 1 - continue - fi - log_msg "The acpid daemon start." - break -done - -/etc/init.d/xcvr_servd start -/etc/init.d/sys_servd start -exit 0; diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh deleted file mode 100755 index 2268e5e0d16e..000000000000 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/script/start_watchdog.sh +++ /dev/null @@ -1,32 +0,0 @@ -#/bin/bash - -DIR=$(dirname $0) - -# include files -source ${DIR}/funcs.sh - -WATCHDOG_PRINT=0 - -while [ 1 ] -do - if [ `dpkg -l |grep -c "watchdog "` -eq "0" ]; then - dpkg -i /opt/debs/watchdog_5.14-3_amd64.deb - if [ "$?" -ne "0" ]; then - if [ $WATCHDOG_PRINT -eq 0 ]; then - WATCHDOG_PRINT=1 - log_msg "Wait for watchdog package install." - fi - sleep 1 - continue - else - log_msg "Install watchdog package success." - fi - fi - break -done - -ln -sf /opt/watchdog/watchdog.conf /etc/watchdog.conf - -/usr/sbin/watchdog -c /etc/watchdog.conf - -exit 0; diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/Makefile b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/Makefile new file mode 100644 index 000000000000..2c4580f79045 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/Makefile @@ -0,0 +1,54 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +TARGETS := sys-servd +INC = $(wildcard *.h) +OBJ=$(subst .c,.o,$(wildcard *.c)) + +.PHONY: all +all: $(TARGETS) + +.PHONY: config +config: + +.PHONY: patch +patch: + +.PHONY: install +install: + mkdir -p $(INST_DIR)/sys-serv/ + cp $(TARGETS) $(INST_DIR)/sys-serv/ + +.PHONY: uninstall +uninstall: + rm -f $(addprefix $(INST_DIR)/xcvr-serv/,$(TARGETS)) + +.PHONY: clean +clean: + rm -rf $(OBJ) $(TARGETS) + +.PHONY: distclean +distclean: clean + +$(OBJ): $(INC) +%.o: %.c + $(CC) -c -o $@ $< -Wall -Wextra -Werror + +$(TARGETS): $(OBJ) + $(CC) $^ -lrt -pthread -o $@ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_cpu_temp_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_cpu_temp_servd.c new file mode 100644 index 000000000000..ac0bde06e4e3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_cpu_temp_servd.c @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_irq_sysd.h" + +#include + +/* +* FEATURE: +* bms_cpu_temp_msq_open +* PURPOSE: +* open POSIX message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_cpu_temp_msq_open(const char *qname, + mqd_t *mqd) +{ + int flags = (O_RDONLY), ret_code = 0; + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + +/* +* FEATURE: +* bms_cpu_temp_servd +* PURPOSE: +* service to handle message queue event of cpu temperature +* PARAMETERS: +* args (IN) message queue name +* RETURNS: +* open success, this function will wait for message queue. +* for other cases, will exit this program. +*/ +void* +bms_cpu_temp_servd(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + bms_sys_serv_mq_data_t msg; + int ret_code; + + /* Open message queue */ + if (bms_cpu_temp_msq_open(mq_name, &mq_desc) < 0) { + goto quit; + } + + while (1) { + /* Wait for message queue */ + if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code)); + goto quit; + } + + switch (msg.serv_type) { + case SERV_TYPE_RX_INTR: /* CPU_THERMTRIP_IRQ interrupt */ + syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name); + break; + + default: + syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name); + break; + } + } + +quit: + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_polld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_polld.c new file mode 100644 index 000000000000..f1797c297c8e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_polld.c @@ -0,0 +1,333 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "bms_sys_serv_common.h" +#include "bms_fan_servd.h" + +/* +* FEATURE: +* bms_fan_poll_msq_open +* PURPOSE: +* open POSIX message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_poll_msq_open(const char *qname, + mqd_t *mqd) +{ + int flags = (O_WRONLY | O_NONBLOCK), ret_code = 0; + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + +/* +* FEATURE: +* bms_fan_poll_msq_send +* PURPOSE: +* send POSIX message queue +* PARAMETERS: +* msg (IN) message of send data +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_poll_msq_send(bms_sys_serv_mq_data_t* msg, + mqd_t *mqd) +{ + int ret_code; + + if (mq_send(*mqd, (char*)msg, sizeof(*msg), 0) < 0) { + ret_code = errno; + if (ret_code == EAGAIN) { + syslog(LOG_WARNING|LOG_USER,"Message queue %s is full\n", msg->serv_name); + } + else { + syslog(LOG_WARNING|LOG_USER,"Failed to send message to %s (%s)\n", msg->serv_name, strerror(ret_code)); + } + } + + return -ret_code; +} + + +/* +* FEATURE: +* bms_fan_poll_init +* PURPOSE: +* initial all +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_poll_init(char *mq_name, + mqd_t *mq_desc) +{ + int ret_code = 0; + + /* open message queue*/ + if ((ret_code = bms_fan_poll_msq_open(mq_name, mq_desc)) < 0) { + return ret_code; + } + + return ret_code; +} + +/* +* FEATURE: +* bms_fan_poll_detect_fan_status +* PURPOSE: +* datect fan status is present or non present +* PARAMETERS: +* present_bmap (OUT) pointer of present bmap +* nonpresent_bmap (OUT) pointer of non-present bmap +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_poll_detect_module_status(unsigned int *present_bmap, + unsigned int *nonpresent_bmap, + unsigned int *intr_bmap) +{ + int ret_code = 0, i, j; + unsigned int module_present_bmap; + unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM]; + unsigned int module_intr[BMS_FAN_MODULE_NUM] = {BMS_FAN_INTR_NORMAL}; + unsigned int intr_tmp; + + for(i = 0 ; i < BMS_FAN_MODULE_NUM; i++){ + bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]); + } + + /* read fan present from sysfs, 0 for present and 1 for non-present */ + if((ret_code = bms_fan_serv_fan_present_get( &module_present_bmap)) < 0){ + return ret_code; + } + + /* get interrupt source from fan control */ + for(i = 0 ; i < BMS_FAN_MODULE_NUM; i++){ + for(j = 0 ; j < BMS_FAN_NUM_PER_MODULE; j++){ + if((ret_code = bms_fan_serv_fan_intr_get(((i * BMS_FAN_NUM_PER_MODULE) + j), &intr_tmp)) < 0){ + return ret_code; + } + if(intr_tmp == BMS_FAN_INTR_FAULT){ + module_intr[i] = BMS_FAN_INTR_FAULT; + break; + } + } + } + + /* present */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + //bms_fan_serv_cache_module_status_get(i, &status); + if((cache_status[i] == BMS_FAN_MODULE_STATUS_NONPRESENT) || + (cache_status[i] == BMS_FAN_MODULE_STATUS_NONREADY) || + (cache_status[i] == BMS_FAN_MODULE_STATUS_NONINIT)){ + if(!(module_present_bmap & (1 << i))){ + *present_bmap |= (1 << i); + } + } + } + + + //mask = 1; + + /* non preent */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + //bms_fan_serv_cache_module_status_get(i, &status); + if((cache_status[i] == BMS_FAN_MODULE_STATUS_NORMAL) || + (cache_status[i] == BMS_FAN_MODULE_STATUS_NONINIT) || + (cache_status[i] == BMS_FAN_MODULE_STATUS_FAILED)){ + if(module_present_bmap & (1 << i)){ + *nonpresent_bmap |= (1 << i); + } + } + } + + /* fan fault */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if((cache_status[i] == BMS_FAN_MODULE_STATUS_NORMAL) || + (cache_status[i] == BMS_FAN_MODULE_STATUS_NONREADY)){ + if(module_intr[i] == BMS_FAN_INTR_FAULT){ + *intr_bmap |= (1 << i); + } + } + } + + return ret_code; +} + + + +/* +* FEATURE: +* bms_fan_poll_module_fault_reset +* PURPOSE: +* reset fan fault status in fan controller +* PARAMETERS: +* fan_number (IN) fan number +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_poll_module_fault_reset(unsigned int module_number) +{ + return bms_fan_serv_fan_pwm_set(module_number, BMS_FAN_PWM_DUTY_CYCLE_MAX); +} + +/* +* FEATURE: +* bms_fan_polld +* PURPOSE: +* bms fan module polling daemon +* PARAMETERS: +* args (IN) input value(message name) +* RETURNS: +* The process will always polling fan module. +*/ +void* +bms_fan_polld(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + int ret_code = 0, i; + unsigned int module_type; + bms_sys_serv_mq_data_t msg; + unsigned int present_bmap = 0, nonpresent_bmap = 0, intr_bmap = 0; + unsigned int cache_status, cache_type, cache_retry; + + msg.serv_name = mq_name; + + if((ret_code = bms_fan_poll_init(mq_name, &mq_desc)) < 0){ + goto quit; + } + + while(!bms_fan_init_done){ + sleep(1); + } + + while(1){ + present_bmap = 0; + nonpresent_bmap = 0; + intr_bmap = 0; + + if((ret_code = bms_fan_poll_detect_module_status(&present_bmap, &nonpresent_bmap, &intr_bmap)) < 0){ + goto wait; + } + + if((present_bmap == 0) && + (nonpresent_bmap == 0) && + (intr_bmap == 0)) + goto wait; + + if(present_bmap != 0){ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if(present_bmap & (1 << i)){ + bms_fan_serv_cache_module_cache_get(i, &cache_status, &cache_type); + + bms_fan_serv_cache_module_cache_retry_get(i, &cache_retry); + + /* Due to max31790 driver has cache to protect i2c, so we will get older data sometimes. + * That data will confuse the fan fault status. + * So we will read fan fault status after wait 3 second delay. + */ + if(cache_retry == BMS_FAN_NONREADY_RETRY_INIT){ + if((ret_code = bms_fan_poll_module_fault_reset(i)) < 0){ + continue; + } + bms_fan_serv_cache_module_cache_retry_set(i, ++cache_retry); + }else{ + if(cache_retry < BMS_FAN_NONREADY_RETRY){ + bms_fan_serv_cache_module_cache_retry_set(i, ++cache_retry); + continue; + } + } + msg.serv_type = SERV_TYPE_FAN_MODULE_PRESENT; + msg.number = i; + + if((ret_code = bms_fan_serv_module_type_get(i, &module_type)) < 0){ + continue; + } + msg.type = module_type; + + bms_fan_poll_msq_send(&msg, &mq_desc); + } + } + } + + if(nonpresent_bmap != 0){ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if(nonpresent_bmap & (1 << i)){ + msg.number = i; + msg.serv_type = SERV_TYPE_FAN_MODULE_NONPRESENT; + bms_fan_poll_msq_send(&msg, &mq_desc); + } + } + } + + /* handle interrupt bit map */ + if(intr_bmap != 0){ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if(intr_bmap & (1 << i)){ + + bms_fan_serv_cache_module_cache_retry_get(i, &cache_retry); + + if(cache_retry < BMS_FAN_NONREADY_RETRY){ + continue; + } + + msg.number = i; + msg.serv_type = SERV_TYPE_RX_INTR; + bms_fan_poll_msq_send(&msg, &mq_desc); + } + } + } + +wait: + sleep(1); + } + +quit: + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.c new file mode 100644 index 000000000000..59f1e7ee02be --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.c @@ -0,0 +1,1386 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "bms_sys_serv_common.h" +#include "bms_fan_servd.h" + +bms_fan_serv_data_t bms_fan_serv_data[BMS_FAN_MODULE_NUM * BMS_FAN_NUM_PER_MODULE] = { + { + .number = 1, + .hwmon_path = "/sys/bus/i2c/devices/3-0020/hwmon", + .intr_src = "fan1_fault", + .intr_msk = "fan1_fault_mask", + .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray1_led", + .type = "/sys/bus/i2c/devices/1-0032/fan_type1", + .present = "/sys/bus/i2c/devices/1-0032/fan_tray1_6_present", + .pwm = "pwm1", + .pwm_enable = "pwm1_enable", + .input = "fan1_input", + .smart_fan_path = "/etc/init.d/fan-ctrld", + }, + { + .number = 2, + .hwmon_path = NULL, /* share same path with FAN number 1 */ + .intr_src = "fan2_fault", + .intr_msk = "fan2_fault_mask", + .tray_led = NULL, + .type = NULL, + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm2", + .pwm_enable = "pwm2_enable", + .input = "fan2_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 3, + .hwmon_path = NULL, /* share same path with FAN number 1 */ + .intr_src = "fan3_fault", + .intr_msk = "fan3_fault_mask", + .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray2_led", + .type = "/sys/bus/i2c/devices/1-0032/fan_type2", + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm3", + .pwm_enable = "pwm3_enable", + .input = "fan3_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 4, + .hwmon_path = NULL, /* share same path with FAN number 1 */ + .intr_src = "fan4_fault", + .intr_msk = "fan4_fault_mask", + .tray_led = NULL, + .type = NULL, + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm4", + .pwm_enable = "pwm4_enable", + .input = "fan4_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 5, + .hwmon_path = NULL, /* share same path with FAN number 1 */ + .intr_src = "fan5_fault", + .intr_msk = "fan5_fault_mask", + .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray3_led", + .type = "/sys/bus/i2c/devices/1-0032/fan_type3", + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm5", + .pwm_enable = "pwm5_enable", + .input = "fan5_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 6, + .hwmon_path = NULL, /* share same path with FAN number 1 */ + .intr_src = "fan6_fault", + .intr_msk = "fan6_fault_mask", + .tray_led = NULL, + .type = NULL, + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm6", + .pwm_enable = "pwm6_enable", + .input = "fan6_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 7, + .hwmon_path = "/sys/bus/i2c/devices/3-0023/hwmon", + .intr_src = "fan1_fault", + .intr_msk = "fan1_fault_mask", + .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray4_led", + .type = "/sys/bus/i2c/devices/1-0032/fan_type4", + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm1", + .pwm_enable = "pwm1_enable", + .input = "fan1_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 8, + .hwmon_path = NULL, /* share same path with FAN number 7 */ + .intr_src = "fan2_fault", + .intr_msk = "fan2_fault_mask", + .tray_led = NULL, + .type = NULL, + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm2", + .pwm_enable = "pwm2_enable", + .input = "fan2_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 9, + .hwmon_path = NULL, /* share same path with FAN number 7 */ + .intr_src = "fan3_fault", + .intr_msk = "fan3_fault_mask", + .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray5_led", + .type = "/sys/bus/i2c/devices/1-0032/fan_type5", + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm3", + .pwm_enable = "pwm3_enable", + .input = "fan3_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 10, + .hwmon_path = NULL, /* share same path with FAN number 7 */ + .intr_src = "fan4_fault", + .intr_msk = "fan4_fault_mask", + .tray_led = NULL, + .type = NULL, + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm4", + .pwm_enable = "pwm4_enable", + .input = "fan4_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 11, + .hwmon_path = NULL, /* share same path with FAN number 7 */ + .intr_src = "fan5_fault", + .intr_msk = "fan5_fault_mask", + .tray_led = "/sys/bus/i2c/devices/1-0032/fan_tray6_led", + .type = "/sys/bus/i2c/devices/1-0032/fan_type6", + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm5", + .pwm_enable = "pwm5_enable", + .input = "fan5_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, + { + .number = 12, + .hwmon_path = NULL, /* share same path with FAN number 7 */ + .intr_src = "fan6_fault", + .intr_msk = "fan6_fault_mask", + .tray_led = NULL, + .type = NULL, + .present = NULL, /* share same byte with FAN1 */ + .pwm = "pwm6", + .pwm_enable = "pwm6_enable", + .input = "fan6_input", + .smart_fan_path = NULL, /* share same path with FAN1 */ + }, +}; + +unsigned int bms_fan_status[BMS_FAN_MODULE_NUM]; +unsigned int bms_fan_type[BMS_FAN_MODULE_NUM]; +unsigned int bms_fan_retry[BMS_FAN_MODULE_NUM]; +unsigned int bms_board_type; +int bms_fan_init_done = 0; +pthread_mutex_t bms_fan_cache_lock; + + +/* +* FEATURE: +* bms_fan_serv_fan_module_led_set +* PURPOSE: +* fan service fan module led set to file system +* PARAMETERS: +* module_number (IN) module number +* value (IN) setting value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_module_led_set(unsigned int module_number, + unsigned int value) +{ + return bms_sys_serv_write(bms_fan_serv_data[module_number * BMS_FAN_NUM_PER_MODULE].tray_led, value); +} + +/* +* FEATURE: +* bms_fan_serv_fan_pwm_set +* PURPOSE: +* fan service fan pwm duty cycle set to file system +* PARAMETERS: +* module_number (IN) module number +* value (IN) setting value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_pwm_set(unsigned int module_number, + unsigned int value) +{ + int i, ret_code = 0; + + for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){ + if((ret_code = bms_sys_serv_write(bms_fan_serv_data[(module_number * BMS_FAN_NUM_PER_MODULE) + i].pwm, value)) < 0){ + break; + } + } + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_fan_pwm_enable_set +* PURPOSE: +* fan service fan pwm mode set to file system +* PARAMETERS: +* module_number (IN) module number +* value (IN) setting value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_pwm_enable_set(unsigned int module_number, + unsigned int value) +{ + int i, ret_code = 0; + + for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){ + if((ret_code = bms_sys_serv_write(bms_fan_serv_data[(module_number * BMS_FAN_NUM_PER_MODULE) + i].pwm_enable, value)) < 0){ + break; + } + } + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_fan_mask_set +* PURPOSE: +* fan service fan mask set to file system in fan controller +* PARAMETERS: +* fan_number (IN) fan number +* value (IN) setting value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_mask_set(unsigned int fan_number, + unsigned int value) +{ +/* +* within kernel 4.9 max31790 driver, there is no "fan_fault_mask" file nodes +* so just return 0 +*/ +#if 1 +#define UNUSED(x) (void)(x) + UNUSED(fan_number); + UNUSED(value); + return 0; +#else + return bms_sys_serv_write(bms_fan_serv_data[fan_number].intr_msk, value); +#endif +} + +/* +* FEATURE: +* bms_fan_serv_fan_global_mask_set +* PURPOSE: +* fan service fan global mask set to file system +* PARAMETERS: +* index (IN) fan index in bms_sys_serv_data +* value (IN) setting value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_global_mask_set(unsigned int index, + unsigned int value) +{ + return bms_sys_serv_write(bms_sys_serv_data[index].intr_msk, value); +} + +/* +* FEATURE: +* bms_fan_serv_fan_panel_led_set +* PURPOSE: +* fan service fan panel led set to file system in CPLD +* PARAMETERS: +* value (IN) setting value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_panel_led_set(unsigned int value) +{ + return bms_sys_serv_write(BMS_SYSFS_FAN_PANEL_LED, value); +} + +/* +* FEATURE: +* bms_fan_serv_fan_intr_get +* PURPOSE: +* fan service fan interrupt get from file system +* PARAMETERS: +* fan_number (IN) fan number +* value (out) pointer of get value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_intr_get(unsigned int fan_number, + unsigned int *value) +{ + return bms_sys_serv_dec_read(bms_fan_serv_data[fan_number].intr_src, value); +} + +/* +* FEATURE: +* bms_fan_serv_fan_input_get +* PURPOSE: +* fan service fan input value get from file system +* PARAMETERS: +* fan_number (IN) fan number +* value (out) pointer of get value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_input_get(unsigned int fan_number, + unsigned int *value) +{ + return bms_sys_serv_dec_read(bms_fan_serv_data[fan_number].input, value); +} + +/* +* FEATURE: +* bms_fan_serv_fan_mask_get +* PURPOSE: +* fan service fan fault mask value get from file system +* PARAMETERS: +* fan_number (IN) fan number +* value (out) pointer of get value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_mask_get(unsigned int fan_number, + unsigned int *value) +{ + return bms_sys_serv_dec_read(bms_fan_serv_data[fan_number].intr_msk, value); +} + +/* +* FEATURE: +* bms_fan_serv_module_type_get +* PURPOSE: +* fan service fan type get from file system +* PARAMETERS: +* module_number (IN) module number +* value (OUT) pointer of get value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_module_type_get(unsigned int module_number, + unsigned int *value) +{ + return bms_sys_serv_hex_read(bms_fan_serv_data[module_number * BMS_FAN_NUM_PER_MODULE].type, value); +} + +/* +* FEATURE: +* bms_fan_serv_fan_present_get +* PURPOSE: +* fan service fan present get from file system +* PARAMETERS: +* value (OUT) pointer of present bitmap +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_present_get(unsigned int *value) +{ + return bms_sys_serv_hex_read(bms_fan_serv_data[0].present, value); +} + +/* +* FEATURE: +* bms_fan_serv_fan_board_type_get +* PURPOSE: +* fan service fan board get from file system +* PARAMETERS: +* value (OUT) pointer of get value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_board_type_get(unsigned int *value) +{ + return bms_sys_serv_hex_read(BMS_SYSFS_BOARD_TYPE, value); +} + +/* +* FEATURE: +* bms_fan_serv_mask_init +* PURPOSE: +* enable all fan interrupt mask in fan controller +* PARAMETERS: +* +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_mask_init(void) +{ + int i, ret_code = 0; + + for(i = 0; i < BMS_FAN_NUM_PER_MODULE * BMS_FAN_MODULE_NUM; i++){ + if((ret_code = bms_fan_serv_fan_mask_set(i, BMS_FAN_INTR_MASKED)) < 0){ + break; + } + } + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_cache_init +* PURPOSE: +* initial fan status and fan type +* PARAMETERS: +* +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_cache_init(void) +{ + int ret_code = 0, i; + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + bms_fan_status[i] = BMS_FAN_MODULE_STATUS_NONINIT; + bms_fan_retry[i] = BMS_FAN_NONREADY_RETRY_INIT; + if((bms_board_type == BMS_AC_PSU_NORMAL_FAN) || (bms_board_type == BMS_DC_PSU_NORMAL_FAN)){ + bms_fan_type[i] = BMS_FAN_MODULE_TYPE_NORMAL; + }else if((bms_board_type == BMS_AC_PSU_REVERSE_FAN) || (bms_board_type == BMS_DC_PSU_REVERSE_FAN)){ + bms_fan_type[i] = BMS_FAN_MODULE_TYPE_REVERSE; + }else{ + syslog(LOG_WARNING|LOG_USER,"Can't identify board_type.\n"); + return -EINVAL; + } + } + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_pwm_init +* PURPOSE: +* initial all fan pwm mode and duty cycle +* PARAMETERS: +* +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_pwm_init(void) +{ + int ret_code, i; + + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if((ret_code = bms_fan_serv_fan_pwm_enable_set(i, BMS_FAN_PWM_ENABLE_PWM)) < 0){ + break; + } + if((ret_code = bms_fan_serv_fan_pwm_set(i, BMS_FAN_PWM_DUTY_CYCLE_MAX)) < 0){ + break; + } + } + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_mutex_init +* PURPOSE: +* initial mutex +* PARAMETERS: +* +* RETURNS: +* init success, this function shall return zero. +* otherwise, an error number shall be returned to indicate the error. +*/ +static int +bms_fan_serv_mutex_init(void) +{ + int ret_code; + + if((ret_code = pthread_mutex_init(&bms_fan_cache_lock, NULL)) != 0){ + return -ret_code; + } + + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_cache_module_cache_get +* PURPOSE: +* fan service cache get +* PARAMETERS: +* module_number (IN) module number +* module_status (OUT) pointer of module status +* module_type (OUT) pointer of module type +* RETURNS: +*/ +void +bms_fan_serv_cache_module_cache_get(unsigned int module_number, + unsigned int* module_status, + unsigned int* module_type) +{ + pthread_mutex_lock(&bms_fan_cache_lock); + *module_status = bms_fan_status[module_number]; + *module_type = bms_fan_type[module_number]; + pthread_mutex_unlock(&bms_fan_cache_lock); +} + +/* +* FEATURE: +* bms_fan_serv_cache_module_cache_retry_get +* PURPOSE: +* fan service cache retry get +* PARAMETERS: +* module_number (IN) module number +* module_retry (OUT) pointer of module retry +* RETURNS: +*/ +void +bms_fan_serv_cache_module_cache_retry_get(unsigned int module_number, + unsigned int* module_retry) +{ + pthread_mutex_lock(&bms_fan_cache_lock); + *module_retry = bms_fan_retry[module_number]; + pthread_mutex_unlock(&bms_fan_cache_lock); +} + +/* +* FEATURE: +* bms_fan_serv_cache_module_cache_retry_set +* PURPOSE: +* fan service cache retry set +* PARAMETERS: +* module_number (IN) module number +* value (OUT) retry value +* RETURNS: +*/ +void +bms_fan_serv_cache_module_cache_retry_set(unsigned int module_number, + unsigned int value) +{ + pthread_mutex_lock(&bms_fan_cache_lock); + bms_fan_retry[module_number] = value; + pthread_mutex_unlock(&bms_fan_cache_lock); +} + +/* +* FEATURE: +* bms_fan_serv_file_path_rename +* PURPOSE: +* rename sysfs path +* PARAMETERS: +* RETURNS: +* success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_file_path_rename(void) +{ + int i, ret_code = 0; + + for(i = 0; i < BMS_FAN_MODULE_NUM * BMS_FAN_CONTROL_NUM ; i++){ + if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path, + bms_fan_serv_data[i].intr_src)) < 0){ + return -ret_code; + } + if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path, + bms_fan_serv_data[i].intr_msk)) < 0){ + return -ret_code; + } + if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path, + bms_fan_serv_data[i].pwm)) < 0){ + return -ret_code; + } + if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path, + bms_fan_serv_data[i].pwm_enable)) < 0){ + return -ret_code; + } + if((ret_code = bms_sys_serv_hwmon_path_find(bms_fan_serv_data[(i/BMS_FAN_MODULE_NUM) * BMS_FAN_MODULE_NUM].hwmon_path, + bms_fan_serv_data[i].input)) < 0){ + return -ret_code; + } + } + + return ret_code; +} + + +/* +* FEATURE: +* bms_fan_serv_init +* PURPOSE: +* initial fan servd +* PARAMETERS: +* mq_name (IN) message queue name +* mq_desc (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_init(char *mq_name, + mqd_t *mq_desc) +{ + int ret_code = 0; + + /* 1. record board type from CPLD */ + if((ret_code = bms_fan_serv_fan_board_type_get(&bms_board_type)) < 0){ + return ret_code; + } + + /* 2. initial cache to maintain fan statue and type. */ + if((ret_code = bms_fan_serv_cache_init()) < 0){ + return ret_code; + } + + /* 3. rename file path */ + if((ret_code = bms_fan_serv_file_path_rename()) < 0){ + return ret_code; + } + + /* 4. enable all fan mask */ + if((ret_code = bms_fan_serv_mask_init()) < 0) + return ret_code; + + /* 5. open message queue */ + if ((ret_code = bms_sys_serv_msq_open(mq_name, mq_desc)) < 0) { + return ret_code; + } + + /* 6. default set PWM mode */ + if ((ret_code = bms_fan_serv_pwm_init() < 0)) { + return ret_code; + } + + /* 7. initial Mutexes */ + if ((ret_code = bms_fan_serv_mutex_init() < 0)) { + return ret_code; + } + + /* 8. set initial flag */ + bms_fan_init_done = 1; + + return ret_code; +} + + +/* + * FEATURE: + * bms_fan_serv_source_identify + * PURPOSE: + * identify interrupt source from absent or interrupt + * PARAMETERS: + * module_bmap (OUT) module bi map + * module_cause (OUT) module status + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_fan_serv_source_identify(unsigned int *module_bmap, + unsigned int *module_cause) +{ + unsigned int module_present_bmap, fan_intr; + unsigned int mask = 1; + unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM]; + int ret_code = 0, i; + + for(i = 0 ; i < BMS_FAN_MODULE_NUM; i++){ + bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]); + } + /* Is fan interrupt, return bmap */ + /* this i is fan number */ + for(i = 0 ; i < BMS_FAN_MODULE_NUM * BMS_FAN_NUM_PER_MODULE; i++){ + /* read from max31790, 0 for normal and 1 for failed */ + if((ret_code = bms_fan_serv_fan_intr_get(i, &fan_intr)) < 0){ + return ret_code; + } + + if(((cache_status[i / BMS_FAN_NUM_PER_MODULE] == BMS_FAN_MODULE_STATUS_NORMAL) || + (cache_status[i / BMS_FAN_NUM_PER_MODULE] == BMS_FAN_MODULE_STATUS_NONREADY)) + && (fan_intr == BMS_FAN_INTR_FAULT)){ + *module_bmap |= (mask << ((i / BMS_FAN_NUM_PER_MODULE))); + *module_cause = BMS_FAN_MODULE_STATUS_FAILED; + } + } + + if(*module_bmap != 0){ + return ret_code; + } + + /* read fan module present from sysfs, 0 for present and 1 for non-present */ + if((ret_code = bms_fan_serv_fan_present_get(&module_present_bmap)) < 0){ + return ret_code; + } + + /* Is module non-present, return module number, because we don't care non-present here. */ + /* this i is fan module */ + for(i = 0 ; i < BMS_FAN_MODULE_NUM; i++){ + if((cache_status[i] == BMS_FAN_MODULE_STATUS_NORMAL) || + (cache_status[i] == BMS_FAN_MODULE_STATUS_NONREADY) || + (cache_status[i] == BMS_FAN_MODULE_STATUS_FAILED)){ + if((module_present_bmap & mask)){ + *module_bmap = i; + *module_cause = BMS_FAN_MODULE_STATUS_NONPRESENT; + return ret_code; + } + } + mask = mask << 1; + } + + syslog(LOG_WARNING|LOG_USER,"Can't found fan interrupt source .\n"); + return -EINVAL; +} + +/* +* FEATURE: +* bms_fan_serv_cause_log +* PURPOSE: +* log of fan cause +* PARAMETERS: +* module_number (IN) module number +* module_cause (IN) cause of fan module status +* RETURNS: +*/ +static void +bms_fan_serv_cause_log(unsigned int module_number, + unsigned int module_cause) +{ + if(module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT) + syslog(LOG_DEBUG|LOG_USER,"The fan module %u was non present\n", module_number + 1); + else if(module_cause == BMS_FAN_MODULE_STATUS_FAILED) + syslog(LOG_WARNING|LOG_USER,"The fan module %u was fault\n", module_number + 1); + else if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL) + syslog(LOG_DEBUG|LOG_USER,"The fan module %u was present\n", module_number + 1); + else + syslog(LOG_WARNING|LOG_USER,"LOG error, unknown fan_cause in fan module %u\n", module_number + 1); +} + +/* +* FEATURE: +* bms_fan_serv_intr_mask_set +* PURPOSE: +* set specific fan mask +* PARAMETERS: +* module_number (IN) module number +* module_mask (IN) module mask +* RETURNS: +* success, this function returns zero. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_intr_mask_set(unsigned int module_number, + unsigned int module_mask) +{ + int ret_code = 0, i; + + /* write to max31790, 0 for unmask and 1 for masked */ + for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){ + if((ret_code = bms_fan_serv_fan_mask_set((module_number * BMS_FAN_NUM_PER_MODULE) + i, module_mask)) < 0){ + return ret_code; + } + } + + return ret_code; +} + + +/* +* FEATURE: +* bms_fan_serv_find_serv_data_index +* PURPOSE: +* find index of fan of serv_data +* PARAMETERS: + +* RETURNS: +* success, this function returns value. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_find_serv_data_index(void) +{ + int i; + for(i = 0; i < bms_sys_serv_data_num; i++){ + if(strcmp(bms_sys_serv_data[i].name, BMS_FAN_SERV_DATA_NAME) == 0) + return i; + } + + syslog(LOG_WARNING|LOG_USER,"Can't find %s item index in bms_sys_serv_data\n", BMS_FAN_SERV_DATA_NAME); + return -EINVAL; +} + + +/* +* FEATURE: +* bms_fan_serv_global_mask_enable +* PURPOSE: +* enable fan global mask +* PARAMETERS: + +* RETURNS: +* success, this function returns zero. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_global_mask_enable(void) +{ + int ret_code = 0, index; + + if((ret_code = bms_fan_serv_find_serv_data_index()) < 0) + return ret_code; + + index = ret_code; + if((ret_code = bms_fan_serv_fan_global_mask_set(index, BMS_FAN_GLOBAL_INTR_UNMASKED)) < 0){ + return ret_code; + } + + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_board_type_comp +* PURPOSE: +* compare board tpye with fan type +* PARAMETERS: +* module_type (IN) module type +* RETURNS: +* success, compare the same return zero. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_board_type_comp(unsigned int module_type) +{ + + if(((bms_board_type == BMS_AC_PSU_NORMAL_FAN) || (bms_board_type == BMS_DC_PSU_NORMAL_FAN)) && + (module_type == BMS_FAN_MODULE_TYPE_NORMAL)){ + return 0; + } + + if(((bms_board_type == BMS_AC_PSU_REVERSE_FAN) || (bms_board_type == BMS_DC_PSU_REVERSE_FAN)) && + (module_type == BMS_FAN_MODULE_TYPE_REVERSE)){ + return 0; + } + + return -EINVAL; +} + +/* +* FEATURE: +* bms_fan_serv_module_led_update +* PURPOSE: +* update fan module led +* PARAMETERS: +* module_number (IN) module number +* module_cause (IN) cause of fan module event +* module_type (IN) fan module type +* RETURNS: +* success, compare the same return zero. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_module_led_update(unsigned int module_number, + unsigned int module_cause, + unsigned int module_type) +{ + int ret_code = 0; + unsigned int cache_status, cache_type; + + bms_fan_serv_cache_module_cache_get(module_number, &cache_status, &cache_type); + + /* current fan module led status */ + if(cache_status == BMS_FAN_MODULE_STATUS_NORMAL){ + if(bms_fan_serv_board_type_comp(cache_type) == 0){ + /* current fan module led is green */ + if(module_cause == BMS_FAN_MODULE_STATUS_FAILED){ + /* change fan module led to amber */ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_AMBER)) < 0){ + return ret_code; + } + return ret_code; + }else if(module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT){ + /* shutdown fan module led */ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_OFF)) < 0){ + return ret_code; + } + return ret_code; + }else if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL){ + /* Do nothing */ + return ret_code; + } + }else{ + /* current fan module is amber */ + if(module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT){ + /* shutdown fan module led */ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_OFF)) < 0){ + return ret_code; + } + return ret_code; + }else if(module_cause == BMS_FAN_MODULE_STATUS_FAILED){ + /* Do nothing */ + return ret_code; + }else if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL){ + if(bms_fan_serv_board_type_comp(module_type) == 0){ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_GREEN)) < 0){ + return ret_code; + } + }else{ + /* Do nothing */ + return ret_code; + } + } + } + }else + if((cache_status == BMS_FAN_MODULE_STATUS_NONPRESENT) || + (cache_status == BMS_FAN_MODULE_STATUS_NONINIT) || + (cache_status == BMS_FAN_MODULE_STATUS_NONREADY)){ + /* current fan module is off */ + if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL){ + if(bms_fan_serv_board_type_comp(module_type) == 0){ + /* change fan module led to green */ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_GREEN)) < 0){ + return ret_code; + } + return ret_code; + }else{ + /* change fan module to amber */ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_AMBER)) < 0){ + return ret_code; + } + return ret_code; + } + }else if(module_cause == BMS_FAN_MODULE_STATUS_FAILED){ + /* change fan module led to amber */ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_AMBER)) < 0){ + return ret_code; + } + return ret_code; + }else if(module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT){ + /* Do nothing */ + return ret_code; + } + }else + if(cache_status == BMS_FAN_MODULE_STATUS_FAILED){ + /* current fan module led is amber */ + /* mast be present the fan cause will be BMS_FAN_MODULE_STATUS_NORMAL */ + if(module_cause == BMS_FAN_MODULE_STATUS_NORMAL){ + if (bms_fan_serv_board_type_comp(module_type) == 0){ + /* change fan module led to green */ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_GREEN)) < 0){ + return ret_code; + } + return ret_code; + }else{ + /* fan type was different from board type, current fan module led was amber, so do nothing */ + return ret_code; + } + }else if((module_cause == BMS_FAN_MODULE_STATUS_NONPRESENT)){ + /* shutdown fan module led */ + if((ret_code = bms_fan_serv_fan_module_led_set(module_number, BMS_FAN_MODULE_LED_OFF)) < 0){ + return ret_code; + } + return ret_code; + }else if((module_cause == BMS_FAN_MODULE_STATUS_FAILED)){ + /* Do nothing */ + return ret_code; + } + } + + syslog(LOG_WARNING|LOG_USER,"Error input different from cache.\n"); + return -EINVAL; +} + +/* +* FEATURE: +* bms_fan_serv_cache_update +* PURPOSE: +* update data to cache +* PARAMETERS: +* module_number (IN) module number +* module_cause (IN) cause of fan module event +* module_type (IN) fan module type +* RETURNS: +*/ +static void +bms_fan_serv_cache_update(unsigned int module_number, + unsigned int module_cause, + unsigned int module_type) +{ + pthread_mutex_lock(&bms_fan_cache_lock); + bms_fan_status[module_number] = module_cause; + + if((int)module_type != -1){ + bms_fan_type[module_number] = module_type; + } + pthread_mutex_unlock(&bms_fan_cache_lock); +} + +/* +* FEATURE: +* bms_fan_serv_panel_led_by_cache_get +* PURPOSE: +* get panel led status from scan cache +* PARAMETERS: +* +* RETURNS: +* BMS_FAN_PANEL_LED_AMBER or BMS_FAN_PANEL_LED_GREEN +*/ +static int +bms_fan_serv_panel_led_by_cache_get(void) +{ + int i = 0; + unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM]; + + /* read value from cache */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]); + } + + /* is cache have any non init status */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if(cache_status[i] == BMS_FAN_MODULE_STATUS_NONINIT){ + return BMS_FAN_PANEL_LED_OFF; + } + } + + /* is cache all normal and fan type the same with board type */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if((cache_status[i] != BMS_FAN_MODULE_STATUS_NORMAL) || + (bms_fan_serv_board_type_comp(cache_type[i]) != 0)){ + return BMS_FAN_PANEL_LED_AMBER; + } + } + return BMS_FAN_PANEL_LED_GREEN; +} + +/* +* FEATURE: +* bms_fan_serv_panel_led_speed_normal_change +* PURPOSE: +* change panel fan led to green and fan speed to normal +* PARAMETERS: +* +* RETURNS: +* success, compare the same return zero. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_panel_led_speed_normal_change(void) +{ + int ret_code = 0, i; + unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM]; + char buf[64]; + + /* read value from cache */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]); + } + + if((ret_code = bms_fan_serv_fan_panel_led_set(BMS_FAN_PANEL_LED_GREEN)) < 0){ + return ret_code; + } + + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if(cache_status[i] == BMS_FAN_MODULE_STATUS_NONPRESENT) + continue; + if((ret_code = bms_fan_serv_fan_pwm_set(i, BMS_FAN_PWM_DUTY_CYCLE_NORMAL)) < 0){ + return ret_code; + } + } + + snprintf(buf, sizeof(buf),"%s start", bms_fan_serv_data[0].smart_fan_path); + system(buf); + + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_panel_led_speed_failed_change +* PURPOSE: +* change panel fan led to amber and fan speed to max +* PARAMETERS: +* +* RETURNS: +* success, compare the same return zero. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_panel_led_speed_failed_change(void) +{ + int ret_code = 0, i; + unsigned int cache_status[BMS_FAN_MODULE_NUM], cache_type[BMS_FAN_MODULE_NUM]; + char buf[64]; + + /* read value from cache */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + bms_fan_serv_cache_module_cache_get(i, &cache_status[i], &cache_type[i]); + } + + if((ret_code = bms_fan_serv_fan_panel_led_set(BMS_FAN_PANEL_LED_AMBER)) < 0){ + return ret_code; + } + + snprintf(buf, sizeof(buf),"%s stop", bms_fan_serv_data[0].smart_fan_path); + system(buf); + + for(i = 0; i < BMS_FAN_MODULE_NUM; i++){ + if(cache_status[i] == BMS_FAN_MODULE_STATUS_NONPRESENT) + continue; + if((ret_code = bms_fan_serv_fan_pwm_set(i, BMS_FAN_PWM_DUTY_CYCLE_MAX)) < 0){ + return ret_code; + } + } + + return ret_code; +} + +/* +* FEATURE: +* bms_fan_cache_airflow_module_panel_led_update +* PURPOSE: +* update all fan cache, air flow, fan module and panel led +* PARAMETERS: +* module_number (IN) module number +* module_cause (IN) cause of fan module event +* module_type (IN) fan module type +* RETURNS: +* success, compare the same return zero. +* for other cases, negative errno is returned. +*/ +static int +bms_fan_serv_cache_airflow_module_panel_led_update(unsigned int module_number, + unsigned int module_cause, + unsigned int module_type) +{ + int ret_code = 0; + unsigned int pre_status, cur_status; + if((ret_code = bms_fan_serv_module_led_update(module_number, module_cause, module_type)) < 0) + return ret_code; + + pre_status = bms_fan_serv_panel_led_by_cache_get(); + + bms_fan_serv_cache_update(module_number, module_cause, module_type); + + cur_status = bms_fan_serv_panel_led_by_cache_get(); + + + if(cur_status == pre_status) + return ret_code; + if(cur_status == BMS_FAN_PANEL_LED_GREEN){ + if((ret_code = bms_fan_serv_panel_led_speed_normal_change()) < 0){ + return ret_code; + } + }else{ + if((ret_code = bms_fan_serv_panel_led_speed_failed_change()) < 0){ + return ret_code; + } + } + return ret_code; +} + +/* +* FEATURE: +* bms_fan_serv_fan_failed_datect +* PURPOSE: +* detect fan failed cause +* PARAMETERS: +* module_number (IN) module number +* module_status (OUT) cause of fan module status +* success, compare the same return zero. +* for other cases, negative errno is returned. +*/ +int +bms_fan_serv_fan_failed_datect(unsigned int module_number, + unsigned int *fan_status) +{ + unsigned int fan_intr, fan_input; + int ret_code, i; + + /* fan failed datect */ + /* read from max31790, 0 for normal and 1 for failed */ + for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){ + if((ret_code = bms_fan_serv_fan_intr_get((module_number * BMS_FAN_NUM_PER_MODULE) + i, &fan_intr)) < 0){ + return ret_code; + } + if(fan_intr){ + *fan_status = BMS_FAN_MODULE_STATUS_FAILED; + return ret_code; + } + } + + /* detect fan speed */ + for(i = 0; i < BMS_FAN_NUM_PER_MODULE; i++){ + if((ret_code = bms_fan_serv_fan_input_get((module_number * BMS_FAN_NUM_PER_MODULE) + i, &fan_input)) < 0){ + return ret_code; + } + + if(fan_input == BMS_FAN_MIN_FAN_SPEED){ + *fan_status = BMS_FAN_MODULE_STATUS_FAILED; + return ret_code; + } + } + + *fan_status = BMS_FAN_MODULE_STATUS_NORMAL; + + return ret_code; +} + + +/* +* FEATURE: +* bms_fan_servd +* PURPOSE: +* service to handle message queue event of fan +* PARAMETERS: +* args (IN) message queue name +* RETURNS: +* open success, this function will wait for message queue. +* for other cases, will exit this program. +*/ +void* +bms_fan_servd(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + bms_sys_serv_mq_data_t msg; + int ret_code; + unsigned int module_number, module_type; + unsigned int module_status; + unsigned int cache_status, cache_type; + + /* initial */ + if(bms_fan_serv_init(mq_name, &mq_desc) != 0) + goto quit; + + while (1) { + /* Wait for message queue */ + if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code)); + goto quit; + } + + switch (msg.serv_type) { + case SERV_TYPE_RX_INTR: /* FAN_ALERT_INT interrupt */ + module_number = msg.number; + + bms_fan_serv_cause_log(module_number, BMS_FAN_MODULE_STATUS_FAILED); + + if(bms_fan_serv_cache_airflow_module_panel_led_update(module_number, BMS_FAN_MODULE_STATUS_FAILED, -1) < 0){ + break; + } + break; + + case SERV_TYPE_FAN_MODULE_PRESENT: + module_number = msg.number; + module_type = msg.type; + + /* ignore wrong status */ + bms_fan_serv_cache_module_cache_get(module_number, &cache_status, &cache_type); + if((cache_status != BMS_FAN_MODULE_STATUS_NONREADY) && + (cache_status != BMS_FAN_MODULE_STATUS_NONINIT) && + (cache_status != BMS_FAN_MODULE_STATUS_NONPRESENT)){ + break; + } + + if((cache_status == BMS_FAN_MODULE_STATUS_NONPRESENT) || + (cache_status == BMS_FAN_MODULE_STATUS_NONINIT)){ + /* we assume fan module must failed when fan present */ + module_status = BMS_FAN_MODULE_STATUS_FAILED; + }else{ + if(bms_fan_serv_fan_failed_datect(module_number, &module_status) < 0){ + break; + } + } + + if(module_status == BMS_FAN_MODULE_STATUS_FAILED){ + /* if fan present within 1 second, set fan status to non-ready */ + bms_fan_serv_cache_update(module_number, BMS_FAN_MODULE_STATUS_NONREADY, module_type); + }else if(module_status == BMS_FAN_MODULE_STATUS_NORMAL){ + + bms_fan_serv_cause_log(module_number, BMS_FAN_MODULE_STATUS_NORMAL); + bms_fan_serv_cache_airflow_module_panel_led_update(module_number, BMS_FAN_MODULE_STATUS_NORMAL, module_type); + + } + + if((cache_status == BMS_FAN_MODULE_STATUS_NONINIT) || + (cache_status == BMS_FAN_MODULE_STATUS_NONPRESENT)){ + if(bms_fan_serv_board_type_comp(module_type) < 0){ + syslog(LOG_WARNING|LOG_USER,"The fan module %u type was wrong\n", module_number + 1); + } + } + + break; + case SERV_TYPE_FAN_MODULE_NONPRESENT: + module_number = msg.number; + + /* ignore wrong status */ + bms_fan_serv_cache_module_cache_get(module_number, &cache_status, &cache_type); + if(cache_status == BMS_FAN_MODULE_STATUS_NONPRESENT){ + break; + } + + /* clear retry cache */ + bms_fan_serv_cache_module_cache_retry_set(module_number, BMS_FAN_NONREADY_RETRY_INIT); + + if(cache_status != BMS_FAN_MODULE_STATUS_NONINIT){ + bms_fan_serv_cause_log(module_number, BMS_FAN_MODULE_STATUS_NONPRESENT); + } + if(bms_fan_serv_cache_airflow_module_panel_led_update(module_number, BMS_FAN_MODULE_STATUS_NONPRESENT, -1) < 0) + break; + + break; + default: + syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name); + break; + } + } + +quit: + pthread_mutex_destroy(&bms_fan_cache_lock); + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.h new file mode 100644 index 000000000000..a70d3c98f47f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_fan_servd.h @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __BMS_FAN_SERVD_H__ +#define __BMS_FAN_SERVD_H__ + +#include "bms_irq_sysd.h" + +#define FAN_FILE_PATH_LEN 64 + +typedef struct { + int number; + char *hwmon_path; + char intr_src[FAN_FILE_PATH_LEN]; + char intr_msk[FAN_FILE_PATH_LEN]; + char *tray_led; + char *type; + char *present; + char pwm[FAN_FILE_PATH_LEN]; + char pwm_enable[FAN_FILE_PATH_LEN]; + char input[FAN_FILE_PATH_LEN]; + char *smart_fan_path; +}bms_fan_serv_data_t; + +enum { + BMS_AC_PSU_NORMAL_FAN = 0, + BMS_AC_PSU_REVERSE_FAN, + BMS_DC_PSU_NORMAL_FAN, + BMS_DC_PSU_REVERSE_FAN, +}; + +enum { + BMS_FAN_MODULE_STATUS_NONINIT = 0, + BMS_FAN_MODULE_STATUS_NONREADY, + BMS_FAN_MODULE_STATUS_NORMAL, + BMS_FAN_MODULE_STATUS_NONPRESENT, + BMS_FAN_MODULE_STATUS_FAILED, +}; + +enum { + BMS_FAN_MODULE_TYPE_REVERSE = 0, + BMS_FAN_MODULE_TYPE_NORMAL, +}; + +enum { + BMS_FAN_INTR_UNMASKED = 0, + BMS_FAN_INTR_MASKED, +}; + +enum { + BMS_FAN_INTR_NORMAL = 0, + BMS_FAN_INTR_FAULT, +}; + +enum { + BMS_FAN_GLOBAL_INTR_MASKED = 0, + BMS_FAN_GLOBAL_INTR_UNMASKED, +}; + +enum { + BMS_FAN_MODULE_LED_OFF = 0, + BMS_FAN_MODULE_LED_GREEN, + BMS_FAN_MODULE_LED_AMBER, +}; + +enum { + BMS_FAN_PANEL_LED_OFF = 0, + BMS_FAN_PANEL_LED_AMBER, + BMS_FAN_PANEL_LED_GREEN, +}; + +enum { + BMS_FAN_PWM_ENABLE_OFF = 0, + BMS_FAN_PWM_ENABLE_PWM, + BMS_FAN_PWM_ENABLE_RPM +}; + +enum { + BMS_FAN_PWM_DUTY_CYCLE_NORMAL = 254, + BMS_FAN_PWM_DUTY_CYCLE_MAX = 255, +}; + + +extern bms_sys_serv_data_t bms_sys_serv_data[]; +extern int bms_sys_serv_data_num; + +extern int bms_fan_init_done; +extern void bms_fan_serv_fan_debug_cache_print(char * test); +extern bms_fan_serv_data_t bms_fan_serv_data[]; +extern unsigned int bms_fan_status[]; +extern unsigned int bms_fan_type[]; +extern unsigned int bms_board_type; + +extern void bms_fan_serv_cache_module_cache_get(unsigned int module_number, unsigned int* module_status, unsigned int* module_type); +extern int bms_fan_serv_fan_present_get(unsigned int *value); +extern int bms_fan_serv_module_type_get(unsigned int module_number, unsigned int *value); +extern void bms_fan_serv_cache_module_cache_retry_get(unsigned int module_number, unsigned int* module_retry); +extern void bms_fan_serv_cache_module_cache_retry_set(unsigned int module_number, unsigned int value); +extern int bms_fan_serv_fan_pwm_set(unsigned int module_number, unsigned int value); +extern int bms_fan_serv_fan_input_get(unsigned int fan_number, unsigned int *value); +extern int bms_fan_serv_fan_intr_get(unsigned int fan_number, unsigned int *value); + + +#define BMS_SYSFS_FAN_PANEL_LED "/sys/bus/i2c/devices/1-0032/fan_led" +#define BMS_FAN_NUM_PER_MODULE 2 +#define BMS_FAN_MODULE_NUM 6 +#define BMS_FAN_MIN_FAN_SPEED 480 +#define BMS_FAN_NONREADY_RETRY_INIT 0 +#define BMS_FAN_NONREADY_RETRY 3 +#define BMS_FAN_SERV_DATA_NAME "FAN" +#define BMS_FAN_CONTROL_NUM 2 + +/* fan message queue range define 100~199 */ +#define SERV_TYPE_FAN_MODULE_PRESENT 100 +#define SERV_TYPE_FAN_MODULE_NONPRESENT 101 + +#endif /* __BMS_FAN_SERVD_H__ */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.c new file mode 100644 index 000000000000..168ca469b202 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.c @@ -0,0 +1,513 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_irq_sysd.h" +#include "bms_sys_serv_common.h" +#include "bms_fan_servd.h" +#include "bms_psu_servd.h" + +#define PROC_PRIORITY 90 + +/* MIC_FEAT_SYS_INT : 1 means interrupt, 0 means polling */ +#define MIC_FEAT_SYS_INT 0 + + + +#if (MIC_FEAT_SYS_INT) +#include +#include +#include + +#define BMS_SYS_GPE_SYSFS "/sys/firmware/acpi/interrupts/gpe%.2X" +#define BMS_SYS_GPE_SYSFS_CHAR_NUM 40 /* ex. /sys/firmware/acpi/interrupts/gpe01 */ +#define BMS_SYS_GPE_DISABLE 0 +#define BMS_SYS_GPE_INIT_SKIP 0xFF +#define BMS_SYS_ACPID_SOCKET_SYSFS "/var/run/acpid.socket" +#define BMS_SYS_GPE_INTR_TAG "bms_acpi PNP0C01:00 000000%.2X 00000000" +#define BMS_SYS_GPE_INTR_TAG_CHAR_NUM 38 /* ex. bms_acpi PNP0C01:00 00000002 00000000 */ +#endif + + +bms_sys_serv_data_t bms_sys_serv_data[] = { + { + .name = "VRHOT", + .intr_src = "/sys/bus/i2c/devices/1-0031/vrhot_irq", + .intr_msk = "/sys/bus/i2c/devices/1-0031/vrhot_irq_en", + .mq_name = "/sys_vrhot_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_irq_sys_isr, + .isrd = bms_vrhot_servd, + .polld = NULL, + .intr_msk_default = !SYS_SERV_INTR_MASK_EN, + }, + { + .name = "CPU_TEMP", + .intr_src = "/sys/bus/i2c/devices/1-0031/cpu_thermtrip_irq", + .intr_msk = "/sys/bus/i2c/devices/1-0031/cpu_thermtrip_irq_en", + .mq_name = "/sys_isr_cpu_thermtrip_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_irq_sys_isr, + .isrd = bms_cpu_temp_servd, + .polld = NULL, + .intr_msk_default = !SYS_SERV_INTR_MASK_EN, + }, + { + .name = "SYS_TEMP", + .intr_src = "/sys/bus/i2c/devices/1-0031/temp_alert_irq", + .intr_msk = "/sys/bus/i2c/devices/1-0031/temp_alert_irq_en", + .mq_name = "/sys_temp_alert_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_irq_sys_isr, + .isrd = bms_sys_temp_servd, + .polld = NULL, + .intr_msk_default = !SYS_SERV_INTR_MASK_EN, + }, + { + .name = "PS1", + .intr_src = "/sys/bus/i2c/devices/1-0032/ps1_int", + .intr_msk = "/sys/bus/i2c/devices/1-0032/ps1_int_msk", + .mq_name = "/sys_psu_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_irq_sys_isr, + .isrd = bms_psu_servd, + .polld = bms_psu_polld, + .intr_msk_default = SYS_SERV_INTR_MASK_EN,/* detect by polling */ + }, + { + .name = "PS2", + .intr_src = "/sys/bus/i2c/devices/1-0032/ps2_int", + .intr_msk = "/sys/bus/i2c/devices/1-0032/ps2_int_msk", + .mq_name = "/sys_psu_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_irq_sys_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PSU1 */ + .polld = NULL, + .intr_msk_default = SYS_SERV_INTR_MASK_EN,/* detect by polling */ + }, + { + .name = "USB", + .intr_src = "/sys/bus/i2c/devices/1-0032/usb_fault", + .intr_msk = "/sys/bus/i2c/devices/1-0032/usb_fault_msk", + .mq_name = "/sys_usb_fault_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_irq_sys_isr, + .isrd = bms_usb_servd, + .polld = NULL, + .intr_msk_default = !SYS_SERV_INTR_MASK_EN, + }, + { + .name = "PCIE", + .intr_src = "/sys/bus/i2c/devices/1-0032/pcie_int", + .intr_msk = "/sys/bus/i2c/devices/1-0032/pcie_int_msk", + .mq_name = "/sys_pcie_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_irq_sys_isr, + .isrd = bms_pcie_servd, + .polld = NULL, + .intr_msk_default = SYS_SERV_INTR_MASK_EN, + }, + { + .name = "FAN", + .intr_src = "/sys/bus/i2c/devices/1-0032/fan_alert_int", + .intr_msk = "/sys/bus/i2c/devices/1-0032/fan_alert_int_msk", + .mq_name = "/sys_fan_alert_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_irq_sys_isr, + .isrd = bms_fan_servd, + .polld = bms_fan_polld, + .intr_msk_default = SYS_SERV_INTR_MASK_EN, + }, +}; + +int bms_sys_serv_data_num = sizeof(bms_sys_serv_data) / sizeof(bms_sys_serv_data[0]); + +/* +* FEATURE: +* bms_irq_sys_isr +* PURPOSE: +* Handle system interrupt routine +* PARAMETERS: +* name (IN) service name +* qname (IN) message queue name +* mq_desc (IN) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_irq_sys_isr(char *name, + char *qname, + mqd_t mq_desc) +{ + int ret_code = 0; + bms_sys_serv_mq_data_t msg; + + msg.serv_type = SERV_TYPE_RX_INTR; + msg.serv_name = name; + + if (mq_send(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + if (ret_code == EAGAIN) { + syslog(LOG_WARNING|LOG_USER,"Message queue %s is full\n", qname); + } + else { + syslog(LOG_WARNING|LOG_USER,"Failed to send message to %s (%s)\n", qname, strerror(ret_code)); + } + } + + return -ret_code; +} + +#if MIC_FEAT_SYS_INT == 1 +/* + * FEATURE: + * bms_gpe_event_write + * PURPOSE: + * set event to gpe + * PARAMETERS: + * gpe_num (IN) gpe number + * enable (IN) 1 means enable, 0 means disable, others set 0. + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_sys_serv_gpe_event_write(unsigned int gpe_num, + unsigned int enable) +{ + char buf[10], filename[BMS_SYS_GPE_SYSFS_CHAR_NUM] = { 0 }; + int fd, ret_code = 0, buf_size = sizeof(buf); + ssize_t count; + + snprintf(filename, sizeof(filename), BMS_SYS_GPE_SYSFS, gpe_num); + /* Open file */ + if ((fd = open(filename, O_WRONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Write file */ + if (enable == BMS_SYS_GPE_DISABLE) { + snprintf(buf, buf_size, "%s", "disable\n"); + } else if (enable == !BMS_SYS_GPE_DISABLE) { + snprintf(buf, buf_size, "%s", "enable\n"); + } else if (enable == BMS_SYS_GPE_INIT_SKIP) { + snprintf(buf, buf_size, "%s", "disable\n"); + } else { + snprintf(buf, buf_size, "%d", 0); + } + if ((count = write(fd, buf, buf_size)) != (-1)) {;} + else if (enable == BMS_SYS_GPE_INIT_SKIP) {;} + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} +#endif + + +/* +* FEATURE: +* bms_irq_sys_msq_create +* PURPOSE: +* Create message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_irq_sys_msq_create(char *qname, + mqd_t *mqd) +{ + int flags = (O_CREAT | O_EXCL | O_WRONLY | O_NONBLOCK), ret_code = 0, i; + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + struct mq_attr attr = { + .mq_maxmsg = 64, + .mq_msgsize = sizeof(bms_sys_serv_mq_data_t), + }; + + /* Check others item had the same qname that already created */ + for(i = 0; i < bms_sys_serv_data_num; i++){ + if(bms_sys_serv_data[i].mq_name){ + if(strcmp(bms_sys_serv_data[i].mq_name, qname) == 0){ + if(bms_sys_serv_data[i].mq_desc != (mqd_t)-1){ + *mqd = bms_sys_serv_data[i].mq_desc; + return 0; + } + } + } + } + + /* destroy message queue if it presents */ + if ((mq_unlink(qname) < 0) && (errno != ENOENT)) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to destroy message queue %s (%s)\n", qname, strerror(ret_code)); + } + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags, mode, &attr)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to create message queue %s (%s)\n", qname, strerror(ret_code)); + return -ret_code; + } + + syslog(LOG_DEBUG|LOG_USER,"Create message queue %s\n", qname); + + return -ret_code; +} + +/* +* FEATURE: +* bms_irq_sys_terminator +* PURPOSE: +* Do someting when terminator flag coming +* PARAMETERS: +* sig (IN) signal +* RETURNS: +*/ +void +bms_irq_sys_terminator(int sig) +{ + int i; + if (sig) {;} + + for (i = 0; i < bms_sys_serv_data_num; i++) { + /* Disable interrupt function */ + bms_sys_serv_write(bms_sys_serv_data[i].intr_msk, SYS_SERV_INTR_MASK_EN); + + /* destroy message queue */ + mq_unlink(bms_sys_serv_data[i].mq_name); + } + + syslog(LOG_DEBUG|LOG_USER,"Terminate %s\n", __FILE__); + + exit(0); +} + + + +/* +* FEATURE: +* main +* PURPOSE: +* main start +* PARAMETERS: +* +* RETURNS: +*/ +int +main(void) +{ + int i, value = 0, ret_code = 0; + struct sched_param sched_param = {.sched_priority = PROC_PRIORITY}; + pthread_attr_t attr; + +#if(MIC_FEAT_SYS_INT) + int socket_dsc = 0; + struct sockaddr_un socket_addr; + char buf[BMS_SYS_GPE_INTR_TAG_CHAR_NUM],gpe_tag[BMS_SYS_GPE_INTR_TAG_CHAR_NUM]; + unsigned int gpe_num = 0x1; + int unknow_interrupt = 1; +#else + int mask; +#endif + + /* Set priority and make it be real-time */ + nice(-1); + sched_setscheduler(0, SCHED_FIFO, &sched_param); + + /* Make the process be a background daemon */ + daemon(0 /* change working directory to root */, + 0 /* redirect stdin, stdout, and stderr to /dev/null */); + + /* Register handler for termination */ + signal(SIGTERM, bms_irq_sys_terminator); + + /* Create message queue for each interrupt service routine (ISR) */ + for (i = 0; i < bms_sys_serv_data_num; i++) { + if (bms_sys_serv_data[i].mq_name) { + if ((ret_code = bms_irq_sys_msq_create(bms_sys_serv_data[i].mq_name, &bms_sys_serv_data[i].mq_desc)) < 0) { + goto quit; + } + } + } + + /* Enable Interrupt function */ + for (i = 0; i < bms_sys_serv_data_num; i++) { + if((ret_code = bms_sys_serv_write(bms_sys_serv_data[i].intr_msk, bms_sys_serv_data[i].intr_msk_default)) < 0) { + goto quit; + } + } + + /* Disable fan module led */ + for(i = 0; i < BMS_FAN_MODULE_NUM; i++ ){ + if((ret_code = bms_sys_serv_write(bms_fan_serv_data[i * BMS_FAN_NUM_PER_MODULE].tray_led, BMS_FAN_MODULE_LED_OFF)) < 0) { + goto quit; + } + } + + /* Disable panel fan led */ + if((ret_code = bms_sys_serv_write(BMS_SYSFS_FAN_PANEL_LED, BMS_FAN_PANEL_LED_OFF)) < 0) { + goto quit; + } + + + /* Spawn interrupt service routine (ISR) daemon */ + for (i = 0; i < bms_sys_serv_data_num; i++) { + if (bms_sys_serv_data[i].isrd) { + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + pthread_attr_setschedparam(&attr, &sched_param); + if (pthread_create(&bms_sys_serv_data[i].isrd_tid, &attr, bms_sys_serv_data[i].isrd, (void*)bms_sys_serv_data[i].mq_name) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to create pthread (%s)\n", strerror(ret_code)); + goto quit; + } + } + if (bms_sys_serv_data[i].polld) { + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + pthread_attr_setschedparam(&attr, &sched_param); + if (pthread_create(&bms_sys_serv_data[i].polld_tid, &attr, bms_sys_serv_data[i].polld, (void*)bms_sys_serv_data[i].mq_name) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to create pthread (%s)\n", strerror(ret_code)); + goto quit; + } + } + } + +#if(MIC_FEAT_SYS_INT) + snprintf(gpe_tag, sizeof(gpe_tag), BMS_SYS_GPE_INTR_TAG, gpe_num); + /* set default value for GPE status */ + bms_sys_serv_gpe_event_write(gpe_num, BMS_SYS_GPE_INIT_SKIP); + + /* 3. Open the acpi socket. */ + if ((socket_dsc = socket(AF_UNIX, SOCK_STREAM, 0)) == (-1)) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code)); + goto quit; + } + socket_addr.sun_family = AF_UNIX; + strcpy(socket_addr.sun_path, BMS_SYS_ACPID_SOCKET_SYSFS); + if (connect(socket_dsc, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) == (-1)) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to connect ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code)); + + } +#endif + + + while (1) { +#if(MIC_FEAT_SYS_INT) + unknow_interrupt = 1; + /* 3. Enable IRQ */ + if((ret_code = bms_sys_serv_gpe_event_write(gpe_num, !BMS_SYS_GPE_DISABLE)) < 0) + goto quit; + + /* Wait for interrupt occurs; this is a blocking call and may leave + * the blocking state unexpectly while receiving a signal. In such + * a case, we go back to wait for the arriving of interrupt. + */ + +wait_irq: + memset(buf,0,sizeof(buf)); + if (recv(socket_dsc, buf, sizeof(buf), 0) <= 0) { + if (errno == EINTR) {goto wait_irq;} + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code)); + goto quit; + } + if (!strncmp(buf, gpe_tag, sizeof(gpe_tag)-1)) { + /* Due to bms_gpe hanlder does not set disable now. */ + if((ret_code = bms_sys_serv_gpe_event_write(gpe_num, BMS_SYS_GPE_DISABLE)) < 0) + goto quit; + } else { + goto wait_irq; + } +#endif + + /* Probe all interrupt sources */ + for (i = 0; i < bms_sys_serv_data_num; i++) { + /* Detect which source(s) trigger the interrupt. 0 is assert, 1 is not assert */ + if ((ret_code = bms_sys_serv_hex_read(bms_sys_serv_data[i].intr_src, (unsigned int*)&value)) < 0) { + goto quit; + } + +#if(MIC_FEAT_SYS_INT) + if (value != SYS_SERV_INTR_STATUS_EN) + continue; +#else + /* 0 is masked, 1 is not mask */ + if ((ret_code = bms_sys_serv_hex_read(bms_sys_serv_data[i].intr_msk, (unsigned int*)&mask)) < 0) { + goto quit; + } + + if((value != SYS_SERV_INTR_STATUS_EN) || (mask != (!SYS_SERV_INTR_MASK_EN))) + continue; +#endif + + /* Disable the source that triggers the interrupt */ + if ((ret_code = bms_sys_serv_write(bms_sys_serv_data[i].intr_msk, SYS_SERV_INTR_MASK_EN)) < 0) { + goto quit; + } + + /* Call interrupt service routine (ISR) */ + syslog(LOG_DEBUG|LOG_USER,"%s interrupt arrivals\n", bms_sys_serv_data[i].name); + bms_sys_serv_data[i].isr(bms_sys_serv_data[i].name, bms_sys_serv_data[i].mq_name, bms_sys_serv_data[i].mq_desc); +#if(MIC_FEAT_SYS_INT) + unknow_interrupt = 0; +#endif + } +#if(MIC_FEAT_SYS_INT) + /* Log unknown interrupt */ + if (unknow_interrupt) { + syslog(LOG_WARNING|LOG_USER,"Receive an unknown interrupt from system interrput\n"); + } +#else + sleep(2); +#endif + + } + +quit: + syslog(LOG_DEBUG|LOG_USER,"Quit daemon %s\n", __FILE__); + exit(ret_code); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.h new file mode 100644 index 000000000000..229b73e83f36 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_irq_sysd.h @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __BMS_IRQ_SYSD_H__ +#define __BMS_IRQ_SYSD_H__ + +#define SYS_SERV_INTR_STATUS_EN 0 +#define SYS_SERV_INTR_MASK_EN 0 + +typedef int (*isr_t)(char *, char *, mqd_t); +typedef void* (*isrd_t)(void*); + +typedef struct { + char *name; + char *intr_src; + char *intr_msk; + char *mq_name; + mqd_t mq_desc; + isr_t isr; + pthread_t isrd_tid; + isrd_t isrd; + pthread_t polld_tid; + isrd_t polld; + unsigned int intr_msk_default; +} bms_sys_serv_data_t; + +typedef struct { + unsigned char serv_type; +#define SERV_TYPE_RX_INTR 1 /* Receving an interrupt */ + char *serv_name; /* service name */ + unsigned int number; + unsigned int type; + unsigned int cause; +} bms_sys_serv_mq_data_t; + +extern void* bms_vrhot_servd(void *args); +extern void* bms_cpu_temp_servd(void *args); +extern void* bms_sys_temp_servd(void *args); +extern void* bms_psu_servd(void *args); +extern void* bms_usb_servd(void *args); +extern void* bms_pcie_servd(void *args); +extern void* bms_fan_servd(void *args); +extern void* bms_fan_polld(void *args); +extern int bms_irq_sys_isr(char *name, char *qname, mqd_t mq_desc); +extern void* bms_psu_polld(void *args); +#endif /* __BMS_IRQ_SYSD_H__ */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_pcie_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_pcie_servd.c new file mode 100644 index 000000000000..72d935d317fc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_pcie_servd.c @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_irq_sysd.h" + +#include + + +/* +* FEATURE: +* bms_pcie_msq_open +* PURPOSE: +* open POSIX message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_pcie_msq_open(const char *qname, + mqd_t *mqd) +{ + int flags = (O_RDONLY), ret_code = 0; + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + +/* +* FEATURE: +* bms_pcie_servd +* PURPOSE: +* service to handle message queue event of pcie +* PARAMETERS: +* args (IN) message queue name +* RETURNS: +* open success, this function will wait for message queue. +* for other cases, will exit this program. +*/ +void* +bms_pcie_servd(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + bms_sys_serv_mq_data_t msg; + int ret_code; + + /* Open message queue */ + if (bms_pcie_msq_open(mq_name, &mq_desc) < 0) { + goto quit; + } + + while (1) { + /* Wait for message queue */ + if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code)); + goto quit; + } + + switch (msg.serv_type) { + case SERV_TYPE_RX_INTR: /* PCIE_INT interrupt */ + syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name); + break; + + default: + syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name); + break; + } + } + +quit: + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_polld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_polld.c new file mode 100644 index 000000000000..5632bae073cd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_polld.c @@ -0,0 +1,329 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include "bms_psu_servd.h" +#include "bms_sys_serv_common.h" + + +/* +* FEATURE: +* bms_psu_poll_msq_open +* PURPOSE: +* open POSIX message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_psu_poll_msq_open(const char *qname, + mqd_t *mqd) +{ + int flags = (O_WRONLY | O_NONBLOCK), ret_code = 0; + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + + +/* +* FEATURE: +* bms_psu_poll_init +* PURPOSE: +* initial all +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_psu_poll_init(char *mq_name, + mqd_t *mq_desc) +{ + int ret_code = 0; + + /* open message queue*/ + if ((ret_code = bms_psu_poll_msq_open(mq_name, mq_desc)) < 0) { + return ret_code; + } + + return ret_code; +} + + +/* +* FEATURE: +* bms_psu_poll_detect_psu_status +* PURPOSE: +* datect psu status is present or non present +* PARAMETERS: +* present_bmap (OUT) pointer of present bmap +* nonpresent_bmap (OUT) pointer of non-present bmap +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_psu_poll_detect_module_status(unsigned int *present_pg_bmap, + unsigned int *present_bmap, + unsigned int *nonpresent_bmap, + unsigned int *intr_table, + unsigned int *intr_recovery_table) +{ + int ret_code = 0, i; + unsigned int ps_pg_status; + unsigned int cache_status[BMS_PSU_NUM], cache_type[BMS_PSU_NUM],psu_present[BMS_PSU_NUM], psu_power_good[BMS_PSU_NUM]; + unsigned int intr_status[BMS_PSU_NUM * BMS_PSU_INTR_NUM], intr_cache[BMS_PSU_NUM * BMS_PSU_INTR_NUM]; + + memset(intr_status, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM); + memset(intr_cache, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM); + + /* read pg */ + if((ret_code = bms_psu_serv_power_status_get(&ps_pg_status)) < 0) { + return ret_code; + } + + for(i = 0; i < BMS_PSU_NUM; i++) { + bms_psu_serv_cache_get(i, &cache_status[i], &cache_type[i]); + psu_present[i] = ((ps_pg_status & (1 << (bms_psu_serv_data[i].ps_offset))) > 0) ? BMS_PSU_PS_NONPRESENT : BMS_PSU_PS_PRESENT; + psu_power_good[i] = ((ps_pg_status & (1 << (bms_psu_serv_data[i].pg_offset))) > 0) ? BMS_PSU_PG_FAILED : BMS_PSU_PG_GOOD; + } + + /* read interrupt cache */ + bms_psu_serv_intr_cache_get(intr_cache); + + /* read interrupt from file system */ + for(i = 0; i < BMS_PSU_NUM * BMS_PSU_INTR_NUM; i++){ + if((cache_status[i / BMS_PSU_INTR_NUM] != BMS_PSU_STATUS_NORMAL) && + (cache_status[i / BMS_PSU_INTR_NUM] != BMS_PSU_STATUS_FAULT)) { + continue; + } + if((ret_code = bms_sys_serv_dec_read(bms_psu_serv_data[i / BMS_PSU_INTR_NUM].intr_src[i % BMS_PSU_INTR_NUM], &intr_status[i])) < 0){ + return ret_code; + } + } + + for(i = 0; i < BMS_PSU_NUM; i++) { + if(cache_status[i] == BMS_PSU_STATUS_ABSENT) { + if(psu_present[i] == BMS_PSU_PS_PRESENT) { + /* case 1 current status is absent, and have a psu plug in */ + *present_bmap |= (1 << i); + } + continue; + } + + if(cache_status[i] == BMS_PSU_STATUS_PRESENT) { + if(psu_present[i] == BMS_PSU_PS_PRESENT) { + if(psu_power_good[i] == BMS_PSU_PG_GOOD) { + /* case 2 current status is present, and detect power good now */ + *present_pg_bmap |= (1 << i); + } + }else + if(psu_present[i] == BMS_PSU_PS_NONPRESENT) { + /* case 3 current status is is present, and detect non present */ + *nonpresent_bmap |= (1 << i); + } + continue; + } + + if((cache_status[i] == BMS_PSU_STATUS_NORMAL) || + (cache_status[i] == BMS_PSU_STATUS_FAULT)) { + if(psu_present[i] == BMS_PSU_PS_NONPRESENT) { + /* case 4 current status is is normal or fault, and detect non present */ + *nonpresent_bmap |= (1 << i); + }else + if(psu_present[i] == BMS_PSU_PS_PRESENT) { + if(psu_power_good[i] == BMS_PSU_PG_FAILED) { + /* case 5 current status is is normal or fault, and detect non power good */ + *present_bmap |= (1 << i); + } + } + continue; + } + + syslog(LOG_DEBUG|LOG_USER,"[%s] Unknown cache status %u and present status %u\n", __FUNCTION__, cache_status[i], psu_present[i]); + + } + + for(i = 0; i < BMS_PSU_NUM * BMS_PSU_INTR_NUM; i++){ + if(intr_status[i] == intr_cache[i]) + continue; + + if(psu_power_good[i / BMS_PSU_INTR_NUM] == BMS_PSU_PG_FAILED){ + continue; + } + + if(intr_status[i] == BMS_PSU_SOURCE_INTR_ASSERTED){ + intr_table[i] = 1; + } + else{ + intr_recovery_table[i] = 1; + } + } + + return ret_code; +} + +/* +* FEATURE: +* bms_psu_poll_msq_send +* PURPOSE: +* send POSIX message queue +* PARAMETERS: +* msg (IN) message of send data +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_psu_poll_msq_send(bms_sys_serv_mq_data_t* msg, + mqd_t *mqd) +{ + int ret_code; + + if (mq_send(*mqd, (char*)msg, sizeof(*msg), 0) < 0) { + ret_code = errno; + if (ret_code == EAGAIN) { + syslog(LOG_WARNING|LOG_USER,"Message queue %s is full\n", msg->serv_name); + } + else { + syslog(LOG_WARNING|LOG_USER,"Failed to send message to %s (%s)\n", msg->serv_name, strerror(ret_code)); + } + } + + return -ret_code; +} + + +/* +* FEATURE: +* bms_psu_polld +* PURPOSE: +* bms psu polling daemon +* PARAMETERS: +* args (IN) input value(message name) +* RETURNS: +* The process will always polling psu module. +*/ +void* +bms_psu_polld(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + int ret_code = 0, i; + + bms_sys_serv_mq_data_t msg; + unsigned int present_pg_bmap = 0, nonpresent_bmap = 0; + unsigned int present_bmap = 0; + unsigned int intr_table[BMS_PSU_NUM * BMS_PSU_INTR_NUM], intr_recovery_table[BMS_PSU_NUM * BMS_PSU_INTR_NUM]; + + msg.serv_name = mq_name; + + if((ret_code = bms_psu_poll_init(mq_name, &mq_desc)) < 0) { + goto quit; + } + + while(!bms_psu_init_done) { + sleep(1); + } + + while(1) { + present_pg_bmap = 0; + nonpresent_bmap = 0; + present_bmap = 0; + memset(intr_table, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM); + memset(intr_recovery_table, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM); + + if((ret_code = bms_psu_poll_detect_module_status(&present_pg_bmap, &present_bmap, + &nonpresent_bmap, intr_table, intr_recovery_table)) < 0) { + goto wait; + } + + + if(present_pg_bmap != 0) { + for(i = 0; i < BMS_PSU_NUM; i++) { + if(present_pg_bmap & (1 << i)) { + msg.serv_type = SERV_TYPE_PSU_NORMAL; + msg.number = i; + bms_psu_poll_msq_send(&msg, &mq_desc); + } + } + } + + if(present_bmap != 0) { + for(i = 0; i < BMS_PSU_NUM; i++) { + if(present_bmap & (1 << i)) { + msg.serv_type = SERV_TYPE_PSU_PRESENT; + msg.number = i; + bms_psu_poll_msq_send(&msg, &mq_desc); + } + } + } + + if(nonpresent_bmap != 0) { + for(i = 0; i < BMS_PSU_NUM; i++) { + if(nonpresent_bmap & (1 << i)) { + msg.serv_type = SERV_TYPE_PSU_ABSENT; + msg.number = i; + bms_psu_poll_msq_send(&msg, &mq_desc); + } + } + } + + for(i = 0; i < BMS_PSU_NUM * BMS_PSU_INTR_NUM; i++) { + if(intr_table[i] == 1) { + msg.serv_type = SERV_TYPE_RX_INTR; + msg.number = i / BMS_PSU_INTR_NUM; + msg.cause = i % BMS_PSU_INTR_NUM; + bms_psu_poll_msq_send(&msg, &mq_desc); + } + } + + for(i = 0; i < BMS_PSU_NUM * BMS_PSU_INTR_NUM; i++) { + if(intr_recovery_table[i] == 1) { + msg.serv_type = SERV_TYPE_PSU_INTR_RECOVERY; + msg.number = i / BMS_PSU_INTR_NUM; + msg.cause = i % BMS_PSU_INTR_NUM; + bms_psu_poll_msq_send(&msg, &mq_desc); + } + } + +wait: + sleep(1); + } + +quit: + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.c new file mode 100644 index 000000000000..4819faa47938 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.c @@ -0,0 +1,1047 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_irq_sysd.h" +#include "bms_sys_serv_common.h" +#include "bms_psu_servd.h" + +bms_psu_serv_data_t bms_psu_serv_data[BMS_PSU_NUM] = { + { + .name = "PS1", + .i2c_path = "/sys/bus/i2c/devices/i2c-5/new_device", + .driver_name = "fse000", + .pg_offset = 6, + .ps_offset = 7, + .address = 0x58, + .pg_ps_reg = "/sys/bus/i2c/devices/1-0032/psu_en_status_fld", + .model_reg = "mfr_model", + .hwmon_path = "/sys/bus/i2c/devices/5-0058/hwmon", + .intr_src = { + "vout_ov_fault", + "vout_uv_fault", + "curr2_crit_alarm", + "curr2_max_alarm", + "ot_fault", + "ot_warning", + "vin_uv_warning", + "vin_uv_fault", + "fan1_fault", + "fan1_alarm", + }, + }, + { + .name = "PS2", + .i2c_path = NULL, /* share with ps1 i2c_path */ + .driver_name = NULL, /* share with ps1 driver_name */ + .pg_offset = 2, + .ps_offset = 3, + .address = 0x59, + .pg_ps_reg = NULL, /* share with ps1 pg_ps_reg */ + .model_reg = "mfr_model", + .hwmon_path = "/sys/bus/i2c/devices/5-0059/hwmon", + .intr_src = { + "vout_ov_fault", + "vout_uv_fault", + "curr2_crit_alarm", + "curr2_max_alarm", + "ot_fault", + "ot_warning", + "vin_uv_warning", + "vin_uv_fault", + "fan1_fault", + "fan1_alarm", + }, + }, +}; + +char *bms_psu_mfr_model[] = { + "FSE047-180G", + "FSE048-180G", + "FSE050-180G", + "FSE049-180G" +}; + +unsigned int bms_psu_board_type; +unsigned int bms_psu_status[BMS_PSU_NUM]; +unsigned int bms_psu_type[BMS_PSU_NUM]; +unsigned int bms_psu_driver_init[BMS_PSU_NUM] = {0}; +unsigned int bms_psu_init_done = 0; +unsigned int bms_psu_intr_cache[BMS_PSU_NUM * BMS_PSU_INTR_NUM] = {0}; +pthread_mutex_t bms_psu_st_cache_lock; +pthread_mutex_t bms_psu_intr_cache_lock; + +/* +* FEATURE: +* bms_psu_serv_power_status_get +* PURPOSE: +* psu service psu status get from file system +* PARAMETERS: +* psu_number (IN) psu number +* value (OUT) pointer of get value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_psu_serv_power_status_get(unsigned int *value) +{ + return bms_sys_serv_hex_read(bms_psu_serv_data[0].pg_ps_reg, value); +} + +/* +* FEATURE: +* bms_psu_serv_type_get +* PURPOSE: +* psu service psu type get from file system +* PARAMETERS: +* psu_number (IN) psu number +* value (OUT) pointer of get value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_psu_serv_type_get(unsigned int psu_number, + unsigned int *value) +{ + int ret_code, i, type_num; + char buf[32] = {0}; + + /* size of type number */ + type_num = sizeof(bms_psu_mfr_model) / sizeof(bms_psu_mfr_model[0]); + + if((ret_code = bms_sys_serv_char_read(bms_psu_serv_data[psu_number].model_reg, buf)) < 0) + return ret_code; + + for(i = 0; i < type_num; i++) { + if(strncmp(bms_psu_mfr_model[i], buf, strlen(bms_psu_mfr_model[i])) == 0) { + break; + } + } + + if(i == type_num) { + syslog(LOG_WARNING|LOG_USER,"[%s] can't find type data", __FUNCTION__); + return -EINVAL; + }else{ + *value = i; + } + + return ret_code; +} + +/* +* FEATURE: +* bms_psu_serv_board_type_get +* PURPOSE: +* psu service board get from file system +* PARAMETERS: +* value (OUT) pointer of get value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_psu_serv_board_type_get(unsigned int *value) +{ + return bms_sys_serv_hex_read(BMS_SYSFS_BOARD_TYPE, value); +} + +/* +* FEATURE: +* bms_psu_serv_cache_update +* PURPOSE: +* update data to cache +* PARAMETERS: +* psu_number (IN) psu number +* psu_cause (IN) cause of psu event +* psu_type (IN) psu type +* RETURNS: +*/ +static void +bms_psu_serv_cache_update(unsigned int psu_number, + unsigned int psu_cause, + unsigned int psu_type) +{ + pthread_mutex_lock(&bms_psu_st_cache_lock); + bms_psu_status[psu_number] = psu_cause; + + if((int)psu_type != (-1)) { + bms_psu_type[psu_number] = psu_type; + } + pthread_mutex_unlock(&bms_psu_st_cache_lock); +} + +/* +* FEATURE: +* bms_psu_serv_cache_init +* PURPOSE: +* initial psu status and psu type +* PARAMETERS: +* +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static void +bms_psu_serv_cache_init(void) +{ + int i; + + for(i = 0; i < BMS_PSU_NUM; i++) { + bms_psu_serv_cache_update(i, BMS_PSU_STATUS_ABSENT, bms_psu_board_type); + } + memset(bms_psu_intr_cache, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM); +} + + +/* +* FEATURE: +* bms_psu_serv_power_led_set +* PURPOSE: +* psu service power led set to file system in CPLD +* PARAMETERS: +* value (IN) setting value +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_psu_serv_power_led_set(unsigned int value) +{ + return bms_sys_serv_write(BMS_SYSFS_POWER_LED, value); +} + + +/* +* FEATURE: +* bms_psu_serv_mutex_init +* PURPOSE: +* initial mutex +* PARAMETERS: +* +* RETURNS: +* init success, this function shall return zero. +* otherwise, an error number shall be returned to indicate the error. +*/ +static int +bms_psu_serv_mutex_init(void) +{ + int ret_code; + + if((ret_code = pthread_mutex_init(&bms_psu_st_cache_lock, NULL)) != 0) { + return -ret_code; + } + + if((ret_code = pthread_mutex_init(&bms_psu_intr_cache_lock, NULL)) != 0) { + return -ret_code; + } + + return ret_code; +} + +/* +* FEATURE: +* bms_psu_serv_file_path_rename +* PURPOSE: +* psu hwmon path rename +* PARAMETERS: +* +* RETURNS: +* init success, this function shall return zero. +* otherwise, an error number shall be returned to indicate the error. +*/ +int +bms_psu_serv_file_path_rename(unsigned int psu_number) +{ + int ret_code = 0; + unsigned int i; + + for(i = psu_number * BMS_PSU_INTR_NUM; i < ((BMS_PSU_INTR_NUM * psu_number) + BMS_PSU_INTR_NUM); i++){ + if(bms_psu_driver_init[i / BMS_PSU_INTR_NUM] == BMS_PSU_DRIVER_UNINIT) + continue; + if((ret_code = bms_sys_serv_hwmon_path_find(bms_psu_serv_data[i / BMS_PSU_INTR_NUM].hwmon_path, + bms_psu_serv_data[i / BMS_PSU_INTR_NUM].intr_src[i % BMS_PSU_INTR_NUM])) < 0){ + return -ret_code; + } + } + + if(bms_psu_driver_init[psu_number] == BMS_PSU_DRIVER_INIT_DONE){ + if((ret_code = bms_sys_serv_hwmon_path_find(bms_psu_serv_data[psu_number].hwmon_path, + bms_psu_serv_data[psu_number].model_reg)) < 0){ + return -ret_code; + } + } + return ret_code; +} + +/* +* FEATURE: +* bms_psu_serv_driver_plugin +* PURPOSE: +* plug in driver to create sysfs +* PARAMETERS: +* +* RETURNS: +* init success, this function shall return zero. +* otherwise, an error number shall be returned to indicate the error. +*/ +int +bms_psu_serv_driver_plugin(int psu_number) +{ + char buf[64]; + int buf_size = sizeof(buf); + int ret_code = 0; + + if(bms_sys_serv_file_exist(bms_psu_serv_data[psu_number].hwmon_path) == 1){ + /* hwmon path not exist*/ + + /* echo driver to create sysfs */ + snprintf(buf, buf_size, "%s %d",bms_psu_serv_data[0].driver_name, bms_psu_serv_data[psu_number].address);// + if((ret_code = bms_sys_serv_buf_write(bms_psu_serv_data[0].i2c_path, buf, buf_size)) < 0) + return ret_code; + } + bms_psu_driver_init[psu_number] = BMS_PSU_DRIVER_INIT_DONE; + + if ((ret_code = bms_psu_serv_file_path_rename(psu_number)) < 0) { + return ret_code; + } + + return ret_code; +} + +/* +* FEATURE: +* bms_psu_serv_driver_init +* PURPOSE: +* Initial sysfs and rename path of sysfs +* PARAMETERS: +* +* RETURNS: +* init success, this function shall return zero. +* otherwise, an error number shall be returned to indicate the error. +*/ +static int +bms_psu_serv_driver_init(void) +{ + int ret_code = 0; + unsigned int psu_ps_pg = 0, i; + + if((ret_code = bms_sys_serv_hex_read(bms_psu_serv_data[0].pg_ps_reg, &psu_ps_pg)) < 0) + return ret_code; + + for(i = 0; i < BMS_PSU_NUM ; i++){ + if((psu_ps_pg & (1 << bms_psu_serv_data[i].pg_offset)) == BMS_PSU_PG_GOOD){ + if((ret_code = bms_psu_serv_driver_plugin(i)) < 0) + return ret_code; + } + } + return ret_code; +} + +/* +* FEATURE: +* bms_psu_serv_init +* PURPOSE: +* initial psu servd +* PARAMETERS: +* mq_name (IN) message queue name +* mq_desc (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_psu_serv_init(char *mq_name, + mqd_t *mq_desc) +{ + int ret_code = 0; + + /* 1 init pmbus to create sysfs */ + if((ret_code = bms_psu_serv_driver_init()) < 0) { + return ret_code; + } + + /* 2. record board type from CPLD */ + if((ret_code = bms_psu_serv_board_type_get(&bms_psu_board_type)) < 0) { + return ret_code; + } + + /* 3. initial cache to maintain psu statue and type. */ + bms_psu_serv_cache_init(); + + /* 4. open message queue */ + if ((ret_code = bms_sys_serv_msq_open(mq_name, mq_desc)) < 0) { + return ret_code; + } + + /* 5. initial Mutexes */ + if ((ret_code = bms_psu_serv_mutex_init() < 0)) { + return ret_code; + } + + /* 6. set initial flag */ + bms_psu_init_done = 1; + + return ret_code; +} + +/* +* FEATURE: +* bms_psu_serv_cache_get +* PURPOSE: +* psu service cache get +* PARAMETERS: +* psu_number (IN) psu number +* psu_status (OUT) pointer of psu status +* psu_type (OUT) pointer of psu type +* RETURNS: +*/ +void +bms_psu_serv_cache_get(unsigned int psu_number, + unsigned int* psu_status, + unsigned int* psu_type) +{ + pthread_mutex_lock(&bms_psu_st_cache_lock); + *psu_status = bms_psu_status[psu_number]; + *psu_type = bms_psu_type[psu_number]; + pthread_mutex_unlock(&bms_psu_st_cache_lock); +} + +/* +* FEATURE: +* bms_psu_serv_intr_cache_get +* PURPOSE: +* psu service interrupt cache get +* PARAMETERS: +* intr_status (OUT) pointer of psu type +* RETURNS: +*/ +void +bms_psu_serv_intr_cache_get(unsigned int* intr_status) +{ + pthread_mutex_lock(&bms_psu_intr_cache_lock); + memcpy(intr_status, bms_psu_intr_cache, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM); + pthread_mutex_unlock(&bms_psu_intr_cache_lock); +} + + +/* +* FEATURE: +* bms_psu_serv_intr_cache_update +* PURPOSE: +* psu service interrupt cache update +* PARAMETERS: +* psu_number (IN) psu number +* psu_cause (IN) psu update index +* value (IN) update value +* RETURNS: +*/ +void +bms_psu_serv_intr_cache_update(unsigned int psu_number, + unsigned int psu_cause, + unsigned int value) +{ + pthread_mutex_lock(&bms_psu_intr_cache_lock); + bms_psu_intr_cache[(psu_number * BMS_PSU_INTR_NUM) + psu_cause] = value; + pthread_mutex_unlock(&bms_psu_intr_cache_lock); +} + +/* +* FEATURE: +* bms_psu_serv_intr_cache_clear +* PURPOSE: +* psu specific interrupt cache clear +* PARAMETERS: +* psu_number (IN) psu number +* RETURNS: +*/ +void +bms_psu_serv_intr_cache_clear(unsigned int psu_number) +{ + int i = 0; + + pthread_mutex_lock(&bms_psu_intr_cache_lock); + + for(i = 0; i < BMS_PSU_INTR_NUM; i++) { + bms_psu_intr_cache[(psu_number * BMS_PSU_INTR_NUM) + i] = 0; + } + + pthread_mutex_unlock(&bms_psu_intr_cache_lock); +} + + +/* +* FEATURE: +* bms_psu_serv_power_led_by_cache_get +* PURPOSE: +* get power led status from cache +* PARAMETERS: +* +* RETURNS: +* BMS_PSU_POWER_LED_OFF or BMS_PSU_POWER_LED_AMBER or BMS_PSU_POWER_LED_GREEN, +*/ +static int +bms_psu_serv_power_led_by_cache_get(void) +{ + int i = 0; + unsigned int cache_status[BMS_PSU_NUM], cache_type[BMS_PSU_NUM]; + + /* read value from cache */ + for(i = 0; i < BMS_PSU_NUM; i++) { + bms_psu_serv_cache_get(i, &cache_status[i], &cache_type[i]); + } + + for(i = 0; i < BMS_PSU_NUM; i++) { + if((cache_status[i] == BMS_PSU_STATUS_NORMAL) || + (cache_status[i] == BMS_PSU_STATUS_FAULT)) { + break; + } + } + + if(i == BMS_PSU_NUM) { + return BMS_PSU_POWER_LED_OFF; + } + + for(i = 0; i < BMS_PSU_NUM; i++) { + if((cache_status[i] == BMS_PSU_STATUS_FAULT) || + (cache_type[i] != bms_psu_board_type)) { + return BMS_PSU_POWER_LED_AMBER; + } + } + + return BMS_PSU_POWER_LED_GREEN; +} + + +/* +* FEATURE: +* bms_psu_serv_cache_power_led_update +* PURPOSE: +* update psu cache and power led +* PARAMETERS: +* psu_number (IN) psu number +* psu_cause (IN) cause of psu event +* psu_type (IN) psu type +* RETURNS: +* success, compare the same return zero. +* for other cases, negative errno is returned. +*/ +static int +bms_psu_serv_cache_power_led_update(unsigned int psu_number, + unsigned int psu_cause, + unsigned int psu_type) +{ + int ret_code = 0; + unsigned int pre_status, cur_status; + + pre_status = bms_psu_serv_power_led_by_cache_get(); + + bms_psu_serv_cache_update(psu_number, psu_cause, psu_type); + + cur_status = bms_psu_serv_power_led_by_cache_get(); + + if(cur_status == pre_status) + return ret_code; + + if(cur_status == BMS_PSU_POWER_LED_GREEN) { + if((ret_code = bms_psu_serv_power_led_set(BMS_PSU_POWER_LED_GREEN)) < 0) { + return ret_code; + } + }else + if(cur_status == BMS_PSU_POWER_LED_AMBER) { + if((ret_code = bms_psu_serv_power_led_set(BMS_PSU_POWER_LED_AMBER)) < 0) { + return ret_code; + } + }else{ + syslog(LOG_WARNING|LOG_USER,"[%s] Invaild vailed in cache\n", __FUNCTION__); + return -EINVAL; + } + + return ret_code; +} + + +/* +* FEATURE: +* bms_psu_serv_find_serv_data_index +* PURPOSE: +* find index of psu of serv_data +* PARAMETERS: +* psu_number (IN) psu number +* RETURNS: +* success, this function returns value. +* for other cases, negative errno is returned. +*/ +static int +bms_psu_serv_find_serv_data_index(unsigned int psu_number) +{ + int i; + + for(i = 0; i < bms_sys_serv_data_num; i++) { + if(strcmp(bms_sys_serv_data[i].name, bms_psu_serv_data[psu_number].name) == 0) + return i; + } + + syslog(LOG_WARNING|LOG_USER,"Can't find %s item index in bms_sys_serv_data\n", bms_psu_serv_data[psu_number].name); + return -EINVAL; +} + + +/* +* FEATURE: +* bms_psu_serv_intr_mask_set +* PURPOSE: +* set psu intr mask +* PARAMETERS: +* psu_number (IN) psu number +* value (IN) mask of setting value +* RETURNS: +* success, this function returns zero. +* for other cases, negative errno is returned. +*/ +int +bms_psu_serv_intr_mask_set(unsigned int psu_number, + unsigned int value) +{ + int ret_code = 0, index; + + if((ret_code = bms_psu_serv_find_serv_data_index(psu_number)) < 0) + return ret_code; + + index = ret_code; + if((ret_code = bms_sys_serv_write(bms_sys_serv_data[index].intr_msk, value)) < 0) { + return ret_code; + } + + return ret_code; +} + + +/* +* FEATURE: +* bms_psu_serv_intr_get +* PURPOSE: +* set psu intr mask +* PARAMETERS: +* psu_number (IN) psu number +* value (OUT) mask of setting value +* RETURNS: +* success, this function returns zero. +* for other cases, negative errno is returned. +*/ +int +bms_psu_serv_intr_get(unsigned int psu_number, + unsigned int *value) +{ + int ret_code = 0, index; + + if((ret_code = bms_psu_serv_find_serv_data_index(psu_number)) < 0) + return ret_code; + + index = ret_code; + + if((ret_code = bms_sys_serv_hex_read(bms_sys_serv_data[index].intr_src, value)) < 0) { + return ret_code; + } + + return ret_code; +} + + +/* +* FEATURE: +* bms_psu_serv_psu_fault_datect +* PURPOSE: +* detect psu fault cause +* PARAMETERS: +* psu_number (IN) psu number +* psu_status (OUT) pointer of psu status +*/ +void +bms_psu_serv_psu_fault_datect(unsigned int psu_number, + unsigned int *psu_status) +{ + unsigned int intr_table[BMS_PSU_NUM * BMS_PSU_INTR_NUM], i; + + memset(intr_table, 0, sizeof(unsigned int) * BMS_PSU_NUM * BMS_PSU_INTR_NUM); + + bms_psu_serv_intr_cache_get(intr_table); + + for(i = 0; i < BMS_PSU_INTR_NUM; i++) { + if(intr_table[i + (psu_number * BMS_PSU_INTR_NUM)] == BMS_PSU_SOURCE_INTR_ASSERTED){ + *psu_status = BMS_PSU_STATUS_FAULT; + return; + } + } + + *psu_status = BMS_PSU_STATUS_NORMAL; +} + +/* +* FEATURE: +* bms_psu_serv_cause_log +* PURPOSE: +* log of psu cause +* PARAMETERS: +* psu_number (IN) psu number +* psu_cause (IN) cause of psu status +* RETURNS: +*/ +static void +bms_psu_serv_cause_log(unsigned int psu_number, + unsigned int psu_cause) +{ + unsigned int cache_type, cache_status; + + bms_psu_serv_cache_get(psu_number, &cache_status, &cache_type); + + if(psu_cause == BMS_PSU_STATUS_PRESENT) { + if((cache_status == BMS_PSU_STATUS_NORMAL) || + (cache_status == BMS_PSU_STATUS_FAULT)) { + syslog(LOG_DEBUG|LOG_USER,"The psu %u was no power.", psu_number + 1); + }else + if(cache_status == BMS_PSU_STATUS_ABSENT) { + syslog(LOG_DEBUG|LOG_USER,"The psu %u was present, but no power.", psu_number + 1); + }else{ + syslog(LOG_WARNING|LOG_USER,"LOG error, unknown psu_cause in psu %u\n", psu_number + 1); + } + }else + if(psu_cause == BMS_PSU_STATUS_NORMAL) { + if(cache_status == BMS_PSU_STATUS_ABSENT) { + syslog(LOG_DEBUG|LOG_USER,"The psu %u was present, and work normal.", psu_number + 1); + }else + if(cache_status == BMS_PSU_STATUS_PRESENT) { + syslog(LOG_DEBUG|LOG_USER,"The psu %u has power.", psu_number + 1); + }else + if(cache_status == BMS_PSU_STATUS_FAULT) { + /* Don't show any log */ + }else{ + syslog(LOG_WARNING|LOG_USER,"LOG error, unknown psu_cause in psu %u\n", psu_number + 1); + } + }else + if(psu_cause == BMS_PSU_STATUS_FAULT) { + syslog(LOG_WARNING|LOG_USER,"The psu %u was fault\n", psu_number + 1); + }else + if(psu_cause == BMS_PSU_STATUS_ABSENT) { + syslog(LOG_DEBUG|LOG_USER,"The psu %u was non present\n", psu_number + 1); + }else{ + syslog(LOG_WARNING|LOG_USER,"LOG error, unknown psu_cause in psu %u\n", psu_number + 1); + } +} + + +/* +* FEATURE: +* bms_psu_serv_intr_log +* PURPOSE: +* log of psu intrrupt +* PARAMETERS: +* psu_number (IN) psu number +* psu_cause (IN) psu interrupt cause +* RETURNS: +*/ +void +bms_psu_serv_intr_log(unsigned int psu_number, + unsigned int psu_cause) +{ + switch (psu_cause) { + case BMS_PSU_VOUT_OV_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by over output voltage.\n", psu_number + 1); + break; + + case BMS_PSU_VOUT_UV_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by under output voltage.\n", psu_number + 1); + break; + + case BMS_PSU_IOUT_OC_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by over currents.\n", psu_number + 1); + break; + + case BMS_PSU_IOUT_OC_WARNING: + syslog(LOG_WARNING|LOG_USER,"The psu %u is warning by over currents.\n", psu_number + 1); + break; + + case BMS_PSU_OT_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by over temperature.\n", psu_number + 1); + break; + + case BMS_PSU_OT_WARNING: + syslog(LOG_WARNING|LOG_USER,"The psu %u is warning by over temperature.\n", psu_number + 1); + break; + + case BMS_PSU_VIN_UV_WARNING: + syslog(LOG_WARNING|LOG_USER,"The psu %u is warning by under input voltage.\n", psu_number + 1); + break; + + case BMS_PSU_VIN_UV_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u is fault by under input voltage.\n", psu_number + 1); + break; + + case BMS_PSU_FAN1_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u is fault.\n", psu_number + 1); + break; + + case BMS_PSU_FAN1_WARNING: + syslog(LOG_WARNING|LOG_USER,"The psu %u is warning.\n", psu_number + 1); + break; + + default: + syslog(LOG_WARNING|LOG_USER,"The psu %u receive unknown item %d.\n", psu_number + 1, psu_cause); + break; + } +} + +/* +* FEATURE: +* bms_psu_serv_intr_recovery_log +* PURPOSE: +* log of psu recovery intrrupt +* PARAMETERS: +* psu_number (IN) psu number +* psu_cause (IN) psu interrupt cause +* RETURNS: +*/ +void +bms_psu_serv_intr_recovery_log(unsigned int psu_number, + unsigned int psu_cause) +{ + switch (psu_cause) { + case BMS_PSU_VOUT_OV_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u over output voltage is recovery.\n", psu_number + 1); + break; + + case BMS_PSU_VOUT_UV_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u under output voltage is recovery.\n", psu_number + 1); + break; + + case BMS_PSU_IOUT_OC_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u over currents fault is recovery.\n", psu_number + 1); + break; + + case BMS_PSU_IOUT_OC_WARNING: + syslog(LOG_WARNING|LOG_USER,"The psu %u over currents warning is recovery.\n", psu_number + 1); + break; + + case BMS_PSU_OT_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u over temperature fault is recovery.\n", psu_number + 1); + break; + + case BMS_PSU_OT_WARNING: + syslog(LOG_WARNING|LOG_USER,"The psu %u over temperature warning is recovery.\n", psu_number + 1); + break; + + case BMS_PSU_VIN_UV_WARNING: + syslog(LOG_WARNING|LOG_USER,"The psu %u under input voltage warning is recovery.\n", psu_number + 1); + break; + + case BMS_PSU_VIN_UV_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u under input voltage fault is recovery .\n", psu_number + 1); + break; + + case BMS_PSU_FAN1_FAULT: + syslog(LOG_WARNING|LOG_USER,"The psu %u fan fault is recovery.\n", psu_number + 1); + break; + + case BMS_PSU_FAN1_WARNING: + syslog(LOG_WARNING|LOG_USER,"The psu %u fan warning is recovery.\n", psu_number + 1); + break; + + default: + syslog(LOG_WARNING|LOG_USER,"The psu %u receive unknown item %d recovery.\n", psu_number + 1, psu_cause); + break; + } + +} + +/* +* FEATURE: +* bms_psu_serv_board_type_comp +* PURPOSE: +* compare psu type is the same with board type +* PARAMETERS: +* psu_type (IN) psu type +* RETURNS: +*/ +static int +bms_psu_serv_board_type_comp(unsigned int psu_type) +{ + + if(bms_psu_board_type == psu_type) { + return 0; + } + + return -EINVAL; +} + +/* +* FEATURE: +* bms_psu_serv_type_log +* PURPOSE: +* log of psu the is the same with board type +* PARAMETERS: +* psu_number (IN) psu number +* psu_type (IN) psu type +* RETURNS: +*/ +static void +bms_psu_serv_type_log(unsigned int psu_number, + unsigned int psu_type) +{ + if((bms_psu_serv_board_type_comp(psu_type) < 0)) + syslog(LOG_WARNING|LOG_USER,"The psu %u type was wrong\n", psu_number + 1); +} + + +/* +* FEATURE: +* bms_psu_servd +* PURPOSE: +* service to handle message queue event of cpu temperature +* PARAMETERS: +* args (IN) message queue name +* RETURNS: +* open success, this function will wait for message queue. +* for other cases, will exit this program. +*/ +void* +bms_psu_servd(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + bms_sys_serv_mq_data_t msg; + int ret_code; + unsigned int psu_number, psu_type, psu_status, pg_status; + unsigned int psu_pg; + + /* Open message queue */ + if (bms_psu_serv_init(mq_name, &mq_desc) < 0) { + goto quit; + } + + while (1) { + /* Wait for message queue */ + if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code)); + goto quit; + } + + switch (msg.serv_type) { + case SERV_TYPE_RX_INTR: + psu_number = msg.number; + + bms_psu_serv_intr_cache_update(psu_number, msg.cause, BMS_PSU_SOURCE_INTR_ASSERTED); + + bms_psu_serv_intr_log(psu_number, msg.cause); + + bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_FAULT, -1); + break; + + case SERV_TYPE_PSU_NORMAL: + psu_number = msg.number; +PSU_NORMAL: + + if(bms_psu_driver_init[psu_number] == BMS_PSU_DRIVER_UNINIT){ + if ((ret_code = bms_psu_serv_driver_plugin(psu_number)) < 0) { + break; + } + } + + if((ret_code = bms_psu_serv_type_get(psu_number, &psu_type)) < 0) { + break; + } + + bms_psu_serv_psu_fault_datect(psu_number, &psu_status); + + if(psu_status == BMS_PSU_STATUS_FAULT) { + bms_psu_serv_cache_update(psu_number, BMS_PSU_STATUS_NORMAL, psu_type); + bms_psu_serv_type_log(psu_number, psu_type); + }else{ + bms_psu_serv_cause_log(psu_number, BMS_PSU_STATUS_NORMAL); + bms_psu_serv_type_log(psu_number, psu_type); + bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_NORMAL, psu_type); + } + + break; + + case SERV_TYPE_PSU_PRESENT: + psu_number = msg.number; + + if ((ret_code = bms_psu_serv_power_status_get(&pg_status)) < 0) { + break; + } + + psu_pg = ((pg_status & (1 << (bms_psu_serv_data[psu_number].pg_offset))) > 0) ? BMS_PSU_PG_FAILED : BMS_PSU_PG_GOOD; + + if(psu_pg == BMS_PSU_PG_GOOD) { + goto PSU_NORMAL; + }else{ + bms_psu_serv_cause_log(psu_number, BMS_PSU_STATUS_PRESENT); + + bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_PRESENT, -1); + } + break; + + case SERV_TYPE_PSU_ABSENT: + psu_number = msg.number; + + bms_psu_serv_intr_cache_clear(psu_number); + + bms_psu_serv_cause_log(psu_number, BMS_PSU_STATUS_ABSENT); + bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_ABSENT, -1); + + break; + + case SERV_TYPE_PSU_INTR_RECOVERY: + psu_number = msg.number; + bms_psu_serv_intr_cache_update(psu_number, msg.cause, BMS_PSU_SOURCE_INTR_DEASSERTED); + + bms_psu_serv_intr_recovery_log(psu_number, msg.cause); + + bms_psu_serv_psu_fault_datect(psu_number, &psu_status); + + if(psu_status == BMS_PSU_STATUS_FAULT) { + bms_psu_serv_cache_power_led_update(psu_number, BMS_PSU_STATUS_FAULT, -1); + } + else if(psu_status == BMS_PSU_STATUS_NORMAL) { + goto PSU_NORMAL; + }else{ + syslog(LOG_WARNING|LOG_USER,"Receive psu %d INTR_RECOVERY message, but can't find next status\n", psu_number); + } + + break; + + default: + syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name); + break; + } + } + +quit: + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.h new file mode 100644 index 000000000000..ee60f17aab0c --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_psu_servd.h @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __BMS_PSU_SERVD_H__ +#define __BMS_PSU_SERVD_H__ +#include "bms_irq_sysd.h" + +#define PSU_FILE_PATH_LEN 64 + +enum { + BMS_PSU_AC_NORMAL_FAN = 0, + BMS_PSU_AC_REVERSE_FAN, + BMS_PSU_DC_NORMAL_FAN, + BMS_PSU_DC_REVERSE_FAN, +}; + +enum { + BMS_PSU_STATUS_NORMAL = 0, + BMS_PSU_STATUS_PRESENT, + BMS_PSU_STATUS_ABSENT, + BMS_PSU_STATUS_FAULT, +}; + +enum { + BMS_PSU_POWER_LED_OFF = 0, + BMS_PSU_POWER_LED_AMBER, + BMS_PSU_POWER_LED_GREEN, +}; + +enum { + BMS_PSU_INTR_MASKED = 0, + BMS_PSU_INTR_UNMASKED, +}; + +enum { + BMS_PSU_INTR_ASSERTED = 0, + BMS_PSU_INTR_DEASSERTED, +}; + +enum { + BMS_PSU_SOURCE_INTR_DEASSERTED = 0, + BMS_PSU_SOURCE_INTR_ASSERTED, +}; + +enum { + BMS_PSU_PG_GOOD = 0, + BMS_PSU_PG_FAILED, +}; + +enum { + BMS_PSU_PS_PRESENT = 0, + BMS_PSU_PS_NONPRESENT, +}; + +enum { + BMS_PSU_DRIVER_UNINIT = 0, + BMS_PSU_DRIVER_INIT_DONE, +}; + +enum { + BMS_PSU_VOUT_OV_FAULT = 0, + BMS_PSU_VOUT_UV_FAULT, + BMS_PSU_IOUT_OC_FAULT, + BMS_PSU_IOUT_OC_WARNING, + BMS_PSU_OT_FAULT, + BMS_PSU_OT_WARNING, + BMS_PSU_VIN_UV_WARNING, + BMS_PSU_VIN_UV_FAULT, + BMS_PSU_FAN1_FAULT, + BMS_PSU_FAN1_WARNING, +/*----------------------------------*/ + BMS_PSU_INTR_NUM, +}; + +typedef struct { + char* name; + int pg_offset; + int ps_offset; + int address; + char* pg_ps_reg; + char model_reg[PSU_FILE_PATH_LEN]; + char* hwmon_path; + char intr_src[BMS_PSU_INTR_NUM][PSU_FILE_PATH_LEN]; + char* i2c_path; + char* driver_name; +}bms_psu_serv_data_t; + + +#define BMS_PSU_NUM 2 +#define BMS_SYSFS_POWER_LED "/sys/bus/i2c/devices/1-0032/power_led" + +/* PSU message queue range define 200~299 */ +#define SERV_TYPE_PSU_PRESENT 200 +#define SERV_TYPE_PSU_ABSENT 201 +#define SERV_TYPE_PSU_NORMAL 202 +#define SERV_TYPE_PSU_INTR_RECOVERY 203 + +extern bms_sys_serv_data_t bms_sys_serv_data[]; +extern int bms_sys_serv_data_num; +extern unsigned int bms_psu_init_done; +extern int bms_psu_serv_power_status_get(unsigned int *value); +extern void bms_psu_serv_cache_get(unsigned int psu_number, unsigned int* psu_status, unsigned int* psu_type); +extern bms_psu_serv_data_t bms_psu_serv_data[]; +extern void bms_psu_serv_intr_cache_get(unsigned int* intr_status); + +#endif /* __BMS_PSU_SERVD_H__ */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.c new file mode 100644 index 000000000000..78cf23cffb93 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.c @@ -0,0 +1,329 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* +* FEATURE: +* bms_sys_serv_msq_open +* PURPOSE: +* open POSIX message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +int +bms_sys_serv_msq_open(const char *qname, + mqd_t *mqd) +{ + int flags = (O_RDONLY), ret_code = 0; + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + + + +/* + * FEATURE: + * bms_sys_serv_hex_read + * PURPOSE: + * hex read from file system + * PARAMETERS: + * filename (IN) file path in the sysfs + * value (OUT) pointer of current value buffer + * RETURNS: + * open success, this function returns zero. + * for other cases, negative errno is returned. + */ +int +bms_sys_serv_hex_read(char *filename, + unsigned int *value) +{ + char buf[32] = {0}; + int fd, ret_code = 0, buf_size = sizeof(buf); + ssize_t count; + + /* Open xcvr pin file */ + if ((fd = open(filename, O_RDONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Read pin file */ + if ((count = read(fd, buf, buf_size)) != (-1)) { + *value = strtol(buf, NULL, 16); + } + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to read %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} + +/* + * FEATURE: + * bms_sys_serv_dec_read + * PURPOSE: + * dec read from file system + * PARAMETERS: + * filename (IN) file path in the sysfs + * value (OUT) pointer of current value buffer + * RETURNS: + * open success, this function returns zero. + * for other cases, negative errno is returned. + */ +int +bms_sys_serv_dec_read(char *filename, + unsigned int *value) +{ + char buf[32]; + int fd, ret_code = 0, buf_size = sizeof(buf); + ssize_t count; + + /* Open file */ + if ((fd = open(filename, O_RDONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Read pin file */ + if ((count = read(fd, buf, buf_size)) != (-1)) { + *value = strtol(buf, NULL, 10); + } + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to read %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} + +/* + * FEATURE: + * bms_sys_serv_char_read + * PURPOSE: + * char read from file system + * PARAMETERS: + * filename (IN) file path in the sysfs + * value (OUT) pointer of current value buffer + * RETURNS: + * open success, this function returns zero. + * for other cases, negative errno is returned. + */ +int +bms_sys_serv_char_read(char *filename, + char *value) +{ + char buf[32]; + int fd, ret_code = 0, buf_size = sizeof(buf); + ssize_t count; + + /* Open file */ + if ((fd = open(filename, O_RDONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Read pin file */ + if ((count = read(fd, buf, buf_size)) != (-1)) { + /* the last character was \n*/ + memcpy(value, buf, count); + } + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to read %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} + + +/* + * FEATURE: + * bms_sys_serv_write + * PURPOSE: + * byte data write to file system + * PARAMETERS: + * filename (IN) file path in the sysfs + * value (IN) new register value + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_sys_serv_write(char *filename, + unsigned int value) +{ + char buf[4]; + int fd, ret_code = 0, buf_size = sizeof(buf); + ssize_t count; + + /* Open file */ + if ((fd = open(filename, O_WRONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Write file */ + snprintf(buf, buf_size, "%d", value); + if ((count = write(fd, buf, buf_size)) != (-1)) {;} + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} + +/* + * FEATURE: + * bms_sys_serv_buf_write + * PURPOSE: + * buf data write to file system + * PARAMETERS: + * filename (IN) file path in the sysfs + * buf (IN) buf data + * buf_size (IN) buf size + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_sys_serv_buf_write(char *filename, + char *buf, + int buf_size) +{ + int fd, ret_code = 0; + ssize_t count; + + /* Open file */ + if ((fd = open(filename, O_WRONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Write file */ + if ((count = write(fd, buf, buf_size)) != (-1)) {;} + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} + +/* + * FEATURE: + * bms_sys_serv_hwmon_path_find + * PURPOSE: + * find hwmon path for when insert different order + * PARAMETERS: + * filename (IN) file path in the sysfs + * value (IN) new register value + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_sys_serv_hwmon_path_find(char *filepath, + char *filename) +{ + struct dirent **namelist; + int ret_code = 0; + char name[32]; + + memcpy(name, filename, strlen(filename)+1); + + ret_code = scandir(filepath , &namelist, NULL, alphasort); + + if (ret_code < 0){ + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to scandir %s (%s)\n", filepath, strerror(ret_code)); + return -ret_code; + } + + /* if counter is 2, that mean the folder is empty that include "." and ".." */ + if(ret_code <= 2){ + syslog(LOG_WARNING|LOG_USER,"Failed to find folder hwmon (%s)\n", strerror(ret_code)); + return -ENXIO; + } + + sprintf(filename, "%s/%s/%s", filepath, namelist[--ret_code]->d_name, name); + free(namelist); + return ret_code; +} + +/* + * FEATURE: + * bms_sys_serv_file_exist + * PURPOSE: + * find file name exist + * PARAMETERS: + * filename (IN) file name + * RETURNS: + * file exist, return zero + * for other cases, return 1 + */ +int +bms_sys_serv_file_exist(char *filename) +{ + if( access( filename, F_OK ) != -1 ) { + // file exists + return 0; + } + // file doesn't exist + return 1; +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.h new file mode 100644 index 000000000000..b0a8539357b8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_serv_common.h @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __BMS_SYS_SERV_COMMON_H__ +#define __BMS_SYS_SERV_COMMON_H__ + +#define BMS_SYSFS_BOARD_TYPE "/sys/bus/i2c/devices/1-0032/brd_type" + +extern int bms_sys_serv_msq_open(const char *qname, mqd_t *mqd); +extern int bms_sys_serv_hex_read(char *filename, unsigned int *value); +extern int bms_sys_serv_write(char *filename, unsigned int value); +extern int bms_sys_serv_dec_read(char *filename, unsigned int *value); +extern int bms_sys_serv_char_read(char *filename, char *value); +extern int bms_sys_serv_hwmon_path_find(char *filepath, char *filename); +extern int bms_sys_serv_buf_write(char *filename, char *buf, int buf_size); +extern int bms_sys_serv_file_exist(char *filename); + + +#endif /* __BMS_SYS_SERV_COMMON_H__ */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_temp_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_temp_servd.c new file mode 100644 index 000000000000..1930019c2cce --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_sys_temp_servd.c @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_irq_sysd.h" + +#include + +/* +* FEATURE: +* bms_sys_temp_msq_open +* PURPOSE: +* open POSIX message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_sys_temp_msq_open(const char *qname, + mqd_t *mqd) +{ + int flags = (O_RDONLY), ret_code = 0; + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + +/* +* FEATURE: +* bms_sys_temp_servd +* PURPOSE: +* service to handle message queue event of cpu temperature +* PARAMETERS: +* args (IN) message queue name +* RETURNS: +* open success, this function will wait for message queue. +* for other cases, will exit this program. +*/ +void* +bms_sys_temp_servd(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + bms_sys_serv_mq_data_t msg; + int ret_code; + + /* Open message queue */ + if (bms_sys_temp_msq_open(mq_name, &mq_desc) < 0) { + goto quit; + } + + while (1) { + /* Wait for message queue */ + if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code)); + goto quit; + } + + switch (msg.serv_type) { + case SERV_TYPE_RX_INTR: /* TEMP_ALERT_IRQ interrupt */ + syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name); + break; + + default: + syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name); + break; + } + } + +quit: + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_usb_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_usb_servd.c new file mode 100644 index 000000000000..737fd0df6612 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_usb_servd.c @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_irq_sysd.h" + +#include + +/* +* FEATURE: +* bms_usb_msq_open +* PURPOSE: +* open POSIX message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_usb_msq_open(const char *qname, + mqd_t *mqd) +{ + int flags = (O_RDONLY), ret_code = 0; + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + +/* +* FEATURE: +* bms_usb_servd +* PURPOSE: +* service to handle message queue event of cpu temperature +* PARAMETERS: +* args (IN) message queue name +* RETURNS: +* open success, this function will wait for message queue. +* for other cases, will exit this program. +*/ +void* +bms_usb_servd(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + bms_sys_serv_mq_data_t msg; + int ret_code; + + /* Open message queue */ + if (bms_usb_msq_open(mq_name, &mq_desc) < 0) { + goto quit; + } + + while (1) { + /* Wait for message queue */ + if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code)); + goto quit; + } + + switch (msg.serv_type) { + case SERV_TYPE_RX_INTR: /* USB_FAULT interrupt */ + syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name); + break; + + default: + syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name); + break; + } + } + +quit: + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_vrhot_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_vrhot_servd.c new file mode 100644 index 000000000000..97366f8fcd98 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/bms_vrhot_servd.c @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_irq_sysd.h" + +#include + +/* +* FEATURE: +* bms_vrhot_msq_open +* PURPOSE: +* open POSIX message queue +* PARAMETERS: +* qname (IN) message queue name +* mqd (OUT) pointer of message queue description +* RETURNS: +* open success, this function returns 0. +* for other cases, negative errno is returned. +*/ +static int +bms_vrhot_msq_open(const char *qname, + mqd_t *mqd) +{ + int flags = (O_RDONLY), ret_code = 0; + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + +/* +* FEATURE: +* bms_vrhot_servd +* PURPOSE: +* service to handle message queue event of cpu temperature +* PARAMETERS: +* args (IN) message queue name +* RETURNS: +* open success, this function will wait for message queue. +* for other cases, will exit this program. +*/ +void* +bms_vrhot_servd(void *args) +{ + char *mq_name = (char*)args; + mqd_t mq_desc; + bms_sys_serv_mq_data_t msg; + int ret_code; + + /* Open message queue */ + if (bms_vrhot_msq_open(mq_name, &mq_desc) < 0) { + goto quit; + } + + while (1) { + /* Wait for message queue */ + if (mq_receive(mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code)); + goto quit; + } + + switch (msg.serv_type) { + case SERV_TYPE_RX_INTR: /* VRHOT_IRQ interrupt */ + syslog(LOG_DEBUG|LOG_USER,"%s interrupt has handled\n", msg.serv_name); + break; + + default: + syslog(LOG_WARNING|LOG_USER,"Receive an unknown message %d from %s\n", msg.serv_type, mq_name); + break; + } + } + +quit: + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd deleted file mode 100755 index a1b4f177897c..000000000000 Binary files a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/sys-serv/sys-servd and /dev/null differ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf deleted file mode 100644 index 81f0b7b819bf..000000000000 --- a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/watchdog/watchdog.conf +++ /dev/null @@ -1,45 +0,0 @@ -#ping = 172.31.14.1 -#ping = 172.26.1.255 -#interface = eth0 -#file = /var/log/messages -#change = 1407 - -# Uncomment to enable test. Setting one of these values to '0' disables it. -# These values will hopefully never reboot your machine during normal use -# (if your machine is really hung, the loadavg will go much higher than 25) -#max-load-1 = 24 -#max-load-5 = 18 -#max-load-15 = 12 - -# Note that this is the number of pages! -# To get the real size, check how large the pagesize is on your machine. -#min-memory = 1 -#allocatable-memory = 1 - -#repair-binary = /usr/sbin/repair -#repair-timeout = -#test-binary = -#test-timeout = - -watchdog-device = /dev/watchdog - -# Defaults compiled into the binary -#temperature-device = -#max-temperature = 120 - -# Defaults compiled into the binary -#admin = root -#interval = 1 -#logtick = 1 -#log-dir = /var/log/watchdog - -# This greatly decreases the chance that watchdog won't be scheduled before -# your machine is really loaded -realtime = yes -priority = 99 - -# Check if rsyslogd is still running by enabling the following line -#pidfile = /var/run/rsyslogd.pid - -# timeout : 15 , 30 , 60 , 90 , 120 , 180 , 240 sec -watchdog-timeout = 120 diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/Makefile b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/Makefile new file mode 100644 index 000000000000..aa6c45795ab4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/Makefile @@ -0,0 +1,54 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +TARGETS := xcvr-servd +INC = $(wildcard *.h) +OBJ=$(subst .c,.o,$(wildcard *.c)) + +.PHONY: all +all: $(TARGETS) + +.PHONY: config +config: + +.PHONY: patch +patch: + +.PHONY: install +install: + mkdir -p $(INST_DIR)/xcvr-serv/ + cp $(TARGETS) $(INST_DIR)/xcvr-serv/ + +.PHONY: uninstall +uninstall: + rm -f $(addprefix $(INST_DIR)/xcvr-serv/,$(TARGETS)) + +.PHONY: clean +clean: + rm -rf $(OBJ) $(TARGETS) + +.PHONY: distclean +distclean: clean + +$(OBJ): $(INC) +%.o: %.c + $(CC) -c -o $@ $< -Wall -Wextra -Werror + +$(TARGETS): $(OBJ) + $(CC) $^ -lrt -pthread -o $@ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.c new file mode 100644 index 000000000000..fc505dd186f4 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.c @@ -0,0 +1,345 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "bms_xcvr_access.h" + +#define DISABLE_MASK 0xFF + +#define SFF_UPPER_PAGE_BYTE_START 128 +#define HIGH_POWER_CLASS_MASK 0x03 +#define LEGACY_POWER_CLASS_MASK 0xC0 + +#define XCVR_HW_INTR_MASK_START 100 +#define XCVR_CHANNEL_INTR_MASK_START 242 +#define XCVR_HW_INTR_MASK_PAGE 0 +#define XCVR_CHANNEL_INTR_MASK_PAGE 3 +#define XCVR_HW_INTR_MASK_BYTES 5 +#define XCVR_CHANNEL_INTR_MASK_BYTES 6 + +/* TODO might be 0x50 or 0x51 */ +unsigned char bms_xcvr_addr = 0x50; + +static int bms_xcvr_i2c_open(unsigned char bus, int *i2c_fd); +static int bms_xcvr_i2c_read(unsigned char bus, unsigned char addr, unsigned short offset, unsigned char *val); +static int bms_xcvr_i2c_write(unsigned char bus, unsigned char addr, unsigned short offset, unsigned char val); + +typedef struct { + unsigned short page; + unsigned short offset; + unsigned char shift; + unsigned char width; +} bms_xcvr_data_t; + +bms_xcvr_data_t bms_xcvr_data_list[] = { + /*page, offset, shift, width */ + { 0, 2, 0, 1 },/* "Data_Note_Ready" is bit0 of byte2 in the page0 */ + { 0, 127, 0, 8 },/* "Page Select" is byte128 in the page0 */ + { 0, 6, 0, 1 },/* "Initialization complete flag" is bit0 of byte 6 in the page0 */ + { 0, 129, 0, 8 },/* "Ext. Identifier" is bit0-1 of byte129 in the page0 */ + { 0, 93, 0, 3 },/* "Power Mode Control" is bit0-2 of byte 93 in the page0 */ +}; +int bms_xcvr_data_list_num = sizeof(bms_xcvr_data_list) / sizeof(bms_xcvr_data_list[0]); + +/* + * FEATURE: + * bms_xcvr_i2c_open + * PURPOSE: + * low-level function to open an I2C adapter device file + * PARAMETERS: + * bus (IN) I2C bus to be looking for + * i2c_fd (OUT) file descriptor + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +static int +bms_xcvr_i2c_open(unsigned char bus, + int *i2c_fd) +{ + int err = 0; + char dev_name[20]; + + sprintf(dev_name, "/dev/i2c-%u", bus); + if ((*i2c_fd = open(dev_name, O_RDWR)) < 0) { + err = errno; + syslog(LOG_DEBUG|LOG_USER, + "[%s] could not open I2C adapter %s: %s\n", + __func__, dev_name, strerror(err)); + return -err; + } + + return err; +} + +/* + * FEATURE: + * bms_xcvr_i2c_read + * PURPOSE: + * low-level function to read 8-bit data from an I2C slave component + * PARAMETERS: + * bus (IN) I2C bus to be looking for + * addr (IN) I2C slave address of the transceiver + * offset (IN) register offset + * val (OUT) pointer of current value buffer + * RETURNS: + * read success, this function returns 0. + * for other cases, negative errno is returned. + */ +static int +bms_xcvr_i2c_read(unsigned char bus, + unsigned char addr, + unsigned short offset, + unsigned char *val) +{ + int err = 0, value; + int i2c_fd = 0; + + if ((err = bms_xcvr_i2c_open(bus, &i2c_fd)) < 0) {goto quit;} + if ((ioctl(i2c_fd, I2C_SLAVE_FORCE, addr)) < 0) { + err = errno; + return -err; + } + value = i2c_smbus_read_byte_data(i2c_fd, offset); + if (value < 0) { + err = errno; + syslog(LOG_DEBUG|LOG_USER, + "[%s] could not read register 0x%X: %s\n", + __func__, offset, strerror(err)); + close(i2c_fd); + return -err; + } + *val = value; + +quit: + close(i2c_fd); + return err; +} + +/* + * FEATURE: + * bms_xcvr_i2c_write + * PURPOSE: + * low-level function to write 8-bit data to an I2C slave component + * PARAMETERS: + * bus (IN) I2C bus to be looking for + * addr (IN) I2C slave address of the transceiver + * offset (IN) register offset + * val (IN) new register value + * RETURNS: + * write success, this function returns 0. + * for other cases, negative errno is returned. + */ +static int +bms_xcvr_i2c_write(unsigned char bus, + unsigned char addr, + unsigned short offset, + unsigned char val) +{ + int err = 0; + int i2c_fd = 0; + + if ((err = bms_xcvr_i2c_open(bus, &i2c_fd)) < 0) {goto quit;} + if ((ioctl(i2c_fd, I2C_SLAVE_FORCE, addr)) < 0) { + err = errno; + return -err; + } + if (i2c_smbus_write_byte_data(i2c_fd, offset, val) < 0) { + err = errno; + syslog(LOG_DEBUG|LOG_USER, + "[%s] could not write register 0x%X: %s\n", + __func__, offset, strerror(err)); + close(i2c_fd); + return -err; + } + +quit: + close(i2c_fd); + return err; +} + +/* + * FEATURE: + * bms_xcvr_max_power_class + * PURPOSE: + * setup max power class for high or legacy device + * PARAMETERS: + * bus (IN) I2C bus to be looking for + * addr (IN) I2C slave address of transceiver + * legacy_power (IN) 1 means power class 2-4 and 0 means power class 5-7 + * RETURNS: + * set success, this function returns 0. + * for other cases, negative errno is returned. + */ +int +bms_xcvr_max_power_class(unsigned char bus, + unsigned char addr, + unsigned char legacy_power) +{ + int err = 0, item = REG_POWER_MODE_CONTROL; + unsigned short val = (legacy_power ? 0x1 : 0x5); + + err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[item].offset, val); + return err; +} + +/* + * FEATURE: + * bms_xcvr_min_power_class + * PURPOSE: + * setup minpower class for high or legacy device + * PARAMETERS: + * bus (IN) I2C bus to be looking for + * addr (IN) I2C slave address of transceiver + * RETURNS: + * set success, this function returns 0. + * for other cases, negative errno is returned. + */ +int +bms_xcvr_min_power_class(unsigned char bus, + unsigned char addr) +{ + int err = 0, item = REG_POWER_MODE_CONTROL; + unsigned short val = 0x7; /* Legacy device will skip bit2 */ + + err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[item].offset, val); + return err; +} + +/* + * FEATURE: + * bms_xcvr_read + * PURPOSE: + * read register of transceiver + * PARAMETERS: + * bus (IN) I2C bus to be looking for + * addr (IN) I2C slave address of transceiver + * reg_item (IN) the regitster of transceiver + * value (OUT) pointer of current value buffer + * RETURNS: + * read success, this function returns 0. + * for other cases, negative errno is returned. + */ +int +bms_xcvr_read(unsigned char bus, + unsigned char addr, + int reg_item, + unsigned char *value) +{ + int err = 0; + unsigned short page = bms_xcvr_data_list[reg_item].page; + unsigned short offset = bms_xcvr_data_list[reg_item].offset; + unsigned char shift = bms_xcvr_data_list[reg_item].shift; + unsigned char width = bms_xcvr_data_list[reg_item].width; + unsigned char mask = ((((unsigned char)1) << (width)) - 1); + unsigned char val = 0; + + if (offset >= SFF_UPPER_PAGE_BYTE_START) { + val = page; + if ((err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[REG_PAGE_SELECT].offset, val)) < 0) {goto quit;} + } + if ((err = bms_xcvr_i2c_read( bus, addr, offset, &val)) < 0) {goto quit;} + *value = ((val >> shift) & mask); +quit: + return err; +} + +/* + * FEATURE: + * bms_xcvr_intr_mask + * PURPOSE: + * mask interrupt for initianl process + * PARAMETERS: + * bus (IN) I2C bus to be looking for + * addr (IN) I2C slave address of transceiver + * RETURNS: + * set success, this function returns 0. + * for other cases, negative errno is returned. + */ +int +bms_xcvr_intr_mask(unsigned char bus, + unsigned char addr) +{ + int err = 0, i = 0, bytes = 0; + unsigned short val = 0; + + /* Switch to register "Hardware Interrupt Pin Masks". + * It starts from byte 100 of page 0 and includes the following 5 bytes. + * When interrupt pin masks are 0xFF, the hardware interrupt will not trigger interrupt pin of transceiver. + */ + val = XCVR_HW_INTR_MASK_PAGE; + if ((err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[REG_PAGE_SELECT].offset, val)) < 0) {goto quit;} + bytes = XCVR_HW_INTR_MASK_BYTES; + val = DISABLE_MASK; + for (i = 0; i < bytes; i++) { + if ((err = bms_xcvr_i2c_write( bus, addr, (XCVR_HW_INTR_MASK_START + i), val)) < 0) {goto quit;} + } + + /* Switch to register "Channel Masks". + * It starts from byte 242 of page 3 and includes the following 6 bytes. + * When interrupt pin masks are 0xFF, the channel interrupt will not trigger interrupt pin of transceiver. + */ + val = XCVR_CHANNEL_INTR_MASK_PAGE; + if ((err = bms_xcvr_i2c_write( bus, addr, bms_xcvr_data_list[REG_PAGE_SELECT].offset, val)) < 0) {goto quit;} + bytes = XCVR_CHANNEL_INTR_MASK_BYTES; + val = DISABLE_MASK; + for (i = 0; i < bytes; i++) { + if ((err = bms_xcvr_i2c_write( bus, addr, (XCVR_CHANNEL_INTR_MASK_START + i), val)) < 0) {goto quit;} + } +quit: + return err; +} + +/* + * FEATURE: + * bms_xcvr_check_power_class + * PURPOSE: + * check power class from transceiver register + * PARAMETERS: + * xcvr_power_data (IN) power data is from Power Class byte + * xcvr_power_class (OUT) pointer of current value buffer + * RETURNS: + * no. + */ +void +bms_xcvr_check_power_class(unsigned char xcvr_power_data, + unsigned char *xcvr_power_class) +{ + unsigned char value, power_class = 0; + value = xcvr_power_data & HIGH_POWER_CLASS_MASK; + if (value == 0) + value = xcvr_power_data & LEGACY_POWER_CLASS_MASK; + switch (value) { + case 0x00: power_class = 1; break; + case 0x40: power_class = 2; break; + case 0x80: power_class = 3; break; + case 0xC0: power_class = 4; break; + case 0x01: power_class = 5; break; + case 0x02: power_class = 6; break; + case 0x03: power_class = 7; break; + default: power_class = 1; break; + } + *xcvr_power_class = power_class; +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.h new file mode 100644 index 000000000000..ac4affef48ec --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_access.h @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __BMS_XCVR_ACCESS_H__ +#define __BMS_XCVR_ACCESS_H__ +enum { + REG_DATA_NOT_READY = 0, + REG_PAGE_SELECT, + REG_INITIALIZATION_COMPLETE_FLAG, + REG_HIGH_POWER_CLASS, + REG_POWER_MODE_CONTROL, +}; + +extern unsigned char bms_xcvr_addr; +#define XCVR_READY 0 +#define XCVR_INIT_COMPLETE 1 +#define XCVR_LEGACY_POWER 1 +#define XCVR_POWER_INIT_MASK 0x1 + +#define POWER_CLASS_MASK 0xC3 + +extern void bms_xcvr_check_power_class(unsigned char xcvr_read_byte, unsigned char *xcvr_power_class); +extern int bms_xcvr_intr_mask(unsigned char bus, unsigned char addr); +extern int bms_xcvr_read(unsigned char bus, unsigned char addr, int reg_item, unsigned char *val); +extern int bms_xcvr_max_power_class(unsigned char bus, unsigned char addr, unsigned char legacy_power); +extern int bms_xcvr_min_power_class(unsigned char bus, unsigned char addr); + +#endif /*__BMS_XCVR_ACCESS_H__*/ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_isrd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_isrd.c new file mode 100644 index 000000000000..2da7e91caaae --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_isrd.c @@ -0,0 +1,315 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_xcvr_servd.h" + +#define MASTER_CPLD_START_PORT 1 +#define SLAVE_CPLD_START_PORT 17 + +/* MIC_FEAT_XCVR_INT : 1 means interrupt, 0 means polling */ +#define MIC_FEAT_XCVR_INT 0 + +#if MIC_FEAT_XCVR_INT == 1 +#include +#include +#include + +#define GPE_SYSFS "/sys/firmware/acpi/interrupts/gpe%.2X" +#define GPE_SYSFS_CHAR_NUM 40 /* ex. /sys/firmware/acpi/interrupts/gpe01 */ +#define GPE_DISABLE 0 +#define GPE_INIT_SKIP 0xFF +#define ACPID_SOCKET_SYSFS "/var/run/acpid.socket" +#define GPE_INTR_TAG "bms_acpi PNP0C01:00 000000%.2X 00000000" +#define GPE_INTR_TAG_CHAR_NUM 38 /* ex. bms_acpi PNP0C01:00 00000002 00000000 */ +#endif + +#if MIC_FEAT_XCVR_INT == 1 +/* + * FEATURE: + * bms_gpe_event_write + * PURPOSE: + * set event to gpe + * PARAMETERS: + * gpe_num (IN) gpe number + * enable (IN) 1 means enable, 0 means disable, others set 0. + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_gpe_event_write(unsigned int gpe_num, + unsigned int enable) +{ + char buf[10], filename[GPE_SYSFS_CHAR_NUM] = { 0 }; + int fd, ret_code = 0, buf_size = sizeof(buf); + ssize_t count; + + snprintf(filename, sizeof(filename), GPE_SYSFS, gpe_num); + /* Open file */ + if ((fd = open(filename, O_WRONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Write file */ + if (enable == GPE_DISABLE) { + snprintf(buf, buf_size, "%s", "disable\n"); + } else if (enable == !GPE_DISABLE) { + snprintf(buf, buf_size, "%s", "enable\n"); + } else if (enable == GPE_INIT_SKIP) { + snprintf(buf, buf_size, "%s", "disable\n"); + } else { + snprintf(buf, buf_size, "%d", 0); + } + if ((count = write(fd, buf, buf_size)) != (-1)) {;} + else if (enable == GPE_INIT_SKIP) {;} + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} +#endif + +/* + * FEATURE: + * open_msq + * PURPOSE: + * open message queue + * PARAMETERS: + * qname (IN) queue name + * mqd (OUT) pointer of message queue description + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +open_msq(const char *qname, + mqd_t *mqd) +{ + int flags = (O_WRONLY | O_NONBLOCK), ret_code = 0; + + /* open POSIX message queue */ + if ((*mqd = mq_open(qname, flags)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open message queue %s (%s)\n", qname, strerror(ret_code)); + } + + return -ret_code; +} + +/* + * FEATURE: + * bms_xcvr_isr + * PURPOSE: + * send message queue + * PARAMETERS: + * port_bmap (IN) bmap of triggered port + * qname (IN) queue name + * mq_desc (IN) message queue description + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_xcvr_isr(unsigned int port_bmap, + char *qname, + mqd_t mq_desc) +{ + int ret_code = 0; + bms_xcvr_serv_mq_data_t msg; + + msg.intr_type = INTR_TYPE_RX_INTR; + msg.port_bmap = port_bmap; + + if (mq_send(mq_desc, (const char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + if (ret_code == EAGAIN) { + syslog(LOG_WARNING|LOG_USER,"Message queue %s is full\n", qname); + } + else { + syslog(LOG_WARNING|LOG_USER,"Failed to send message to %s (%s)\n", qname, strerror(ret_code)); + } + } + + return -ret_code; +} + +/* + * FEATURE: + * bms_xcvr_isrd + * PURPOSE: + * wait for interrupt and call bms_xcvr_isr function + * PARAMETERS: + * args (IN) base port number by master or slave CPLD + * RETURNS: + * no. + */ +void* +bms_xcvr_isrd(void *args) +{ + mqd_t mq_handle; + unsigned int port_num = *(unsigned int *)args, start_port, end_port, value = 0; + unsigned int irq_trigger_bmap = 0, intr_msk_bmap = 0, intr_msk_cache_bmap = 0; + int i, ret_code = 0; +#if MIC_FEAT_XCVR_INT == 1 + int socket_dsc = 0; + struct sockaddr_un socket_addr; + char buf[GPE_INTR_TAG_CHAR_NUM],gpe_tag[GPE_INTR_TAG_CHAR_NUM]; + unsigned int gpe_num = 0x0; +#endif + /* Initial of bms_xcvr_isrd */ + + /* 1. the ISR is for master or slave CPLD */ + if (port_num == MASTER_CPLD_START_PORT) { + start_port = MASTER_CPLD_START_PORT - 1; +#if MIC_FEAT_XCVR_INT == 1 + gpe_num = 0x47; +#endif + } else if (port_num == SLAVE_CPLD_START_PORT) { + start_port = SLAVE_CPLD_START_PORT - 1; +#if MIC_FEAT_XCVR_INT == 1 + gpe_num = 0x2; +#endif + } + end_port = start_port + (SLAVE_CPLD_START_PORT - MASTER_CPLD_START_PORT); + + /* 2. Open message queue */ + if (open_msq(xcvrirq_data[0].mq_name, &mq_handle) < 0) { + goto quit; + } + +#if MIC_FEAT_XCVR_INT == 1 + snprintf(gpe_tag, sizeof(gpe_tag), GPE_INTR_TAG, gpe_num); + /* set default value for GPE status */ + bms_gpe_event_write(gpe_num, GPE_INIT_SKIP); + + /* 3. Open the acpi socket. */ + if ((socket_dsc = socket(AF_UNIX, SOCK_STREAM, 0)) == (-1)) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code)); + goto quit; + } + socket_addr.sun_family = AF_UNIX; + strcpy(socket_addr.sun_path, ACPID_SOCKET_SYSFS); + if (connect(socket_dsc, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) == (-1)) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to connect ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code)); + goto quit; + } +#endif + + while (1) { +#if MIC_FEAT_XCVR_INT == 1 + /* 3. Enable IRQ */ + if((ret_code = bms_gpe_event_write(gpe_num, !GPE_DISABLE)) < 0) + goto quit; + + /* Wait for interrupt occurs; this is a blocking call and may leave + * the blocking state unexpectly while receiving a signal. In such + * a case, we go back to wait for the arriving of interrupt. + */ +wait_irq: + memset(buf,0,sizeof(buf)); + if (recv(socket_dsc, buf, sizeof(buf), 0) <= 0) { + if (errno == EINTR) {goto wait_irq;} + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive ACPI socket for GPE%.2X (%s)\n", gpe_num, strerror(ret_code)); + goto quit; + } + if (!strncmp(buf, gpe_tag, sizeof(gpe_tag)-1)) { + /* Due to bms_gpe hanlder does not set disable now. */ + if((ret_code = bms_gpe_event_write(gpe_num, GPE_DISABLE)) < 0) + goto quit; + } else { + goto wait_irq; + } +#else + usleep(100000); +#endif + + /* Detect xcvr interrupt pin - mark irq_trigger_bmap from xcvr interrupt pin */ + /* Detect which source(s) trigger the interrupt from 16 port */ + for (i = (int)start_port, irq_trigger_bmap = 0; i < (int)end_port; i++) { + if (xcvrirq_data[i].intr_src) { + if ((ret_code = bms_xcvr_pin_read(xcvrirq_data[i].intr_src, &value)) < 0) { + goto quit; + } + irq_trigger_bmap |= ((~value & 0xff) << i); + } + } + + /* send event with irq_trigger_bmap */ + if (irq_trigger_bmap) { + /* 1. enable irq_trigger_bmap that triggers the interrupt mask */ + /* Read irq_msk pin from cache */ + pthread_mutex_lock(&bms_xcvr_data_lock); + bms_xcvr_data_read(XCVR_INTR_MSK, &intr_msk_cache_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + intr_msk_bmap = intr_msk_cache_bmap; + + /* Disable the source that triggers the interrupt mask */ + bms_xcvr_bmap_modify( &intr_msk_bmap, irq_trigger_bmap, INTR_MASK_EN); + + pthread_mutex_lock(&bms_xcvr_data_lock); + if ((ret_code = bms_xcvr_pin_bmap_modify(XCVR_INTR_MSK, intr_msk_bmap, intr_msk_cache_bmap)) < 0) { + goto quit; + } + bms_xcvr_data_write(XCVR_INTR_MSK, intr_msk_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + bms_xcvr_bmap_to_num(irq_trigger_bmap); + syslog(LOG_DEBUG|LOG_USER,"Interrupt port %s arrivals.\n", bms_xcvr_bmap_to_num_str); + /* 2. send event to message queue */ + /* Call interrupt service routine (ISR) with only one queue name (xcvrirq_data[0]) */ + xcvrirq_data[start_port].isr(irq_trigger_bmap, xcvrirq_data[0].mq_name, mq_handle); + } else { +#if MIC_FEAT_XCVR_INT == 1 + /* Log unknown interrupt */ + syslog(LOG_WARNING|LOG_USER,"Receive unknown interrupt from port%d - port%d (%s)\n", start_port + 1, end_port, buf); +#endif + } + } + +quit: + syslog(LOG_WARNING|LOG_USER,"Quit thread from %s function (port%d - port%d)\n", __func__, start_port + 1, end_port); +#if MIC_FEAT_XCVR_INT == 1 + close(socket_dsc); +#endif + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_polld.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_polld.c new file mode 100644 index 000000000000..b440f955140f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_polld.c @@ -0,0 +1,421 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_xcvr_servd.h" +#include + +pthread_mutex_t bms_xcvr_data_lock; +pthread_t polld_tid; + +/* Set default value based on CPLD spec */ +unsigned int bms_xcvr_present_cache_bmap = 0xFFFFFFFF;/* ~PRESENT_EN */ +unsigned int bms_xcvr_reset_cache_bmap = 0x0;/* RST_EN */ +unsigned int bms_xcvr_modsel_cache_bmap = 0xFFFFFFFF;/* ~MODSEL_EN */ +unsigned int bms_xcvr_intr_msk_cache_bmap = 0x0;/* INTR_MASK_EN */ +unsigned int bms_xcvr_init_done_cache_bmap = 0x0;/* ~INIT_DONE_EN */ +unsigned int bms_xcvr_lpmode_cache_bmap = 0x0;/* LPMODE_DIS */ + +/* + * FEATURE: + * bms_xcvr_pin_read + * PURPOSE: + * read pin status from file of sysfs + * PARAMETERS: + * filename (IN) file path in the sysfs + * value (OUT) pointer of current value buffer + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_xcvr_pin_read(char *filename, + unsigned int *value) +{ + char buf[32] = {0}; + int fd, ret_code = 0, buf_size = sizeof(buf); + ssize_t count; + + /* Open xcvr pin file */ + if ((fd = open(filename, O_RDONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Read pin file */ + if ((count = read(fd, buf, buf_size)) != (-1)) { + *value = strtol(buf, NULL, 16); + } + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to read %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} + +/* + * FEATURE: + * bms_xcvr_pin_write + * PURPOSE: + * write value to file of sysfs + * PARAMETERS: + * filename (IN) file path in the sysfs + * value (IN) new register value + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_xcvr_pin_write(char *filename, + unsigned int value) +{ + char buf[3]; + int fd, ret_code = 0, buf_size = sizeof(buf); + ssize_t count; + + /* Open file */ + if ((fd = open(filename, O_WRONLY)) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to open %s (%s)\n", filename, strerror(ret_code)); + return -ret_code; + } + + /* Write file */ + snprintf(buf, buf_size, "%x", value); + if ((count = write(fd, buf, buf_size)) != (-1)) {;} + else { + ret_code = (count >= 0) ? EIO : errno; + syslog(LOG_WARNING|LOG_USER,"Failed to write %s (%s)\n", filename, strerror(ret_code)); + close(fd); + return -ret_code; + } + + close(fd); + return ret_code; +} + +/* + * FEATURE: + * bms_xcvr_data_read + * PURPOSE: + * read pin status from data base + * PARAMETERS: + * pin_num (IN) the number means different pin name + * value (OUT) pointer of current value buffer + * RETURNS: + * no + */ +void +bms_xcvr_data_read(int pin_num, + unsigned int *value) +{ + switch (pin_num) { + case XCVR_PRESENT: + *value = bms_xcvr_present_cache_bmap; + break; + case XCVR_MODSEL: + *value = bms_xcvr_modsel_cache_bmap; + break; + case XCVR_RESET: + *value = bms_xcvr_reset_cache_bmap; + break; + case XCVR_INTR_MSK: + *value = bms_xcvr_intr_msk_cache_bmap; + break; + case XCVR_INIT_DONE: + *value = bms_xcvr_init_done_cache_bmap; + break; + case XCVR_LPMODE: + *value = bms_xcvr_lpmode_cache_bmap; + break; + default: + *value = 0; + break; + } +} + +/* + * FEATURE: + * bms_xcvr_data_write + * PURPOSE: + * write new value to data base + * PARAMETERS: + * pin_num (IN) the number means different pin name + * value (IN) new register value + * RETURNS: + * no. + */ +void +bms_xcvr_data_write(int pin_num, + unsigned int value) +{ + switch (pin_num) { + case XCVR_PRESENT: + bms_xcvr_present_cache_bmap = value; + break; + case XCVR_MODSEL: + bms_xcvr_modsel_cache_bmap = value; + break; + case XCVR_RESET: + bms_xcvr_reset_cache_bmap = value; + break; + case XCVR_INTR_MSK: + bms_xcvr_intr_msk_cache_bmap = value; + break; + case XCVR_INIT_DONE: + bms_xcvr_init_done_cache_bmap = value; + break; + case XCVR_LPMODE: + bms_xcvr_lpmode_cache_bmap = value; + break; + default: + break; + } +} + +/* + * FEATURE: + * bms_xcvr_pin_bmap_write + * PURPOSE: + * write bmap to file of sysfs + * PARAMETERS: + * pin_num (IN) the number means different pin name + * value (IN) new register value + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_xcvr_pin_bmap_write(int pin_num, + unsigned int value) +{ + int ret_code = 0, i; + unsigned int val = 0; + + for(i = 0; i < xcvrirq_data_num; i++) { + if (xcvrirq_data[i].present) { + val = (value >> i) & 0xff; + switch (pin_num) { + case XCVR_PRESENT: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].present, val); + break; + case XCVR_MODSEL: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].modsel, val); + break; + case XCVR_RESET: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].reset, val); + break; + case XCVR_INTR_MSK: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].intr_msk, val); + break; + case XCVR_INTR_SRC: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].intr_src, val); + break; + case XCVR_LPMODE: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].lpmode, val); + break; + default: + ret_code = -ENOTSUP; + break; + } + if (ret_code < 0) + goto quit; + } + } +quit: + return ret_code; +} + +/* + * FEATURE: + * bms_xcvr_pin_bmap_modify + * PURPOSE: + * write bmap to file of sysfs if the value is modified + * PARAMETERS: + * pin_num (IN) the number means different pin name + * value (IN) new register value + * old_value (IN) last register value + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_xcvr_pin_bmap_modify(int pin_num, + unsigned int value, + unsigned int old_value) +{ + int ret_code = 0, i; + unsigned int val = 0; + + for(i = 0; i < xcvrirq_data_num; i++) { + if (xcvrirq_data[i].present && (((old_value ^ value) >> i) & 0xff) ) { + val = (value >> i) & 0xff; + switch (pin_num) { + case XCVR_PRESENT: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].present, val); + break; + case XCVR_MODSEL: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].modsel, val); + break; + case XCVR_RESET: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].reset, val); + break; + case XCVR_INTR_MSK: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].intr_msk, val); + break; + case XCVR_INTR_SRC: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].intr_src, val); + break; + case XCVR_LPMODE: + ret_code = bms_xcvr_pin_write(xcvrirq_data[i].lpmode, val); + break; + default: + ret_code = -ENOTSUP; + break; + } + if (ret_code < 0) + goto quit; + } + } +quit: + return ret_code; +} + +/* + * FEATURE: + * bms_xcvr_polld + * PURPOSE: + * poll present pin for each port + * PARAMETERS: + * args (IN) NULL + * RETURNS: + * No. + */ +void* bms_xcvr_polld(void *args) +{ + int ret_code = 0, i = *(int*)args; + unsigned int present_bmap, present_cache_bmap, present_switch_bmap; + unsigned int reset_bmap, reset_cache_bmap; + unsigned int modsel_bmap, modsel_cache_bmap; + unsigned int xcvr_insert_bmap, xcvr_remove_bmap, value, init_done_cache_bmap; +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + unsigned int lpmode_bmap, lpmode_cache_bmap; +#endif + + while (1) { + + /* Detect xcvr present pin */ + /* 1. read present pin of all xcvr */ + for (i = 0, present_bmap = 0; i < xcvrirq_data_num; i++) { + if (xcvrirq_data[i].present) { + if ((ret_code = bms_xcvr_pin_read(xcvrirq_data[i].present, &value)) < 0) { + goto quit; + } + present_bmap |= (value << i); + } + } + + /* 2. read present,reset,modsel status from database*/ + pthread_mutex_lock(&bms_xcvr_data_lock); + bms_xcvr_data_read(XCVR_PRESENT, &present_cache_bmap); + bms_xcvr_data_read(XCVR_RESET, &reset_cache_bmap); + bms_xcvr_data_read(XCVR_MODSEL, &modsel_cache_bmap); + bms_xcvr_data_read(XCVR_INIT_DONE, &init_done_cache_bmap); +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + bms_xcvr_data_read(XCVR_LPMODE, &lpmode_cache_bmap); +#endif + pthread_mutex_unlock(&bms_xcvr_data_lock); + + reset_bmap = reset_cache_bmap; + modsel_bmap = modsel_cache_bmap; +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + lpmode_bmap = lpmode_cache_bmap; +#endif + + /* 3. mark present_switch_bmap if switching present pin (present <-> absent)*/ + present_switch_bmap = present_bmap ^ present_cache_bmap; + + /* Handle present_switch_bmap */ + if (present_switch_bmap) { + + /* 1. filter to xcvr_insert_bmap and xcvr_remove_bmap */ + xcvr_insert_bmap = (present_switch_bmap & ~present_bmap); + xcvr_remove_bmap = (present_switch_bmap & present_bmap); + + /* 2. deassert reset pin for xcvr insert port */ + bms_xcvr_bmap_modify( &reset_bmap, xcvr_insert_bmap, ~RST_EN); + /* 3. assert reset pin for xcvr remove port */ + bms_xcvr_bmap_modify( &reset_bmap, xcvr_remove_bmap, RST_EN); + + /* 4. For suppot DAC to enable modsel for xcvr insert port */ + bms_xcvr_bmap_modify( &modsel_bmap, xcvr_insert_bmap, MODSEL_EN); + /* 4. No matter what status , set unmodsel for remove port */ + bms_xcvr_bmap_modify( &modsel_bmap, xcvr_remove_bmap, ~MODSEL_EN); + +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + /* 4. No matter what status , set low power mode for remove port */ + bms_xcvr_bmap_modify( &lpmode_bmap, xcvr_remove_bmap, ~LPMODE_DIS); +#endif + + /* 5. Cancel init_done port for xcvr remove port */ + init_done_cache_bmap &= ~xcvr_remove_bmap; + + /* Write present,reset,modsel,init_done pin status of present switch port to database*/ + pthread_mutex_lock(&bms_xcvr_data_lock); + if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_RESET, reset_bmap, reset_cache_bmap)) < 0) { + goto quit; + } + if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_MODSEL, modsel_bmap, modsel_cache_bmap)) < 0) { + goto quit; + } +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_LPMODE, lpmode_bmap, lpmode_cache_bmap)) < 0) { + goto quit; + } + bms_xcvr_data_write(XCVR_LPMODE, lpmode_bmap); +#endif + bms_xcvr_data_write(XCVR_PRESENT, present_bmap); + bms_xcvr_data_write(XCVR_RESET, reset_bmap); + bms_xcvr_data_write(XCVR_MODSEL, modsel_bmap); + bms_xcvr_data_write(XCVR_INIT_DONE, init_done_cache_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + } + sleep(1); + } + +quit: + syslog(LOG_DEBUG|LOG_USER,"Quit thread from %s function (%s)\n", __func__, strerror(ret_code)); + pthread_exit(NULL); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.c b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.c new file mode 100644 index 000000000000..eed3467f8c86 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.c @@ -0,0 +1,987 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bms_xcvr_servd.h" +#include "bms_xcvr_access.h" + +#define PROC_PRIORITY 90 +/* The XCVR_LPMODE_PIN_USE is used when system can not acces with transceiver eeprom */ +#define XCVR_LPMODE_PIN_USE 0 + +#define STR_LEN 100 +char bms_xcvr_bmap_to_num_str[STR_LEN] = { 0 }; + +extern int bms_xcvr_isr(unsigned int port_num, char *qname, mqd_t mq_desc); +extern void* bms_xcvr_isrd(void *args); + +extern pthread_mutex_t bms_xcvr_data_lock; +extern void* bms_xcvr_polld(void *args); +extern pthread_t polld_tid; + +bms_xcvr_serv_data_t xcvrirq_data[] = { + { + .port_num = 1, + .present = "/sys/bus/i2c/devices/1-0032/port_1_8_present", + .intr_src = "/sys/bus/i2c/devices/1-0032/port_1_8_irq_status", + .intr_msk = "/sys/bus/i2c/devices/1-0032/port_1_8_irq_msk", + .modsel = "/sys/bus/i2c/devices/1-0032/port_1_8_modsel", + .lpmode = "/sys/bus/i2c/devices/1-0032/port_1_8_lpmode", + .reset = "/sys/bus/i2c/devices/1-0032/port_1_8_rst", + .mq_name = "/xcvr_isr_mq", + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = bms_xcvr_isrd, + .smbus_num= 10, + }, + { + .port_num = 2, + .present = NULL, /* Share same byte with PORT1 */ + .intr_src = NULL, /* Share same byte with PORT1 */ + .intr_msk = NULL, /* Share same byte with PORT1 */ + .modsel = NULL, /* Share same byte with PORT1 */ + .lpmode = NULL, /* Share same byte with PORT1 */ + .reset = NULL, /* Share same byte with PORT1 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 11, + }, + { + .port_num = 3, + .present = NULL, /* Share same byte with PORT1 */ + .intr_src = NULL, /* Share same byte with PORT1 */ + .intr_msk = NULL, /* Share same byte with PORT1 */ + .modsel = NULL, /* Share same byte with PORT1 */ + .lpmode = NULL, /* Share same byte with PORT1 */ + .reset = NULL, /* Share same byte with PORT1 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 12, + }, + { + .port_num = 4, + .present = NULL, /* Share same byte with PORT1 */ + .intr_src = NULL, /* Share same byte with PORT1 */ + .intr_msk = NULL, /* Share same byte with PORT1 */ + .modsel = NULL, /* Share same byte with PORT1 */ + .lpmode = NULL, /* Share same byte with PORT1 */ + .reset = NULL, /* Share same byte with PORT1 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 13, + }, + { + .port_num = 5, + .present = NULL, /* Share same byte with PORT1 */ + .intr_src = NULL, /* Share same byte with PORT1 */ + .intr_msk = NULL, /* Share same byte with PORT1 */ + .modsel = NULL, /* Share same byte with PORT1 */ + .lpmode = NULL, /* Share same byte with PORT1 */ + .reset = NULL, /* Share same byte with PORT1 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 14, + }, + { + .port_num = 6, + .present = NULL, /* Share same byte with PORT1 */ + .intr_src = NULL, /* Share same byte with PORT1 */ + .intr_msk = NULL, /* Share same byte with PORT1 */ + .modsel = NULL, /* Share same byte with PORT1 */ + .lpmode = NULL, /* Share same byte with PORT1 */ + .reset = NULL, /* Share same byte with PORT1 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 15, + }, + { + .port_num = 7, + .present = NULL, /* Share same byte with PORT1 */ + .intr_src = NULL, /* Share same byte with PORT1 */ + .intr_msk = NULL, /* Share same byte with PORT1 */ + .modsel = NULL, /* Share same byte with PORT1 */ + .lpmode = NULL, /* Share same byte with PORT1 */ + .reset = NULL, /* Share same byte with PORT1 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 16, + }, + { + .port_num = 8, + .present = NULL, /* Share same byte with PORT1 */ + .intr_src = NULL, /* Share same byte with PORT1 */ + .intr_msk = NULL, /* Share same byte with PORT1 */ + .modsel = NULL, /* Share same byte with PORT1 */ + .lpmode = NULL, /* Share same byte with PORT1 */ + .reset = NULL, /* Share same byte with PORT1 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 17, + }, + { + .port_num = 9, + .present = "/sys/bus/i2c/devices/1-0032/port_9_16_present", + .intr_src = "/sys/bus/i2c/devices/1-0032/port_9_16_irq_status", + .intr_msk = "/sys/bus/i2c/devices/1-0032/port_9_16_irq_msk", + .modsel = "/sys/bus/i2c/devices/1-0032/port_9_16_modsel", + .lpmode = "/sys/bus/i2c/devices/1-0032/port_9_16_lpmode", + .reset = "/sys/bus/i2c/devices/1-0032/port_9_16_rst", + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 18, + }, + { + .port_num = 10, + .present = NULL, /* Share same byte with PORT9 */ + .intr_src = NULL, /* Share same byte with PORT9 */ + .intr_msk = NULL, /* Share same byte with PORT9 */ + .modsel = NULL, /* Share same byte with PORT9 */ + .lpmode = NULL, /* Share same byte with PORT9 */ + .reset = NULL, /* Share same byte with PORT9 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 19, + }, + { + .port_num = 11, + .present = NULL, /* Share same byte with PORT9 */ + .intr_src = NULL, /* Share same byte with PORT9 */ + .intr_msk = NULL, /* Share same byte with PORT9 */ + .modsel = NULL, /* Share same byte with PORT9 */ + .lpmode = NULL, /* Share same byte with PORT9 */ + .reset = NULL, /* Share same byte with PORT9 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 20, + }, + { + .port_num = 12, + .present = NULL, /* Share same byte with PORT9 */ + .intr_src = NULL, /* Share same byte with PORT9 */ + .intr_msk = NULL, /* Share same byte with PORT9 */ + .modsel = NULL, /* Share same byte with PORT9 */ + .lpmode = NULL, /* Share same byte with PORT9 */ + .reset = NULL, /* Share same byte with PORT9 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 21, + }, + { + .port_num = 13, + .present = NULL, /* Share same byte with PORT9 */ + .intr_src = NULL, /* Share same byte with PORT9 */ + .intr_msk = NULL, /* Share same byte with PORT9 */ + .modsel = NULL, /* Share same byte with PORT9 */ + .lpmode = NULL, /* Share same byte with PORT9 */ + .reset = NULL, /* Share same byte with PORT9 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 22, + }, + { + .port_num = 14, + .present = NULL, /* Share same byte with PORT9 */ + .intr_src = NULL, /* Share same byte with PORT9 */ + .intr_msk = NULL, /* Share same byte with PORT9 */ + .modsel = NULL, /* Share same byte with PORT9 */ + .lpmode = NULL, /* Share same byte with PORT9 */ + .reset = NULL, /* Share same byte with PORT9 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 23, + }, + { + .port_num = 15, + .present = NULL, /* Share same byte with PORT9 */ + .intr_src = NULL, /* Share same byte with PORT9 */ + .intr_msk = NULL, /* Share same byte with PORT9 */ + .modsel = NULL, /* Share same byte with PORT9 */ + .lpmode = NULL, /* Share same byte with PORT9 */ + .reset = NULL, /* Share same byte with PORT9 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 24, + }, + { + .port_num = 16, + .present = NULL, /* Share same byte with PORT9 */ + .intr_src = NULL, /* Share same byte with PORT9 */ + .intr_msk = NULL, /* Share same byte with PORT9 */ + .modsel = NULL, /* Share same byte with PORT9 */ + .lpmode = NULL, /* Share same byte with PORT9 */ + .reset = NULL, /* Share same byte with PORT9 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT1 */ + .smbus_num= 25, + }, + { + .port_num = 17, + .present = "/sys/bus/i2c/devices/1-0033/port_17_24_present", + .intr_src = "/sys/bus/i2c/devices/1-0033/port_17_24_irq_status", + .intr_msk = "/sys/bus/i2c/devices/1-0033/port_17_24_irq_msk", + .modsel = "/sys/bus/i2c/devices/1-0033/port_17_24_modsel", + .lpmode = "/sys/bus/i2c/devices/1-0033/port_17_24_lpmode", + .reset = "/sys/bus/i2c/devices/1-0033/port_17_24_rst", + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = bms_xcvr_isrd, + .smbus_num= 26, + }, + { + .port_num = 18, + .present = NULL, /* Share same byte with PORT17 */ + .intr_src = NULL, /* Share same byte with PORT17 */ + .intr_msk = NULL, /* Share same byte with PORT17 */ + .modsel = NULL, /* Share same byte with PORT17 */ + .lpmode = NULL, /* Share same byte with PORT17 */ + .reset = NULL, /* Share same byte with PORT17 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 27, + }, + { + .port_num = 19, + .present = NULL, /* Share same byte with PORT17 */ + .intr_src = NULL, /* Share same byte with PORT17 */ + .intr_msk = NULL, /* Share same byte with PORT17 */ + .modsel = NULL, /* Share same byte with PORT17 */ + .lpmode = NULL, /* Share same byte with PORT17 */ + .reset = NULL, /* Share same byte with PORT17 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 28, + }, + { + .port_num = 20, + .present = NULL, /* Share same byte with PORT17 */ + .intr_src = NULL, /* Share same byte with PORT17 */ + .intr_msk = NULL, /* Share same byte with PORT17 */ + .modsel = NULL, /* Share same byte with PORT17 */ + .lpmode = NULL, /* Share same byte with PORT17 */ + .reset = NULL, /* Share same byte with PORT17 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 29, + }, + { + .port_num = 21, + .present = NULL, /* Share same byte with PORT17 */ + .intr_src = NULL, /* Share same byte with PORT17 */ + .intr_msk = NULL, /* Share same byte with PORT17 */ + .modsel = NULL, /* Share same byte with PORT17 */ + .lpmode = NULL, /* Share same byte with PORT17 */ + .reset = NULL, /* Share same byte with PORT17 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 30, + }, + { + .port_num = 22, + .present = NULL, /* Share same byte with PORT17 */ + .intr_src = NULL, /* Share same byte with PORT17 */ + .intr_msk = NULL, /* Share same byte with PORT17 */ + .modsel = NULL, /* Share same byte with PORT17 */ + .lpmode = NULL, /* Share same byte with PORT17 */ + .reset = NULL, /* Share same byte with PORT17 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 31, + }, + { + .port_num = 23, + .present = NULL, /* Share same byte with PORT17 */ + .intr_src = NULL, /* Share same byte with PORT17 */ + .intr_msk = NULL, /* Share same byte with PORT17 */ + .modsel = NULL, /* Share same byte with PORT17 */ + .lpmode = NULL, /* Share same byte with PORT17 */ + .reset = NULL, /* Share same byte with PORT17 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 32, + }, + { + .port_num = 24, + .present = NULL, /* Share same byte with PORT17 */ + .intr_src = NULL, /* Share same byte with PORT17 */ + .intr_msk = NULL, /* Share same byte with PORT17 */ + .modsel = NULL, /* Share same byte with PORT17 */ + .lpmode = NULL, /* Share same byte with PORT17 */ + .reset = NULL, /* Share same byte with PORT17 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 33, + }, + { + .port_num = 25, + .present = "/sys/bus/i2c/devices/1-0033/port_25_32_present", + .intr_src = "/sys/bus/i2c/devices/1-0033/port_25_32_irq_status", + .intr_msk = "/sys/bus/i2c/devices/1-0033/port_25_32_irq_msk", + .modsel = "/sys/bus/i2c/devices/1-0033/port_25_32_modsel", + .lpmode = "/sys/bus/i2c/devices/1-0033/port_25_32_lpmode", + .reset = "/sys/bus/i2c/devices/1-0033/port_25_32_rst", + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 34, + }, + { + .port_num = 26, + .present = NULL, /* Share same byte with PORT25 */ + .intr_src = NULL, /* Share same byte with PORT25 */ + .intr_msk = NULL, /* Share same byte with PORT25 */ + .modsel = NULL, /* Share same byte with PORT25 */ + .lpmode = NULL, /* Share same byte with PORT25 */ + .reset = NULL, /* Share same byte with PORT25 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 35, + }, + { + .port_num = 27, + .present = NULL, /* Share same byte with PORT25 */ + .intr_src = NULL, /* Share same byte with PORT25 */ + .intr_msk = NULL, /* Share same byte with PORT25 */ + .modsel = NULL, /* Share same byte with PORT25 */ + .lpmode = NULL, /* Share same byte with PORT25 */ + .reset = NULL, /* Share same byte with PORT25 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 36, + }, + { + .port_num = 28, + .present = NULL, /* Share same byte with PORT25 */ + .intr_src = NULL, /* Share same byte with PORT25 */ + .intr_msk = NULL, /* Share same byte with PORT25 */ + .modsel = NULL, /* Share same byte with PORT25 */ + .lpmode = NULL, /* Share same byte with PORT25 */ + .reset = NULL, /* Share same byte with PORT25 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 37, + }, + { + .port_num = 29, + .present = NULL, /* Share same byte with PORT25 */ + .intr_src = NULL, /* Share same byte with PORT25 */ + .intr_msk = NULL, /* Share same byte with PORT25 */ + .modsel = NULL, /* Share same byte with PORT25 */ + .lpmode = NULL, /* Share same byte with PORT25 */ + .reset = NULL, /* Share same byte with PORT25 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 38, + }, + { + .port_num = 30, + .present = NULL, /* Share same byte with PORT25 */ + .intr_src = NULL, /* Share same byte with PORT25 */ + .intr_msk = NULL, /* Share same byte with PORT25 */ + .modsel = NULL, /* Share same byte with PORT25 */ + .lpmode = NULL, /* Share same byte with PORT25 */ + .reset = NULL, /* Share same byte with PORT25 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 39, + }, + { + .port_num = 31, + .present = NULL, /* Share same byte with PORT25 */ + .intr_src = NULL, /* Share same byte with PORT25 */ + .intr_msk = NULL, /* Share same byte with PORT25 */ + .modsel = NULL, /* Share same byte with PORT25 */ + .lpmode = NULL, /* Share same byte with PORT25 */ + .reset = NULL, /* Share same byte with PORT25 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 40, + }, + { + .port_num = 32, + .present = NULL, /* Share same byte with PORT25 */ + .intr_src = NULL, /* Share same byte with PORT25 */ + .intr_msk = NULL, /* Share same byte with PORT25 */ + .modsel = NULL, /* Share same byte with PORT25 */ + .lpmode = NULL, /* Share same byte with PORT25 */ + .reset = NULL, /* Share same byte with PORT25 */ + .mq_name = NULL, /* Share same message queue with PORT1 */ + .mq_desc = (mqd_t)-1, + .isr = bms_xcvr_isr, + .isrd = NULL, /* Share same interrupt service routine (ISR) with PORT17 */ + .smbus_num= 41, + }, +}; +int xcvrirq_data_num = sizeof(xcvrirq_data) / sizeof(xcvrirq_data[0]); + +/* + * FEATURE: + * bms_xcvr_create_msq + * PURPOSE: + * Create POSIX message queue + * PARAMETERS: + * qname (IN) I2C bus to be looking for + * mqd (OUT) pointer of message queue description + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +bms_xcvr_create_msq(char *qname, + mqd_t *mqd) +{ + int flags = (O_CREAT | O_EXCL | O_RDONLY), ret_code = 0; + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + struct mq_attr attr = { + .mq_maxmsg = 64, + .mq_msgsize = sizeof(bms_xcvr_serv_mq_data_t), + }; + + /* destroy message queue if it presents */ + if ((mq_unlink(qname) < 0) && (errno != ENOENT)) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to destroy message queue %s (%s)\n", qname, strerror(ret_code)); + } + + /* create POSIX message queue */ + if ((*mqd = mq_open(qname, flags, mode, &attr)) == (mqd_t)-1) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to create message queue %s (%s)\n", qname, strerror(ret_code)); + return -ret_code; + } + + syslog(LOG_DEBUG|LOG_USER,"Create message queue %s\n", qname); + + return -ret_code; +} + +/* + * FEATURE: + * bms_xcvr_terminator + * PURPOSE: + * restore xcvr pin status based on CPLD spec when system reboot/halt + * PARAMETERS: + * sig (IN) system signature + * RETURNS: + * no. + */ +void +bms_xcvr_terminator(int sig) +{ + char *mq_name = xcvrirq_data[0].mq_name; + if (sig) {;} + + /* disable interrupt function */ + bms_xcvr_pin_bmap_write(XCVR_INTR_MSK, INTR_MASK_EN); + + /* disable module select function */ + bms_xcvr_pin_bmap_write(XCVR_MODSEL, ~MODSEL_EN); + + /* assert reset function */ + bms_xcvr_pin_bmap_write(XCVR_RESET, RST_EN); + + /* assert lpmode function */ + bms_xcvr_pin_bmap_write(XCVR_LPMODE, ~LPMODE_DIS); + + /* destroy message queue */ + mq_unlink(mq_name); + + /* destroy mutex lock */ + pthread_mutex_destroy(&bms_xcvr_data_lock); + + syslog(LOG_DEBUG|LOG_USER,"Terminate %s\n", __FILE__); + + exit(0); +} + +/* + * FEATURE: + * bms_xcvr_bmap_modify + * PURPOSE: + * modify the status of pin bmap + * PARAMETERS: + * changed_bmap (OUT) pointer of pin bmap + * check_bmap (IN) modified when the bit is 1. + * switch_status (IN) status that it will switch + * RETURNS: + * no. + */ +void +bms_xcvr_bmap_modify(unsigned int *changed_bmap, + unsigned int check_bmap, + unsigned int switch_status) +{ + if ( switch_status ) { + *changed_bmap |= check_bmap; + } else { + *changed_bmap &= ~check_bmap; + } +} + +/* + * FEATURE: + * bms_xcvr_bmap_to_num + * PURPOSE: + * translate to number from bit-map + * PARAMETERS: + * bmap (IN) bit-map. + * RETURNS: + * no. + */ +void bms_xcvr_bmap_to_num(unsigned int bmap) +{ + char temp[4] = { 0 }; + int i, first = 1; + memset(bms_xcvr_bmap_to_num_str, 0, sizeof(bms_xcvr_bmap_to_num_str)); + for (i = 0; i < xcvrirq_data_num; i++) { + if (bmap & (((unsigned int)1) << i)) { + if (first) { + snprintf(temp, sizeof(temp), "%d", i + 1); + first = 0; + } else { + snprintf(temp, sizeof(temp), ",%d", i + 1); + } + strncat(bms_xcvr_bmap_to_num_str, temp, 4); + } + } +} + +/* +* FEATURE: +* bms_xcvr_mutex_init +* PURPOSE: +* initial mutex +* PARAMETERS: +* +* RETURNS: +* init success, this function shall return zero. +* otherwise, an error number shall be returned to indicate the error. +*/ +static int +bms_xcvr_mutex_init(void) +{ + int ret_code; + + if((ret_code = pthread_mutex_init(&bms_xcvr_data_lock, NULL)) != 0){ + return -ret_code; + } + + return ret_code; +} + +/* + * FEATURE: + * bms_xcvr_reset + * PURPOSE: + * reset transceiver + * PARAMETERS: + * bmap (IN) port bmap for reset + * RETURNS: + * no. + */ +static int +bms_xcvr_reset(unsigned int bmap) +{ + int ret_code = 0; + unsigned int reset_cache_bmap, modsel_cache_bmap, reset_bmap, modsel_bmap; + + if (bmap) { + /* Read reset,modsel status of all port from database*/ + pthread_mutex_lock(&bms_xcvr_data_lock); + bms_xcvr_data_read(XCVR_RESET, &reset_cache_bmap); + bms_xcvr_data_read(XCVR_MODSEL, &modsel_cache_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + /* 1. Assert ResetL of the transceiver. */ + reset_bmap = reset_cache_bmap; + bms_xcvr_bmap_modify( &reset_bmap, bmap, RST_EN); + /* 2. De-assert ModSelL of the transceiver. */ + modsel_bmap = modsel_cache_bmap; + bms_xcvr_bmap_modify( &modsel_bmap, bmap, ~MODSEL_EN); + + pthread_mutex_lock(&bms_xcvr_data_lock); + if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_RESET, reset_bmap, reset_cache_bmap)) < 0) + return -1; + if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_MODSEL, modsel_bmap, modsel_cache_bmap)) < 0) + return -1; + bms_xcvr_data_write(XCVR_RESET, reset_bmap); + bms_xcvr_data_write(XCVR_MODSEL, modsel_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + /* 3. Wait 2 micro second (t_reset_init from SFF-8679). */ + usleep(2); + + /* Read reset,modsel status of all port from database*/ + pthread_mutex_lock(&bms_xcvr_data_lock); + bms_xcvr_data_read(XCVR_RESET, &reset_cache_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + /* 4. De-assert ResetL of the transceiver */ + reset_bmap = reset_cache_bmap; + bms_xcvr_bmap_modify( &reset_bmap, bmap, ~RST_EN); + + pthread_mutex_lock(&bms_xcvr_data_lock); + if((ret_code = bms_xcvr_pin_bmap_modify(XCVR_RESET, reset_bmap, reset_cache_bmap)) < 0) + return -1; + bms_xcvr_data_write(XCVR_RESET, reset_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + bms_xcvr_bmap_to_num(bmap); + syslog(LOG_WARNING|LOG_USER,"Transceiver is reset, port %s .\n", bms_xcvr_bmap_to_num_str); + } + return 0; +} + +/* + * FEATURE: + * main + * PURPOSE: + * initial xcvr service and handle the message queue + * PARAMETERS: + * no + * RETURNS: + * open success, this function returns . + * for other cases, negative errno is returned. + */ +int +main(void) +{ + int i, ret_code = 0, unused; + struct sched_param sched_param = {.sched_priority = PROC_PRIORITY}; + pthread_attr_t attr; + char *mq_name = xcvrirq_data[0].mq_name; + bms_xcvr_serv_mq_data_t msg; + unsigned char xcvr_bus, xcvr_read_byte, xcvr_power_class; + unsigned int modsel_cache_bmap, intr_msk_cache_bmap; + unsigned int modsel_bmap, intr_msk_bmap; + unsigned int xcvr_init_intr_bmap, xcvr_intr_bmap; + unsigned int irq_trigger_bmap, init_fail_bmap, insert_port, xcvr_init_done_bmap; + unsigned int xcvr_init_pass_bmap; + unsigned int reset_port_bmap,intr_port; +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + unsigned int lpmode_bmap, lpmode_cache_bmap; +#endif + + /* Initial of bms_irq_xcvrd */ + /* 0. initial Mutexes */ + if ((ret_code = bms_xcvr_mutex_init() < 0)) { + return ret_code; + } + + /* 1. Set priority and parameter of this process */ + nice(-1); + sched_setscheduler(0, SCHED_FIFO, &sched_param); + + /* 2. Daemonize, make the process be a background daemon */ + daemon(0 /* change working directory to root */, + 0 /* redirect stdin, stdout, and stderr to /dev/null */); + + /* 3. Register handler for termination */ + signal(SIGTERM, bms_xcvr_terminator); + + /* 4. set default for xcvr pin status */ + if ((ret_code = bms_xcvr_pin_bmap_write(XCVR_RESET, RST_EN)) < 0) + goto quit; + if ((ret_code = bms_xcvr_pin_bmap_write(XCVR_MODSEL, ~MODSEL_EN)) < 0) + goto quit; + if ((ret_code = bms_xcvr_pin_bmap_write(XCVR_INTR_MSK, ~INTR_MASK_EN)) < 0) + goto quit; + if ((ret_code = bms_xcvr_pin_bmap_write(XCVR_LPMODE, ~LPMODE_DIS)) < 0) + goto quit; + + /* set default for xcvr pin cache */ + pthread_mutex_lock(&bms_xcvr_data_lock); + bms_xcvr_data_write(XCVR_PRESENT, ~PRESENT_EN); + bms_xcvr_data_write(XCVR_RESET, RST_EN); + bms_xcvr_data_write(XCVR_MODSEL, ~MODSEL_EN); + bms_xcvr_data_write(XCVR_INTR_MSK, ~INTR_MASK_EN); + bms_xcvr_data_write(XCVR_INIT_DONE, INIT_DONE_DIS); + bms_xcvr_data_write(XCVR_LPMODE, ~LPMODE_DIS); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + /* 5. Create message queue for each interrupt service routine (ISR) */ + for (i = 0; i < xcvrirq_data_num; i++) { + if (xcvrirq_data[i].mq_name) { + if ((ret_code = bms_xcvr_create_msq(xcvrirq_data[i].mq_name, &xcvrirq_data[i].mq_desc)) < 0) { + goto quit; + } + } + } + + /* 6. Spawn interrupt service routine (ISR) daemon */ + for (i = 0; i < xcvrirq_data_num; i++) { + if (xcvrirq_data[i].isrd) { + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + pthread_attr_setschedparam(&attr, &sched_param); + if (pthread_create(&xcvrirq_data[i].isrd_tid, &attr, xcvrirq_data[i].isrd, (void*)&xcvrirq_data[i].port_num) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to create pthread to headle transceiver interrupt (%s)\n", strerror(ret_code)); + goto quit; + } + } + } + + /* 6. Spawn polling daemon */ + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + pthread_attr_setschedparam(&attr, &sched_param); + if (pthread_create(&polld_tid, &attr, bms_xcvr_polld, (void*)&unused) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to create pthread for polling transceiver present (%s)\n", strerror(ret_code)); + goto quit; + } + + while (1) { + + /* Wait for message queue */ + if (mq_receive(xcvrirq_data[0].mq_desc, (char*)&msg, sizeof(msg), 0) < 0) { + ret_code = errno; + syslog(LOG_WARNING|LOG_USER,"Failed to receive message from %s (%s)\n", mq_name, strerror(ret_code)); + goto quit; + } + + /* Handle irq_trigger_bmap */ + irq_trigger_bmap = msg.port_bmap; + + /* Read modsel,init_done status of all port from database*/ + pthread_mutex_lock(&bms_xcvr_data_lock); + bms_xcvr_data_read(XCVR_MODSEL, &modsel_cache_bmap); + bms_xcvr_data_read(XCVR_INIT_DONE, &xcvr_init_done_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + modsel_bmap = modsel_cache_bmap; + + /* Filter to xcvr_init_intr and xcvr_intr bmap by xcvr_init_done_bmap from irq_trigger_bmap */ + xcvr_intr_bmap = xcvr_init_done_bmap & irq_trigger_bmap; + xcvr_init_intr_bmap = xcvr_intr_bmap ^ irq_trigger_bmap; + + if ( xcvr_init_intr_bmap ) { + + /* Enable modsel for xcvr init intr port*/ + modsel_cache_bmap = modsel_bmap; + bms_xcvr_bmap_modify( &modsel_bmap, xcvr_init_intr_bmap, MODSEL_EN); + + /* Write modsel status to xcvr pin and database */ + pthread_mutex_lock(&bms_xcvr_data_lock); + if ((ret_code = bms_xcvr_pin_bmap_modify(XCVR_MODSEL, modsel_bmap, modsel_cache_bmap)) < 0) + goto quit; + bms_xcvr_data_write(XCVR_MODSEL, modsel_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + + /* Some QSFP cables have a quirk that asserts the IntN line as a side + * effect of power up on plug-in. We ignore this false positive + * interrupt until the module has finished powering up by waiting for + * a minimum timeout of the module inrush initialization time of + * 500 ms (SFF 8679 Table 5-6) to ensure the voltage rails in the + * module have stabilized. + */ + usleep(500000); + + for (i = 0, init_fail_bmap = 0, xcvr_init_pass_bmap = 0; i < xcvrirq_data_num; i++) { + + insert_port = xcvr_init_intr_bmap & (((unsigned int)1) << i); + if (insert_port) { + xcvr_bus = xcvrirq_data[i].smbus_num; + /* read DataNotReady */ + ret_code = bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_DATA_NOT_READY, &xcvr_read_byte); + /* Init xcvr */ + if (xcvr_read_byte == XCVR_READY) { + if (ret_code >= 0) { + /* 1. Read "Initialization commplete flag" bit (SFF-8636 page 0 byte 6) and the bit is introduced after SFF rev2.5 (SFF-8636 page 0 byte 221) */ + ret_code = bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_INITIALIZATION_COMPLETE_FLAG, &xcvr_read_byte); + } + if (ret_code >= 0) { + /* 2. Mask interrupts of the transceiver for init process */ + ret_code = bms_xcvr_intr_mask(xcvr_bus, bms_xcvr_addr); + } + if (ret_code >= 0) { + /* 3. Read power class (SFF-8636 page 0 byte 129) of the transceiver */ + ret_code = bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_HIGH_POWER_CLASS, &xcvr_read_byte); + bms_xcvr_check_power_class(xcvr_read_byte, &xcvr_power_class); + if (ret_code >= 0) { + /* 3.1 If the transceiver's allowed max power class is 1, set 1 to "High_Power_Class_enable" bit, set 1 to "Power_override" bit, set 1 to "Power_set" bit (SFF-8636 page 0 byte 93, SFF-8679 table 5-5) */ + if (xcvr_power_class == 1) { + ret_code = bms_xcvr_min_power_class(xcvr_bus, bms_xcvr_addr); + } else if (xcvr_power_class < 5) { + /* 3.2 If the transceiver's allowed max power class is 2-4, set 0 to "High_Power_Class_enable" bit, set 1 to "Power_override" bit, set 0 to "Power_set" bit (SFF-8636 page 0 byte 93, SFF-8679 table 5-5) */ + ret_code = bms_xcvr_max_power_class(xcvr_bus, bms_xcvr_addr, XCVR_LEGACY_POWER); + } else { + /* 3.3 If the transceiver's allowed max power class is 5-7, set 1 to "High_Power_Class_enable" bit, set 1 to "Power_override" bit, set 0 to "Power_set" bit (SFF-8636 page 0 byte 93, SFF-8679 table 5-5). */ + ret_code = bms_xcvr_max_power_class(xcvr_bus, bms_xcvr_addr, !XCVR_LEGACY_POWER); + } + } + } + /* 4. If xcvr access fail, go to (INIT FAIL) */ + if (ret_code < 0) { + init_fail_bmap |= insert_port; + syslog(LOG_DEBUG|LOG_USER,"Port %d transceiver is ready by DataNotReady bit, but setup fail\n", i+1); + } else { + /* 5. mark xcvr_init_done_bmap for init success port */ + xcvr_init_done_bmap |= insert_port; + xcvr_init_pass_bmap |= insert_port; + syslog(LOG_DEBUG|LOG_USER,"Port %d transceiver is ready by DataNotReady bit and setup pass\n", i+1); + } + } else { + init_fail_bmap |= insert_port; + syslog(LOG_DEBUG|LOG_USER,"Port %d transceiver is not ready and re-init\n", i+1); + } + } + } + + /* Reset xcvr - (INIT FAIL) When "Data_Not_Ready" bit (SFF-8636 page 0 byte 2) is not ready */ + if (bms_xcvr_reset(init_fail_bmap) < 0) + goto quit; + } + + if ( xcvr_intr_bmap ) { + + for (i = 0, reset_port_bmap = 0; i < xcvrirq_data_num; i++) { + + intr_port = xcvr_intr_bmap & (((unsigned int)1) << i); + if (intr_port) { + xcvr_bus = xcvrirq_data[i].smbus_num; + ret_code = bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_POWER_MODE_CONTROL, &xcvr_read_byte); + if (ret_code >= 0) { + if (!(xcvr_read_byte & XCVR_POWER_INIT_MASK)) { + reset_port_bmap |= intr_port; + /* Read "Initialization commplete flag" bit (SFF-8636 page 0 byte 6) and the bit is introduced after SFF rev2.5 (SFF-8636 page 0 byte 221) */ + bms_xcvr_read(xcvr_bus, bms_xcvr_addr, REG_INITIALIZATION_COMPLETE_FLAG, &xcvr_read_byte); + syslog(LOG_DEBUG|LOG_USER,"Port %d transceiver is reset by re-insert\n", i+1); + } + } else { + reset_port_bmap |= intr_port; + } + } + } + + bms_xcvr_bmap_modify( &xcvr_init_done_bmap, reset_port_bmap, INIT_DONE_DIS); + + if (bms_xcvr_reset(reset_port_bmap) < 0) + goto quit; + + /* TODO : handle transceiver interrupt */ + + bms_xcvr_bmap_to_num(xcvr_intr_bmap); + syslog(LOG_DEBUG|LOG_USER,"Transceiver interrupt has handled, port %s\n", bms_xcvr_bmap_to_num_str); + } + + /* Read intr_msk status of all port from database*/ + pthread_mutex_lock(&bms_xcvr_data_lock); + bms_xcvr_data_read(XCVR_INTR_MSK, &intr_msk_cache_bmap); +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + bms_xcvr_data_read(XCVR_LPMODE, &lpmode_cache_bmap); +#endif + pthread_mutex_unlock(&bms_xcvr_data_lock); + + /* Disable the source that triggers the interrupt */ + intr_msk_bmap = intr_msk_cache_bmap; +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + lpmode_bmap = lpmode_cache_bmap; + bms_xcvr_bmap_modify( &lpmode_bmap, xcvr_init_pass_bmap, LPMODE_DIS); +#endif + bms_xcvr_bmap_modify( &intr_msk_bmap, irq_trigger_bmap, ~INTR_MASK_EN); + + pthread_mutex_lock(&bms_xcvr_data_lock); + if ((ret_code = bms_xcvr_pin_bmap_modify(XCVR_INTR_MSK, intr_msk_bmap, intr_msk_cache_bmap)) < 0) + goto quit; +#if XCVR_LPMODE_PIN_USE == 1 /* LPMODE is reserved */ + if ((ret_code = bms_xcvr_pin_bmap_modify(XCVR_LPMODE, lpmode_bmap, lpmode_cache_bmap)) < 0) + goto quit; + bms_xcvr_data_write(XCVR_LPMODE, lpmode_bmap); +#endif + bms_xcvr_data_write(XCVR_INTR_MSK, intr_msk_bmap); + bms_xcvr_data_write(XCVR_INIT_DONE, xcvr_init_done_bmap); + pthread_mutex_unlock(&bms_xcvr_data_lock); + } + +quit: + pthread_mutex_destroy(&bms_xcvr_data_lock); + syslog(LOG_DEBUG|LOG_USER,"Quit daemon %s for monitor xcvr status\n", __FILE__); + exit(-ret_code); +} diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.h b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.h new file mode 100644 index 000000000000..812d8951c641 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/bms_xcvr_servd.h @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __BMS_IRQ_XCVRD_H__ +#define __BMS_IRQ_XCVRD_H__ + +/* these defines need to be 0*/ +#define INTR_MASK_EN 0 +#define INTR_STATUS_EN 0 +#define MODSEL_EN 0 +#define RST_EN 0 +#define PRESENT_EN 0 +#define INIT_DONE_DIS 0 +#define LPMODE_DIS 0 + +typedef int (*isr_t)(unsigned int, char*, mqd_t); +typedef void* (*isrd_t)(void*); + +typedef struct { + unsigned int port_num; + char *present; + char *intr_src; + char *intr_msk; + char *modsel; + char *reset; + char *lpmode; + char *mq_name; + mqd_t mq_desc; + isr_t isr; + pthread_t isrd_tid; + isrd_t isrd; + unsigned char smbus_num; +} bms_xcvr_serv_data_t; + +typedef struct { + unsigned char intr_type; +#define INTR_TYPE_RX_INTR 1 /* Receving an interrupt */ + unsigned int port_bmap; +} bms_xcvr_serv_mq_data_t; + +enum { + XCVR_PRESENT = 0, + XCVR_MODSEL, + XCVR_RESET, + XCVR_INTR_MSK, + XCVR_INTR_SRC, + XCVR_INIT_DONE, + XCVR_LPMODE, +}; + +extern bms_xcvr_serv_data_t xcvrirq_data[]; +extern int xcvrirq_data_num; +extern pthread_mutex_t bms_xcvr_data_lock; +extern char bms_xcvr_bmap_to_num_str[]; + +extern int bms_xcvr_pin_read(char *filename, unsigned int *value); +extern void bms_xcvr_data_read(int pin_name, unsigned int *value); +extern void bms_xcvr_data_write(int pin_name, unsigned int value); +extern int bms_xcvr_pin_bmap_write(int pin_name, unsigned int value); +extern int bms_xcvr_pin_bmap_modify(int pin_num, unsigned int value, unsigned int old_value); +extern void bms_xcvr_bmap_modify(unsigned int *changed_bmap, unsigned int check_bmap, unsigned int enable_disable); +extern void bms_xcvr_bmap_to_num(unsigned int bmap); + +#endif /* __BMS_IRQ_XCVRD_H__ */ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd deleted file mode 100755 index c882ff8e335a..000000000000 Binary files a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/opt/xcvr-serv/xcvr-servd and /dev/null differ diff --git a/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/service/ly1200-32x-platform-init.service b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/service/ly1200-32x-platform-init.service new file mode 100644 index 000000000000..20e38495a7d5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-mitac/ly1200-32x/service/ly1200-32x-platform-init.service @@ -0,0 +1,14 @@ +[Unit] +Description=Mitac ly1200_32x platform initialization service +Before=pmon.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/etc/init.d/sonic-platform-mitac-ly1200-32x start +ExecStop=/etc/init.d/sonic-platform-mitac-ly1200-32x stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target + diff --git a/sonic-slave-stretch/Dockerfile b/sonic-slave-stretch/Dockerfile index d34cfda71c06..25b99b8231ff 100644 --- a/sonic-slave-stretch/Dockerfile +++ b/sonic-slave-stretch/Dockerfile @@ -77,6 +77,7 @@ RUN apt-get update && apt-get install -y \ stgit \ # For platform-modules build module-assistant \ + libi2c-dev \ # For thrift build\ gem2deb \ libboost-all-dev \