diff --git a/123.patch b/123.patch deleted file mode 100644 index f6ee0957d8..0000000000 --- a/123.patch +++ /dev/null @@ -1,5611 +0,0 @@ -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/hwsku.json b/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/hwsku.json -new file mode 100755 -index 000000000..faf0aac09 ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/hwsku.json -@@ -0,0 +1,315 @@ -+{ -+ "interfaces": { -+ "Ethernet0": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet1": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet2": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet3": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet4": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet5": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet6": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet7": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet8": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet9": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet10": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet11": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet12": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet13": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet14": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet15": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet16": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet17": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet18": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet19": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet20": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet21": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet22": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet23": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet24": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet25": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet26": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet27": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet28": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet29": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet30": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet31": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet32": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet33": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet34": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet35": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet36": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet37": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet38": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet39": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet40": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet41": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet42": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet43": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet44": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet45": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet46": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet47": { -+ "default_brkout_mode": "1x1G", -+ "autoneg": "on", -+ "port_type": "RJ45" -+ }, -+ -+ "Ethernet48": { -+ "default_brkout_mode": "1x25G[10G]" -+ }, -+ -+ "Ethernet49": { -+ "default_brkout_mode": "1x25G[10G]" -+ }, -+ -+ "Ethernet50": { -+ "default_brkout_mode": "1x25G[10G]" -+ }, -+ -+ "Ethernet51": { -+ "default_brkout_mode": "1x25G[10G]" -+ }, -+ -+ "Ethernet52": { -+ "default_brkout_mode": "1x100G[40G]" -+ }, -+ -+ "Ethernet56": { -+ "default_brkout_mode": "1x100G[40G]" -+ } -+ } -+} -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/hx5-as4630-48x1G+4x25G+2x100G.bcm b/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/hx5-as4630-48x1G+4x25G+2x100G.bcm -new file mode 100755 -index 000000000..1a0241506 ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/hx5-as4630-48x1G+4x25G+2x100G.bcm -@@ -0,0 +1,502 @@ -+stable_size=76303168 -+ -+#polarity/lanemap is using TH2 style. -+core_clock_frequency=893 -+dpp_clock_ratio=2:3 -+ -+ptp_ts_pll_fref=50000000 -+ptp_bs_fref_0=50000000 -+ptp_bs_fref_1=50000000 -+ -+#oversubscribe_mode=1 -+ -+pbmp_xport_xe=0x1FFFFFFE000000000000 -+ -+parity_enable=0 -+mem_cache_enable=1 -+ -+l2_mem_entries=32768 -+#l3_mem_entries=49152 -+#fpem_mem_entries=16384 -+l2xmsg_mode=1 -+l3_alpm_enable=2 -+ipv6_lpm_128b_enable=1 -+port_flex_enable=1 -+pcie_hot_swap_timeout_usec=10000 -+ifp_inports_support_enable=1 -+ -+#3x PM4x10Q (3 * 16 = 48 physical ports) -+#Doesn't support oversubscribe in Q mode -+#MCQ0 -+port_gmii_mode_1=1 #Q mode -+ -+#riot vxlan -+#dport_map_direct=1 -+flow_init_mode=1 -+riot_enable=1 -+riot_overlay_l3_intf_mem_size=4096 -+riot_overlay_l3_egress_mem_size=8192 -+l3_ecmp_levels=2 -+riot_overlay_ecmp_resilient_hash_size=16384 -+use_all_splithorizon_groups=1 -+host_as_route_disable=1 -+max_vp_lags=448 -+ -+#PHY4 U56 xx1, MDC/MDIO2, PHYADDR:0x00-0x07, 0x08 -+port_phy_addr_1=0x40 -+port_phy_addr_2=0x41 -+port_phy_addr_3=0x42 -+port_phy_addr_4=0x43 -+port_phy_addr_5=0x44 -+port_phy_addr_6=0x45 -+port_phy_addr_7=0x46 -+port_phy_addr_8=0x47 -+phy_port_primary_and_offset_1=0x0100 -+phy_port_primary_and_offset_2=0x0101 -+phy_port_primary_and_offset_3=0x0102 -+phy_port_primary_and_offset_4=0x0103 -+phy_port_primary_and_offset_5=0x0104 -+phy_port_primary_and_offset_6=0x0105 -+phy_port_primary_and_offset_7=0x0106 -+phy_port_primary_and_offset_8=0x0107 -+dport_map_port_1=26 -+dport_map_port_2=25 -+dport_map_port_3=28 -+dport_map_port_4=27 -+dport_map_port_5=30 -+dport_map_port_6=29 -+dport_map_port_7=32 -+dport_map_port_8=31 -+portmap_1=1:1 -+portmap_2=2:1 -+portmap_3=3:1 -+portmap_4=4:1 -+portmap_5=5:1 -+portmap_6=6:1 -+portmap_7=7:1 -+portmap_8=8:1 -+phy_chain_rx_lane_map_physical{1.0}=0x3210 -+phy_chain_rx_lane_map_physical{2.0}=0x3210 -+phy_chain_rx_lane_map_physical{3.0}=0x3210 -+phy_chain_rx_lane_map_physical{4.0}=0x3210 -+phy_chain_rx_lane_map_physical{5.0}=0x3210 -+phy_chain_rx_lane_map_physical{6.0}=0x3210 -+phy_chain_rx_lane_map_physical{7.0}=0x3210 -+phy_chain_rx_lane_map_physical{8.0}=0x3210 -+phy_chain_tx_lane_map_physical{1.0}=0x3210 -+phy_chain_tx_lane_map_physical{2.0}=0x3210 -+phy_chain_tx_lane_map_physical{3.0}=0x3210 -+phy_chain_tx_lane_map_physical{4.0}=0x3210 -+phy_chain_tx_lane_map_physical{5.0}=0x3210 -+phy_chain_tx_lane_map_physical{6.0}=0x3210 -+phy_chain_tx_lane_map_physical{7.0}=0x3210 -+phy_chain_tx_lane_map_physical{8.0}=0x3210 -+phy_chain_rx_polarity_flip_physical{1.0}=0x0 -+phy_chain_rx_polarity_flip_physical{2.0}=0x0 -+phy_chain_rx_polarity_flip_physical{3.0}=0x0 -+phy_chain_rx_polarity_flip_physical{4.0}=0x0 -+phy_chain_rx_polarity_flip_physical{5.0}=0x0 -+phy_chain_rx_polarity_flip_physical{6.0}=0x0 -+phy_chain_rx_polarity_flip_physical{7.0}=0x0 -+phy_chain_rx_polarity_flip_physical{8.0}=0x0 -+phy_chain_tx_polarity_flip_physical{1.0}=0x0 -+phy_chain_tx_polarity_flip_physical{2.0}=0x0 -+phy_chain_tx_polarity_flip_physical{3.0}=0x0 -+phy_chain_tx_polarity_flip_physical{4.0}=0x0 -+phy_chain_tx_polarity_flip_physical{5.0}=0x0 -+phy_chain_tx_polarity_flip_physical{6.0}=0x0 -+phy_chain_tx_polarity_flip_physical{7.0}=0x0 -+phy_chain_tx_polarity_flip_physical{8.0}=0x0 -+ -+ -+#PHY5 U57 x1x, MDC/MDIO2, PHYADDR:0x09-0x10, 0x11 -+port_phy_addr_9=0x49 -+port_phy_addr_10=0x4A -+port_phy_addr_11=0x4B -+port_phy_addr_12=0x4C -+port_phy_addr_13=0x4D -+port_phy_addr_14=0x4E -+port_phy_addr_15=0x4F -+port_phy_addr_16=0x50 -+phy_port_primary_and_offset_9=0x0900 -+phy_port_primary_and_offset_10=0x0901 -+phy_port_primary_and_offset_11=0x0902 -+phy_port_primary_and_offset_12=0x0903 -+phy_port_primary_and_offset_13=0x0904 -+phy_port_primary_and_offset_14=0x0905 -+phy_port_primary_and_offset_15=0x0906 -+phy_port_primary_and_offset_16=0x0907 -+dport_map_port_9=34 -+dport_map_port_10=33 -+dport_map_port_11=36 -+dport_map_port_12=35 -+dport_map_port_13=38 -+dport_map_port_14=37 -+dport_map_port_15=40 -+dport_map_port_16=39 -+portmap_9=9:1 -+portmap_10=10:1 -+portmap_11=11:1 -+portmap_12=12:1 -+portmap_13=13:1 -+portmap_14=14:1 -+portmap_15=15:1 -+portmap_16=16:1 -+phy_chain_rx_lane_map_physical{9.0}=0x3210 -+phy_chain_rx_lane_map_physical{10.0}=0x3210 -+phy_chain_rx_lane_map_physical{11.0}=0x3210 -+phy_chain_rx_lane_map_physical{12.0}=0x3210 -+phy_chain_rx_lane_map_physical{13.0}=0x3210 -+phy_chain_rx_lane_map_physical{14.0}=0x3210 -+phy_chain_rx_lane_map_physical{15.0}=0x3210 -+phy_chain_rx_lane_map_physical{16.0}=0x3210 -+phy_chain_tx_lane_map_physical{9.0}=0x3210 -+phy_chain_tx_lane_map_physical{10.0}=0x3210 -+phy_chain_tx_lane_map_physical{11.0}=0x3210 -+phy_chain_tx_lane_map_physical{12.0}=0x3210 -+phy_chain_tx_lane_map_physical{13.0}=0x3210 -+phy_chain_tx_lane_map_physical{14.0}=0x3210 -+phy_chain_tx_lane_map_physical{15.0}=0x3210 -+phy_chain_tx_lane_map_physical{16.0}=0x3210 -+phy_chain_rx_polarity_flip_physical{9.0}=0x0 -+phy_chain_rx_polarity_flip_physical{10.0}=0x0 -+phy_chain_rx_polarity_flip_physical{11.0}=0x0 -+phy_chain_rx_polarity_flip_physical{12.0}=0x0 -+phy_chain_rx_polarity_flip_physical{13.0}=0x0 -+phy_chain_rx_polarity_flip_physical{14.0}=0x0 -+phy_chain_rx_polarity_flip_physical{15.0}=0x0 -+phy_chain_rx_polarity_flip_physical{16.0}=0x0 -+phy_chain_tx_polarity_flip_physical{9.0}=0x0 -+phy_chain_tx_polarity_flip_physical{10.0}=0x0 -+phy_chain_tx_polarity_flip_physical{11.0}=0x0 -+phy_chain_tx_polarity_flip_physical{12.0}=0x0 -+phy_chain_tx_polarity_flip_physical{13.0}=0x0 -+phy_chain_tx_polarity_flip_physical{14.0}=0x0 -+phy_chain_tx_polarity_flip_physical{15.0}=0x0 -+phy_chain_tx_polarity_flip_physical{16.0}=0x0 -+ -+#MCQ1 -+port_gmii_mode_17=1 #Q mode -+ -+#PHY6 U58 11x, MDC/MDIO2, PHYADDR:0x12-0x19, 0x1A -+port_phy_addr_17=0x52 -+port_phy_addr_18=0x53 -+port_phy_addr_19=0x54 -+port_phy_addr_20=0x55 -+port_phy_addr_21=0x56 -+port_phy_addr_22=0x57 -+port_phy_addr_23=0x58 -+port_phy_addr_24=0x59 -+phy_port_primary_and_offset_17=0x1100 -+phy_port_primary_and_offset_18=0x1101 -+phy_port_primary_and_offset_19=0x1102 -+phy_port_primary_and_offset_20=0x1103 -+phy_port_primary_and_offset_21=0x1104 -+phy_port_primary_and_offset_22=0x1105 -+phy_port_primary_and_offset_23=0x1106 -+phy_port_primary_and_offset_24=0x1107 -+dport_map_port_17=42 -+dport_map_port_18=41 -+dport_map_port_19=44 -+dport_map_port_20=43 -+dport_map_port_21=46 -+dport_map_port_22=45 -+dport_map_port_23=48 -+dport_map_port_24=47 -+portmap_17=17:1 -+portmap_18=18:1 -+portmap_19=19:1 -+portmap_20=20:1 -+portmap_21=21:1 -+portmap_22=22:1 -+portmap_23=23:1 -+portmap_24=24:1 -+phy_chain_rx_lane_map_physical{17.0}=0x3210 -+phy_chain_rx_lane_map_physical{18.0}=0x3210 -+phy_chain_rx_lane_map_physical{19.0}=0x3210 -+phy_chain_rx_lane_map_physical{20.0}=0x3210 -+phy_chain_rx_lane_map_physical{21.0}=0x3210 -+phy_chain_rx_lane_map_physical{22.0}=0x3210 -+phy_chain_rx_lane_map_physical{23.0}=0x3210 -+phy_chain_rx_lane_map_physical{24.0}=0x3210 -+phy_chain_tx_lane_map_physical{17.0}=0x3210 -+phy_chain_tx_lane_map_physical{18.0}=0x3210 -+phy_chain_tx_lane_map_physical{19.0}=0x3210 -+phy_chain_tx_lane_map_physical{20.0}=0x3210 -+phy_chain_tx_lane_map_physical{21.0}=0x3210 -+phy_chain_tx_lane_map_physical{22.0}=0x3210 -+phy_chain_tx_lane_map_physical{23.0}=0x3210 -+phy_chain_tx_lane_map_physical{24.0}=0x3210 -+phy_chain_rx_polarity_flip_physical{17.0}=0x0 -+phy_chain_rx_polarity_flip_physical{18.0}=0x0 -+phy_chain_rx_polarity_flip_physical{19.0}=0x0 -+phy_chain_rx_polarity_flip_physical{20.0}=0x0 -+phy_chain_rx_polarity_flip_physical{21.0}=0x0 -+phy_chain_rx_polarity_flip_physical{22.0}=0x0 -+phy_chain_rx_polarity_flip_physical{23.0}=0x0 -+phy_chain_rx_polarity_flip_physical{24.0}=0x0 -+phy_chain_tx_polarity_flip_physical{17.0}=0x0 -+phy_chain_tx_polarity_flip_physical{18.0}=0x0 -+phy_chain_tx_polarity_flip_physical{19.0}=0x0 -+phy_chain_tx_polarity_flip_physical{20.0}=0x0 -+phy_chain_tx_polarity_flip_physical{21.0}=0x0 -+phy_chain_tx_polarity_flip_physical{22.0}=0x0 -+phy_chain_tx_polarity_flip_physical{23.0}=0x0 -+phy_chain_tx_polarity_flip_physical{24.0}=0x0 -+ -+#PHY1 U53 xx1, MDC/MDIO0, PHYADDR:0x00-0x07, 0x08 -+port_phy_addr_25=0x00 -+port_phy_addr_26=0x01 -+port_phy_addr_27=0x02 -+port_phy_addr_28=0x03 -+port_phy_addr_29=0x04 -+port_phy_addr_30=0x05 -+port_phy_addr_31=0x06 -+port_phy_addr_32=0x07 -+phy_port_primary_and_offset_25=0x1900 -+phy_port_primary_and_offset_26=0x1901 -+phy_port_primary_and_offset_27=0x1902 -+phy_port_primary_and_offset_28=0x1903 -+phy_port_primary_and_offset_29=0x1904 -+phy_port_primary_and_offset_30=0x1905 -+phy_port_primary_and_offset_31=0x1906 -+phy_port_primary_and_offset_32=0x1907 -+dport_map_port_25=2 -+dport_map_port_26=1 -+dport_map_port_27=4 -+dport_map_port_28=3 -+dport_map_port_29=6 -+dport_map_port_30=5 -+dport_map_port_31=8 -+dport_map_port_32=7 -+portmap_25=25:1 -+portmap_26=26:1 -+portmap_27=27:1 -+portmap_28=28:1 -+portmap_29=29:1 -+portmap_30=30:1 -+portmap_31=31:1 -+portmap_32=32:1 -+phy_chain_rx_lane_map_physical{25.0}=0x3210 -+phy_chain_rx_lane_map_physical{26.0}=0x3210 -+phy_chain_rx_lane_map_physical{27.0}=0x3210 -+phy_chain_rx_lane_map_physical{28.0}=0x3210 -+phy_chain_rx_lane_map_physical{29.0}=0x3210 -+phy_chain_rx_lane_map_physical{30.0}=0x3210 -+phy_chain_rx_lane_map_physical{31.0}=0x3210 -+phy_chain_rx_lane_map_physical{32.0}=0x3210 -+phy_chain_tx_lane_map_physical{25.0}=0x3210 -+phy_chain_tx_lane_map_physical{26.0}=0x3210 -+phy_chain_tx_lane_map_physical{27.0}=0x3210 -+phy_chain_tx_lane_map_physical{28.0}=0x3210 -+phy_chain_tx_lane_map_physical{29.0}=0x3210 -+phy_chain_tx_lane_map_physical{30.0}=0x3210 -+phy_chain_tx_lane_map_physical{31.0}=0x3210 -+phy_chain_tx_lane_map_physical{32.0}=0x3210 -+phy_chain_rx_polarity_flip_physical{25.0}=0x0 -+phy_chain_rx_polarity_flip_physical{26.0}=0x0 -+phy_chain_rx_polarity_flip_physical{27.0}=0x0 -+phy_chain_rx_polarity_flip_physical{28.0}=0x0 -+phy_chain_rx_polarity_flip_physical{29.0}=0x0 -+phy_chain_rx_polarity_flip_physical{30.0}=0x0 -+phy_chain_rx_polarity_flip_physical{31.0}=0x0 -+phy_chain_rx_polarity_flip_physical{32.0}=0x0 -+phy_chain_tx_polarity_flip_physical{25.0}=0x0 -+phy_chain_tx_polarity_flip_physical{26.0}=0x0 -+phy_chain_tx_polarity_flip_physical{27.0}=0x0 -+phy_chain_tx_polarity_flip_physical{28.0}=0x0 -+phy_chain_tx_polarity_flip_physical{29.0}=0x0 -+phy_chain_tx_polarity_flip_physical{30.0}=0x0 -+phy_chain_tx_polarity_flip_physical{31.0}=0x0 -+phy_chain_tx_polarity_flip_physical{32.0}=0x0 -+ -+#MCQ2 -+port_gmii_mode_33=1 #Q mode -+ -+#PHY2 U54 x1x, MDC/MDIO0, PHYADDR:0x09-0x10, 0x11 -+port_phy_addr_33=0x0D -+port_phy_addr_34=0x0E -+port_phy_addr_35=0x0F -+port_phy_addr_36=0x10 -+port_phy_addr_37=0x09 -+port_phy_addr_38=0x0A -+port_phy_addr_39=0x0B -+port_phy_addr_40=0x0C -+phy_port_primary_and_offset_33=0x2504 -+phy_port_primary_and_offset_34=0x2505 -+phy_port_primary_and_offset_35=0x2506 -+phy_port_primary_and_offset_36=0x2507 -+phy_port_primary_and_offset_37=0x2500 -+phy_port_primary_and_offset_38=0x2501 -+phy_port_primary_and_offset_39=0x2502 -+phy_port_primary_and_offset_40=0x2503 -+dport_map_port_33=14 -+dport_map_port_34=13 -+dport_map_port_35=16 -+dport_map_port_36=15 -+dport_map_port_37=10 -+dport_map_port_38=9 -+dport_map_port_39=12 -+dport_map_port_40=11 -+portmap_33=33:1 -+portmap_34=34:1 -+portmap_35=35:1 -+portmap_36=36:1 -+portmap_37=37:1 -+portmap_38=38:1 -+portmap_39=39:1 -+portmap_40=40:1 -+phy_chain_rx_lane_map_physical{33.0}=0x3210 -+phy_chain_rx_lane_map_physical{34.0}=0x3210 -+phy_chain_rx_lane_map_physical{35.0}=0x3210 -+phy_chain_rx_lane_map_physical{36.0}=0x3210 -+phy_chain_rx_lane_map_physical{37.0}=0x3210 -+phy_chain_rx_lane_map_physical{38.0}=0x3210 -+phy_chain_rx_lane_map_physical{39.0}=0x3210 -+phy_chain_rx_lane_map_physical{40.0}=0x3210 -+phy_chain_tx_lane_map_physical{33.0}=0x3210 -+phy_chain_tx_lane_map_physical{34.0}=0x3210 -+phy_chain_tx_lane_map_physical{35.0}=0x3210 -+phy_chain_tx_lane_map_physical{36.0}=0x3210 -+phy_chain_tx_lane_map_physical{37.0}=0x3210 -+phy_chain_tx_lane_map_physical{38.0}=0x3210 -+phy_chain_tx_lane_map_physical{39.0}=0x3210 -+phy_chain_tx_lane_map_physical{40.0}=0x3210 -+phy_chain_rx_polarity_flip_physical{33.0}=0x1 -+phy_chain_rx_polarity_flip_physical{34.0}=0x1 -+phy_chain_rx_polarity_flip_physical{35.0}=0x1 -+phy_chain_rx_polarity_flip_physical{36.0}=0x1 -+phy_chain_rx_polarity_flip_physical{37.0}=0x1 -+phy_chain_rx_polarity_flip_physical{38.0}=0x1 -+phy_chain_rx_polarity_flip_physical{39.0}=0x1 -+phy_chain_rx_polarity_flip_physical{40.0}=0x1 -+phy_chain_tx_polarity_flip_physical{33.0}=0x1 -+phy_chain_tx_polarity_flip_physical{34.0}=0x1 -+phy_chain_tx_polarity_flip_physical{35.0}=0x1 -+phy_chain_tx_polarity_flip_physical{36.0}=0x1 -+phy_chain_tx_polarity_flip_physical{37.0}=0x1 -+phy_chain_tx_polarity_flip_physical{38.0}=0x1 -+phy_chain_tx_polarity_flip_physical{39.0}=0x1 -+phy_chain_tx_polarity_flip_physical{40.0}=0x1 -+ -+#PHY3 U55 11x, MDC/MDIO0, PHYADDR:0x12-0x19, 0x1A -+port_phy_addr_41=0x16 -+port_phy_addr_42=0x17 -+port_phy_addr_43=0x18 -+port_phy_addr_44=0x19 -+port_phy_addr_45=0x12 -+port_phy_addr_46=0x13 -+port_phy_addr_47=0x14 -+port_phy_addr_48=0x15 -+phy_port_primary_and_offset_41=0x2D00 -+phy_port_primary_and_offset_42=0x2D01 -+phy_port_primary_and_offset_43=0x2D02 -+phy_port_primary_and_offset_44=0x2D03 -+phy_port_primary_and_offset_45=0x2D04 -+phy_port_primary_and_offset_46=0x2D05 -+phy_port_primary_and_offset_47=0x2D06 -+phy_port_primary_and_offset_48=0x2D07 -+dport_map_port_41=22 -+dport_map_port_42=21 -+dport_map_port_43=24 -+dport_map_port_44=23 -+dport_map_port_45=18 -+dport_map_port_46=17 -+dport_map_port_47=20 -+dport_map_port_48=19 -+portmap_41=41:1 -+portmap_42=42:1 -+portmap_43=43:1 -+portmap_44=44:1 -+portmap_45=45:1 -+portmap_46=46:1 -+portmap_47=47:1 -+portmap_48=48:1 -+phy_chain_rx_lane_map_physical{41.0}=0x3210 -+phy_chain_rx_lane_map_physical{42.0}=0x3210 -+phy_chain_rx_lane_map_physical{43.0}=0x3210 -+phy_chain_rx_lane_map_physical{44.0}=0x3210 -+phy_chain_rx_lane_map_physical{45.0}=0x3210 -+phy_chain_rx_lane_map_physical{46.0}=0x3210 -+phy_chain_rx_lane_map_physical{47.0}=0x3210 -+phy_chain_rx_lane_map_physical{48.0}=0x3210 -+phy_chain_tx_lane_map_physical{41.0}=0x3210 -+phy_chain_tx_lane_map_physical{42.0}=0x3210 -+phy_chain_tx_lane_map_physical{43.0}=0x3210 -+phy_chain_tx_lane_map_physical{44.0}=0x3210 -+phy_chain_tx_lane_map_physical{45.0}=0x3210 -+phy_chain_tx_lane_map_physical{46.0}=0x3210 -+phy_chain_tx_lane_map_physical{47.0}=0x3210 -+phy_chain_tx_lane_map_physical{48.0}=0x3210 -+phy_chain_rx_polarity_flip_physical{41.0}=0x1 -+phy_chain_rx_polarity_flip_physical{42.0}=0x1 -+phy_chain_rx_polarity_flip_physical{43.0}=0x1 -+phy_chain_rx_polarity_flip_physical{44.0}=0x1 -+phy_chain_rx_polarity_flip_physical{45.0}=0x1 -+phy_chain_rx_polarity_flip_physical{46.0}=0x1 -+phy_chain_rx_polarity_flip_physical{47.0}=0x1 -+phy_chain_rx_polarity_flip_physical{48.0}=0x1 -+phy_chain_tx_polarity_flip_physical{41.0}=0x1 -+phy_chain_tx_polarity_flip_physical{42.0}=0x1 -+phy_chain_tx_polarity_flip_physical{43.0}=0x1 -+phy_chain_tx_polarity_flip_physical{44.0}=0x1 -+phy_chain_tx_polarity_flip_physical{45.0}=0x1 -+phy_chain_tx_polarity_flip_physical{46.0}=0x1 -+phy_chain_tx_polarity_flip_physical{47.0}=0x1 -+phy_chain_tx_polarity_flip_physical{48.0}=0x1 -+ -+#3x PM4x25 (3 * 4 = 12 physical ports) -+#FC0 -+dport_map_port_49=51 -+dport_map_port_50=50 -+dport_map_port_51=49 -+dport_map_port_52=52 -+portmap_49=65:25 -+portmap_50=66:25 -+portmap_51=67:25 -+portmap_52=68:25 -+#FC1 -+dport_map_port_53=57 -+dport_map_port_54=58 -+dport_map_port_55=59 -+dport_map_port_56=60 -+portmap_53=69:100:4 -+#portmap_55=71:50 -+#portmap_54=70:25 -+#portmap_55=71:25 -+#portmap_56=72:25 -+#FC2 -+dport_map_port_57=53 -+dport_map_port_58=54 -+dport_map_port_59=55 -+dport_map_port_60=56 -+portmap_57=73:100:4 -+#portmap_59=75:50 -+#portmap_58=74:25 -+#portmap_59=75:25 -+#portmap_60=76:25 -+ -+#4x PM4x10 (4 * 4 = 16 physical ports) -+#MC0 No connection -+#MC1 No connection -+#MC2 No connection -+#MC3 No connection -+#portmap_=49:10 -+#portmap_=50:10 -+#portmap_=51:10 -+#portmap_=52:10 -+ -+#portmap_=53:10 -+#portmap_=54:10 -+#portmap_=55:10 -+#portmap_=56:10 -+ -+#portmap_=57:10 -+#portmap_=58:10 -+#portmap_=59:10 -+#portmap_=60:10 -+ -+#portmap_=61:10 -+#portmap_=62:10 -+#portmap_=63:10 -+#portmap_=64:10 -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/port_config.ini b/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/port_config.ini -index 7040875fa..c30f99f48 100755 ---- a/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/port_config.ini -+++ b/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/port_config.ini -@@ -1,55 +1,55 @@ --# name lanes alias index speed autoneg --Ethernet0 26 thousandE1 1 1000 on --Ethernet1 25 thousandE2 2 1000 on --Ethernet2 28 thousandE3 3 1000 on --Ethernet3 27 thousandE4 4 1000 on --Ethernet4 30 thousandE5 5 1000 on --Ethernet5 29 thousandE6 6 1000 on --Ethernet6 32 thousandE7 7 1000 on --Ethernet7 31 thousandE8 8 1000 on --Ethernet8 38 thousandE9 9 1000 on --Ethernet9 37 thousandE10 10 1000 on --Ethernet10 40 thousandE11 11 1000 on --Ethernet11 39 thousandE12 12 1000 on --Ethernet12 34 thousandE13 13 1000 on --Ethernet13 33 thousandE14 14 1000 on --Ethernet14 36 thousandE15 15 1000 on --Ethernet15 35 thousandE16 16 1000 on --Ethernet16 46 thousandE17 17 1000 on --Ethernet17 45 thousandE18 18 1000 on --Ethernet18 48 thousandE19 19 1000 on --Ethernet19 47 thousandE20 20 1000 on --Ethernet20 42 thousandE21 21 1000 on --Ethernet21 41 thousandE22 22 1000 on --Ethernet22 44 thousandE23 23 1000 on --Ethernet23 43 thousandE24 24 1000 on --Ethernet24 2 thousandE25 25 1000 on --Ethernet25 1 thousandE26 26 1000 on --Ethernet26 4 thousandE27 27 1000 on --Ethernet27 3 thousandE28 28 1000 on --Ethernet28 6 thousandE29 29 1000 on --Ethernet29 5 thousandE30 30 1000 on --Ethernet30 8 thousandE31 31 1000 on --Ethernet31 7 thousandE32 32 1000 on --Ethernet32 10 thousandE33 33 1000 on --Ethernet33 9 thousandE34 34 1000 on --Ethernet34 12 thousandE35 35 1000 on --Ethernet35 11 thousandE36 36 1000 on --Ethernet36 14 thousandE37 37 1000 on --Ethernet37 13 thousandE38 38 1000 on --Ethernet38 16 thousandE39 39 1000 on --Ethernet39 15 thousandE40 40 1000 on --Ethernet40 18 thousandE41 41 1000 on --Ethernet41 17 thousandE42 42 1000 on --Ethernet42 20 thousandE43 43 1000 on --Ethernet43 19 thousandE44 44 1000 on --Ethernet44 22 thousandE45 45 1000 on --Ethernet45 21 thousandE46 46 1000 on --Ethernet46 24 thousandE47 47 1000 on --Ethernet47 23 thousandE48 48 1000 on --Ethernet48 67 twentyfiveGigE49 49 25000 off --Ethernet49 66 twentyfiveGigE50 50 25000 off --Ethernet50 65 twentyfiveGigE51 51 25000 off --Ethernet51 68 twentyfiveGigE52 52 25000 off --Ethernet52 73,74,75,76 hundredGigE53 53 100000 off --Ethernet56 69,70,71,72 hundredGigE54 54 100000 off -+# name lanes alias index speed autoneg -+Ethernet0 26 Eth1(Port1) 1 1000 on -+Ethernet1 25 Eth2(Port2) 2 1000 on -+Ethernet2 28 Eth3(Port3) 3 1000 on -+Ethernet3 27 Eth4(Port4) 4 1000 on -+Ethernet4 30 Eth5(Port5) 5 1000 on -+Ethernet5 29 Eth6(Port6) 6 1000 on -+Ethernet6 32 Eth7(Port7) 7 1000 on -+Ethernet7 31 Eth8(Port8) 8 1000 on -+Ethernet8 38 Eth9(Port9) 9 1000 on -+Ethernet9 37 Eth10(Port10) 10 1000 on -+Ethernet10 40 Eth11(Port11) 11 1000 on -+Ethernet11 39 Eth12(Port12) 12 1000 on -+Ethernet12 34 Eth13(Port13) 13 1000 on -+Ethernet13 33 Eth14(Port14) 14 1000 on -+Ethernet14 36 Eth15(Port15) 15 1000 on -+Ethernet15 35 Eth16(Port16) 16 1000 on -+Ethernet16 46 Eth17(Port17) 17 1000 on -+Ethernet17 45 Eth18(Port18) 18 1000 on -+Ethernet18 48 Eth19(Port19) 19 1000 on -+Ethernet19 47 Eth20(Port20) 20 1000 on -+Ethernet20 42 Eth21(Port21) 21 1000 on -+Ethernet21 41 Eth22(Port22) 22 1000 on -+Ethernet22 44 Eth23(Port23) 23 1000 on -+Ethernet23 43 Eth24(Port24) 24 1000 on -+Ethernet24 2 Eth25(Port25) 25 1000 on -+Ethernet25 1 Eth26(Port26) 26 1000 on -+Ethernet26 4 Eth27(Port27) 27 1000 on -+Ethernet27 3 Eth28(Port28) 28 1000 on -+Ethernet28 6 Eth29(Port29) 29 1000 on -+Ethernet29 5 Eth30(Port30) 30 1000 on -+Ethernet30 8 Eth31(Port31) 31 1000 on -+Ethernet31 7 Eth32(Port32) 32 1000 on -+Ethernet32 10 Eth33(Port33) 33 1000 on -+Ethernet33 9 Eth34(Port34) 34 1000 on -+Ethernet34 12 Eth35(Port35) 35 1000 on -+Ethernet35 11 Eth36(Port36) 36 1000 on -+Ethernet36 14 Eth37(Port37) 37 1000 on -+Ethernet37 13 Eth38(Port38) 38 1000 on -+Ethernet38 16 Eth39(Port39) 39 1000 on -+Ethernet39 15 Eth40(Port40) 40 1000 on -+Ethernet40 18 Eth41(Port41) 41 1000 on -+Ethernet41 17 Eth42(Port42) 42 1000 on -+Ethernet42 20 Eth43(Port43) 43 1000 on -+Ethernet43 19 Eth44(Port44) 44 1000 on -+Ethernet44 22 Eth45(Port45) 45 1000 on -+Ethernet45 21 Eth46(Port46) 46 1000 on -+Ethernet46 24 Eth47(Port47) 47 1000 on -+Ethernet47 23 Eth48(Port48) 48 1000 on -+Ethernet48 67 Eth49(Port49) 49 25000 off -+Ethernet49 66 Eth50(Port50) 50 25000 off -+Ethernet50 65 Eth51(Port51) 51 25000 off -+Ethernet51 68 Eth52(Port52) 52 25000 off -+Ethernet52 73,74,75,76 Eth53(Port53) 53 100000 off -+Ethernet56 69,70,71,72 Eth54(Port54) 54 100000 off -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/sai.profile b/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/sai.profile -new file mode 100755 -index 000000000..5329410fe ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/Accton-AS4630-54TE/sai.profile -@@ -0,0 +1 @@ -+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/hx5-as4630-48x1G+4x25G+2x100G.bcm -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/installer.conf b/device/accton/x86_64-accton_as4630_54te-r0/installer.conf -index 925a32fc0..d5f9419d7 100755 ---- a/device/accton/x86_64-accton_as4630_54te-r0/installer.conf -+++ b/device/accton/x86_64-accton_as4630_54te-r0/installer.conf -@@ -1,3 +1,4 @@ - CONSOLE_PORT=0x3f8 - CONSOLE_DEV=0 - CONSOLE_SPEED=115200 -+ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pcie_aspm=off" -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/led_proc_init.soc b/device/accton/x86_64-accton_as4630_54te-r0/led_proc_init.soc -new file mode 100644 -index 000000000..696632b6e ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/led_proc_init.soc -@@ -0,0 +1,3 @@ -+#m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin -+led start -+#led auto on -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/pcie.yaml b/device/accton/x86_64-accton_as4630_54te-r0/pcie.yaml -new file mode 100644 -index 000000000..c7e99c867 ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/pcie.yaml -@@ -0,0 +1,167 @@ -+- bus: '00' -+ dev: '00' -+ fn: '0' -+ id: '1980' -+ name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent (rev -+ 11)' -+- bus: '00' -+ dev: '04' -+ fn: '0' -+ id: 19a1 -+ name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers -+ (rev 11)' -+- bus: '00' -+ dev: '05' -+ fn: '0' -+ id: 19a2 -+ name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000 -+ Series Root Complex Event Collector (rev 11)' -+- bus: '00' -+ dev: '06' -+ fn: '0' -+ id: 19a3 -+ name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT -+ Root Port (rev 11)' -+- bus: '00' -+ dev: 09 -+ fn: '0' -+ id: 19a4 -+ name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root -+ Port #0 (rev 11)' -+- bus: '00' -+ dev: 0b -+ fn: '0' -+ id: 19a6 -+ name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root -+ Port #2 (rev 11)' -+- bus: '00' -+ dev: 0e -+ fn: '0' -+ id: 19a8 -+ name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root -+ Port #4 (rev 11)' -+- bus: '00' -+ dev: '10' -+ fn: '0' -+ id: 19aa -+ name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root -+ Port #6 (rev 11)' -+- bus: '00' -+ dev: '12' -+ fn: '0' -+ id: 19ac -+ name: 'System peripheral: Intel Corporation Atom Processor C3000 Series SMBus Contoller -+ - Host (rev 11)' -+- bus: '00' -+ dev: '13' -+ fn: '0' -+ id: 19b2 -+ name: 'SATA controller: Intel Corporation Atom Processor C3000 Series SATA Controller -+ 0 (rev 11)' -+- bus: '00' -+ dev: '15' -+ fn: '0' -+ id: 19d0 -+ name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI -+ Controller (rev 11)' -+- bus: '00' -+ dev: '16' -+ fn: '0' -+ id: 19d1 -+ name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN -+ Root Port #0 (rev 11)' -+- bus: '00' -+ dev: '17' -+ fn: '0' -+ id: 19d2 -+ name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN -+ Root Port #1 (rev 11)' -+- bus: '00' -+ dev: '18' -+ fn: '0' -+ id: 19d3 -+ name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME -+ HECI 1 (rev 11)' -+- bus: '00' -+ dev: 1a -+ fn: '0' -+ id: 19d8 -+ name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller -+ (rev 11)' -+- bus: '00' -+ dev: 1a -+ fn: '1' -+ id: 19d8 -+ name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller -+ (rev 11)' -+- bus: '00' -+ dev: 1a -+ fn: '2' -+ id: 19d8 -+ name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller -+ (rev 11)' -+- bus: '00' -+ dev: 1c -+ fn: '0' -+ id: 19db -+ name: 'SD Host controller: Intel Corporation Device 19db (rev 11)' -+- bus: '00' -+ dev: 1f -+ fn: '0' -+ id: 19dc -+ name: 'ISA bridge: Intel Corporation Atom Processor C3000 Series LPC or eSPI (rev -+ 11)' -+- bus: '00' -+ dev: 1f -+ fn: '1' -+ id: 19dd -+ name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Primary -+ to Side Band (P2SB) Bridge (rev 11)' -+- bus: '00' -+ dev: 1f -+ fn: '2' -+ id: 19de -+ name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management -+ Controller (rev 11)' -+- bus: '00' -+ dev: 1f -+ fn: '4' -+ id: 19df -+ name: 'SMBus: Intel Corporation Atom Processor C3000 Series SMBus controller (rev -+ 11)' -+- bus: '00' -+ dev: 1f -+ fn: '5' -+ id: 19e0 -+ name: 'Serial bus controller [0c80]: Intel Corporation Atom Processor C3000 Series -+ SPI Controller (rev 11)' -+- bus: '01' -+ dev: '00' -+ fn: '0' -+ id: 19e2 -+ name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology -+ (rev 11)' -+- bus: '05' -+ dev: '00' -+ fn: '0' -+ id: b371 -+ name: 'Ethernet controller: Broadcom Inc. and subsidiaries BCM56371 Switch ASIC -+ (rev 03)' -+- bus: '06' -+ dev: '00' -+ fn: '0' -+ id: 15c2 -+ name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane -+ (rev 11)' -+- bus: '06' -+ dev: '00' -+ fn: '1' -+ id: 15c2 -+ name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane -+ (rev 11)' -+- bus: 08 -+ dev: '00' -+ fn: '0' -+ id: 15e5 -+ name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 1GbE (rev -+ 11)' -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/platform.json b/device/accton/x86_64-accton_as4630_54te-r0/platform.json -new file mode 100644 -index 000000000..af158fc72 ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/platform.json -@@ -0,0 +1,820 @@ -+{ -+ "chassis": { -+ "name": "AS4630-54TE", -+ "thermal_manager":false, -+ "status_led": { -+ "controllable": true, -+ "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_GREEN_BLINK", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"] -+ }, -+ "components": [ -+ { -+ "name": "CPLD1" -+ }, -+ { -+ "name": "CPLD2" -+ }, -+ { -+ "name": "BIOS" -+ } -+ ], -+ "fans": [ -+ { -+ "name": "FAN-1", -+ "speed": { -+ "controllable": true, -+ "minimum": 7 -+ }, -+ "status_led": { -+ "controllable": false -+ } -+ }, -+ { -+ "name": "FAN-2", -+ "speed": { -+ "controllable": true, -+ "minimum": 7 -+ }, -+ "status_led": { -+ "controllable": false -+ } -+ }, -+ { -+ "name": "FAN-3", -+ "speed": { -+ "controllable": true, -+ "minimum": 7 -+ }, -+ "status_led": { -+ "controllable": false -+ } -+ } -+ ], -+ "fan_drawers":[ -+ { -+ "name": "FanTray1", -+ "status_led": { -+ "controllable": false -+ }, -+ "num_fans" : 1, -+ "fans": [ -+ { -+ "name": "FAN-1", -+ "speed": { -+ "controllable": true, -+ "minimum": 7 -+ }, -+ "status_led": { -+ "controllable": false -+ } -+ } -+ ] -+ }, -+ { -+ "name": "FanTray2", -+ "status_led": { -+ "controllable": false -+ }, -+ "num_fans" : 1, -+ "fans": [ -+ { -+ "name": "FAN-2", -+ "speed": { -+ "controllable": true, -+ "minimum": 7 -+ }, -+ "status_led": { -+ "controllable": false -+ } -+ } -+ ] -+ }, -+ { -+ "name": "FanTray3", -+ "status_led": { -+ "controllable": false -+ }, -+ "num_fans" : 1, -+ "fans": [ -+ { -+ "name": "FAN-3", -+ "speed": { -+ "controllable": true, -+ "minimum": 7 -+ }, -+ "status_led": { -+ "controllable": false -+ } -+ } -+ ] -+ } -+ ], -+ "psus": [ -+ { -+ "name": "PSU-1", -+ "status_led": { -+ "controllable": true, -+ "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"] -+ }, -+ "fans": [ -+ { -+ "name": "PSU-1 FAN-1" -+ } -+ ], -+ "thermals": [ -+ { -+ "name": "PSU-1 temp sensor 1", -+ "controllable": false, -+ "low-crit-threshold": false, -+ "high-crit-threshold": false -+ } -+ ] -+ }, -+ { -+ "name": "PSU-2", -+ "status_led": { -+ "controllable": true, -+ "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"] -+ }, -+ "fans": [ -+ { -+ "name": "PSU-2 FAN-1" -+ } -+ ], -+ "thermals": [ -+ { -+ "name": "PSU-2 temp sensor 1", -+ "controllable": false, -+ "low-crit-threshold": false, -+ "high-crit-threshold": false -+ } -+ ] -+ } -+ ], -+ "thermals": [ -+ { -+ "name": "MB_temp(0x48)", -+ "controllable": true, -+ "low-threshold": false, -+ "high-threshold": true, -+ "low-crit-threshold": false, -+ "high-crit-threshold": false -+ }, -+ { -+ "name": "CB_temp(0x4B)", -+ "controllable": true, -+ "low-threshold": false, -+ "high-threshold": true, -+ "low-crit-threshold": false, -+ "high-crit-threshold": false -+ }, -+ { -+ "name": "FB_temp(0x4A)", -+ "controllable": true, -+ "low-threshold": false, -+ "high-threshold": true, -+ "low-crit-threshold": false, -+ "high-crit-threshold": false -+ }, -+ { -+ "name": "CPU_Package_temp", -+ "controllable": false, -+ "low-threshold": false, -+ "high-threshold": true, -+ "low-crit-threshold": false, -+ "high-crit-threshold": true -+ }, -+ { -+ "name": "CPU_Core_0_temp", -+ "controllable": false, -+ "low-threshold": false, -+ "high-threshold": true, -+ "low-crit-threshold": false, -+ "high-crit-threshold": true -+ }, -+ { -+ "name": "CPU_Core_1_temp", -+ "controllable": false, -+ "low-threshold": false, -+ "high-threshold": true, -+ "low-crit-threshold": false, -+ "high-crit-threshold": true -+ }, -+ { -+ "name": "CPU_Core_2_temp", -+ "controllable": false, -+ "low-threshold": false, -+ "high-threshold": true, -+ "low-crit-threshold": false, -+ "high-crit-threshold": true -+ }, -+ { -+ "name": "CPU_Core_3_temp", -+ "controllable": false, -+ "low-threshold": false, -+ "high-threshold": true, -+ "low-crit-threshold": false, -+ "high-crit-threshold": true -+ } -+ ], -+ "sfps": [ -+ { -+ "name": "Ethernet0" -+ }, -+ { -+ "name": "Ethernet1" -+ }, -+ { -+ "name": "Ethernet2" -+ }, -+ { -+ "name": "Ethernet3" -+ }, -+ { -+ "name": "Ethernet4" -+ }, -+ { -+ "name": "Ethernet5" -+ }, -+ { -+ "name": "Ethernet6" -+ }, -+ { -+ "name": "Ethernet7" -+ }, -+ { -+ "name": "Ethernet8" -+ }, -+ { -+ "name": "Ethernet9" -+ }, -+ { -+ "name": "Ethernet10" -+ }, -+ { -+ "name": "Ethernet11" -+ }, -+ { -+ "name": "Ethernet12" -+ }, -+ { -+ "name": "Ethernet13" -+ }, -+ { -+ "name": "Ethernet14" -+ }, -+ { -+ "name": "Ethernet15" -+ }, -+ { -+ "name": "Ethernet16" -+ }, -+ { -+ "name": "Ethernet17" -+ }, -+ { -+ "name": "Ethernet18" -+ }, -+ { -+ "name": "Ethernet19" -+ }, -+ { -+ "name": "Ethernet20" -+ }, -+ { -+ "name": "Ethernet21" -+ }, -+ { -+ "name": "Ethernet22" -+ }, -+ { -+ "name": "Ethernet23" -+ }, -+ { -+ "name": "Ethernet24" -+ }, -+ { -+ "name": "Ethernet25" -+ }, -+ { -+ "name": "Ethernet26" -+ }, -+ { -+ "name": "Ethernet27" -+ }, -+ { -+ "name": "Ethernet28" -+ }, -+ { -+ "name": "Ethernet29" -+ }, -+ { -+ "name": "Ethernet30" -+ }, -+ { -+ "name": "Ethernet31" -+ }, -+ { -+ "name": "Ethernet32" -+ }, -+ { -+ "name": "Ethernet33" -+ }, -+ { -+ "name": "Ethernet34" -+ }, -+ { -+ "name": "Ethernet35" -+ }, -+ { -+ "name": "Ethernet36" -+ }, -+ { -+ "name": "Ethernet37" -+ }, -+ { -+ "name": "Ethernet38" -+ }, -+ { -+ "name": "Ethernet39" -+ }, -+ { -+ "name": "Ethernet40" -+ }, -+ { -+ "name": "Ethernet41" -+ }, -+ { -+ "name": "Ethernet42" -+ }, -+ { -+ "name": "Ethernet43" -+ }, -+ { -+ "name": "Ethernet44" -+ }, -+ { -+ "name": "Ethernet45" -+ }, -+ { -+ "name": "Ethernet46" -+ }, -+ { -+ "name": "Ethernet47" -+ }, -+ { -+ "name": "Ethernet48" -+ }, -+ { -+ "name": "Ethernet49" -+ }, -+ { -+ "name": "Ethernet50" -+ }, -+ { -+ "name": "Ethernet51" -+ }, -+ { -+ "name": "Ethernet52" -+ }, -+ { -+ "name": "Ethernet56" -+ } -+ ] -+ }, -+ "interfaces": { -+ "Ethernet0": { -+ "index": "1", -+ "lanes": "26", -+ "breakout_modes": { -+ "1x1G": ["Eth1(Port1)"] -+ } -+ }, -+ -+ "Ethernet1": { -+ "index": "2", -+ "lanes": "25", -+ "breakout_modes": { -+ "1x1G": ["Eth2(Port2)"] -+ } -+ }, -+ -+ "Ethernet2": { -+ "index": "3", -+ "lanes": "28", -+ "breakout_modes": { -+ "1x1G": ["Eth3(Port3)"] -+ } -+ }, -+ -+ "Ethernet3": { -+ "index": "4", -+ "lanes": "27", -+ "breakout_modes": { -+ "1x1G": ["Eth4(Port4)"] -+ } -+ }, -+ -+ "Ethernet4": { -+ "index": "5", -+ "lanes": "30", -+ "breakout_modes": { -+ "1x1G": ["Eth5(Port5)"] -+ } -+ }, -+ -+ "Ethernet5": { -+ "index": "6", -+ "lanes": "29", -+ "breakout_modes": { -+ "1x1G": ["Eth6(Port6)"] -+ } -+ }, -+ -+ "Ethernet6": { -+ "index": "7", -+ "lanes": "32", -+ "breakout_modes": { -+ "1x1G": ["Eth7(Port7)"] -+ } -+ }, -+ -+ "Ethernet7": { -+ "index": "8", -+ "lanes": "31", -+ "breakout_modes": { -+ "1x1G": ["Eth8(Port8)"] -+ } -+ }, -+ -+ "Ethernet8": { -+ "index": "9", -+ "lanes": "38", -+ "breakout_modes": { -+ "1x1G": ["Eth9(Port9)"] -+ } -+ }, -+ -+ "Ethernet9": { -+ "index": "10", -+ "lanes": "37", -+ "breakout_modes": { -+ "1x1G": ["Eth10(Port10)"] -+ } -+ }, -+ -+ "Ethernet10": { -+ "index": "11", -+ "lanes": "40", -+ "breakout_modes": { -+ "1x1G": ["Eth11(Port11)"] -+ } -+ }, -+ -+ "Ethernet11": { -+ "index": "12", -+ "lanes": "39", -+ "breakout_modes": { -+ "1x1G": ["Eth12(Port12)"] -+ } -+ }, -+ -+ "Ethernet12": { -+ "index": "13", -+ "lanes": "34", -+ "breakout_modes": { -+ "1x1G": ["Eth13(Port13)"] -+ } -+ }, -+ -+ "Ethernet13": { -+ "index": "14", -+ "lanes": "33", -+ "breakout_modes": { -+ "1x1G": ["Eth14(Port14)"] -+ } -+ }, -+ -+ "Ethernet14": { -+ "index": "15", -+ "lanes": "36", -+ "breakout_modes": { -+ "1x1G": ["Eth15(Port15)"] -+ } -+ }, -+ -+ "Ethernet15": { -+ "index": "16", -+ "lanes": "35", -+ "breakout_modes": { -+ "1x1G": ["Eth16(Port16)"] -+ } -+ }, -+ -+ "Ethernet16": { -+ "index": "17", -+ "lanes": "46", -+ "breakout_modes": { -+ "1x1G": ["Eth17(Port17)"] -+ } -+ }, -+ -+ "Ethernet17": { -+ "index": "18", -+ "lanes": "45", -+ "breakout_modes": { -+ "1x1G": ["Eth18(Port18)"] -+ } -+ }, -+ -+ "Ethernet18": { -+ "index": "19", -+ "lanes": "48", -+ "breakout_modes": { -+ "1x1G": ["Eth19(Port19)"] -+ } -+ }, -+ -+ "Ethernet19": { -+ "index": "20", -+ "lanes": "47", -+ "breakout_modes": { -+ "1x1G": ["Eth20(Port20)"] -+ } -+ }, -+ -+ "Ethernet20": { -+ "index": "21", -+ "lanes": "42", -+ "breakout_modes": { -+ "1x1G": ["Eth21(Port21)"] -+ } -+ }, -+ -+ "Ethernet21": { -+ "index": "22", -+ "lanes": "41", -+ "breakout_modes": { -+ "1x1G": ["Eth22(Port22)"] -+ } -+ }, -+ -+ "Ethernet22": { -+ "index": "23", -+ "lanes": "44", -+ "breakout_modes": { -+ "1x1G": ["Eth23(Port23)"] -+ } -+ }, -+ -+ "Ethernet23": { -+ "index": "24", -+ "lanes": "43", -+ "breakout_modes": { -+ "1x1G": ["Eth24(Port24)"] -+ } -+ }, -+ -+ "Ethernet24": { -+ "index": "25", -+ "lanes": "2", -+ "breakout_modes": { -+ "1x1G": ["Eth25(Port25)"] -+ } -+ }, -+ -+ "Ethernet25": { -+ "index": "26", -+ "lanes": "1", -+ "breakout_modes": { -+ "1x1G": ["Eth26(Port26)"] -+ } -+ }, -+ -+ "Ethernet26": { -+ "index": "27", -+ "lanes": "4", -+ "breakout_modes": { -+ "1x1G": ["Eth27(Port27)"] -+ } -+ }, -+ -+ "Ethernet27": { -+ "index": "28", -+ "lanes": "3", -+ "breakout_modes": { -+ "1x1G": ["Eth28(Port28)"] -+ } -+ }, -+ -+ "Ethernet28": { -+ "index": "29", -+ "lanes": "6", -+ "breakout_modes": { -+ "1x1G": ["Eth29(Port29)"] -+ } -+ }, -+ -+ "Ethernet29": { -+ "index": "30", -+ "lanes": "5", -+ "breakout_modes": { -+ "1x1G": ["Eth30(Port30)"] -+ } -+ }, -+ -+ "Ethernet30": { -+ "index": "31", -+ "lanes": "8", -+ "breakout_modes": { -+ "1x1G": ["Eth31(Port31)"] -+ } -+ }, -+ -+ "Ethernet31": { -+ "index": "32", -+ "lanes": "7", -+ "breakout_modes": { -+ "1x1G": ["Eth32(Port32)"] -+ } -+ }, -+ -+ "Ethernet32": { -+ "index": "33", -+ "lanes": "10", -+ "breakout_modes": { -+ "1x1G": ["Eth33(Port33)"] -+ } -+ }, -+ -+ "Ethernet33": { -+ "index": "34", -+ "lanes": "9", -+ "breakout_modes": { -+ "1x1G": ["Eth34(Port34)"] -+ } -+ }, -+ -+ "Ethernet34": { -+ "index": "35", -+ "lanes": "12", -+ "breakout_modes": { -+ "1x1G": ["Eth35(Port35)"] -+ } -+ }, -+ -+ "Ethernet35": { -+ "index": "36", -+ "lanes": "11", -+ "breakout_modes": { -+ "1x1G": ["Eth36(Port36)"] -+ } -+ }, -+ -+ "Ethernet36": { -+ "index": "37", -+ "lanes": "14", -+ "breakout_modes": { -+ "1x1G": ["Eth37(Port37)"] -+ } -+ }, -+ -+ "Ethernet37": { -+ "index": "38", -+ "lanes": "13", -+ "breakout_modes": { -+ "1x1G": ["Eth38(Port38)"] -+ } -+ }, -+ -+ "Ethernet38": { -+ "index": "39", -+ "lanes": "16", -+ "breakout_modes": { -+ "1x1G": ["Eth39(Port39)"] -+ } -+ }, -+ -+ "Ethernet39": { -+ "index": "40", -+ "lanes": "15", -+ "breakout_modes": { -+ "1x1G": ["Eth40(Port40)"] -+ } -+ }, -+ -+ "Ethernet40": { -+ "index": "41", -+ "lanes": "18", -+ "breakout_modes": { -+ "1x1G": ["Eth41(Port41)"] -+ } -+ }, -+ -+ "Ethernet41": { -+ "index": "42", -+ "lanes": "17", -+ "breakout_modes": { -+ "1x1G": ["Eth42(Port42)"] -+ } -+ }, -+ -+ "Ethernet42": { -+ "index": "43", -+ "lanes": "20", -+ "breakout_modes": { -+ "1x1G": ["Eth43(Port43)"] -+ } -+ }, -+ -+ "Ethernet43": { -+ "index": "44", -+ "lanes": "19", -+ "breakout_modes": { -+ "1x1G": ["Eth44(Port44)"] -+ } -+ }, -+ -+ "Ethernet44": { -+ "index": "45", -+ "lanes": "22", -+ "breakout_modes": { -+ "1x1G": ["Eth45(Port45)"] -+ } -+ }, -+ -+ "Ethernet45": { -+ "index": "46", -+ "lanes": "21", -+ "breakout_modes": { -+ "1x1G": ["Eth46(Port46)"] -+ } -+ }, -+ -+ "Ethernet46": { -+ "index": "47", -+ "lanes": "24", -+ "breakout_modes": { -+ "1x1G": ["Eth47(Port47)"] -+ } -+ }, -+ -+ "Ethernet47": { -+ "index": "48", -+ "lanes": "23", -+ "breakout_modes": { -+ "1x1G": ["Eth48(Port48)"] -+ } -+ }, -+ -+ "Ethernet48": { -+ "index": "49", -+ "lanes": "67", -+ "breakout_modes": { -+ "1x25G[10G]": ["Eth49(Port49)"] -+ } -+ }, -+ -+ "Ethernet49": { -+ "index": "50", -+ "lanes": "66", -+ "breakout_modes": { -+ "1x25G[10G]": ["Eth50(Port50)"] -+ } -+ }, -+ -+ "Ethernet50": { -+ "index": "51", -+ "lanes": "65", -+ "breakout_modes": { -+ "1x25G[10G]": ["Eth51(Port51)"] -+ } -+ }, -+ -+ "Ethernet51": { -+ "index": "52", -+ "lanes": "68", -+ "breakout_modes": { -+ "1x25G[10G]": ["Eth52(Port52)"] -+ } -+ }, -+ "Ethernet52": { -+ "index": "53,53,53,53", -+ "lanes": "73,74,75,76", -+ "breakout_modes": { -+ "1x100G[40G]": ["Eth53(Port53)"], -+ "2x50G": ["Eth53/1(Port53)", "Eth53/2(Port53)"], -+ "4x25G[10G]": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"] -+ } -+ }, -+ -+ "Ethernet56": { -+ "index": "54,54,54,54", -+ "lanes": "69,70,71,72", -+ "breakout_modes": { -+ "1x100G[40G]": ["Eth54(Port54)"], -+ "2x50G": ["Eth54/1(Port54)", "Eth54/2(Port54)"], -+ "4x25G[10G]": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"] -+ } -+ } -+ } -+} -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/platform_components.json b/device/accton/x86_64-accton_as4630_54te-r0/platform_components.json -new file mode 100644 -index 000000000..5e70a87a4 ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/platform_components.json -@@ -0,0 +1,11 @@ -+{ -+ "chassis": { -+ "AS4630-54TE-O-AC-F": { -+ "component": { -+ "CPLD1": { }, -+ "CPLD2": { }, -+ "BIOS": { } -+ } -+ } -+ } -+} -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as4630_54te-r0/plugins/eeprom.py -deleted file mode 100755 -index 7409239d0..000000000 ---- a/device/accton/x86_64-accton_as4630_54te-r0/plugins/eeprom.py -+++ /dev/null -@@ -1,13 +0,0 @@ --try: -- from sonic_eeprom import eeprom_tlvinfo -- --except ImportError as e: -- raise ImportError(str(e) + "- required module not found") -- -- --class board(eeprom_tlvinfo.TlvInfoDecoder): -- _TLV_INFO_MAX_LEN = 256 -- -- def __init__(self, name, path, cpld_root, ro): -- self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom" -- super(board, self).__init__(self.eeprom_path, 0, '', True) -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as4630_54te-r0/plugins/psuutil.py -deleted file mode 100755 -index 92ae68eb8..000000000 ---- a/device/accton/x86_64-accton_as4630_54te-r0/plugins/psuutil.py -+++ /dev/null -@@ -1,61 +0,0 @@ --#!/usr/bin/env python -- --############################################################################# --# Accton --# --# Module contains an implementation of SONiC PSU Base API and --# provides the PSUs status which are available in the platform --# --############################################################################# -- -- --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_path = "/sys/bus/i2c/devices/" -- self.psu_presence = "/psu_present" -- self.psu_oper_status = "/psu_power_good" -- self.psu_mapping = { -- 1: "10-0050", -- 2: "11-0051", -- } -- -- def get_num_psus(self): -- return len(self.psu_mapping) -- -- def get_psu_status(self, index): -- if index is None: -- return False -- -- status = 0 -- node = self.psu_path + self.psu_mapping[index] + self.psu_oper_status -- try: -- with open(node, 'r') as power_status: -- status = int(power_status.read()) -- except IOError: -- return False -- -- return status == 1 -- -- def get_psu_presence(self, index): -- if index is None: -- return False -- -- status = 0 -- node = self.psu_path + self.psu_mapping[index] + self.psu_presence -- try: -- with open(node, 'r') as presence_status: -- status = int(presence_status.read()) -- except IOError: -- return False -- -- return status == 1 -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as4630_54te-r0/plugins/sfputil.py -deleted file mode 100755 -index 63e6bd536..000000000 ---- a/device/accton/x86_64-accton_as4630_54te-r0/plugins/sfputil.py -+++ /dev/null -@@ -1,196 +0,0 @@ --# sfputil.py --# --# Platform-specific SFP transceiver interface for SONiC --# -- --try: -- import sys -- import time -- from ctypes import create_string_buffer -- from sonic_sfp.sfputilbase import SfpUtilBase --except ImportError as e: -- raise ImportError("%s - required module not found" % str(e)) -- --SFP_STATUS_INSERTED = '1' --SFP_STATUS_REMOVED = '0' -- -- --class SfpUtil(SfpUtilBase): -- """Platform-specific SfpUtil class""" -- -- PORT_START = 49 -- PORT_END = 54 -- PORTS_IN_BLOCK = 54 -- QSFP_START = 53 -- -- BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/" -- BASE_CPLD_PATH = "/sys/bus/i2c/devices/3-0060/" -- -- _port_to_is_present = {} -- _port_to_lp_mode = {} -- -- _port_to_eeprom_mapping = {} -- _port_to_i2c_mapping = { -- 49: [18], -- 50: [19], -- 51: [20], -- 52: [21], -- 53: [22], -- 54: [23], -- } -- -- @property -- def port_start(self): -- return self.PORT_START -- -- @property -- def port_end(self): -- return self.PORT_END -- -- @property -- def qsfp_ports(self): -- return range(self.PORT_START, self.PORTS_IN_BLOCK + 1) -- -- @property -- def port_to_eeprom_mapping(self): -- return self._port_to_eeprom_mapping -- -- def __init__(self): -- eeprom_path = self.BASE_OOM_PATH + "eeprom" -- for x in range(self.port_start, self.port_end + 1): -- self.port_to_eeprom_mapping[x] = eeprom_path.format( -- self._port_to_i2c_mapping[x][0]) -- SfpUtilBase.__init__(self) -- -- def get_presence(self, port_num): -- # Check for invalid port_num -- if port_num < self.port_start or port_num > self.port_end: -- return False -- -- present_path = self.BASE_CPLD_PATH + "module_present_" + str(port_num) -- self.__port_to_is_present = present_path -- -- try: -- val_file = open(self.__port_to_is_present) -- content = val_file.readline().rstrip() -- val_file.close() -- except IOError as e: -- print ('Error: unable to access file: %s') % str(e) -- return False -- -- if content == "1": -- return True -- -- return False -- -- def get_low_power_mode(self, port_num): -- # Check for invalid port_num -- if port_num < self.QSFP_START or port_num > self.port_end: -- return False -- -- try: -- eeprom = None -- if not self.get_presence(port_num): -- return False -- eeprom = open(self.port_to_eeprom_mapping[port_num], "rb") -- eeprom.seek(93) -- lpmode = ord(eeprom.read(1)) -- -- # if "Power override" bit is 1 and "Power set" bit is 1 -- if ((lpmode & 0x3) == 0x3): -- return True -- -- # High Power Mode if one of the following conditions is matched: -- # 1. "Power override" bit is 0 -- # 2. "Power override" bit is 1 and "Power set" bit is 0 -- else: -- return False -- -- except IOError as e: -- print ('Error: unable to open file: %s') % str(e) -- return False -- finally: -- if eeprom is not None: -- eeprom.close() -- time.sleep(0.01) -- -- def set_low_power_mode(self, port_num, lpmode): -- # Check for invalid port_num -- if port_num < self.QSFP_START or port_num > self.port_end: -- return False -- -- try: -- eeprom = None -- if not self.get_presence(port_num): -- return False # Port is not present, unable to set the eeprom -- -- # Fill in write buffer -- # 0x3:Low Power Mode, 0x1:High Power Mode -- regval = 0x3 if lpmode else 0x1 -- -- buffer = create_string_buffer(1) -- if sys.version_info[0] >= 3: -- buffer[0] = regval -- else: -- buffer[0] = chr(regval) -- -- # Write to eeprom -- eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b") -- eeprom.seek(93) -- eeprom.write(buffer[0]) -- return True -- except IOError as e: -- print ('Error: unable to open file: %s') % str(e) -- return False -- finally: -- if eeprom is not None: -- eeprom.close() -- time.sleep(0.01) -- -- def reset(self, port_num): -- raise NotImplementedError -- -- @property -- def _get_presence_bitmap(self): -- -- bits = [] -- for x in range(self.port_start, self.port_end + 1): -- bits.append(str(int(self.get_presence(x)))) -- -- rev = "".join(bits[::-1]) -- return int(rev, 2) -- -- data = {'present': 0} -- -- def get_transceiver_change_event(self, timeout=0): -- port_dict = {} -- -- if timeout == 0: -- cd_ms = sys.maxsize -- else: -- cd_ms = timeout -- -- # poll per second -- while cd_ms > 0: -- reg_value = self._get_presence_bitmap -- changed_ports = self.data['present'] ^ reg_value -- if changed_ports != 0: -- break -- time.sleep(1) -- cd_ms = cd_ms - 1000 -- -- if changed_ports != 0: -- for port in range(self.port_start, self.port_end + 1): -- # Mask off the bit corresponding to our port -- mask = (1 << (port - self.port_start)) -- if changed_ports & mask: -- if (reg_value & mask) == 0: -- port_dict[port] = SFP_STATUS_REMOVED -- else: -- port_dict[port] = SFP_STATUS_INSERTED -- -- # Update cache -- self.data['present'] = reg_value -- return True, port_dict -- else: -- return True, {} -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/plugins/ssd_util.py b/device/accton/x86_64-accton_as4630_54te-r0/plugins/ssd_util.py -new file mode 100755 -index 000000000..4b173c5e3 ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/plugins/ssd_util.py -@@ -0,0 +1,24 @@ -+# ssd_util.py -+# -+# Platform-specific SSD interface for SONiC -+## -+ -+try: -+ from sonic_platform_base.sonic_ssd.ssd_generic import SsdUtil as MainSsdUtil -+except ImportError as e: -+ raise ImportError (str(e) + "- required module not found") -+ -+NOT_AVAILABLE = "N/A" -+ -+class SsdUtil(MainSsdUtil): -+ """Platform-specific SsdUtil class""" -+ -+ def __init__(self, diskdev): -+ super(SsdUtil, self).__init__(diskdev) -+ -+ # If it has no vendor tool to read SSD information, -+ # ssd_util.py will use generic SSD information -+ # for vendor SSD information. -+ if self.vendor_ssd_info == NOT_AVAILABLE: -+ self.vendor_ssd_info = self.ssd_info -+ -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as4630_54te-r0/pmon_daemon_control.json -index a3b204e20..44bad6494 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/pmon_daemon_control.json -+++ b/device/accton/x86_64-accton_as4630_54te-r0/pmon_daemon_control.json -@@ -1,5 +1,4 @@ - { -- "skip_ledd": true, -- "skip_pcied": true -+ "skip_ledd": true - } - -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sensors.conf b/device/accton/x86_64-accton_as4630_54te-r0/sensors.conf -index b22fff04d..cbb82e0df 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sensors.conf -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sensors.conf -@@ -31,10 +31,10 @@ chip "as4630_54te_cpld-*" - - - chip "lm77-i2c-*-48" -- label temp1 "Main Board Temperature" -+ label temp1 "MB_temp" - - chip "lm75-i2c-*-4a" -- label temp1 "Fan Board Temperature" -+ label temp1 "FB_temp" - - chip "lm75-i2c-*-4b" -- label temp1 "CPU Board Temperature" -+ label temp1 "CB_temp" -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/chassis.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/chassis.py -index 9f39c903c..9ec4c7ccf 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/chassis.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/chassis.py -@@ -6,27 +6,27 @@ - # - ############################################################################# - --import subprocess -- - try: -+ import sys - from sonic_platform_base.chassis_base import ChassisBase - from .helper import APIHelper -+ from .event import SfpEvent - except ImportError as e: - raise ImportError(str(e) + "- required module not found") - - NUM_FAN_TRAY = 3 - NUM_FAN = 2 - NUM_PSU = 2 --NUM_THERMAL = 3 -+NUM_THERMAL = 8 - NUM_QSFP = 6 - PORT_START = 49 - PORT_END = 54 --NUM_COMPONENT = 2 -+NUM_COMPONENT = 3 - HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/" - PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/" - REBOOT_CAUSE_FILE = "reboot-cause.txt" - PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt" --HOST_CHK_CMD = ["docker"] -+HOST_CHK_CMD = "which systemctl > /dev/null 2>&1" - SYSLED_FNODE = "/sys/class/leds/diag/brightness" - SYSLED_MODES = { - "0" : "STATUS_LED_COLOR_OFF", -@@ -42,7 +42,6 @@ class Chassis(ChassisBase): - def __init__(self): - ChassisBase.__init__(self) - self._api_helper = APIHelper() -- self._api_helper = APIHelper() - self.is_host = self._api_helper.is_host() - - self.config_data = {} -@@ -59,6 +58,7 @@ class Chassis(ChassisBase): - for index in range(0, PORT_END): - sfp = Sfp(index) - self._sfp_list.append(sfp) -+ self._sfpevent = SfpEvent(self._sfp_list) - self.sfp_module_initialized = True - - def __initialize_fan(self): -@@ -89,23 +89,6 @@ class Chassis(ChassisBase): - component = Component(index) - self._component_list.append(component) - -- def __initialize_watchdog(self): -- from sonic_platform.watchdog import Watchdog -- self._watchdog = Watchdog() -- -- -- def __is_host(self): -- return subprocess.call(HOST_CHK_CMD) == 0 -- -- def __read_txt_file(self, file_path): -- try: -- with open(file_path, 'r') as fd: -- data = fd.read() -- return data.strip() -- except IOError: -- pass -- return None -- - def get_name(self): - """ - Retrieves the name of the device -@@ -113,7 +96,7 @@ class Chassis(ChassisBase): - string: The name of the device - """ - -- return self._api_helper.hwsku -+ return self._eeprom.get_modelstr() - - def get_presence(self): - """ -@@ -176,6 +159,12 @@ class Chassis(ChassisBase): - - return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause) - -+ def get_change_event(self, timeout=0): -+ # SFP event -+ if not self.sfp_module_initialized: -+ self.__initialize_sfp() -+ return self._sfpevent.get_sfp_event(timeout) -+ - def get_sfp(self, index): - """ - Retrieves sfp represented by (1-based) index -@@ -234,3 +223,28 @@ class Chassis(ChassisBase): - return False - else: - return self._api_helper.write_txt_file(SYSLED_FNODE, mode) -+ -+ def get_model(self): -+ """ -+ Retrieves the model number (or part number) of the device -+ Returns: -+ string: Model/part number of device -+ """ -+ return self._eeprom.get_pn() -+ -+ def get_serial(self): -+ """ -+ Retrieves the serial number of the device -+ Returns: -+ string: Serial number of device -+ """ -+ return self._eeprom.get_serial() -+ -+ def get_revision(self): -+ """ -+ Retrieves the hardware revision of the device -+ -+ Returns: -+ string: Revision value of device -+ """ -+ return self._eeprom.get_revisionstr() -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/component.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/component.py -index 8137d0f3a..f5dafd007 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/component.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/component.py -@@ -6,10 +6,12 @@ - # - ############################################################################# - -- - try: -+ import os -+ import json - from sonic_platform_base.component_base import ComponentBase - from .helper import APIHelper -+ from sonic_py_common.general import getstatusoutput_noshell - except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -@@ -20,6 +22,7 @@ SYSFS_PATH = "/sys/bus/i2c/devices/" - BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version" - COMPONENT_LIST= [ - ("CPLD1", "CPLD 1"), -+ ("CPLD2", "CPLD CPU"), - ("BIOS", "Basic Input/Output System") - - ] -@@ -58,6 +61,15 @@ class Component(ComponentBase): - - return cpld_version - -+ def __get_cpldcpu_version(self): -+ cpld_version = dict() -+ cmd = ["i2cget", "-y", "1", "0x65", "0x01"] -+ status, output1 = getstatusoutput_noshell(cmd) -+ cmd = ["i2cget", "-y", "1", "0x65", "0x02"] -+ status, output2 = getstatusoutput_noshell(cmd) -+ cpld_version[self.name] = "{}{}{}".format(int(output1,16),".",int(output2,16)) -+ return cpld_version -+ - def get_name(self): - """ - Retrieves the name of the component -@@ -85,9 +97,12 @@ class Component(ComponentBase): - - if self.name == "BIOS": - fw_version = self.__get_bios_version() -- elif "CPLD" in self.name: -+ elif self.name == "CPLD1": - cpld_version = self.__get_cpld_version() - fw_version = cpld_version.get(self.name) -+ elif self.name == "CPLD2": -+ cpld_version = self.__get_cpldcpu_version() -+ fw_version = cpld_version.get(self.name) - - return fw_version - -@@ -99,4 +114,85 @@ class Component(ComponentBase): - Returns: - A boolean, True if install successfully, False if not - """ -- raise NotImplementedError -+ ret, output = getstatusoutput_noshell(["tar", "-C", "/tmp", "-xzf", image_path ] ) -+ if ret != 0 : -+ print("Installation failed because of wrong image package") -+ return False -+ -+ if False == os.path.exists("/tmp/install.json") : -+ print("Installation failed without jsonfile") -+ return False -+ -+ input_file = open ('/tmp/install.json') -+ json_array = json.load(input_file) -+ ret = 1 -+ for item in json_array: -+ if item.get('id')==None or item.get('path')==None: -+ continue -+ if self.name == item['id'] and item['path'] and item.get('cpu'): -+ print( "Find", item['id'], item['path'], item['cpu'] ) -+ ret, output = getstatusoutput_noshell(["/tmp/run_install.sh", item['id'], item['path'], item['cpu'] ]) -+ if ret==0: -+ break -+ elif self.name == item['id'] and item['path']: -+ print( "Find", item['id'], item['path'] ) -+ ret, output = getstatusoutput_noshell(["/tmp/run_install.sh", item['id'], item['path'] ]) -+ if ret==0: -+ break -+ -+ if ret==0: -+ return True -+ else : -+ return False -+ -+ def get_presence(self): -+ """ -+ Retrieves the presence of the device -+ Returns: -+ bool: True if device is present, False if not -+ """ -+ return True -+ -+ def get_model(self): -+ """ -+ Retrieves the model number (or part number) of the device -+ Returns: -+ string: Model/part number of device -+ """ -+ return 'N/A' -+ -+ def get_serial(self): -+ """ -+ Retrieves the serial number of the device -+ Returns: -+ string: Serial number of device -+ """ -+ return 'N/A' -+ -+ def get_status(self): -+ """ -+ Retrieves the operational status of the device -+ Returns: -+ A boolean value, True if device is operating properly, False if not -+ """ -+ return True -+ -+ def get_position_in_parent(self): -+ """ -+ Retrieves 1-based relative physical position in parent device. -+ If the agent cannot determine the parent-relative position -+ for some reason, or if the associated value of -+ entPhysicalContainedIn is'0', then the value '-1' is returned -+ Returns: -+ integer: The 1-based relative physical position in parent device -+ or -1 if cannot determine the position -+ """ -+ return -1 -+ -+ def is_replaceable(self): -+ """ -+ Indicate whether this device is replaceable. -+ Returns: -+ bool: True if it is replaceable. -+ """ -+ return False -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/eeprom.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/eeprom.py -index 7bf2bb58d..f3bc202eb 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/eeprom.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/eeprom.py -@@ -13,7 +13,7 @@ except ImportError as e: - - CACHE_ROOT = '/var/cache/sonic/decode-syseeprom' - CACHE_FILE = 'syseeprom_cache' -- -+NULL = 'N/A' - - class Tlv(eeprom_tlvinfo.TlvInfoDecoder): - -@@ -33,7 +33,7 @@ class Tlv(eeprom_tlvinfo.TlvInfoDecoder): - for line in lines: - try: - match = re.search( -- '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)([\S]+)', line) -+ '(0x[0-9a-fA-F]{2})([\s]+[\S]+[\s]+)(.+)', line) - if match is not None: - idx = match.group(1) - value = match.group(3).rstrip('\0') -@@ -92,11 +92,46 @@ class Tlv(eeprom_tlvinfo.TlvInfoDecoder): - - return self.__parse_output(decode_output) - -+ def _valid_tlv(self, eeprom_data): -+ tlvinfo_type_codes_list = [ -+ self._TLV_CODE_PRODUCT_NAME, -+ self._TLV_CODE_PART_NUMBER, -+ self._TLV_CODE_SERIAL_NUMBER, -+ self._TLV_CODE_MAC_BASE, -+ self._TLV_CODE_MANUF_DATE, -+ self._TLV_CODE_DEVICE_VERSION, -+ self._TLV_CODE_LABEL_REVISION, -+ self._TLV_CODE_PLATFORM_NAME, -+ self._TLV_CODE_ONIE_VERSION, -+ self._TLV_CODE_MAC_SIZE, -+ self._TLV_CODE_MANUF_NAME, -+ self._TLV_CODE_MANUF_COUNTRY, -+ self._TLV_CODE_VENDOR_NAME, -+ self._TLV_CODE_DIAG_VERSION, -+ self._TLV_CODE_SERVICE_TAG, -+ self._TLV_CODE_VENDOR_EXT, -+ self._TLV_CODE_CRC_32 -+ ] -+ -+ for code in tlvinfo_type_codes_list: -+ code_str = "0x{:X}".format(code) -+ eeprom_data[code_str] = eeprom_data.get(code_str, NULL) -+ return eeprom_data -+ - def get_eeprom(self): -- return self._eeprom -+ return self._valid_tlv(self._eeprom) -+ -+ def get_pn(self): -+ return self._eeprom.get('0x22', NULL) - - def get_serial(self): -- return self._eeprom.get('0x23', "Undefined.") -+ return self._eeprom.get('0x23', NULL) - - def get_mac(self): -- return self._eeprom.get('0x24', "Undefined.") -+ return self._eeprom.get('0x24', NULL) -+ -+ def get_modelstr(self): -+ return self._eeprom.get('0x21', NULL) -+ -+ def get_revisionstr(self): -+ return self._eeprom.get('0x27', NULL) -\ No newline at end of file -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/event.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/event.py -new file mode 100644 -index 000000000..ade466b2e ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/event.py -@@ -0,0 +1,109 @@ -+try: -+ import time -+ from sonic_py_common.logger import Logger -+ from .sfp import Sfp -+except ImportError as e: -+ raise ImportError(repr(e) + " - required module not found") -+ -+POLL_INTERVAL_IN_SEC = 1 -+ -+# SFP errors that will block eeprom accessing -+SFP_BLOCKING_ERRORS = [ -+ Sfp.SFP_ERROR_BIT_I2C_STUCK, -+ Sfp.SFP_ERROR_BIT_BAD_EEPROM, -+ Sfp.SFP_ERROR_BIT_UNSUPPORTED_CABLE, -+ Sfp.SFP_ERROR_BIT_HIGH_TEMP, -+ Sfp.SFP_ERROR_BIT_BAD_CABLE -+] -+ -+class SfpEvent: -+ ''' Listen to insert/remove sfp events ''' -+ -+ def __init__(self, sfp_list): -+ self._sfp_list = sfp_list -+ self._logger = Logger() -+ self._sfp_change_event_data = {'present': 0} -+ -+ def get_presence_bitmap(self): -+ bitmap = 0 -+ for sfp in self._sfp_list: -+ modpres = sfp.get_presence() -+ i=sfp.get_position_in_parent() - 1 -+ if modpres: -+ bitmap = bitmap | (1 << i) -+ return bitmap -+ -+ def get_sfp_event(self, timeout=2000): -+ port_dict = {} -+ change_dict = {} -+ change_dict['sfp'] = port_dict -+ -+ if timeout < 1000: -+ cd_ms = 1000 -+ else: -+ cd_ms = timeout -+ -+ while cd_ms > 0: -+ bitmap = self.get_presence_bitmap() -+ changed_ports = self._sfp_change_event_data['present'] ^ bitmap -+ if changed_ports != 0: -+ break -+ time.sleep(POLL_INTERVAL_IN_SEC) -+ # timeout=0 means wait for event forever -+ if timeout != 0: -+ cd_ms = cd_ms - POLL_INTERVAL_IN_SEC * 1000 -+ -+ if changed_ports != 0: -+ for sfp in self._sfp_list: -+ i=sfp.get_position_in_parent() - 1 -+ if (changed_ports & (1 << i)) == 0: -+ continue -+ -+ if (bitmap & (1 << i)) == 0: -+ port_dict[i+1] = '0' -+ else: -+ # sfp.refresh_optoe_dev_class() -+ sfp_state_bits = self.get_sfp_state_bits(sfp, True) -+ sfp_state_bits = self.check_sfp_blocking_errors(sfp_state_bits) -+ -+ port_dict[i+1] = str(sfp_state_bits) -+ -+ # Update the cache dict -+ self._sfp_change_event_data['present'] = bitmap -+ return True, change_dict -+ else: -+ return True, change_dict -+ -+ def get_sfp_state_bits(self, sfp, present): -+ sfp_state_bits = 0 -+ -+ if present is True: -+ sfp_state_bits |= Sfp.SFP_STATUS_BIT_INSERTED -+ else: -+ return sfp_state_bits -+ -+ status = sfp.validate_eeprom() -+ if status is None: -+ sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK -+ return sfp_state_bits -+ elif status is not True: -+ sfp_state_bits |= Sfp.SFP_ERROR_BIT_BAD_EEPROM -+ return sfp_state_bits -+ -+ status = sfp.validate_temperature() -+ if status is None: -+ sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK -+ return sfp_state_bits -+ elif status is not True: -+ sfp_state_bits |= Sfp.SFP_ERROR_BIT_HIGH_TEMP -+ return sfp_state_bits -+ -+ return sfp_state_bits -+ -+ def check_sfp_blocking_errors(self, sfp_state_bits): -+ for i in SFP_BLOCKING_ERRORS: -+ if (i & sfp_state_bits) == 0: -+ continue -+ sfp_state_bits |= Sfp.SFP_ERROR_BIT_BLOCKING -+ -+ return sfp_state_bits -\ No newline at end of file -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/fan.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/fan.py -index 8f4893124..e14550355 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/fan.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/fan.py -@@ -38,10 +38,6 @@ PSU_CPLD_I2C_MAPPING = { - }, - } - -- --FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R", -- "FAN-3F", "FAN-3R"] -- - class Fan(FanBase): - """Platform-specific Fan class""" - -@@ -63,7 +59,7 @@ class Fan(FanBase): - self.psu_cpld_path = I2C_PATH.format( - self.psu_i2c_num, self.psu_i2c_addr) - -- FanBase.__init__(self) -+ FanBase.__init__(self) - - - def get_direction(self): -@@ -73,16 +69,14 @@ class Fan(FanBase): - A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST - depending on fan direction - """ -- -- - if not self.is_psu_fan: - dir_str = "{}{}{}".format(CPLD_FAN_I2C_PATH, 'direction_', self.fan_tray_index+1) - val=self._api_helper.read_txt_file(dir_str) - if val is not None: - if int(val, 10)==0:#F2B -- direction=self.FAN_DIRECTION_EXHAUST -- else: - direction=self.FAN_DIRECTION_INTAKE -+ else: -+ direction=self.FAN_DIRECTION_EXHAUST - else: - direction=self.FAN_DIRECTION_EXHAUST - -@@ -105,7 +99,7 @@ class Fan(FanBase): - Returns: - An integer, the percentage of full fan speed, in the range 0 (off) - to 100 (full speed) -- -+ - """ - speed = 0 - if self.is_psu_fan: -@@ -117,7 +111,7 @@ class Fan(FanBase): - speed=100 - else: - return 0 -- elif self.get_presence(): -+ elif self.get_presence(): - speed_path = "{}{}".format(CPLD_FAN_I2C_PATH, 'duty_cycle_percentage') - speed=self._api_helper.read_txt_file(speed_path) - if speed is None: -@@ -156,7 +150,7 @@ class Fan(FanBase): - A boolean, True if speed is set successfully, False if not - """ - -- if not self.is_psu_fan and self.get_presence(): -+ if not self.is_psu_fan and self.get_presence(): - speed_path = "{}{}".format(CPLD_FAN_I2C_PATH, 'duty_cycle_percentage') - return self._api_helper.write_txt_file(speed_path, int(speed)) - -@@ -179,14 +173,13 @@ class Fan(FanBase): - Returns: - A string, one of the predefined STATUS_LED_COLOR_* strings above - """ -- status=self.get_presence() -- if status is None: -- return self.STATUS_LED_COLOR_OFF -+ if self.is_psu_fan: -+ return None - - return { -- 1: self.STATUS_LED_COLOR_GREEN, -- 0: self.STATUS_LED_COLOR_RED -- }.get(status, self.STATUS_LED_COLOR_OFF) -+ True: self.STATUS_LED_COLOR_GREEN, -+ False: self.STATUS_LED_COLOR_OFF -+ }.get(self.get_status(), self.STATUS_LED_COLOR_OFF) - - def get_name(self): - """ -@@ -194,11 +187,10 @@ class Fan(FanBase): - Returns: - string: The name of the device - """ -- fan_name = FAN_NAME_LIST[self.fan_tray_index*2 + self.fan_index] \ -- if not self.is_psu_fan \ -- else "PSU-{} FAN-{}".format(self.psu_index+1, self.fan_index+1) -+ if self.is_psu_fan: -+ return "PSU-{} FAN-{}".format(self.psu_index+1, self.fan_index+1) - -- return fan_name -+ return "FAN-{}".format(self.fan_tray_index+1) - - def get_presence(self): - """ -@@ -206,8 +198,6 @@ class Fan(FanBase): - Returns: - bool: True if FAN is present, False if not - """ -- -- - if self.is_psu_fan: - present_path="{}{}".format(self.psu_cpld_path, 'psu_present') - else: -@@ -226,6 +216,11 @@ class Fan(FanBase): - A boolean value, True if device is operating properly, False if not - """ - if self.is_psu_fan: -+ psu_fan_path = "{}{}".format(self.psu_cpld_path, 'psu_power_good') -+ val = self._api_helper.read_txt_file(psu_fan_path) -+ if val is None or int(val, 10)==0: -+ return False -+ - psu_fan_path= "{}{}".format(self.psu_hwmon_path, 'psu_fan1_fault') - val=self._api_helper.read_txt_file(psu_fan_path) - if val is not None: -@@ -268,7 +263,7 @@ class Fan(FanBase): - integer: The 1-based relative physical position in parent device - or -1 if cannot determine the position - """ -- return (self.fan_tray_index+1) \ -+ return (self.fan_index+1) \ - if not self.is_psu_fan else (self.psu_index+1) - - def is_replaceable(self): -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/fan_drawer.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/fan_drawer.py -index e21163c10..b4c2146b9 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/fan_drawer.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/fan_drawer.py -@@ -10,7 +10,7 @@ try: - except ImportError as e: - raise ImportError(str(e) + "- required module not found") - --FANS_PER_FANTRAY = 2 -+FANS_PER_FANTRAY = 1 - - - class FanDrawer(FanDrawerBase): -@@ -88,3 +88,25 @@ class FanDrawer(FanDrawerBase): - bool: True if it is replaceable. - """ - return True -+ -+ def set_status_led(self, color): -+ """ -+ Sets the state of the fan module status LED -+ Args: -+ color: A string representing the color with which to set the -+ fan module status LED -+ Returns: -+ bool: True if status LED state is set successfully, False if not -+ """ -+ return False # Not supported -+ -+ def get_status_led(self): -+ """ -+ Gets the state of the fan status LED -+ Returns: -+ A string, one of the predefined STATUS_LED_COLOR_* strings above -+ """ -+ return { -+ True: self.STATUS_LED_COLOR_GREEN, -+ False: self.STATUS_LED_COLOR_OFF -+ }.get(self.get_status(), self.STATUS_LED_COLOR_OFF) -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/helper.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/helper.py -index b19fab85d..f6adee309 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/helper.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/helper.py -@@ -1,8 +1,14 @@ - import os - import struct --import subprocess -+import json -+import fcntl - from mmap import * - from sonic_py_common import device_info -+from sonic_py_common import logger -+from threading import Lock -+from typing import cast -+from sonic_py_common.general import getstatusoutput_noshell_pipe -+from sonic_py_common.general import getstatusoutput_noshell - - HOST_CHK_CMD = ["docker"] - EMPTY_STRING = "" -@@ -14,7 +20,11 @@ class APIHelper(): - (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() - - def is_host(self): -- return subprocess.call(HOST_CHK_CMD) == 0 -+ try: -+ status, output = getstatusoutput_noshell(HOST_CHK_CMD) -+ return status == 0 -+ except Exception: -+ return False - - def pci_get_value(self, resource, offset): - status = True -@@ -29,11 +39,20 @@ class APIHelper(): - status = False - return status, result - -+ def run_interactive_command(self, cmd): -+ try: -+ os.system(cmd) -+ except Exception: -+ return False -+ return True -+ - def read_txt_file(self, file_path): - try: - with open(file_path, 'r', errors='replace') as fd: - data = fd.read() -- return data.strip() -+ ret = data.strip() -+ if len(ret) > 0: -+ return ret - except IOError: - pass - return None -@@ -46,3 +65,304 @@ class APIHelper(): - return False - return True - -+ def ipmi_raw(self, netfn, cmd): -+ status = True -+ result = "" -+ try: -+ err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'raw', str(netfn), str(cmd)]) -+ if err == [0]: -+ result = raw_data.strip() -+ else: -+ status = False -+ except Exception: -+ status = False -+ return status, result -+ -+ def ipmi_fru_id(self, id, key=None): -+ status = True -+ result = "" -+ try: -+ if (key is None): -+ err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)]) -+ else: -+ err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)], ['grep', str(key)]) -+ if err == [0] or err == [0, 0]: -+ result = raw_data.strip() -+ else: -+ status = False -+ except Exception: -+ status = False -+ return status, result -+ -+ def ipmi_set_ss_thres(self, id, threshold_key, value): -+ status = True -+ result = "" -+ try: -+ err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'sensor', 'thresh', str(id), str(threshold_key), str(value)]) -+ if err == [0]: -+ result = raw_data.strip() -+ else: -+ status = False -+ except Exception: -+ status = False -+ return status, result -+ -+ -+class FileLock: -+ """ -+ Due to pmon docker not installing the py-filelock, this class -+ implements a simple file lock feature. -+ Ref: https://github.com/tox-dev/py-filelock/blob/main/src/filelock/ -+ """ -+ -+ def __init__(self, lock_file): -+ self._lock_file = lock_file -+ self._thread_lock = Lock() -+ self.is_locked = False -+ -+ def acquire(self): -+ with self._thread_lock: -+ if self.is_locked: -+ return -+ -+ fd = os.open(self._lock_file, flags=(os.O_RDWR | os.O_CREAT | os.O_TRUNC)) -+ fcntl.flock(fd, fcntl.LOCK_EX) -+ self._lock_file_fd = fd -+ self.is_locked = True -+ -+ def release(self): -+ with self._thread_lock: -+ if self.is_locked: -+ fd = cast(int, self._lock_file_fd) -+ self._lock_file_fd = None -+ fcntl.flock(fd, fcntl.LOCK_UN) -+ os.close(fd) -+ self.is_locked = False -+ -+ def __enter__(self): -+ self.acquire() -+ return self -+ -+ def __exit__(self, exc_type, exc_val, traceback): -+ self.release() -+ -+ def __del__(self): -+ self.release() -+ -+ -+DEVICE_THRESHOLD_JSON_PATH = "/tmp/device_threshold.json" -+ -+class DeviceThreshold: -+ HIGH_THRESHOLD = 'high_threshold' -+ LOW_THRESHOLD = 'low_threshold' -+ HIGH_CRIT_THRESHOLD = 'high_critical_threshold' -+ LOW_CRIT_THRESHOLD = 'low_critical_threshold' -+ NOT_AVAILABLE = 'N/A' -+ -+ def __init__(self, th_name = NOT_AVAILABLE): -+ self.flock = FileLock("{}.lock".format(DEVICE_THRESHOLD_JSON_PATH)) -+ self.name = th_name -+ self.__log = logger.Logger(log_identifier="DeviceThreshold") -+ -+ self.__db_data = {} -+ self.__db_mtime = 0 -+ -+ def __reload_db(self): -+ try: -+ db_data = {} -+ with self.flock: -+ with open(DEVICE_THRESHOLD_JSON_PATH, "r") as db_file: -+ db_data = json.load(db_file) -+ except Exception as e: -+ self.__log.log_warning('{}'.format(str(e))) -+ return None -+ -+ return db_data -+ -+ def __get_data(self, field): -+ """ -+ Retrieves data frome JSON file by field -+ -+ Args : -+ field: String -+ -+ Returns: -+ A string if getting is successfully, 'N/A' if not -+ """ -+ if os.path.exists(DEVICE_THRESHOLD_JSON_PATH): -+ new_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH) -+ if new_mtime != self.__db_mtime: -+ new_data = self.__reload_db() -+ if new_data is not None: -+ self.__db_data = new_data -+ self.__db_mtime = new_mtime -+ -+ if self.name not in self.__db_data.keys(): -+ return self.NOT_AVAILABLE -+ -+ if field not in self.__db_data[self.name].keys(): -+ return self.NOT_AVAILABLE -+ -+ return self.__db_data[self.name][field] -+ -+ def __set_data(self, field, new_val): -+ """ -+ Set data to JSON file by field -+ -+ Args : -+ field: String -+ new_val: String -+ -+ Returns: -+ A boolean, True if setting is set successfully, False if not -+ """ -+ if self.name not in self.__db_data.keys(): -+ self.__db_data[self.name] = {} -+ -+ old_val = self.__db_data[self.name].get(field, None) -+ if old_val is not None and old_val == new_val: -+ return True -+ -+ self.__db_data[self.name][field] = new_val -+ -+ try: -+ with self.flock: -+ db_data = {} -+ mode = "r+" if os.path.exists(DEVICE_THRESHOLD_JSON_PATH) else "w+" -+ with open(DEVICE_THRESHOLD_JSON_PATH, mode) as db_file: -+ if mode == "r+": -+ db_data = json.load(db_file) -+ -+ if self.name not in db_data.keys(): -+ db_data[self.name] = {} -+ -+ db_data[self.name][field] = new_val -+ -+ if mode == "r+": -+ db_file.seek(0) -+ # erase old data -+ db_file.truncate(0) -+ # write all data -+ json.dump(db_data, db_file, indent=4) -+ self.__db_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH) -+ except Exception as e: -+ self.__log.log_error('{}'.format(str(e))) -+ return False -+ -+ return True -+ -+ def get_high_threshold(self): -+ """ -+ Retrieves the high threshold temperature from JSON file. -+ -+ Returns: -+ string : the high threshold temperature of thermal, -+ e.g. "30.125" -+ """ -+ return self.__get_data(self.HIGH_THRESHOLD) -+ -+ def set_high_threshold(self, temperature): -+ """ -+ Sets the high threshold temperature of thermal -+ Args : -+ temperature: A string of temperature, e.g. "30.125" -+ Returns: -+ A boolean, True if threshold is set successfully, False if not -+ """ -+ if isinstance(temperature, str) is not True: -+ raise TypeError('The parameter requires string type.') -+ -+ try: -+ if temperature != self.NOT_AVAILABLE: -+ float(temperature) -+ except ValueError: -+ raise ValueError('The parameter requires a float string. ex:\"30.1\"') -+ -+ return self.__set_data(self.HIGH_THRESHOLD, temperature) -+ -+ def get_low_threshold(self): -+ """ -+ Retrieves the low threshold temperature from JSON file. -+ -+ Returns: -+ string : the low threshold temperature of thermal, -+ e.g. "30.125" -+ """ -+ return self.__get_data(self.LOW_THRESHOLD) -+ -+ def set_low_threshold(self, temperature): -+ """ -+ Sets the low threshold temperature of thermal -+ Args : -+ temperature: A string of temperature, e.g. "30.125" -+ Returns: -+ A boolean, True if threshold is set successfully, False if not -+ """ -+ if isinstance(temperature, str) is not True: -+ raise TypeError('The parameter requires string type.') -+ -+ try: -+ if temperature != self.NOT_AVAILABLE: -+ float(temperature) -+ except ValueError: -+ raise ValueError('The parameter requires a float string. ex:\"30.1\"') -+ -+ return self.__set_data(self.LOW_THRESHOLD, temperature) -+ -+ def get_high_critical_threshold(self): -+ """ -+ Retrieves the high critical threshold temperature from JSON file. -+ -+ Returns: -+ string : the high critical threshold temperature of thermal, -+ e.g. "30.125" -+ """ -+ return self.__get_data(self.HIGH_CRIT_THRESHOLD) -+ -+ def set_high_critical_threshold(self, temperature): -+ """ -+ Sets the high critical threshold temperature of thermal -+ Args : -+ temperature: A string of temperature, e.g. "30.125" -+ Returns: -+ A boolean, True if threshold is set successfully, False if not -+ """ -+ if isinstance(temperature, str) is not True: -+ raise TypeError('The parameter requires string type.') -+ -+ try: -+ if temperature != self.NOT_AVAILABLE: -+ float(temperature) -+ except ValueError: -+ raise ValueError('The parameter requires a float string. ex:\"30.1\"') -+ -+ return self.__set_data(self.HIGH_CRIT_THRESHOLD, temperature) -+ -+ def get_low_critical_threshold(self): -+ """ -+ Retrieves the low critical threshold temperature from JSON file. -+ -+ Returns: -+ string : the low critical threshold temperature of thermal, -+ e.g. "30.125" -+ """ -+ return self.__get_data(self.LOW_CRIT_THRESHOLD) -+ -+ def set_low_critical_threshold(self, temperature): -+ """ -+ Sets the low critical threshold temperature of thermal -+ Args : -+ temperature: A string of temperature, e.g. "30.125" -+ Returns: -+ A boolean, True if threshold is set successfully, False if not -+ """ -+ if isinstance(temperature, str) is not True: -+ raise TypeError('The parameter requires string type.') -+ -+ try: -+ if temperature != self.NOT_AVAILABLE: -+ float(temperature) -+ except ValueError: -+ raise ValueError('The parameter requires a float string. ex:\"30.1\"') -+ -+ return self.__set_data(self.LOW_CRIT_THRESHOLD, temperature) -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/pcie.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/pcie.py -new file mode 100644 -index 000000000..73d3627db ---- /dev/null -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/pcie.py -@@ -0,0 +1,19 @@ -+############################################################################# -+# Edgecore -+# -+# Module contains an implementation of SONiC Platform Base API and -+# provides the fan status which are available in the platform -+# Base PCIe class -+############################################################################# -+ -+try: -+ from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil -+except ImportError as e: -+ raise ImportError(str(e) + "- required module not found") -+ -+ -+class Pcie(PcieUtil): -+ """Edgecore Platform-specific PCIe class""" -+ -+ def __init__(self, platform_path): -+ PcieUtil.__init__(self, platform_path) -\ No newline at end of file -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/psu.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/psu.py -index 8eab43891..6df7fd3ff 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/psu.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/psu.py -@@ -10,7 +10,7 @@ - - try: - from sonic_platform_base.psu_base import PsuBase -- #from sonic_platform.fan import Fan -+ from sonic_platform.thermal import Thermal - from .helper import APIHelper - except ImportError as e: - raise ImportError(str(e) + "- required module not found") -@@ -58,19 +58,13 @@ class Psu(PsuBase): - self.i2c_addr = PSU_CPLD_I2C_MAPPING[self.index]["addr"] - self.cpld_path = I2C_PATH.format(self.i2c_num, self.i2c_addr) - self.__initialize_fan() -- ''' -- for fan_index in range(0, PSU_NUM_FAN[self.index]): -- #def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0): -- #fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index) -- fan = Fan(fan_index, 0, True, self.index) -- self._fan_list.append(fan) -- ''' - - def __initialize_fan(self): - from sonic_platform.fan import Fan - for fan_index in range(0, PSU_NUM_FAN[self.index]): - fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index) - self._fan_list.append(fan) -+ self._thermal_list.append(Thermal(is_psu=True, psu_index=self.index)) - - def get_voltage(self): - """ -@@ -79,12 +73,15 @@ class Psu(PsuBase): - A float number, the output voltage in volts, - e.g. 12.1 - """ -+ if self.get_status() is not True: -+ return 0.0 -+ - vout_path = "{}{}".format(self.hwmon_path, 'psu_v_out') - vout_val=self._api_helper.read_txt_file(vout_path) - if vout_val is not None: - return float(vout_val)/ 1000 - else: -- return 0 -+ return 0.0 - - def get_current(self): - """ -@@ -92,12 +89,15 @@ class Psu(PsuBase): - Returns: - A float number, the electric current in amperes, e.g 15.4 - """ -+ if self.get_status() is not True: -+ return 0.0 -+ - iout_path = "{}{}".format(self.hwmon_path, 'psu_i_out') - val=self._api_helper.read_txt_file(iout_path) - if val is not None: - return float(val)/1000 - else: -- return 0 -+ return 0.0 - - def get_power(self): - """ -@@ -105,12 +105,15 @@ class Psu(PsuBase): - Returns: - A float number, the power in watts, e.g. 302.6 - """ -+ if self.get_status() is not True: -+ return 0.0 -+ - pout_path = "{}{}".format(self.hwmon_path, 'psu_p_out') - val=self._api_helper.read_txt_file(pout_path) - if val is not None: - return float(val)/1000 - else: -- return 0 -+ return 0.0 - - def get_powergood_status(self): - """ -@@ -156,12 +159,15 @@ class Psu(PsuBase): - A float number of current temperature in Celsius up to nearest thousandth - of one degree Celsius, e.g. 30.125 - """ -+ if self.get_status() is not True: -+ return 0.0 -+ - temp_path = "{}{}".format(self.hwmon_path, 'psu_temp1_input') - val=self._api_helper.read_txt_file(temp_path) - if val is not None: - return float(val)/1000 - else: -- return 0 -+ return 0.0 - - def get_temperature_high_threshold(self): - """ -@@ -170,7 +176,7 @@ class Psu(PsuBase): - A float number, the high threshold temperature of PSU in Celsius - up to nearest thousandth of one degree Celsius, e.g. 30.125 - """ -- return False #Not supported -+ return self._thermal_list[0].get_high_threshold() - - def get_voltage_high_threshold(self): - """ -@@ -179,12 +185,15 @@ class Psu(PsuBase): - A float number, the high threshold output voltage in volts, - e.g. 12.1 - """ -+ if self.get_status() is not True: -+ return 0.0 -+ - vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_max') - vout_val=self._api_helper.read_txt_file(vout_path) - if vout_val is not None: - return float(vout_val)/ 1000 - else: -- return 0 -+ return 0.0 - - def get_voltage_low_threshold(self): - """ -@@ -193,12 +202,15 @@ class Psu(PsuBase): - A float number, the low threshold output voltage in volts, - e.g. 12.1 - """ -+ if self.get_status() is not True: -+ return 0.0 -+ - vout_path = "{}{}".format(self.hwmon_path, 'psu_mfr_vout_min') - vout_val=self._api_helper.read_txt_file(vout_path) - if vout_val is not None: - return float(vout_val)/ 1000 - else: -- return 0 -+ return 0.0 - - def get_name(self): - """ -@@ -219,7 +231,7 @@ class Psu(PsuBase): - if val is not None: - return int(val, 10) == 1 - else: -- return 0 -+ return False - - def get_status(self): - """ -@@ -232,7 +244,7 @@ class Psu(PsuBase): - if val is not None: - return int(val, 10) == 1 - else: -- return 0 -+ return False - - def get_model(self): - """ -@@ -275,3 +287,34 @@ class Psu(PsuBase): - bool: True if it is replaceable. - """ - return True -+ -+ def get_revision(self): -+ """ -+ Retrieves the hardware revision of the device -+ -+ Returns: -+ string: Revision value of device -+ """ -+ revision_path = "{}{}".format(self.hwmon_path, 'psu_mfr_revision') -+ revision = self._api_helper.read_txt_file(revision_path) -+ if revision is None: -+ return 'N/A' -+ -+ return revision -+ -+ def get_maximum_supplied_power(self): -+ """ -+ Retrieves the maximum supplied power by PSU -+ Returns: -+ A float number, the maximum power output in Watts. -+ e.g. 1200.1 -+ """ -+ if self.get_status() is not True: -+ return 0.0 -+ -+ pout_max_path = "{}{}".format(self.hwmon_path, 'psu_mfr_pout_max') -+ val=self._api_helper.read_txt_file(pout_max_path) -+ if val is not None: -+ return float(val)/1000 -+ else: -+ return 0.0 -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/sfp.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/sfp.py -index adab3d294..d6f894b28 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/sfp.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/sfp.py -@@ -1,5 +1,3 @@ --#!/usr/bin/env python -- - ############################################################################# - # Edgecore - # -@@ -8,115 +6,26 @@ - # - ############################################################################# - -+import os - import time --import sys --import subprocess --from ctypes import create_string_buffer - - try: -- from sonic_platform_base.sfp_base import SfpBase -- from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom -- from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId -- from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom -- from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId -- #from sonic_platform_base.sonic_sfp.sff8472 import sffbase -+ from sonic_py_common.logger import Logger -+ from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase - from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper - from .helper import APIHelper -+ from sonic_py_common import device_info - except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -+NONE_SFP_TYPE = "NONE-SFP" -+SFP_TYPE = "SFP" -+QSFP_TYPE = "QSFP" -+ - CPLD_I2C_PATH = "/sys/bus/i2c/devices/3-0060/" - --QSFP_INFO_OFFSET = 128 --QSFP_DOM_OFFSET = 0 -- --SFP_INFO_OFFSET = 0 --SFP_DOM_OFFSET = 256 -- --XCVR_INTFACE_BULK_OFFSET = 0 --XCVR_INTFACE_BULK_WIDTH_QSFP = 20 --XCVR_INTFACE_BULK_WIDTH_SFP = 21 --XCVR_HW_REV_WIDTH_QSFP = 2 --XCVR_HW_REV_WIDTH_SFP = 4 --XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 --XCVR_VENDOR_NAME_OFFSET = 20 --XCVR_VENDOR_NAME_WIDTH = 16 --XCVR_VENDOR_OUI_OFFSET = 37 --XCVR_VENDOR_OUI_WIDTH = 3 --XCVR_VENDOR_PN_OFFSET = 40 --XCVR_VENDOR_PN_WIDTH = 16 --XCVR_HW_REV_OFFSET = 56 --XCVR_HW_REV_WIDTH_OSFP = 2 --XCVR_HW_REV_WIDTH_SFP = 4 --XCVR_VENDOR_SN_OFFSET = 68 --XCVR_VENDOR_SN_WIDTH = 16 --XCVR_VENDOR_DATE_OFFSET = 84 --XCVR_VENDOR_DATE_WIDTH = 8 --XCVR_DOM_CAPABILITY_OFFSET = 92 --XCVR_DOM_CAPABILITY_WIDTH = 1 -- --# Offset for values in QSFP eeprom --QSFP_DOM_REV_OFFSET = 1 --QSFP_DOM_REV_WIDTH = 1 --QSFP_TEMPE_OFFSET = 22 --QSFP_TEMPE_WIDTH = 2 --QSFP_VOLT_OFFSET = 26 --QSFP_VOLT_WIDTH = 2 --QSFP_CHANNL_MON_OFFSET = 34 --QSFP_CHANNL_MON_WIDTH = 16 --QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 --QSFP_CONTROL_OFFSET = 86 --QSFP_CONTROL_WIDTH = 8 --QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 --QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 --QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 --QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 --QSFP_POWEROVERRIDE_OFFSET = 93 --QSFP_POWEROVERRIDE_WIDTH = 1 --QSFP_PAGE03_OFFSET = 384 --QSFP_MODULE_THRESHOLD_OFFSET = 128 --QSFP_MODULE_THRESHOLD_WIDTH = 24 --QSFP_CHANNEL_THRESHOLD_OFFSET = 176 --QSFP_CHANNEL_THRESHOLD_WIDTH = 16 -- --qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', -- 'Length OM2(m)', 'Length OM1(m)', -- 'Length Cable Assembly(m)') -- --qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', -- 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', -- 'Fibre Channel link length/Transmitter Technology', -- 'Fibre Channel transmission media', 'Fibre Channel Speed') -- -- --# Offset for values in SFP eeprom --SFP_TEMPE_OFFSET = 96 --SFP_TEMPE_WIDTH = 2 --SFP_VOLT_OFFSET = 98 --SFP_VOLT_WIDTH = 2 --SFP_CHANNL_MON_OFFSET = 100 --SFP_CHANNL_MON_WIDTH = 6 --SFP_MODULE_THRESHOLD_OFFSET = 0 --SFP_MODULE_THRESHOLD_WIDTH = 40 --SFP_CHANNL_THRESHOLD_OFFSET = 112 --SFP_CHANNL_THRESHOLD_WIDTH = 2 --SFP_STATUS_CONTROL_OFFSET = 110 --SFP_STATUS_CONTROL_WIDTH = 1 --SFP_TX_DISABLE_HARD_BIT = 7 --SFP_TX_DISABLE_SOFT_BIT = 6 -- --sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', -- 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', -- 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') -- --sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', -- 'ESCONComplianceCodes', 'SONETComplianceCodes', -- 'EthernetComplianceCodes', 'FibreChannelLinkLength', -- 'FibreChannelTechnology', 'SFP+CableTechnology', -- 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') -- -- --class Sfp(SfpBase): -+logger = Logger() -+class Sfp(SfpOptoeBase): - """Platform-specific Sfp class""" - - # Port number -@@ -126,10 +35,7 @@ class Sfp(SfpBase): - # Path to sysfs - PLATFORM_ROOT_PATH = "/usr/share/sonic/device" - PMON_HWSKU_PATH = "/usr/share/sonic/hwsku" -- HOST_CHK_CMD = ["docker"] -- -- PLATFORM = "x86_64-accton_as4630_54te-r0" -- HWSKU = "Accton-AS4630-54TE" -+ HOST_CHK_CMD = "which systemctl > /dev/null 2>&1" - - _port_to_i2c_mapping = { - 49: 18, -@@ -140,510 +46,41 @@ class Sfp(SfpBase): - 54: 23, - } - -+ SFP_TYPE_CODE_LIST = [ -+ 0x03, # SFP/SFP+/SFP28 -+ 0x0b # DWDM-SFP/SFP+ -+ ] -+ QSFP_TYPE_CODE_LIST = [ -+ 0x0c, # QSFP -+ 0x0d, # QSFP+ or later -+ 0x11, # QSFP28 or later -+ 0xe1 # QSFP28 EDFA -+ ] -+ - def __init__(self, sfp_index=0): -+ SfpOptoeBase.__init__(self) - self._api_helper=APIHelper() - # Init index -- self.index = sfp_index -- self.port_num = self.index + 1 -+ self.port_num = sfp_index + 1 -+ self.index = self.port_num -+ if self.port_num < self.PORT_START: -+ self.sfp_type = NONE_SFP_TYPE -+ elif self.port_num < 53: -+ self.sfp_type = SFP_TYPE -+ else: -+ self.sfp_type = QSFP_TYPE -+ - # Init eeprom path - eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom' - self.port_to_eeprom_mapping = {} - for x in range(self.PORT_START, self.PORT_END + 1): - self.port_to_eeprom_mapping[x] = eeprom_path.format(self._port_to_i2c_mapping[x]) - -- self.info_dict_keys = ['type', 'vendor_rev', 'serial', 'manufacturer', 'model', 'connector', 'encoding', 'ext_identifier', -- 'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui', -- 'application_advertisement', 'type_abbrv_name'] -- -- self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage', -- 'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power'] -- -- self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning', -- 'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] -- -- SfpBase.__init__(self) -- -- def _convert_string_to_num(self, value_str): -- if "-inf" in value_str: -- return 'N/A' -- elif "Unknown" in value_str: -- return 'N/A' -- elif 'dBm' in value_str: -- t_str = value_str.rstrip('dBm') -- return float(t_str) -- elif 'mA' in value_str: -- t_str = value_str.rstrip('mA') -- return float(t_str) -- elif 'C' in value_str: -- t_str = value_str.rstrip('C') -- return float(t_str) -- elif 'Volts' in value_str: -- t_str = value_str.rstrip('Volts') -- return float(t_str) -- else: -- return 'N/A' -- -- def __write_txt_file(self, file_path, value): -- try: -- with open(file_path, 'w', buffering=0) as fd: -- fd.write(str(value)) -- except Exception: -- return False -- return True -+ def get_eeprom_path(self): -+ return self.port_to_eeprom_mapping[self.port_num] - - def __is_host(self): -- return subprocess.call(self.HOST_CHK_CMD) == 0 -- -- def __get_path_to_port_config_file(self): -- platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM]) -- hwsku_path = "/".join([platform_path, self.HWSKU] -- ) if self.__is_host() else self.PMON_HWSKU_PATH -- return "/".join([hwsku_path, "port_config.ini"]) -- -- def __read_eeprom_specific_bytes(self, offset, num_bytes): -- sysfsfile_eeprom = None -- eeprom_raw = [] -- for i in range(0, num_bytes): -- eeprom_raw.append("0x00") -- -- sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num] -- try: -- sysfsfile_eeprom = open( -- sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) -- sysfsfile_eeprom.seek(offset) -- raw = sysfsfile_eeprom.read(num_bytes) -- if sys.version_info[0] >= 3: -- for n in range(0, num_bytes): -- eeprom_raw[n] = hex(raw[n])[2:].zfill(2) -- else: -- for n in range(0, num_bytes): -- eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) -- except Exception: -- pass -- finally: -- if sysfsfile_eeprom: -- sysfsfile_eeprom.close() -- -- return eeprom_raw -- -- def get_transceiver_info(self): -- """ -- Retrieves transceiver info of this SFP -- Returns: -- A dict which contains following keys/values : -- ======================================================================== -- keys |Value Format |Information -- ---------------------------|---------------|---------------------------- -- type |1*255VCHAR |type of SFP -- vendor_rev |1*255VCHAR |vendor revision of SFP -- serial |1*255VCHAR |serial number of the SFP -- manufacturer |1*255VCHAR |SFP vendor name -- model |1*255VCHAR |SFP model name -- connector |1*255VCHAR |connector information -- encoding |1*255VCHAR |encoding information -- ext_identifier |1*255VCHAR |extend identifier -- ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance -- cable_length |INT |cable length in m -- nominal_bit_rate |INT |nominal bit rate by 100Mbs -- specification_compliance |1*255VCHAR |specification compliance -- vendor_date |1*255VCHAR |vendor date -- vendor_oui |1*255VCHAR |vendor OUI -- application_advertisement |1*255VCHAR |supported applications advertisement -- ======================================================================== -- """ -- # check present status -- if self.port_num < 49: -- return {} -- elif self.port_num < 53: -- sfpi_obj = sff8472InterfaceId() #SFP -- else: -- sfpi_obj = sff8436InterfaceId() #QSFP -- if not self.get_presence() or not sfpi_obj: -- return {} -- -- if self.port_num < 53: -- offset = SFP_INFO_OFFSET -- sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_SFP) -- else: -- offset = QSFP_INFO_OFFSET -- sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_QSFP) -- -- sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk( -- sfp_interface_bulk_raw, 0) -- -- sfp_vendor_name_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) -- sfp_vendor_name_data = sfpi_obj.parse_vendor_name( -- sfp_vendor_name_raw, 0) -- -- sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) -- sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn( -- sfp_vendor_pn_raw, 0) -- -- if self.port_num < 53: -- sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_SFP) -- else: -- sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_QSFP) -- -- sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev( -- sfp_vendor_rev_raw, 0) -- -- sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) -- sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn( -- sfp_vendor_sn_raw, 0) -- -- sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) -- if sfp_vendor_oui_raw is not None: -- sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui( -- sfp_vendor_oui_raw, 0) -- -- sfp_vendor_date_raw = self.__read_eeprom_specific_bytes( -- (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) -- sfp_vendor_date_data = sfpi_obj.parse_vendor_date( -- sfp_vendor_date_raw, 0) -- -- transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A') -- compliance_code_dict = dict() -- -- if sfp_interface_bulk_data: -- transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] -- transceiver_info_dict['connector'] = sfp_interface_bulk_data['data']['Connector']['value'] -- transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] -- transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] -- transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] -- transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] -- -- transceiver_info_dict['manufacturer'] = sfp_vendor_name_data[ -- 'data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' -- transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' -- transceiver_info_dict['vendor_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' -- transceiver_info_dict['serial'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' -- transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' -- transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[ -- 'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' -- transceiver_info_dict['cable_type'] = "Unknown" -- transceiver_info_dict['cable_length'] = "Unknown" -- -- if self.port_num < 53: -- for key in sfp_cable_length_tup: -- if key in sfp_interface_bulk_data['data']: -- transceiver_info_dict['cable_type'] = key -- transceiver_info_dict['cable_length'] = str( -- sfp_interface_bulk_data['data'][key]['value']) -- -- for key in sfp_compliance_code_tup: -- if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: -- compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] -- -- transceiver_info_dict['specification_compliance'] = str( -- compliance_code_dict) -- transceiver_info_dict['nominal_bit_rate'] = str( -- sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) -- else: -- for key in qsfp_cable_length_tup: -- if key in sfp_interface_bulk_data['data']: -- transceiver_info_dict['cable_type'] = key -- transceiver_info_dict['cable_length'] = str( -- sfp_interface_bulk_data['data'][key]['value']) -- -- for key in qsfp_compliance_code_tup: -- if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: -- compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] -- -- transceiver_info_dict['specification_compliance'] = str( -- compliance_code_dict) -- transceiver_info_dict['nominal_bit_rate'] = str( -- sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) -- -- -- return transceiver_info_dict -- -- def get_transceiver_bulk_status(self): -- """ -- Retrieves transceiver bulk status of this SFP -- Returns: -- A dict which contains following keys/values : -- ======================================================================== -- keys |Value Format |Information -- ---------------------------|---------------|---------------------------- -- rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. -- tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. -- reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. -- lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. -- tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. -- tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 -- | |to channel 3. -- temperature |INT |module temperature in Celsius -- voltage |INT |supply voltage in mV -- txbias |INT |TX Bias Current in mA, n is the channel number, -- | |for example, tx2bias stands for tx bias of channel 2. -- rxpower |INT |received optical power in mW, n is the channel number, -- | |for example, rx2power stands for rx power of channel 2. -- txpower |INT |TX output power in mW, n is the channel number, -- | |for example, tx2power stands for tx power of channel 2. -- ======================================================================== -- """ -- # check present status -- if self.port_num < 53: #SFP case -- sfpd_obj = sff8472Dom() -- if not self.get_presence() or not sfpd_obj: -- return {} -- -- eeprom_ifraw = self.__read_eeprom_specific_bytes(0, SFP_DOM_OFFSET) -- sfpi_obj = sff8472InterfaceId(eeprom_ifraw) -- cal_type = sfpi_obj.get_calibration_type() -- sfpd_obj._calibration_type = cal_type -- -- offset = SFP_DOM_OFFSET -- transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') -- dom_temperature_raw = self.__read_eeprom_specific_bytes( -- (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) -- -- if dom_temperature_raw is not None: -- dom_temperature_data = sfpd_obj.parse_temperature( -- dom_temperature_raw, 0) -- transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] -- -- dom_voltage_raw = self.__read_eeprom_specific_bytes( -- (offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH) -- if dom_voltage_raw is not None: -- dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) -- transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] -- -- dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( -- (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) -- if dom_channel_monitor_raw is not None: -- dom_voltage_data = sfpd_obj.parse_channel_monitor_params( -- dom_channel_monitor_raw, 0) -- transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value'] -- transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value'] -- transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value'] -- -- else: #QSFP case -- sfpd_obj = sff8436Dom() -- sfpi_obj = sff8436InterfaceId() -- -- if not self.get_presence() or not sfpi_obj or not sfpd_obj: -- return {} -- -- transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A') -- offset = QSFP_DOM_OFFSET -- offset_xcvr = QSFP_INFO_OFFSET -- -- # QSFP capability byte parse, through this byte can know whether it support tx_power or not. -- # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, -- # need to add more code for determining the capability and version compliance -- # in SFF-8636 dom capability definitions evolving with the versions. -- qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes( -- (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) -- if qsfp_dom_capability_raw is not None: -- qspf_dom_capability_data = sfpi_obj.parse_dom_capability( -- qsfp_dom_capability_raw, 0) -- else: -- return None -- -- dom_temperature_raw = self.__read_eeprom_specific_bytes( -- (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH) -- if dom_temperature_raw is not None: -- dom_temperature_data = sfpd_obj.parse_temperature( -- dom_temperature_raw, 0) -- transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] -- -- dom_voltage_raw = self.__read_eeprom_specific_bytes( -- (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH) -- if dom_voltage_raw is not None: -- dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) -- transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] -- -- qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes( -- (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH) -- if qsfp_dom_rev_raw is not None: -- qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0) -- qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] -- -- # The tx_power monitoring is only available on QSFP which compliant with SFF-8636 -- # and claimed that it support tx_power with one indicator bit. -- dom_channel_monitor_data = {} -- dom_channel_monitor_raw = None -- qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value'] -- if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): -- dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( -- (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH) -- if dom_channel_monitor_raw is not None: -- dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params( -- dom_channel_monitor_raw, 0) -- -- else: -- dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( -- (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) -- if dom_channel_monitor_raw is not None: -- dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power( -- dom_channel_monitor_raw, 0) -- transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value'] -- transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value'] -- transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value'] -- transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value'] -- -- if dom_channel_monitor_raw: -- transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] -- transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] -- transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] -- transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] -- transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] -- transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] -- transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] -- transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] -- #End of else -- -- -- for key in transceiver_dom_info_dict: -- transceiver_dom_info_dict[key] = self._convert_string_to_num( -- transceiver_dom_info_dict[key]) -- -- transceiver_dom_info_dict['rx_los'] = self.get_rx_los() -- transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() -- transceiver_dom_info_dict['reset_status'] = self.get_reset_status() -- transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() -- -- return transceiver_dom_info_dict -- -- def get_transceiver_threshold_info(self): -- """ -- Retrieves transceiver threshold info of this SFP -- Returns: -- A dict which contains following keys/values : -- ======================================================================== -- keys |Value Format |Information -- ---------------------------|---------------|---------------------------- -- temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. -- templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. -- temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. -- templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. -- vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. -- vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. -- vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. -- vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. -- rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. -- rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. -- rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. -- rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. -- txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. -- txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. -- txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. -- txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. -- txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. -- txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. -- txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. -- txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. -- ======================================================================== -- """ -- # check present status -- if self.port_num < 53: -- sfpd_obj = sff8472Dom() -- -- if not self.get_presence() and not sfpd_obj: -- return {} -- -- eeprom_ifraw = self.__read_eeprom_specific_bytes(0, SFP_DOM_OFFSET) -- sfpi_obj = sff8472InterfaceId(eeprom_ifraw) -- cal_type = sfpi_obj.get_calibration_type() -- sfpd_obj._calibration_type = cal_type -- -- offset = SFP_DOM_OFFSET -- transceiver_dom_threshold_info_dict = dict.fromkeys( -- self.threshold_dict_keys, 'N/A') -- dom_module_threshold_raw = self.__read_eeprom_specific_bytes( -- (offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH) -- if dom_module_threshold_raw is not None: -- dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold( -- dom_module_threshold_raw, 0) -- -- transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] -- transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] -- transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] -- transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] -- transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value'] -- transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] -- transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data[ -- 'data']['VoltageHighWarning']['value'] -- transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] -- transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] -- transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] -- transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] -- transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] -- transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] -- transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] -- transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] -- transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] -- transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] -- transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] -- transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] -- transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] -- -- for key in transceiver_dom_threshold_info_dict: -- transceiver_dom_threshold_info_dict[key] = self._convert_string_to_num( -- transceiver_dom_threshold_info_dict[key]) -- -- return transceiver_dom_threshold_info_dict -- -- -- else: -- sfpd_obj = sff8436Dom() -- -- if not self.get_presence() or not sfpd_obj: -- return {} -- -- offset = QSFP_PAGE03_OFFSET -- transceiver_dom_threshold_dict = dict.fromkeys( -- self.threshold_dict_keys, 'N/A') -- dom_thres_raw = self.__read_eeprom_specific_bytes( -- offset + QSFP_MODULE_THRESHOLD_OFFSET, QSFP_MODULE_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None -- -- if dom_thres_raw: -- module_threshold_values = sfpd_obj.parse_module_threshold_values( -- dom_thres_raw, 0) -- module_threshold_data = module_threshold_values.get('data') -- if module_threshold_data: -- transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] -- transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] -- transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] -- transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] -- transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] -- transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] -- transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] -- transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] -- -- dom_thres_raw = self.__read_eeprom_specific_bytes( -- offset + QSFP_CHANNEL_THRESHOLD_OFFSET, QSFP_CHANNEL_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None -- channel_threshold_values = sfpd_obj.parse_channel_threshold_values( -- dom_thres_raw, 0) -- channel_threshold_data = channel_threshold_values.get('data') -- if channel_threshold_data: -- transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] -- transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] -- transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] -- transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] -- transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm" -- transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm" -- transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm" -- transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm" -- transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] -- transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] -- transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] -- transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] -- -- for key in transceiver_dom_threshold_dict: -- transceiver_dom_threshold_dict[key] = self._convert_string_to_num( -- transceiver_dom_threshold_dict[key]) -- -- return transceiver_dom_threshold_dict -+ return os.system(self.HOST_CHK_CMD) == 0 - - def get_reset_status(self): - """ -@@ -651,7 +88,7 @@ class Sfp(SfpBase): - Returns: - A Boolean, True if reset enabled, False if disabled - """ -- if self.port_num < 53: # non-QSFP ports don't support it. -+ if self.port_num < 53: #Copper port and sfp ports aren't supported. - return False - - reset_path="{}{}{}".format(CPLD_I2C_PATH , "module_reset_" , str(self.port_num)) -@@ -660,7 +97,7 @@ class Sfp(SfpBase): - if val is not None: - return int(val, 10) == 1 - else: -- return False -+ return False # CPLD port doesn't support this feature - - def get_rx_los(self): - """ -@@ -669,34 +106,29 @@ class Sfp(SfpBase): - A Boolean, True if SFP has RX LOS, False if not. - Note : RX LOS status is latched until a call to get_rx_los or a reset. - """ -- rx_los = False -+ rx_los = [False] - - if self.port_num < 49: #Copper port, no sysfs -- return False -+ return [False] - - if self.port_num < 53: -- rx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_rx_los_', self.port_num) -+ rx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_rx_los_', self.port_num) - rx_los=self._api_helper.read_txt_file(rx_path) -- if rx_los is None: -- return False -- #status_control_raw = self.__read_eeprom_specific_bytes( -- # SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) -- #if status_control_raw: -- # data = int(status_control_raw[0], 16) -- # rx_los = (sffbase().test_bit(data, 1) != 0) -- -+ if rx_los is not None: -+ if rx_los == '1': -+ return [True] -+ else: -+ return [False] -+ else: -+ return [False] - else: -- rx_los_list = [] -- dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( -- QSFP_CHANNL_RX_LOS_STATUS_OFFSET, QSFP_CHANNL_RX_LOS_STATUS_WIDTH) if self.get_presence() else None -- if dom_channel_monitor_raw is not None: -- rx_los_data = int(dom_channel_monitor_raw[0], 16) -- rx_los_list.append(rx_los_data & 0x01 != 0) -- rx_los_list.append(rx_los_data & 0x02 != 0) -- rx_los_list.append(rx_los_data & 0x04 != 0) -- rx_los_list.append(rx_los_data & 0x08 != 0) -- rx_los = rx_los_list[0] and rx_los_list[1] and rx_los_list[2] and rx_los_list[3] -- return rx_los -+ api = self.get_xcvr_api() -+ if api is not None: -+ rx_los = api.get_rx_los() -+ if isinstance(rx_los, list) and "N/A" in rx_los: -+ return [False for _ in rx_los] -+ return rx_los -+ return None - - def get_tx_fault(self): - """ -@@ -705,33 +137,28 @@ class Sfp(SfpBase): - A Boolean, True if SFP has TX fault, False if not - Note : TX fault status is lached until a call to get_tx_fault or a reset. - """ -- tx_fault = False -+ tx_fault = [False] - if self.port_num < 49: #Copper port, no sysfs -- return False -+ return [False] - - if self.port_num < 53: -- tx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_tx_fault_', self.port_num) -+ tx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_tx_fault_', self.port_num) - tx_fault=self._api_helper.read_txt_file(tx_path) -- if tx_fault is None: -- return False -- #status_control_raw = self.__read_eeprom_specific_bytes( -- # SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) -- #if status_control_raw: -- # data = int(status_control_raw[0], 16) -- # tx_fault = (sffbase().test_bit(data, 2) != 0) -+ if tx_fault is not None: -+ if tx_fault == '1': -+ return [True] -+ else: -+ return [False] -+ else: -+ return [False] - else: -- tx_fault_list = [] -- dom_channel_monitor_raw = self.__read_eeprom_specific_bytes( -- QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) if self.get_presence() else None -- if dom_channel_monitor_raw is not None: -- tx_fault_data = int(dom_channel_monitor_raw[0], 16) -- tx_fault_list.append(tx_fault_data & 0x01 != 0) -- tx_fault_list.append(tx_fault_data & 0x02 != 0) -- tx_fault_list.append(tx_fault_data & 0x04 != 0) -- tx_fault_list.append(tx_fault_data & 0x08 != 0) -- tx_fault = tx_fault_list[0] and tx_fault_list[1] and tx_fault_list[2] and tx_fault_list[3] -- -- return tx_fault -+ api = self.get_xcvr_api() -+ if api is not None: -+ tx_fault = api.get_tx_fault() -+ if isinstance(tx_fault, list) and "N/A" in tx_fault: -+ return [False for _ in tx_fault] -+ return tx_fault -+ return None - - def get_tx_disable(self): - """ -@@ -742,70 +169,19 @@ class Sfp(SfpBase): - if self.port_num < 49: #Copper port, no sysfs - return False - -- if self.port_num < 53: -- tx_disable = False -+ if self.port_num < 53: -+ tx_disable = False - - tx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_tx_disable_', self.port_num) - tx_disable=self._api_helper.read_txt_file(tx_path) -- -- -- #status_control_raw = self.__read_eeprom_specific_bytes( -- # SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) -- #if status_control_raw: -- # data = int(status_control_raw[0], 16) -- # tx_disable_hard = (sffbase().test_bit( -- # data, SFP_TX_DISABLE_HARD_BIT) != 0) -- # tx_disable_soft = (sffbase().test_bit( -- # data, SFP_TX_DISABLE_SOFT_BIT) != 0) -- # tx_disable = tx_disable_hard | tx_disable_soft - if tx_disable is not None: -- return tx_disable -+ return tx_disable - else: - return False - - else: -- tx_disable_list = [] -- -- sfpd_obj = sff8436Dom() -- if sfpd_obj is None: -- return False -- -- dom_control_raw = self.__read_eeprom_specific_bytes( -- QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None -- if dom_control_raw is not None: -- dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) -- tx_disable_list.append( -- 'On' == dom_control_data['data']['TX1Disable']['value']) -- tx_disable_list.append( -- 'On' == dom_control_data['data']['TX2Disable']['value']) -- tx_disable_list.append( -- 'On' == dom_control_data['data']['TX3Disable']['value']) -- tx_disable_list.append( -- 'On' == dom_control_data['data']['TX4Disable']['value']) -- -- return tx_disable_list -- -- def get_tx_disable_channel(self): -- """ -- Retrieves the TX disabled channels in this SFP -- Returns: -- A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent -- TX channels which have been disabled in this SFP. -- As an example, a returned value of 0x5 indicates that channel 0 -- and channel 2 have been disabled. -- """ -- if self.port_num < 53: -- # SFP doesn't support this feature -- return False -- else: -- tx_disable_list = self.get_tx_disable() -- if tx_disable_list is None: -- return 0 -- tx_disabled = 0 -- for i in range(len(tx_disable_list)): -- if tx_disable_list[i]: -- tx_disabled |= 1 << i -- return tx_disabled -+ api = self.get_xcvr_api() -+ return api.get_tx_disable() if api is not None else None - - def get_lpmode(self): - """ -@@ -813,7 +189,7 @@ class Sfp(SfpBase): - Returns: - A Boolean, True if lpmode is enabled, False if disabled - """ -- if self.port_num < 53: -+ if self.port_num < 53: - # SFP doesn't support this feature - return False - else: -@@ -821,124 +197,14 @@ class Sfp(SfpBase): - power_override = self.get_power_override() - return power_set and power_override - -- -- def get_power_set(self): -- -- if self.port_num < 53: -+ def get_power_set(self): -+ if self.port_num < 53: - # SFP doesn't support this feature - return False - else: -- power_set = False -- -- sfpd_obj = sff8436Dom() -- if sfpd_obj is None: -- return False -- -- dom_control_raw = self.__read_eeprom_specific_bytes( -- QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None -- if dom_control_raw is not None: -- dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) -- power_set = ( -- 'On' == dom_control_data['data']['PowerSet']['value']) -- -- return power_set -- -- def get_power_override(self): -- """ -- Retrieves the power-override status of this SFP -- Returns: -- A Boolean, True if power-override is enabled, False if disabled -- """ -- if self.port_num < 53: -- return False # SFP doesn't support this feature -- else: -- power_override = False -- -- -- sfpd_obj = sff8436Dom() -- if sfpd_obj is None: -- return False -- -- dom_control_raw = self.__read_eeprom_specific_bytes( -- QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None -- if dom_control_raw is not None: -- dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) -- power_override = ( -- 'On' == dom_control_data['data']['PowerOverride']['value']) -- -- return power_override -- -- def get_temperature(self): -- """ -- Retrieves the temperature of this SFP -- Returns: -- An integer number of current temperature in Celsius -- """ -- transceiver_dom_info_dict = self.get_transceiver_bulk_status() -- return transceiver_dom_info_dict.get("temperature", "N/A") -- -- def get_voltage(self): -- """ -- Retrieves the supply voltage of this SFP -- Returns: -- An integer number of supply voltage in mV -- """ -- transceiver_dom_info_dict = self.get_transceiver_bulk_status() -- return transceiver_dom_info_dict.get("voltage", "N/A") -- -- def get_tx_bias(self): -- """ -- Retrieves the TX bias current of this SFP -- Returns: -- A list of four integer numbers, representing TX bias in mA -- for channel 0 to channel 4. -- Ex. ['110.09', '111.12', '108.21', '112.09'] -- """ -- transceiver_dom_info_dict = self.get_transceiver_bulk_status() -+ api = self.get_xcvr_api() -+ return api.get_power_set() if api is not None else None - -- tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") -- if self.port_num < 53: -- return [tx1_bs, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] -- -- tx2_bs = transceiver_dom_info_dict.get("tx2bias", "N/A") -- tx3_bs = transceiver_dom_info_dict.get("tx3bias", "N/A") -- tx4_bs = transceiver_dom_info_dict.get("tx4bias", "N/A") -- return [tx1_bs, tx2_bs, tx3_bs, tx4_bs] if transceiver_dom_info_dict else [] -- -- def get_rx_power(self): -- """ -- Retrieves the received optical power for this SFP -- Returns: -- A list of four integer numbers, representing received optical -- power in mW for channel 0 to channel 4. -- Ex. ['1.77', '1.71', '1.68', '1.70'] -- """ -- transceiver_dom_info_dict = self.get_transceiver_bulk_status() -- -- rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") -- if self.port_num < 53: -- return [rx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] -- rx2_pw = transceiver_dom_info_dict.get("rx2power", "N/A") -- rx3_pw = transceiver_dom_info_dict.get("rx3power", "N/A") -- rx4_pw = transceiver_dom_info_dict.get("rx4power", "N/A") -- return [rx1_pw, rx2_pw, rx3_pw, rx4_pw] if transceiver_dom_info_dict else [] -- -- def get_tx_power(self): -- """ -- Retrieves the TX power of this SFP -- Returns: -- A list of four integer numbers, representing TX power in mW -- for channel 0 to channel 4. -- Ex. ['1.86', '1.86', '1.86', '1.86'] -- """ -- transceiver_dom_info_dict = self.get_transceiver_bulk_status() -- tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") -- if self.port_num < 53: -- return [tx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] -- tx2_pw = transceiver_dom_info_dict.get("tx2power", "N/A") -- tx3_pw = transceiver_dom_info_dict.get("tx3power", "N/A") -- tx4_pw = transceiver_dom_info_dict.get("tx4power", "N/A") -- return [tx1_pw, tx2_pw, tx3_pw, tx4_pw] - - def reset(self): - """ -@@ -947,7 +213,7 @@ class Sfp(SfpBase): - A boolean, True if successful, False if not - """ - # Check for invalid port_num -- if self.port_num < 53: # non-QSFP ports don't support it. -+ if self.port_num < 49: #Copper port, no sysfs - return False - - reset_path = "{}{}{}".format(CPLD_I2C_PATH, 'module_reset_', self.port_num) -@@ -974,8 +240,8 @@ class Sfp(SfpBase): - return False - - if self.port_num < 53: -- tx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_tx_disable_', self.port_num) -- ret = self.__write_txt_file(tx_path, 1 if tx_disable else 0) -+ tx_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_tx_disable_', self.port_num) -+ ret = self._api_helper.write_txt_file(tx_path, 1 if tx_disable else 0) - if ret is not None: - time.sleep(0.01) - return ret -@@ -985,78 +251,8 @@ class Sfp(SfpBase): - else: - if not self.get_presence(): - return False -- sysfsfile_eeprom = None -- try: -- tx_disable_ctl = 0xf if tx_disable else 0x0 -- buffer = create_string_buffer(1) -- if sys.version_info[0] >= 3: -- buffer[0] = tx_disable_ctl -- else: -- buffer[0] = chr(tx_disable_ctl) -- # Write to eeprom -- sysfsfile_eeprom = open( -- self.port_to_eeprom_mapping[self.port_num], "r+b") -- sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) -- sysfsfile_eeprom.write(buffer[0]) -- except IOError as e: -- print ('Error: unable to open file: ',str(e)) -- return False -- finally: -- if sysfsfile_eeprom is not None: -- sysfsfile_eeprom.close() -- time.sleep(0.01) -- return True -- -- def tx_disable_channel(self, channel, disable): -- """ -- Sets the tx_disable for specified SFP channels -- Args: -- channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, -- e.g. 0x5 for channel 0 and channel 2. -- disable : A boolean, True to disable TX channels specified in channel, -- False to enable -- Returns: -- A boolean, True if successful, False if not -- """ -- -- if self.port_num < 53: -- return False # SFP doesn't support this feature -- else: -- if not self.get_presence(): -- return False -- -- sysfsfile_eeprom = None -- try: -- channel_state = self.get_tx_disable_channel() -- -- for i in range(4): -- channel_mask = (1 << i) -- if not (channel & channel_mask): -- continue -- -- if disable: -- channel_state |= channel_mask -- else: -- channel_state &= ~channel_mask -- -- buffer = create_string_buffer(1) -- if sys.version_info[0] >= 3: -- buffer[0] = channel_state -- else: -- buffer[0] = chr(channel_state) -- # Write to eeprom -- sysfsfile_eeprom = open( -- self.port_to_eeprom_mapping[self.port_num], "r+b") -- sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) -- sysfsfile_eeprom.write(buffer[0]) -- except IOError as e: -- print ('Error: unable to open file: ', str(e)) -- return False -- finally: -- if sysfsfile_eeprom is not None: -- sysfsfile_eeprom.close() -- time.sleep(0.01) -- return True -+ api = self.get_xcvr_api() -+ return api.tx_disable(tx_disable) if api is not None else None - - def set_lpmode(self, lpmode): - """ -@@ -1070,12 +266,23 @@ class Sfp(SfpBase): - if self.port_num < 53: - return False # SFP doesn't support this feature - else: -+ ''' -+ use power override to control lpmode -+ ''' -+ if not self.get_presence(): -+ return False -+ api = self.get_xcvr_api() -+ if api is None: -+ return False -+ if api.get_lpmode_support() == False: -+ logger.log_notice("The transceiver of port {} doesn't support to set low power mode.". format(self.port_num)) -+ return True - if lpmode is True: -- self.set_power_override(True, True) -+ ret = api.set_power_override(True, True) - else: -- self.set_power_override(False, False) -+ ret = api.set_power_override(True, False) - -- return True -+ return ret - - def set_power_override(self, power_override, power_set): - """ -@@ -1099,24 +306,8 @@ class Sfp(SfpBase): - else: - if not self.get_presence(): - return False -- try: -- power_override_bit = (1 << 0) if power_override else 0 -- power_set_bit = (1 << 1) if power_set else (1 << 3) -- -- buffer = create_string_buffer(1) -- if sys.version_info[0] >= 3: -- buffer[0] = (power_override_bit | power_set_bit) -- else: -- buffer[0] = chr(power_override_bit | power_set_bit) -- # Write to eeprom -- with open(self.port_to_eeprom_mapping[self.port_num], "r+b") as fd: -- fd.seek(QSFP_POWEROVERRIDE_OFFSET) -- fd.write(buffer[0]) -- time.sleep(0.01) -- except Exception: -- print ('Error: unable to open file: ', str(e)) -- return False -- return True -+ api = self.get_xcvr_api() -+ return api.set_power_override(power_override, power_set) if api is not None else None - - def get_name(self): - """ -@@ -1125,9 +316,9 @@ class Sfp(SfpBase): - string: The name of the device - """ - sfputil_helper = SfpUtilHelper() -- sfputil_helper.read_porttab_mappings( -- self.__get_path_to_port_config_file()) -- name = sfputil_helper.logical[self.index] or "Unknown" -+ port_config_file_path = device_info.get_path_to_port_config_file() -+ sfputil_helper.read_porttab_mappings(port_config_file_path) -+ name = sfputil_helper.logical[self.port_num - 1] or "Unknown" - return name - - def get_presence(self): -@@ -1139,11 +330,11 @@ class Sfp(SfpBase): - if self.port_num < 49: #Copper port, no sysfs - return False - -- present_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_present_', self.port_num) -+ present_path = "{}{}{}".format(CPLD_I2C_PATH, '/module_present_', self.port_num) - val=self._api_helper.read_txt_file(present_path) - if val is not None: - return int(val, 10)==1 -- else: -+ else: - return False - - def get_model(self): -@@ -1170,7 +361,7 @@ class Sfp(SfpBase): - Returns: - A boolean value, True if device is operating properly, False if not - """ -- return self.get_presence() and self.get_transceiver_bulk_status() -+ return self.get_presence() and not self.get_reset_status() - - def get_position_in_parent(self): - """ -@@ -1188,3 +379,150 @@ class Sfp(SfpBase): - bool: True if it is replaceable. - """ - return True -+ -+ def __validate_eeprom_sfp(self): -+ checksum_test = 0 -+ eeprom_raw = self.read_eeprom(0, 96) -+ if eeprom_raw is None: -+ return None -+ -+ for i in range(0, 63): -+ checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF -+ else: -+ if checksum_test != eeprom_raw[63]: -+ return False -+ -+ checksum_test = 0 -+ for i in range(64, 95): -+ checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF -+ else: -+ if checksum_test != eeprom_raw[95]: -+ return False -+ -+ api = self.get_xcvr_api() -+ if api is None: -+ return False -+ -+ if api.is_flat_memory(): -+ return True -+ -+ checksum_test = 0 -+ eeprom_raw = self.read_eeprom(384, 96) -+ if eeprom_raw is None: -+ return None -+ -+ for i in range(0, 95): -+ checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF -+ else: -+ if checksum_test != eeprom_raw[95]: -+ return False -+ -+ return True -+ -+ def __validate_eeprom_qsfp(self): -+ checksum_test = 0 -+ eeprom_raw = self.read_eeprom(128, 96) -+ if eeprom_raw is None: -+ return None -+ -+ for i in range(0, 63): -+ checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF -+ else: -+ if checksum_test != eeprom_raw[63]: -+ return False -+ -+ checksum_test = 0 -+ for i in range(64, 95): -+ checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF -+ else: -+ if checksum_test != eeprom_raw[95]: -+ return False -+ -+ api = self.get_xcvr_api() -+ if api is None: -+ return False -+ -+ if api.is_flat_memory(): -+ return True -+ -+ return True -+ -+ def validate_eeprom(self): -+ id_byte_raw = self.read_eeprom(0, 1) -+ if id_byte_raw is None: -+ return None -+ -+ id = id_byte_raw[0] -+ if id in self.QSFP_TYPE_CODE_LIST: -+ return self.__validate_eeprom_qsfp() -+ elif id in self.SFP_TYPE_CODE_LIST: -+ return self.__validate_eeprom_sfp() -+ else: -+ return False -+ -+ def validate_temperature(self): -+ temperature = self.get_temperature() -+ if temperature is None: -+ return None -+ -+ threshold_dict = self.get_transceiver_threshold_info() -+ if threshold_dict is None: -+ return None -+ -+ if isinstance(temperature, float) is not True: -+ return True -+ -+ if isinstance(threshold_dict['temphighalarm'], float) is not True: -+ return True -+ -+ return threshold_dict['temphighalarm'] > temperature -+ -+ def __get_error_description(self): -+ if not self.get_presence(): -+ return self.SFP_STATUS_UNPLUGGED -+ -+ err_stat = self.SFP_STATUS_BIT_INSERTED -+ -+ status = self.validate_eeprom() -+ if status is not True: -+ err_stat = (err_stat | self.SFP_ERROR_BIT_BAD_EEPROM) -+ -+ status = self.validate_temperature() -+ if status is not True: -+ err_stat = (err_stat | self.SFP_ERROR_BIT_HIGH_TEMP) -+ -+ if err_stat is self.SFP_STATUS_BIT_INSERTED: -+ return self.SFP_STATUS_OK -+ else: -+ err_desc = '' -+ cnt = 0 -+ for key in self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT: -+ if (err_stat & key) != 0: -+ if cnt > 0: -+ err_desc = err_desc + "|" -+ cnt = cnt + 1 -+ err_desc = err_desc + self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT[key] -+ -+ return err_desc -+ -+ def get_error_description(self): -+ """ -+ Retrives the error descriptions of the SFP module -+ -+ Returns: -+ String that represents the current error descriptions of vendor specific errors -+ In case there are multiple errors, they should be joined by '|', -+ like: "Bad EEPROM|Unsupported cable" -+ """ -+ if self.port_num < 49: -+ # RJ45 doesn't support this feature -+ return None -+ else: -+ api = self.get_xcvr_api() -+ if api is not None: -+ try: -+ return api.get_error_description() -+ except NotImplementedError: -+ return self.__get_error_description() -+ else: -+ return self.__get_error_description() -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/thermal.py b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/thermal.py -index 7a453c594..04a714510 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/thermal.py -+++ b/device/accton/x86_64-accton_as4630_54te-r0/sonic_platform/thermal.py -@@ -12,56 +12,189 @@ import glob - - try: - from sonic_platform_base.thermal_base import ThermalBase -+ from .helper import DeviceThreshold - except ImportError as e: - raise ImportError(str(e) + "- required module not found") - -+PSU_I2C_PATH = "/sys/bus/i2c/devices/{}-00{}/" -+PSU_I2C_MAPPING = { -+ 0: { -+ "num": 10, -+ "addr": "58" -+ }, -+ 1: { -+ "num": 11, -+ "addr": "59" -+ }, -+} -+ -+PSU_CPLD_I2C_MAPPING = { -+ 0: { -+ "num": 10, -+ "addr": "50" -+ }, -+ 1: { -+ "num": 11, -+ "addr": "51" -+ }, -+} -+ -+NOT_AVAILABLE = DeviceThreshold.NOT_AVAILABLE -+HIGH_THRESHOLD = DeviceThreshold.HIGH_THRESHOLD -+LOW_THRESHOLD = DeviceThreshold.LOW_THRESHOLD -+HIGH_CRIT_THRESHOLD = DeviceThreshold.HIGH_CRIT_THRESHOLD -+LOW_CRIT_THRESHOLD = DeviceThreshold.LOW_CRIT_THRESHOLD -+ -+DEFAULT_THRESHOLD = { -+ 'MB_temp(0x48)' : { -+ HIGH_THRESHOLD : '80.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'CB_temp(0x4B)' : { -+ HIGH_THRESHOLD : '80.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'FB_temp(0x4A)' : { -+ HIGH_THRESHOLD : '80.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'CPU_Package_temp' : { -+ HIGH_THRESHOLD : '71.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : '91.0', -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'CPU_Core_0_temp' : { -+ HIGH_THRESHOLD : '71.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : '91.0', -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'CPU_Core_1_temp' : { -+ HIGH_THRESHOLD : '71.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : '91.0', -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'CPU_Core_2_temp' : { -+ HIGH_THRESHOLD : '71.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : '91.0', -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'CPU_Core_3_temp' : { -+ HIGH_THRESHOLD : '71.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : '91.0', -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'PSU-1 temp sensor 1' : { -+ HIGH_THRESHOLD : '80.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ }, -+ 'PSU-2 temp sensor 1' : { -+ HIGH_THRESHOLD : '80.0', -+ LOW_THRESHOLD : NOT_AVAILABLE, -+ HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, -+ LOW_CRIT_THRESHOLD : NOT_AVAILABLE -+ } -+} - - class Thermal(ThermalBase): - """Platform-specific Thermal class""" - - THERMAL_NAME_LIST = [] -+ PSU_THERMAL_NAME_LIST = [] - SYSFS_PATH = "/sys/bus/i2c/devices" -+ CPU_SYSFS_PATH = "/sys/devices/platform" - -- def __init__(self, thermal_index=0): -- self.THERMAL_NAME_LIST = [] -- self.SYSFS_PATH = "/sys/bus/i2c/devices" -+ def __init__(self, thermal_index=0, is_psu=False, psu_index=0): - self.index = thermal_index -+ self.is_psu = is_psu -+ self.psu_index = psu_index -+ self.min_temperature = None -+ self.max_temperature = None -+ -+ if self.is_psu: -+ psu_i2c_bus = PSU_I2C_MAPPING[psu_index]["num"] -+ psu_i2c_addr = PSU_I2C_MAPPING[psu_index]["addr"] -+ self.psu_hwmon_path = PSU_I2C_PATH.format(psu_i2c_bus, -+ psu_i2c_addr) -+ psu_i2c_bus = PSU_CPLD_I2C_MAPPING[psu_index]["num"] -+ psu_i2c_addr = PSU_CPLD_I2C_MAPPING[psu_index]["addr"] -+ self.cpld_path = PSU_I2C_PATH.format(psu_i2c_bus, psu_i2c_addr) - # Add thermal name -- self.THERMAL_NAME_LIST.append("Temp sensor 1") -- self.THERMAL_NAME_LIST.append("Temp sensor 2") -- self.THERMAL_NAME_LIST.append("Temp sensor 3") -+ self.THERMAL_NAME_LIST.append("MB_temp(0x48)") -+ self.THERMAL_NAME_LIST.append("CB_temp(0x4B)") -+ self.THERMAL_NAME_LIST.append("FB_temp(0x4A)") -+ self.THERMAL_NAME_LIST.append("CPU_Package_temp") -+ self.THERMAL_NAME_LIST.append("CPU_Core_0_temp") -+ self.THERMAL_NAME_LIST.append("CPU_Core_1_temp") -+ self.THERMAL_NAME_LIST.append("CPU_Core_2_temp") -+ self.THERMAL_NAME_LIST.append("CPU_Core_3_temp") -+ self.PSU_THERMAL_NAME_LIST.append("PSU-1 temp sensor 1") -+ self.PSU_THERMAL_NAME_LIST.append("PSU-2 temp sensor 1") -+ -+ # Threshold Configuration -+ self.__conf = DeviceThreshold(self.get_name()) -+ # Default threshold. -+ self.__default_threshold = DEFAULT_THRESHOLD[self.get_name()] - - # Set hwmon path - i2c_path = { -- 0: "14-0048/hwmon/hwmon*/", -- 1: "24-004b/hwmon/hwmon*/", -- 2: "25-004a/hwmon/hwmon*/" -+ 0: {"hwmon_path":"14-0048/hwmon/hwmon*/", "ss_index":1}, -+ 1: {"hwmon_path":"24-004b/hwmon/hwmon*/", "ss_index":1}, -+ 2: {"hwmon_path":"25-004a/hwmon/hwmon*/", "ss_index":1}, -+ 3: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":1}, -+ 4: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":4}, -+ 5: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":8}, -+ 6: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":10}, -+ 7: {"hwmon_path":"coretemp.0/hwmon/hwmon*/", "ss_index":14} - }.get(self.index, None) - -- self.hwmon_path = "{}/{}".format(self.SYSFS_PATH, i2c_path) -+ self.is_cpu = False -+ if self.index in range(3,8): -+ self.is_cpu = True -+ self.hwmon_path = "{}/{}".format(self.CPU_SYSFS_PATH, i2c_path["hwmon_path"]) -+ else: -+ self.hwmon_path = "{}/{}".format(self.SYSFS_PATH, i2c_path["hwmon_path"]) - self.ss_key = self.THERMAL_NAME_LIST[self.index] -- self.ss_index = 1 -+ self.ss_index = i2c_path["ss_index"] - - def __read_txt_file(self, file_path): - for filename in glob.glob(file_path): - try: -- with open(filename, 'r') as fd: -- data =fd.readline().rstrip() -- return data -+ with open(filename, 'r') as fd: -+ data =fd.readline().strip() -+ if len(data) > 0: -+ return data - except IOError as e: - pass - - return None - - def __get_temp(self, temp_file): -- temp_file_path = os.path.join(self.hwmon_path, temp_file) -+ if not self.is_psu: -+ temp_file_path = os.path.join(self.hwmon_path, temp_file) -+ else: -+ temp_file_path = temp_file - raw_temp = self.__read_txt_file(temp_file_path) - if raw_temp is not None: - return float(raw_temp)/1000 - else: -- return 0 -+ return 0 - - def __set_threshold(self, file_name, temperature): -+ if self.is_psu: -+ return True - temp_file_path = os.path.join(self.hwmon_path, file_name) - for filename in glob.glob(temp_file_path): - try: -@@ -79,41 +212,153 @@ class Thermal(ThermalBase): - A float number of current temperature in Celsius up to nearest thousandth - of one degree Celsius, e.g. 30.125 - """ -- temp_file = "temp{}_input".format(self.ss_index) -- return self.__get_temp(temp_file) -+ if not self.is_psu: -+ temp_file = "temp{}_input".format(self.ss_index) -+ else: -+ temp_file = self.psu_hwmon_path + "psu_temp1_input" - -- def get_high_threshold(self): -- """ -- Retrieves the high threshold temperature of thermal -- Returns: -- A float number, the high threshold temperature of thermal in Celsius -- up to nearest thousandth of one degree Celsius, e.g. 30.125 -- """ -- temp_file = "temp{}_max".format(self.ss_index) -- return self.__get_temp(temp_file) -+ current = self.__get_temp(temp_file) -+ -+ if self.min_temperature is None or \ -+ current < self.min_temperature: -+ self.min_temperature = current -+ -+ if self.max_temperature is None or \ -+ current > self.max_temperature: -+ self.max_temperature = current -+ -+ return current - - def set_high_threshold(self, temperature): -- """ -- Sets the high threshold temperature of thermal -- Args : -- temperature: A float number up to nearest thousandth of one degree Celsius, -- e.g. 30.125 -- Returns: -- A boolean, True if threshold is set successfully, False if not -- """ -- temp_file = "temp{}_max".format(self.ss_index) -- temperature = temperature *1000 -- self.__set_threshold(temp_file, temperature) -+ try: -+ value = float(temperature) -+ except Exception: -+ return False -+ -+ # The new value can not be more than the default value. -+ default_value = self.__default_threshold[HIGH_THRESHOLD] -+ if default_value != NOT_AVAILABLE: -+ if value > float(default_value): -+ return False -+ -+ try: -+ self.__conf.set_high_threshold(str(value)) -+ except Exception: -+ return False -+ -+ return True -+ -+ def get_high_threshold(self): -+ value = self.__conf.get_high_threshold() -+ if value != NOT_AVAILABLE: -+ return float(value) -+ -+ default_value = self.__default_threshold[HIGH_THRESHOLD] -+ if default_value != NOT_AVAILABLE: -+ return float(default_value) -+ -+ raise NotImplementedError -+ -+ def set_low_threshold(self, temperature): -+ try: -+ value = float(temperature) -+ except Exception: -+ return False -+ -+ # The new value can not be less than the default value. -+ default_value = self.__default_threshold[LOW_THRESHOLD] -+ if default_value != NOT_AVAILABLE: -+ if value < float(default_value): -+ return False -+ -+ try: -+ self.__conf.set_low_threshold(str(value)) -+ except Exception: -+ return False -+ -+ return True -+ -+ def get_low_threshold(self): -+ value = self.__conf.get_low_threshold() -+ if value != NOT_AVAILABLE: -+ return float(value) -+ -+ default_value = self.__default_threshold[LOW_THRESHOLD] -+ if default_value != NOT_AVAILABLE: -+ return float(default_value) -+ -+ raise NotImplementedError -+ -+ def set_high_critical_threshold(self, temperature): -+ try: -+ value = float(temperature) -+ except Exception: -+ return False -+ -+ # The new value can not be more than the default value. -+ default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD] -+ if default_value != NOT_AVAILABLE: -+ if value > float(default_value): -+ return False -+ -+ try: -+ self.__conf.set_high_critical_threshold(str(value)) -+ except Exception: -+ return False - - return True - -+ def get_high_critical_threshold(self): -+ value = self.__conf.get_high_critical_threshold() -+ if value != NOT_AVAILABLE: -+ return float(value) -+ -+ default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD] -+ if default_value != NOT_AVAILABLE: -+ return float(default_value) -+ -+ raise NotImplementedError -+ -+ def set_low_critical_threshold(self, temperature): -+ try: -+ value = float(temperature) -+ except Exception: -+ return False -+ -+ # The new value can not be less than the default value. -+ default_value = self.__default_threshold[LOW_CRIT_THRESHOLD] -+ if default_value != NOT_AVAILABLE: -+ if value < float(default_value): -+ return False -+ -+ try: -+ self.__conf.set_low_critical_threshold(str(value)) -+ except Exception: -+ return False -+ -+ return True -+ -+ def get_low_critical_threshold(self): -+ value = self.__conf.get_low_critical_threshold() -+ if value != NOT_AVAILABLE: -+ return float(value) -+ -+ default_value = self.__default_threshold[LOW_CRIT_THRESHOLD] -+ if default_value != NOT_AVAILABLE: -+ return float(default_value) -+ -+ raise NotImplementedError -+ - def get_name(self): - """ - Retrieves the name of the thermal device - Returns: - string: The name of the thermal device - """ -- return self.THERMAL_NAME_LIST[self.index] -+ if self.is_psu: -+ return self.PSU_THERMAL_NAME_LIST[self.psu_index] -+ else: -+ return self.THERMAL_NAME_LIST[self.index] - - def get_presence(self): - """ -@@ -121,6 +366,15 @@ class Thermal(ThermalBase): - Returns: - bool: True if Thermal is present, False if not - """ -+ if self.is_cpu: -+ return True -+ -+ if self.is_psu: -+ val = self.__read_txt_file(self.cpld_path + "psu_present") -+ if val is not None: -+ return int(val, 10) == 1 -+ else: -+ return False - temp_file = "temp{}_input".format(self.ss_index) - temp_file_path = os.path.join(self.hwmon_path, temp_file) - raw_txt = self.__read_txt_file(temp_file_path) -@@ -135,11 +389,78 @@ class Thermal(ThermalBase): - Returns: - A boolean value, True if device is operating properly, False if not - """ -+ if self.is_cpu: -+ return True -+ -+ if self.is_psu: -+ temp_file = self.psu_hwmon_path + "psu_temp_fault" -+ psu_temp_fault = self.__read_txt_file(temp_file) -+ if psu_temp_fault is None: -+ psu_temp_fault = '1' -+ return self.get_presence() and (not int(psu_temp_fault)) - - file_str = "temp{}_input".format(self.ss_index) - file_path = os.path.join(self.hwmon_path, file_str) - raw_txt = self.__read_txt_file(file_path) - if raw_txt is None: - return False -- else: -+ else: - return int(raw_txt) != 0 -+ -+ def get_model(self): -+ """ -+ Retrieves the model number (or part number) of the device -+ Returns: -+ string: Model/part number of device -+ """ -+ -+ return "N/A" -+ -+ def get_serial(self): -+ """ -+ Retrieves the serial number of the device -+ Returns: -+ string: Serial number of device -+ """ -+ return "N/A" -+ -+ def get_position_in_parent(self): -+ """ -+ Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position -+ for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned -+ Returns: -+ integer: The 1-based relative physical position in parent device or -1 if cannot determine the position -+ """ -+ return self.index+1 -+ -+ def is_replaceable(self): -+ """ -+ Retrieves whether thermal module is replaceable -+ Returns: -+ A boolean value, True if replaceable, False if not -+ """ -+ return False -+ -+ def get_minimum_recorded(self): -+ """ -+ Retrieves the minimum recorded temperature of thermal -+ Returns: -+ A float number, the minimum recorded temperature of thermal in Celsius -+ up to nearest thousandth of one degree Celsius, e.g. 30.125 -+ """ -+ if self.min_temperature is None: -+ self.get_temperature() -+ -+ return self.min_temperature -+ -+ def get_maximum_recorded(self): -+ """ -+ Retrieves the maximum recorded temperature of thermal -+ Returns: -+ A float number, the maximum recorded temperature of thermal in Celsius -+ up to nearest thousandth of one degree Celsius, e.g. 30.125 -+ """ -+ if self.max_temperature is None: -+ self.get_temperature() -+ -+ return self.max_temperature -diff --git a/device/accton/x86_64-accton_as4630_54te-r0/system_health_monitoring_config.json b/device/accton/x86_64-accton_as4630_54te-r0/system_health_monitoring_config.json -index 91a29558b..97f9aa305 100644 ---- a/device/accton/x86_64-accton_as4630_54te-r0/system_health_monitoring_config.json -+++ b/device/accton/x86_64-accton_as4630_54te-r0/system_health_monitoring_config.json -@@ -1,9 +1,7 @@ - { - "services_to_ignore": [], - "devices_to_ignore": [ -- "asic", -- "psu.temperature" -- -+ "asic" - ], - "user_defined_checkers": [], - "polling_interval": 60, -diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/modules/x86-64-accton-as4630-54te-psu.c b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/modules/x86-64-accton-as4630-54te-psu.c -index 3a99f19a9..5813d8918 100755 ---- a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/modules/x86-64-accton-as4630-54te-psu.c -+++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/modules/x86-64-accton-as4630-54te-psu.c -@@ -91,7 +91,6 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, - struct as4630_54te_psu_data *data = as4630_54te_psu_update_device(dev); - u8 status = 0; - -- //printk("data->status=0x%x, attr->index=%d,data->index=%d \n", data->status, attr->index, data->index); - if (attr->index == PSU_PRESENT) { - if(data->index==0) - status = !( (data->status >> 5) & 0x1); -@@ -102,7 +101,7 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, - if(data->index==0) - status = ( (data->status >> 6) & 0x1); - else -- status = ( (data->status >> 2) & 0x1); -+ status = ( (data->status >> 2) & 0x1); - } - - return sprintf(buf, "%d\n", status); -@@ -261,13 +260,14 @@ static struct as4630_54te_psu_data *as4630_54te_psu_update_device(struct device - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int status; -+ u8 serial_offset; - int power_good = 0; - - dev_dbg(&client->dev, "Starting as4630_54te update\n"); - - /* Read psu status */ - status = as4630_54te_cpld_read(0x60, 0x22); -- //printk("status=0x%x in %s\n", status, __FUNCTION__); -+ - if (status < 0) { - dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); - } -@@ -278,29 +278,49 @@ static struct as4630_54te_psu_data *as4630_54te_psu_update_device(struct device - /* Read model name */ - memset(data->model_name, 0, sizeof(data->model_name)); - memset(data->serial_number, 0, sizeof(data->serial_number)); -- power_good = (data->status >> (3-data->index) & 0x1); -- -+ if(data->index==0) -+ power_good = ( (data->status >> 6) & 0x1); -+ else -+ power_good = ( (data->status >> 2) & 0x1); -+ - if (power_good) { - status = as4630_54te_psu_read_block(client, 0x20, data->model_name, -- ARRAY_SIZE(data->model_name)-1); -+ ARRAY_SIZE(data->model_name)-1); -+ - if (status < 0) { - data->model_name[0] = '\0'; - dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); -- printk("unable to read model name from (0x%x)\n", client->addr); - } - else { -+ data->model_name[8] = '-'; - data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; -- - } -- /* Read from offset 0x2e ~ 0x3d (16 bytes) */ -- status = as4630_54te_psu_read_block(client, 0x35,data->serial_number, MAX_SERIAL_NUMBER); -+ if(!strncmp(data->model_name, "YM-1151D", strlen("YM-1151D"))) -+ { -+ if (!strncmp(data->model_name, "YM-1151D-A03R", strlen("YM-1151D-A03R"))) -+ { -+ data->model_name[strlen("YM-1151D-A03R")] = '\0'; -+ serial_offset = 0x2E; /* YM-1151D-A03R, F2B dir */ -+ } -+ else -+ { -+ data->model_name[strlen("YM-1151D-A02R")] = '\0'; -+ serial_offset = 0x35; /* YM-1151D-A02R, B2F dir */ -+ } -+ } -+ else -+ serial_offset = 0x2E; -+ -+ /* Read from offset 0x2e ~ 0x3f (16 bytes) */ -+ status = as4630_54te_psu_read_block(client, serial_offset, data->serial_number, MAX_SERIAL_NUMBER); - if (status < 0) - { - data->serial_number[0] = '\0'; - dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); -- printk("unable to read model name from (0x%x) offset(0x2e)\n", client->addr); - } -+ - data->serial_number[MAX_SERIAL_NUMBER-1]='\0'; -+ - } - - data->last_updated = jiffies; -diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/service/as4630-54te-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/service/as4630-54te-platform-monitor.service -index 587e6a1ca..b0c5fe6a7 100644 ---- a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/service/as4630-54te-platform-monitor.service -+++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/service/as4630-54te-platform-monitor.service -@@ -1,6 +1,6 @@ - [Unit] - Description=Accton AS4630-54TE Platform Monitoring service --Before=pmon.service -+Before=pmon.service system-health.service - After=sysinit.target - DefaultDependencies=no - -diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/udev/70-persistent-net.rules b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/udev/70-persistent-net.rules -new file mode 100644 -index 000000000..11ca59a6f ---- /dev/null -+++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/udev/70-persistent-net.rules -@@ -0,0 +1,3 @@ -+ACTION=="add", SUBSYSTEM=="net", DRIVERS=="ixgbe", KERNELS=="0000:08:00.0", NAME:="eth0" -+ACTION=="add", SUBSYSTEM=="net", DRIVERS=="ixgbe", KERNELS=="0000:06:00.1", NAME:="eth1" -+ACTION=="add", SUBSYSTEM=="net", DRIVERS=="ixgbe", KERNELS=="0000:06:00.0", NAME:="eth3" -\ No newline at end of file -diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/accton_as4630_54te_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/accton_as4630_54te_monitor.py -index aa5076c2c..005d9d6b1 100755 ---- a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/accton_as4630_54te_monitor.py -+++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/accton_as4630_54te_monitor.py -@@ -87,6 +87,9 @@ class device_monitor(object): - - def __init__(self, log_file, log_level): - """Needs a logger and a logger level.""" -+ -+ self.thermal = ThermalUtil() -+ self.fan = FanUtil() - # set up logging to file - logging.basicConfig( - filename=log_file, -@@ -138,8 +141,8 @@ class device_monitor(object): - LEVEL_TEMP_CRITICAL: [100, 16, 240000, 300000], - } - temp = [0, 0, 0] -- thermal = ThermalUtil() -- fan = FanUtil() -+ thermal = self.thermal -+ fan = self.fan - ori_duty_cycle = fan.get_fan_duty_cycle() - new_duty_cycle = 0 - -diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/handle_mgmt_interface.sh b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/handle_mgmt_interface.sh -index 82f4d5e02..cdc3c04fc 100755 ---- a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/handle_mgmt_interface.sh -+++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/handle_mgmt_interface.sh -@@ -1,8 +1,7 @@ - #!/bin/bash - --#Due to the hardware design, as4630-54te use "eth2" instead of "eth0" as management interface. --#Rename netdev "eth0" and "eth2" to swap original "eth2" to "eth0". --ifconfig eth0 down --ip link set eth0 name eth3 --ip link set eth2 name eth0 --ifconfig eth0 up -+# Re-install the igb and ixgbe again to make the NIC sequence follow the udev rule -+modprobe -r igb -+modprobe -r ixgbe -+modprobe igb -+modprobe ixgbe -\ No newline at end of file -diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/restart_ixgbe.sh b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/restart_ixgbe.sh -new file mode 100755 -index 000000000..57c14e5ba ---- /dev/null -+++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54te/utils/restart_ixgbe.sh -@@ -0,0 +1,8 @@ -+#!/bin/bash -+ -+/etc/init.d/netfilter-persistent stop -+modprobe -r ixgbe -+udevadm control --reload-rules -+udevadm trigger -+modprobe ixgbe -+/etc/init.d/netfilter-persistent start -diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules -index c47aa3b3e..cfbfeaed7 100755 ---- a/platform/broadcom/sonic-platform-modules-accton/debian/rules -+++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules -@@ -27,6 +27,7 @@ MODULE_DIR := modules - UTILS_DIR := utils - SERVICE_DIR := service - CONF_DIR := conf -+UDEV_DIR := udev - - %: - dh $@ --with systemd,python3 --buildsystem=pybuild -@@ -70,9 +71,15 @@ binary-indep: - dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ - dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ - dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ -+ if [ -d $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR) ]; then \ -+ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc/udev/rules.d; \ -+ fi; \ - cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ - cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ - cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ -+ if [ -f $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR)/* ]; then \ -+ cp $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/udev/rules.d/; \ -+ fi; \ - $(PYTHON3) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ - done) - # Resuming debhelper scripts diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/installer.conf b/device/accton/x86_64-accton_as4630_54pe-r0/installer.conf index 735fa7992d..85bb317cc9 100755 --- a/device/accton/x86_64-accton_as4630_54pe-r0/installer.conf +++ b/device/accton/x86_64-accton_as4630_54pe-r0/installer.conf @@ -1,4 +1,4 @@ CONSOLE_PORT=0x3f8 CONSOLE_DEV=0 CONSOLE_SPEED=115200 -ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off modprobe.blacklist=i2c-ismt,i2c_ismt,i2c-i801,i2c_i801" +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pcie_aspm=off intel_iommu=off modprobe.blacklist=i2c-ismt,i2c_ismt,i2c-i801,i2c_i801" diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pcie.yaml b/device/accton/x86_64-accton_as4630_54pe-r0/pcie.yaml new file mode 100644 index 0000000000..c7e99c8678 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/pcie.yaml @@ -0,0 +1,167 @@ +- bus: '00' + dev: '00' + fn: '0' + id: '1980' + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent (rev + 11)' +- bus: '00' + dev: '04' + fn: '0' + id: 19a1 + name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers + (rev 11)' +- bus: '00' + dev: '05' + fn: '0' + id: 19a2 + name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000 + Series Root Complex Event Collector (rev 11)' +- bus: '00' + dev: '06' + fn: '0' + id: 19a3 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT + Root Port (rev 11)' +- bus: '00' + dev: 09 + fn: '0' + id: 19a4 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #0 (rev 11)' +- bus: '00' + dev: 0b + fn: '0' + id: 19a6 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #2 (rev 11)' +- bus: '00' + dev: 0e + fn: '0' + id: 19a8 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #4 (rev 11)' +- bus: '00' + dev: '10' + fn: '0' + id: 19aa + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root + Port #6 (rev 11)' +- bus: '00' + dev: '12' + fn: '0' + id: 19ac + name: 'System peripheral: Intel Corporation Atom Processor C3000 Series SMBus Contoller + - Host (rev 11)' +- bus: '00' + dev: '13' + fn: '0' + id: 19b2 + name: 'SATA controller: Intel Corporation Atom Processor C3000 Series SATA Controller + 0 (rev 11)' +- bus: '00' + dev: '15' + fn: '0' + id: 19d0 + name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI + Controller (rev 11)' +- bus: '00' + dev: '16' + fn: '0' + id: 19d1 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN + Root Port #0 (rev 11)' +- bus: '00' + dev: '17' + fn: '0' + id: 19d2 + name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN + Root Port #1 (rev 11)' +- bus: '00' + dev: '18' + fn: '0' + id: 19d3 + name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME + HECI 1 (rev 11)' +- bus: '00' + dev: 1a + fn: '0' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '1' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1a + fn: '2' + id: 19d8 + name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller + (rev 11)' +- bus: '00' + dev: 1c + fn: '0' + id: 19db + name: 'SD Host controller: Intel Corporation Device 19db (rev 11)' +- bus: '00' + dev: 1f + fn: '0' + id: 19dc + name: 'ISA bridge: Intel Corporation Atom Processor C3000 Series LPC or eSPI (rev + 11)' +- bus: '00' + dev: 1f + fn: '1' + id: 19dd + name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Primary + to Side Band (P2SB) Bridge (rev 11)' +- bus: '00' + dev: 1f + fn: '2' + id: 19de + name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management + Controller (rev 11)' +- bus: '00' + dev: 1f + fn: '4' + id: 19df + name: 'SMBus: Intel Corporation Atom Processor C3000 Series SMBus controller (rev + 11)' +- bus: '00' + dev: 1f + fn: '5' + id: 19e0 + name: 'Serial bus controller [0c80]: Intel Corporation Atom Processor C3000 Series + SPI Controller (rev 11)' +- bus: '01' + dev: '00' + fn: '0' + id: 19e2 + name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology + (rev 11)' +- bus: '05' + dev: '00' + fn: '0' + id: b371 + name: 'Ethernet controller: Broadcom Inc. and subsidiaries BCM56371 Switch ASIC + (rev 03)' +- bus: '06' + dev: '00' + fn: '0' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' +- bus: '06' + dev: '00' + fn: '1' + id: 15c2 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane + (rev 11)' +- bus: 08 + dev: '00' + fn: '0' + id: 15e5 + name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 1GbE (rev + 11)' diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pd-plugin.json b/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pd-plugin.json index 0abf66aab7..77dfdc8276 100644 --- a/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pd-plugin.json +++ b/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pd-plugin.json @@ -33,11 +33,11 @@ { "i2c": { - "valmap": { "F2B":"EXHAUST", "B2F":"INTAKE" } + "valmap": { "F2B":"exhaust", "B2F":"intake" } } }, - "PSU_FAN_MAX_SPEED":"18000" + "PSU_FAN_MAX_SPEED":"26688" }, "FAN": @@ -46,7 +46,7 @@ { "i2c": { - "valmap": {"1":"EXHAUST", "0":"INTAKE"} + "valmap": {"1":"exhaust", "0":"intake"} } }, diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pddf-device.json b/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pddf-device.json index 34013b2a84..95da95496c 100644 --- a/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pddf-device.json +++ b/device/accton/x86_64-accton_as4630_54pe-r0/pddf/pddf-device.json @@ -5,7 +5,7 @@ "num_fantrays":3, "num_fans_pertray":1, "num_ports":54, - "num_temps": 3, + "num_temps": 4, "pddf_dev_types": { "description":"AS4630 - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo > /new_device' method", @@ -211,6 +211,21 @@ } }, + "TEMP4" : + { + "dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4"}, + "dev_attr": { "display_name":"coretemp-isa-0000"}, + "i2c": + { + "path_info": {"sysfs_base_path": "/sys/class/hwmon/hwmon1"}, + "attr_list": + [ + { "attr_name": "temp1_high_crit_threshold", "drv_attr_name":"temp1_crit"}, + { "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"}, + { "attr_name": "temp1_input"} + ] + } + }, "CPLD1": { @@ -251,15 +266,15 @@ "SYS_LED": { "dev_info": { "device_type":"LED", "device_name":"SYS_LED"}, - "dev_attr": { "index":"0"}, + "dev_attr": { "index":"0", "flag": "rw"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "7:5", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_GREEN_BLINK", "bits" : "7:5", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "7:5", "descr" : "", "value" : "0x4", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_AMBER_BLINK", "bits" : "7:5", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "7:5", "descr" : "", "value" : "0x7", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} + {"attr_name":"green", "bits" : "7:5", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"green_blink", "bits" : "7:5", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"amber", "bits" : "7:5", "descr" : "", "value" : "0x4", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"amber_blink", "bits" : "7:5", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"off", "bits" : "7:5", "descr" : "", "value" : "0x7", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} ] } }, @@ -268,13 +283,13 @@ "PSU1_LED": { "dev_info": { "device_type":"LED", "device_name":"PSU_LED"}, - "dev_attr": { "index":"0"}, + "dev_attr": { "index":"0", "flag": "r"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "1:0", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "1:0", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "1:0", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} + {"attr_name":"green", "bits" : "1:0", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"amber", "bits" : "1:0", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}, + {"attr_name":"off", "bits" : "1:0", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"} ] } }, @@ -282,13 +297,13 @@ "PSU2_LED": { "dev_info": { "device_type":"LED", "device_name":"PSU_LED"}, - "dev_attr": { "index":"1"}, + "dev_attr": { "index":"1", "flag": "r"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "7:6", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, - {"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "7:6", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "7:6", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} + {"attr_name":"green", "bits" : "7:6", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"amber", "bits" : "7:6", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"off", "bits" : "7:6", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} ] } }, @@ -296,13 +311,13 @@ "FAN_LED": { "dev_info": { "device_type":"LED", "device_name":"FAN_LED"}, - "dev_attr": { "index":"0"}, + "dev_attr": { "index":"0", "flag": "r"}, "i2c" : { "attr_list": [ - {"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "3:2", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, - {"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "3:2", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, - {"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "3:2", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} + {"attr_name":"green", "bits" : "3:2", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"amber", "bits" : "3:2", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}, + {"attr_name":"off", "bits" : "3:2", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"} ] } }, @@ -336,7 +351,11 @@ { "attr_name":"psu_i_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_p_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + { "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_max", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_min", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_p_out_max", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa8", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} ] } }, @@ -387,7 +406,11 @@ { "attr_name":"psu_i_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_p_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, { "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, - { "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} + { "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_max", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_v_out_min", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_p_out_max", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}, + { "attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa8", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"} ] } }, @@ -592,7 +615,9 @@ "topo_info": { "parent_bus":"0x16", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, "attr_list": [ - { "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"} + { "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x3", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"} ] } }, @@ -630,7 +655,9 @@ "topo_info": { "parent_bus":"0x17", "dev_addr":"0x53", "dev_type":"pddf_xcvr"}, "attr_list": [ - { "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"} + { "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_reset", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x7", "attr_cmpval":"0x0", "attr_len":"1"}, + { "attr_name":"xcvr_intr_status", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x5", "attr_cmpval":"0x0", "attr_len":"1"} ] } } diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/platform.json b/device/accton/x86_64-accton_as4630_54pe-r0/platform.json new file mode 100644 index 0000000000..72461beac3 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/platform.json @@ -0,0 +1,785 @@ +{ + "chassis": { + "name": "4630-54PE", + "thermal_manager":false, + "status_led": { + "controllable": true, + "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_GREEN_BLINK", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_AMBER_BLINK", "STATUS_LED_COLOR_OFF"] + }, + "components": [ + { + "name": "CPLD1" + }, + { + "name": "BIOS" + } + ], + "fans": [ + { + "name": "FAN-1", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-2", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + }, + { + "name": "FAN-3", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ], + "fan_drawers":[ + { + "name": "FanTray1", + "status_led": { + "controllable": false + }, + "num_fans" : 1, + "fans": [ + { + "name": "FAN-1", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray2", + "status_led": { + "controllable": false + }, + "num_fans" : 1, + "fans": [ + { + "name": "FAN-2", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + }, + { + "name": "FanTray3", + "status_led": { + "controllable": false + }, + "num_fans" : 1, + "fans": [ + { + "name": "FAN-3", + "speed": { + "controllable": true, + "minimum": 7 + }, + "status_led": { + "controllable": false + } + } + ] + } + ], + "psus": [ + { + "name": "PSU-1", + "status_led": { + "controllable": true, + "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"] + }, + "fans": [ + { + "name": "PSU-1 FAN-1" + } + ], + "thermals": [ + { + "name": "PSU-1 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ] + }, + { + "name": "PSU-2", + "status_led": { + "controllable": true, + "colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"] + }, + "fans": [ + { + "name": "PSU-2 FAN-1" + } + ], + "thermals": [ + { + "name": "PSU-2 temp sensor 1", + "controllable": false, + "low-crit-threshold": false, + "high-crit-threshold": false + } + ] + } + ], + "thermals": [ + { + "name": "Temp sensor 1", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "Temp sensor 2", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "Temp sensor 3", + "controllable": true, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": false + }, + { + "name": "Temp sensor 4", + "controllable": false, + "low-threshold": false, + "high-threshold": true, + "low-crit-threshold": false, + "high-crit-threshold": true + } + ], + "sfps": [ + { + "name": "Ethernet0" + }, + { + "name": "Ethernet1" + }, + { + "name": "Ethernet2" + }, + { + "name": "Ethernet3" + }, + { + "name": "Ethernet4" + }, + { + "name": "Ethernet5" + }, + { + "name": "Ethernet6" + }, + { + "name": "Ethernet7" + }, + { + "name": "Ethernet8" + }, + { + "name": "Ethernet9" + }, + { + "name": "Ethernet10" + }, + { + "name": "Ethernet11" + }, + { + "name": "Ethernet12" + }, + { + "name": "Ethernet13" + }, + { + "name": "Ethernet14" + }, + { + "name": "Ethernet15" + }, + { + "name": "Ethernet16" + }, + { + "name": "Ethernet17" + }, + { + "name": "Ethernet18" + }, + { + "name": "Ethernet19" + }, + { + "name": "Ethernet20" + }, + { + "name": "Ethernet21" + }, + { + "name": "Ethernet22" + }, + { + "name": "Ethernet23" + }, + { + "name": "Ethernet24" + }, + { + "name": "Ethernet25" + }, + { + "name": "Ethernet26" + }, + { + "name": "Ethernet27" + }, + { + "name": "Ethernet28" + }, + { + "name": "Ethernet29" + }, + { + "name": "Ethernet30" + }, + { + "name": "Ethernet31" + }, + { + "name": "Ethernet32" + }, + { + "name": "Ethernet33" + }, + { + "name": "Ethernet34" + }, + { + "name": "Ethernet35" + }, + { + "name": "Ethernet36" + }, + { + "name": "Ethernet37" + }, + { + "name": "Ethernet38" + }, + { + "name": "Ethernet39" + }, + { + "name": "Ethernet40" + }, + { + "name": "Ethernet41" + }, + { + "name": "Ethernet42" + }, + { + "name": "Ethernet43" + }, + { + "name": "Ethernet44" + }, + { + "name": "Ethernet45" + }, + { + "name": "Ethernet46" + }, + { + "name": "Ethernet47" + }, + { + "name": "Ethernet48" + }, + { + "name": "Ethernet49" + }, + { + "name": "Ethernet50" + }, + { + "name": "Ethernet51" + }, + { + "name": "Ethernet52" + }, + { + "name": "Ethernet56" + } + ] + }, + "interfaces": { + "Ethernet0": { + "index": "1", + "lanes": "26", + "breakout_modes": { + "1x1G": ["Eth1(Port1)"] + } + }, + + "Ethernet1": { + "index": "2", + "lanes": "25", + "breakout_modes": { + "1x1G": ["Eth2(Port2)"] + } + }, + + "Ethernet2": { + "index": "3", + "lanes": "28", + "breakout_modes": { + "1x1G": ["Eth3(Port3)"] + } + }, + + "Ethernet3": { + "index": "4", + "lanes": "27", + "breakout_modes": { + "1x1G": ["Eth4(Port4)"] + } + }, + + "Ethernet4": { + "index": "5", + "lanes": "30", + "breakout_modes": { + "1x1G": ["Eth5(Port5)"] + } + }, + + "Ethernet5": { + "index": "6", + "lanes": "29", + "breakout_modes": { + "1x1G": ["Eth6(Port6)"] + } + }, + + "Ethernet6": { + "index": "7", + "lanes": "32", + "breakout_modes": { + "1x1G": ["Eth7(Port7)"] + } + }, + + "Ethernet7": { + "index": "8", + "lanes": "31", + "breakout_modes": { + "1x1G": ["Eth8(Port8)"] + } + }, + + "Ethernet8": { + "index": "9", + "lanes": "38", + "breakout_modes": { + "1x1G": ["Eth9(Port9)"] + } + }, + + "Ethernet9": { + "index": "10", + "lanes": "37", + "breakout_modes": { + "1x1G": ["Eth10(Port10)"] + } + }, + + "Ethernet10": { + "index": "11", + "lanes": "40", + "breakout_modes": { + "1x1G": ["Eth11(Port11)"] + } + }, + + "Ethernet11": { + "index": "12", + "lanes": "39", + "breakout_modes": { + "1x1G": ["Eth12(Port12)"] + } + }, + + "Ethernet12": { + "index": "13", + "lanes": "34", + "breakout_modes": { + "1x1G": ["Eth13(Port13)"] + } + }, + + "Ethernet13": { + "index": "14", + "lanes": "33", + "breakout_modes": { + "1x1G": ["Eth14(Port14)"] + } + }, + + "Ethernet14": { + "index": "15", + "lanes": "36", + "breakout_modes": { + "1x1G": ["Eth15(Port15)"] + } + }, + + "Ethernet15": { + "index": "16", + "lanes": "35", + "breakout_modes": { + "1x1G": ["Eth16(Port16)"] + } + }, + + "Ethernet16": { + "index": "17", + "lanes": "46", + "breakout_modes": { + "1x1G": ["Eth17(Port17)"] + } + }, + + "Ethernet17": { + "index": "18", + "lanes": "45", + "breakout_modes": { + "1x1G": ["Eth18(Port18)"] + } + }, + + "Ethernet18": { + "index": "19", + "lanes": "48", + "breakout_modes": { + "1x1G": ["Eth19(Port19)"] + } + }, + + "Ethernet19": { + "index": "20", + "lanes": "47", + "breakout_modes": { + "1x1G": ["Eth20(Port20)"] + } + }, + + "Ethernet20": { + "index": "21", + "lanes": "42", + "breakout_modes": { + "1x1G": ["Eth21(Port21)"] + } + }, + + "Ethernet21": { + "index": "22", + "lanes": "41", + "breakout_modes": { + "1x1G": ["Eth22(Port22)"] + } + }, + + "Ethernet22": { + "index": "23", + "lanes": "44", + "breakout_modes": { + "1x1G": ["Eth23(Port23)"] + } + }, + + "Ethernet23": { + "index": "24", + "lanes": "43", + "breakout_modes": { + "1x1G": ["Eth24(Port24)"] + } + }, + + "Ethernet24": { + "index": "25", + "lanes": "2", + "breakout_modes": { + "1x1G": ["Eth25(Port25)"] + } + }, + + "Ethernet25": { + "index": "26", + "lanes": "1", + "breakout_modes": { + "1x1G": ["Eth26(Port26)"] + } + }, + + "Ethernet26": { + "index": "27", + "lanes": "4", + "breakout_modes": { + "1x1G": ["Eth27(Port27)"] + } + }, + + "Ethernet27": { + "index": "28", + "lanes": "3", + "breakout_modes": { + "1x1G": ["Eth28(Port28)"] + } + }, + + "Ethernet28": { + "index": "29", + "lanes": "6", + "breakout_modes": { + "1x1G": ["Eth29(Port29)"] + } + }, + + "Ethernet29": { + "index": "30", + "lanes": "5", + "breakout_modes": { + "1x1G": ["Eth30(Port30)"] + } + }, + + "Ethernet30": { + "index": "31", + "lanes": "8", + "breakout_modes": { + "1x1G": ["Eth31(Port31)"] + } + }, + + "Ethernet31": { + "index": "32", + "lanes": "7", + "breakout_modes": { + "1x1G": ["Eth32(Port32)"] + } + }, + + "Ethernet32": { + "index": "33", + "lanes": "10", + "breakout_modes": { + "1x1G": ["Eth33(Port33)"] + } + }, + + "Ethernet33": { + "index": "34", + "lanes": "9", + "breakout_modes": { + "1x1G": ["Eth34(Port34)"] + } + }, + + "Ethernet34": { + "index": "35", + "lanes": "12", + "breakout_modes": { + "1x1G": ["Eth35(Port35)"] + } + }, + + "Ethernet35": { + "index": "36", + "lanes": "11", + "breakout_modes": { + "1x1G": ["Eth36(Port36)"] + } + }, + + "Ethernet36": { + "index": "37", + "lanes": "14", + "breakout_modes": { + "1x1G": ["Eth37(Port37)"] + } + }, + + "Ethernet37": { + "index": "38", + "lanes": "13", + "breakout_modes": { + "1x1G": ["Eth38(Port38)"] + } + }, + + "Ethernet38": { + "index": "39", + "lanes": "16", + "breakout_modes": { + "1x1G": ["Eth39(Port39)"] + } + }, + + "Ethernet39": { + "index": "40", + "lanes": "15", + "breakout_modes": { + "1x1G": ["Eth40(Port40)"] + } + }, + + "Ethernet40": { + "index": "41", + "lanes": "18", + "breakout_modes": { + "1x1G": ["Eth41(Port41)"] + } + }, + + "Ethernet41": { + "index": "42", + "lanes": "17", + "breakout_modes": { + "1x1G": ["Eth42(Port42)"] + } + }, + + "Ethernet42": { + "index": "43", + "lanes": "20", + "breakout_modes": { + "1x1G": ["Eth43(Port43)"] + } + }, + + "Ethernet43": { + "index": "44", + "lanes": "19", + "breakout_modes": { + "1x1G": ["Eth44(Port44)"] + } + }, + + "Ethernet44": { + "index": "45", + "lanes": "22", + "breakout_modes": { + "1x1G": ["Eth45(Port45)"] + } + }, + + "Ethernet45": { + "index": "46", + "lanes": "21", + "breakout_modes": { + "1x1G": ["Eth46(Port46)"] + } + }, + + "Ethernet46": { + "index": "47", + "lanes": "24", + "breakout_modes": { + "1x1G": ["Eth47(Port47)"] + } + }, + + "Ethernet47": { + "index": "48", + "lanes": "23", + "breakout_modes": { + "1x1G": ["Eth48(Port48)"] + } + }, + + "Ethernet48": { + "index": "49", + "lanes": "67", + "breakout_modes": { + "1x25G[10G]": ["Eth49(Port49)"] + } + }, + + "Ethernet49": { + "index": "50", + "lanes": "66", + "breakout_modes": { + "1x25G[10G]": ["Eth50(Port50)"] + } + }, + + "Ethernet50": { + "index": "51", + "lanes": "65", + "breakout_modes": { + "1x25G[10G]": ["Eth51(Port51)"] + } + }, + + "Ethernet51": { + "index": "52", + "lanes": "68", + "breakout_modes": { + "1x25G[10G]": ["Eth52(Port52)"] + } + }, + "Ethernet52": { + "index": "53,53,53,53", + "lanes": "73,74,75,76", + "breakout_modes": { + "1x100G[40G]": ["Eth53(Port53)"], + "2x50G": ["Eth53/1(Port53)", "Eth53/2(Port53)"], + "4x25G[10G]": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"] + } + }, + + "Ethernet56": { + "index": "54,54,54,54", + "lanes": "69,70,71,72", + "breakout_modes": { + "1x100G[40G]": ["Eth54(Port54)"], + "2x50G": ["Eth54/1(Port54)", "Eth54/2(Port54)"], + "4x25G[10G]": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"] + } + } + } +} diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/platform_components.json b/device/accton/x86_64-accton_as4630_54pe-r0/platform_components.json new file mode 100644 index 0000000000..c1465e1374 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/platform_components.json @@ -0,0 +1,10 @@ +{ + "chassis": { + "4630-54PE-O-AC-F": { + "component": { + "CPLD1": { }, + "BIOS": { } + } + } + } +} \ No newline at end of file diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/plugins/ssd_util.py b/device/accton/x86_64-accton_as4630_54pe-r0/plugins/ssd_util.py new file mode 100755 index 0000000000..4b173c5e38 --- /dev/null +++ b/device/accton/x86_64-accton_as4630_54pe-r0/plugins/ssd_util.py @@ -0,0 +1,24 @@ +# ssd_util.py +# +# Platform-specific SSD interface for SONiC +## + +try: + from sonic_platform_base.sonic_ssd.ssd_generic import SsdUtil as MainSsdUtil +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +NOT_AVAILABLE = "N/A" + +class SsdUtil(MainSsdUtil): + """Platform-specific SsdUtil class""" + + def __init__(self, diskdev): + super(SsdUtil, self).__init__(diskdev) + + # If it has no vendor tool to read SSD information, + # ssd_util.py will use generic SSD information + # for vendor SSD information. + if self.vendor_ssd_info == NOT_AVAILABLE: + self.vendor_ssd_info = self.ssd_info + diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json index a3b204e20d..44bad64942 100644 --- a/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json +++ b/device/accton/x86_64-accton_as4630_54pe-r0/pmon_daemon_control.json @@ -1,5 +1,4 @@ { - "skip_ledd": true, - "skip_pcied": true + "skip_ledd": true } diff --git a/device/accton/x86_64-accton_as4630_54pe-r0/system_health_monitoring_config.json b/device/accton/x86_64-accton_as4630_54pe-r0/system_health_monitoring_config.json index 61f624ee34..deb3745e14 100644 --- a/device/accton/x86_64-accton_as4630_54pe-r0/system_health_monitoring_config.json +++ b/device/accton/x86_64-accton_as4630_54pe-r0/system_health_monitoring_config.json @@ -1,17 +1,13 @@ { "services_to_ignore": [], "devices_to_ignore": [ - "asic", - "psu.voltage", - "psu.temperature", - "PSU1_FAN1.speed", - "PSU2_FAN1.speed" + "asic" ], "user_defined_checkers": [], "polling_interval": 60, "led_color": { - "fault": "STATUS_LED_COLOR_AMBER", - "normal": "STATUS_LED_COLOR_GREEN", - "booting": "STATUS_LED_COLOR_GREEN_BLINK" + "fault": "amber", + "normal": "green", + "booting": "green_blink" } } diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/accton_psu_api.h b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/accton_psu_api.h new file mode 120000 index 0000000000..a6b156930a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/accton_psu_api.h @@ -0,0 +1 @@ +../../common/modules/accton_psu_api.h \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/accton_psu_defs.h b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/accton_psu_defs.h new file mode 120000 index 0000000000..96202b3ead --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/modules/accton_psu_defs.h @@ -0,0 +1 @@ +../../common/modules/accton_psu_defs.h \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-pddf-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-pddf-platform-monitor.service new file mode 100644 index 0000000000..99bca2684f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/service/as4630-54pe-pddf-platform-monitor.service @@ -0,0 +1,16 @@ +[Unit] +Description=Accton AS4630-54PE Platform Monitoring service +Before=pmon.service +After=pddf-platform-init.service +DefaultDependencies=no + +[Service] +ExecStart=/usr/local/bin/accton_as4630_54pe_pddf_monitor.py +KillSignal=SIGKILL +SuccessExitStatus=SIGKILL + +# Resource Limitations +LimitCORE=infinity + +[Install] +WantedBy=multi-user.target diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/chassis.py index 1dfca24ab3..8ec7deb95a 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/chassis.py @@ -10,10 +10,14 @@ import sys from sonic_platform_pddf_base.pddf_chassis import PddfChassis from .event import SfpEvent + from .helper import APIHelper except ImportError as e: raise ImportError(str(e) + "- required module not found") NUM_COMPONENT = 2 +HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/" +PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/" +REBOOT_CAUSE_FILE = "reboot-cause.txt" class Chassis(PddfChassis): """ @@ -26,6 +30,7 @@ def __init__(self, pddf_data=None, pddf_plugin_data=None): PddfChassis.__init__(self, pddf_data, pddf_plugin_data) self.__initialize_components() self._sfpevent = SfpEvent(self.get_all_sfps()) + self._api_helper = APIHelper() def __initialize_components(self): from sonic_platform.component import Component @@ -68,3 +73,57 @@ def get_status_led(self): def set_status_led(self, color): return self.set_system_led(self.SYSLED_DEV_NAME, color) + + + def get_port_or_cage_type(self, port): + from sonic_platform_base.sfp_base import SfpBase + if port in range(1, 49): + return SfpBase.SFP_PORT_TYPE_BIT_RJ45 + elif port in range(49, 53): + return SfpBase.SFP_PORT_TYPE_BIT_SFP | SfpBase.SFP_PORT_TYPE_BIT_SFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_SFP28 + else: + return SfpBase.SFP_PORT_TYPE_BIT_QSFP | SfpBase.SFP_PORT_TYPE_BIT_QSFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_QSFP28 + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + + reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) + sw_reboot_cause = self._api_helper.read_txt_file( + reboot_cause_path) or "Unknown" + + + return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause) + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position + for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + return self._eeprom.revision_str() diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/component.py index 2659d16f1c..a30b4630e0 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/component.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/component.py @@ -8,6 +8,8 @@ ############################################################################# try: + import os + import json from sonic_platform_base.component_base import ComponentBase from sonic_py_common.general import getstatusoutput_noshell except ImportError as e: @@ -82,4 +84,85 @@ def install_firmware(self, image_path): Returns: A boolean, True if install successfully, False if not """ - raise NotImplementedError + ret, output = getstatusoutput_noshell(["tar", "-C", "/tmp", "-xzf", image_path ] ) + if ret != 0 : + print("Installation failed because of wrong image package") + return False + + if os.path.exists("/tmp/install.json") is False: + print("Installation failed without jsonfile") + return False + + input_file = open ('/tmp/install.json') + json_array = json.load(input_file) + ret = 1 + for item in json_array: + if item.get('id')==None or item.get('path')==None: + continue + if self.name == item['id'] and item['path'] and item.get('cpu'): + print( "Find", item['id'], item['path'], item['cpu'] ) + ret, output = getstatusoutput_noshell(["/tmp/run_install.sh", item['id'], item['path'], item['cpu'] ]) + if ret==0: + break + elif self.name == item['id'] and item['path']: + print( "Find", item['id'], item['path'] ) + ret, output = getstatusoutput_noshell(["/tmp/run_install.sh", item['id'], item['path'] ]) + if ret==0: + break + + if ret==0: + return True + else : + return False + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return 'N/A' + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return 'N/A' + + def get_status(self): + """ + Retrieves the operational status of the device + Returns: + A boolean value, True if device is operating properly, False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + If the agent cannot determine the parent-relative position + for some reason, or if the associated value of + entPhysicalContainedIn is'0', then the value '-1' is returned + Returns: + integer: The 1-based relative physical position in parent device + or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/event.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/event.py index d5dac6d7f7..1a2f60dbb6 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/event.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/event.py @@ -1,11 +1,21 @@ try: import time from sonic_py_common.logger import Logger + from .sfp import Sfp except ImportError as e: raise ImportError(repr(e) + " - required module not found") POLL_INTERVAL_IN_SEC = 1 +# SFP errors that will block eeprom accessing +SFP_BLOCKING_ERRORS = [ + Sfp.SFP_ERROR_BIT_I2C_STUCK, + Sfp.SFP_ERROR_BIT_BAD_EEPROM, + Sfp.SFP_ERROR_BIT_UNSUPPORTED_CABLE, + Sfp.SFP_ERROR_BIT_HIGH_TEMP, + Sfp.SFP_ERROR_BIT_BAD_CABLE +] + class SfpEvent: ''' Listen to insert/remove sfp events ''' @@ -46,15 +56,54 @@ def get_sfp_event(self, timeout=2000): if changed_ports != 0: for sfp in self._sfp_list: i=sfp.get_position_in_parent() - 1 - if (changed_ports & (1 << i)): - if (bitmap & (1 << i)) == 0: - port_dict[i+1] = '0' - else: - port_dict[i+1] = '1' + if (changed_ports & (1 << i)) == 0: + continue + + if (bitmap & (1 << i)) == 0: + port_dict[i+1] = '0' + else: + # sfp.refresh_optoe_dev_class() + sfp_state_bits = self.get_sfp_state_bits(sfp, True) + sfp_state_bits = self.check_sfp_blocking_errors(sfp_state_bits) + port_dict[i+1] = str(sfp_state_bits) # Update the cache dict self._sfp_change_event_data['present'] = bitmap return True, change_dict else: return True, change_dict + + def get_sfp_state_bits(self, sfp, present): + sfp_state_bits = 0 + + if present is True: + sfp_state_bits |= Sfp.SFP_STATUS_BIT_INSERTED + else: + return sfp_state_bits + + status = sfp.validate_eeprom() + if status is None: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK + return sfp_state_bits + elif status is not True: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_BAD_EEPROM + return sfp_state_bits + + status = sfp.validate_temperature() + if status is None: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK + return sfp_state_bits + elif status is not True: + sfp_state_bits |= Sfp.SFP_ERROR_BIT_HIGH_TEMP + return sfp_state_bits + + return sfp_state_bits + + def check_sfp_blocking_errors(self, sfp_state_bits): + for i in SFP_BLOCKING_ERRORS: + if (i & sfp_state_bits) == 0: + continue + sfp_state_bits |= Sfp.SFP_ERROR_BIT_BLOCKING + + return sfp_state_bits diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan.py index ef8deaffb6..b9be5e3ca3 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan.py @@ -6,6 +6,7 @@ except ImportError as e: raise ImportError(str(e) + "- required module not found") +FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3"] class Fan(PddfFan): """PDDF Platform-Specific Fan class""" @@ -24,25 +25,53 @@ def get_direction(self): A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST depending on fan direction """ + direction = 'N/A' if self.is_psu_fan: direction = self.FAN_DIRECTION_EXHAUST - else: - idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index - attr = "fan" + str(idx) + "_direction" - output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr) - if not output: - return False - - mode = output['mode'] - val = output['status'] - - val = val.rstrip() - vmap = self.plugin_data['FAN']['direction'][mode]['valmap'] - if val in vmap: - direction = vmap[val] - else: - direction = val + direction = super().get_direction() + if direction is not None and len(direction) > 0: + return direction return direction + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + fan_name = FAN_NAME_LIST[self.fantray_index - 1] \ + if not self.is_psu_fan \ + else "PSU-{} FAN-{}".format(self.fans_psu_index, self.fan_index) + + return fan_name + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return 'N/A' + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return 'N/A' + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + if self.is_psu_fan: + return super().get_speed() + else: + return super().get_target_speed() diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan_drawer.py index 3b9bb607f6..eae95191e1 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan_drawer.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/fan_drawer.py @@ -15,3 +15,26 @@ def __init__(self, tray_idx, pddf_data=None, pddf_plugin_data=None): PddfFanDrawer.__init__(self, tray_idx, pddf_data, pddf_plugin_data) # Provide the functions/variables below for which implementation is to be overwritten + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantray_index) + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + return 'N/A' + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return 'N/A' diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/helper.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/helper.py new file mode 100644 index 0000000000..f6adee3098 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/helper.py @@ -0,0 +1,368 @@ +import os +import struct +import json +import fcntl +from mmap import * +from sonic_py_common import device_info +from sonic_py_common import logger +from threading import Lock +from typing import cast +from sonic_py_common.general import getstatusoutput_noshell_pipe +from sonic_py_common.general import getstatusoutput_noshell + +HOST_CHK_CMD = ["docker"] +EMPTY_STRING = "" + + +class APIHelper(): + + def __init__(self): + (self.platform, self.hwsku) = device_info.get_platform_and_hwsku() + + def is_host(self): + try: + status, output = getstatusoutput_noshell(HOST_CHK_CMD) + return status == 0 + except Exception: + return False + + def pci_get_value(self, resource, offset): + status = True + result = "" + try: + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + mm.seek(int(offset)) + read_data_stream = mm.read(4) + result = struct.unpack('I', read_data_stream) + except Exception: + status = False + return status, result + + def run_interactive_command(self, cmd): + try: + os.system(cmd) + except Exception: + return False + return True + + def read_txt_file(self, file_path): + try: + with open(file_path, 'r', errors='replace') as fd: + data = fd.read() + ret = data.strip() + if len(ret) > 0: + return ret + except IOError: + pass + return None + + def write_txt_file(self, file_path, value): + try: + with open(file_path, 'w') as fd: + fd.write(str(value)) + except IOError: + return False + return True + + def ipmi_raw(self, netfn, cmd): + status = True + result = "" + try: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'raw', str(netfn), str(cmd)]) + if err == [0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + def ipmi_fru_id(self, id, key=None): + status = True + result = "" + try: + if (key is None): + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)]) + else: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)], ['grep', str(key)]) + if err == [0] or err == [0, 0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + def ipmi_set_ss_thres(self, id, threshold_key, value): + status = True + result = "" + try: + err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'sensor', 'thresh', str(id), str(threshold_key), str(value)]) + if err == [0]: + result = raw_data.strip() + else: + status = False + except Exception: + status = False + return status, result + + +class FileLock: + """ + Due to pmon docker not installing the py-filelock, this class + implements a simple file lock feature. + Ref: https://github.com/tox-dev/py-filelock/blob/main/src/filelock/ + """ + + def __init__(self, lock_file): + self._lock_file = lock_file + self._thread_lock = Lock() + self.is_locked = False + + def acquire(self): + with self._thread_lock: + if self.is_locked: + return + + fd = os.open(self._lock_file, flags=(os.O_RDWR | os.O_CREAT | os.O_TRUNC)) + fcntl.flock(fd, fcntl.LOCK_EX) + self._lock_file_fd = fd + self.is_locked = True + + def release(self): + with self._thread_lock: + if self.is_locked: + fd = cast(int, self._lock_file_fd) + self._lock_file_fd = None + fcntl.flock(fd, fcntl.LOCK_UN) + os.close(fd) + self.is_locked = False + + def __enter__(self): + self.acquire() + return self + + def __exit__(self, exc_type, exc_val, traceback): + self.release() + + def __del__(self): + self.release() + + +DEVICE_THRESHOLD_JSON_PATH = "/tmp/device_threshold.json" + +class DeviceThreshold: + HIGH_THRESHOLD = 'high_threshold' + LOW_THRESHOLD = 'low_threshold' + HIGH_CRIT_THRESHOLD = 'high_critical_threshold' + LOW_CRIT_THRESHOLD = 'low_critical_threshold' + NOT_AVAILABLE = 'N/A' + + def __init__(self, th_name = NOT_AVAILABLE): + self.flock = FileLock("{}.lock".format(DEVICE_THRESHOLD_JSON_PATH)) + self.name = th_name + self.__log = logger.Logger(log_identifier="DeviceThreshold") + + self.__db_data = {} + self.__db_mtime = 0 + + def __reload_db(self): + try: + db_data = {} + with self.flock: + with open(DEVICE_THRESHOLD_JSON_PATH, "r") as db_file: + db_data = json.load(db_file) + except Exception as e: + self.__log.log_warning('{}'.format(str(e))) + return None + + return db_data + + def __get_data(self, field): + """ + Retrieves data frome JSON file by field + + Args : + field: String + + Returns: + A string if getting is successfully, 'N/A' if not + """ + if os.path.exists(DEVICE_THRESHOLD_JSON_PATH): + new_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH) + if new_mtime != self.__db_mtime: + new_data = self.__reload_db() + if new_data is not None: + self.__db_data = new_data + self.__db_mtime = new_mtime + + if self.name not in self.__db_data.keys(): + return self.NOT_AVAILABLE + + if field not in self.__db_data[self.name].keys(): + return self.NOT_AVAILABLE + + return self.__db_data[self.name][field] + + def __set_data(self, field, new_val): + """ + Set data to JSON file by field + + Args : + field: String + new_val: String + + Returns: + A boolean, True if setting is set successfully, False if not + """ + if self.name not in self.__db_data.keys(): + self.__db_data[self.name] = {} + + old_val = self.__db_data[self.name].get(field, None) + if old_val is not None and old_val == new_val: + return True + + self.__db_data[self.name][field] = new_val + + try: + with self.flock: + db_data = {} + mode = "r+" if os.path.exists(DEVICE_THRESHOLD_JSON_PATH) else "w+" + with open(DEVICE_THRESHOLD_JSON_PATH, mode) as db_file: + if mode == "r+": + db_data = json.load(db_file) + + if self.name not in db_data.keys(): + db_data[self.name] = {} + + db_data[self.name][field] = new_val + + if mode == "r+": + db_file.seek(0) + # erase old data + db_file.truncate(0) + # write all data + json.dump(db_data, db_file, indent=4) + self.__db_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH) + except Exception as e: + self.__log.log_error('{}'.format(str(e))) + return False + + return True + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature from JSON file. + + Returns: + string : the high threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.HIGH_THRESHOLD) + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.HIGH_THRESHOLD, temperature) + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature from JSON file. + + Returns: + string : the low threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.LOW_THRESHOLD) + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.LOW_THRESHOLD, temperature) + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature from JSON file. + + Returns: + string : the high critical threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.HIGH_CRIT_THRESHOLD) + + def set_high_critical_threshold(self, temperature): + """ + Sets the high critical threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.HIGH_CRIT_THRESHOLD, temperature) + + def get_low_critical_threshold(self): + """ + Retrieves the low critical threshold temperature from JSON file. + + Returns: + string : the low critical threshold temperature of thermal, + e.g. "30.125" + """ + return self.__get_data(self.LOW_CRIT_THRESHOLD) + + def set_low_critical_threshold(self, temperature): + """ + Sets the low critical threshold temperature of thermal + Args : + temperature: A string of temperature, e.g. "30.125" + Returns: + A boolean, True if threshold is set successfully, False if not + """ + if isinstance(temperature, str) is not True: + raise TypeError('The parameter requires string type.') + + try: + if temperature != self.NOT_AVAILABLE: + float(temperature) + except ValueError: + raise ValueError('The parameter requires a float string. ex:\"30.1\"') + + return self.__set_data(self.LOW_CRIT_THRESHOLD, temperature) diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/pcie.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/pcie.py new file mode 100644 index 0000000000..73d3627dbf --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/pcie.py @@ -0,0 +1,19 @@ +############################################################################# +# Edgecore +# +# Module contains an implementation of SONiC Platform Base API and +# provides the fan status which are available in the platform +# Base PCIe class +############################################################################# + +try: + from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Pcie(PcieUtil): + """Edgecore Platform-specific PCIe class""" + + def __init__(self, platform_path): + PcieUtil.__init__(self, platform_path) \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/psu.py index f002f5e039..f9c32ec3b8 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/psu.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/psu.py @@ -10,42 +10,103 @@ class Psu(PddfPsu): """PDDF Platform-Specific PSU class""" - - PLATFORM_PSU_CAPACITY = 1200 def __init__(self, index, pddf_data=None, pddf_plugin_data=None): PddfPsu.__init__(self, index, pddf_data, pddf_plugin_data) # Provide the functions/variables below for which implementation is to be overwritten - def get_capacity(self): + def get_name(self): + return "PSU-{}".format(self.psu_index) + + def get_revision(self): """ - Gets the capacity (maximum output power) of the PSU in watts + Retrieves the hardware revision of the device Returns: - An integer, the capacity of PSU + string: Revision value of device """ - return (self.PLATFORM_PSU_CAPACITY) + return 'N/A' - def get_type(self): + def get_temperature_high_threshold(self): + """ + Retrieves the high threshold temperature of PSU + Returns: + A float number, the high threshold temperature of PSU in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 """ - Gets the type of the PSU + threshold = super().get_temperature_high_threshold() + + for psu_thermal_idx in range(self.num_psu_thermals): + try: + tmp = self._thermal_list[psu_thermal_idx].get_high_threshold() + if threshold > tmp or threshold == 0.0: + threshold = tmp + except Exception: + pass + + return threshold + + def get_model(self): + """ + Retrieves the model number (or part number) of the device Returns: - A string, the type of PSU (AC/DC) - """ - ptype = "AC" - # Currently the platform supports only AC type of PSUs - #try: - #import sonic_platform.platform - #ch=sonic_platform.platform.Platform().get_chassis() - #e=ch.sys_eeprom.read_eeprom() - #ret, prod_name = ch.sys_eeprom.get_tlv_field(e,0x21) - #if ret: - #prod_name = prod_name[2] - ##print("Product name is {}".format(prod_name)) - #if '48V' in prod_name: - #ptype = 'DC' - #except Exception as e: - #print("Error while trying to read syseeprom to get PSU type") - - return ptype + string: Model/part number of device + """ + model = super().get_model() + if model and model.strip() == "": + return None + + return model + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + serial = super().get_serial() + if serial and serial.strip() == "": + return None + + return serial + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + if self.get_status() is not True: + return 0.0 + + return super().get_voltage() + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + if self.get_status() is not True: + return 0.0 + + return super().get_current() + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + if self.get_status() is not True: + return 0.0 + + return super().get_power() diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/sfp.py index c9fb07d636..534834d878 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/sfp.py @@ -1,7 +1,10 @@ #!/usr/bin/env python try: + import natsort from sonic_platform_pddf_base.pddf_sfp import PddfSfp + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from sonic_py_common import device_info except ImportError as e: raise ImportError (str(e) + "- required module not found") @@ -11,10 +14,197 @@ class Sfp(PddfSfp): PDDF Platform-Specific Sfp class """ + SFP_TYPE_CODE_LIST = [ + 0x03, # SFP/SFP+/SFP28 + 0x0b # DWDM-SFP/SFP+ + ] + QSFP_TYPE_CODE_LIST = [ + 0x0c, # QSFP + 0x0d, # QSFP+ or later + 0x11, # QSFP28 or later + 0xe1 # QSFP28 EDFA + ] + def __init__(self, index, pddf_data=None, pddf_plugin_data=None): PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data) + self.index = self.port_index # Provide the functions/variables below for which implementation is to be overwritten def get_position_in_parent(self): """Retrieves 1-based relative physical position in parent device.""" return self.port_index + + def __get_path_to_port_config_file(self): + platform, hwsku = device_info.get_platform_and_hwsku() + hwsku_path = "/".join(["/usr/share/sonic/platform",hwsku]) + return "/".join([hwsku_path, "port_config.ini"]) + + def get_name(self): + """ + Retrieves the name of the device + Returns: + string: The name of the device + """ + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings( + self.__get_path_to_port_config_file()) + + logical_port_list = sfputil_helper.logical + logical_port_list = natsort.natsorted(logical_port_list) + name = logical_port_list[self.port_index-1] or "Unknown" + + return name + + def __validate_eeprom_sfp(self): + checksum_test = 0 + eeprom_raw = self.read_eeprom(0, 96) + if eeprom_raw is None: + return None + + for i in range(0, 63): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[63]: + return False + + checksum_test = 0 + for i in range(64, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + api = self.get_xcvr_api() + if api is None: + return False + + if api.is_flat_memory(): + return True + + checksum_test = 0 + eeprom_raw = self.read_eeprom(384, 96) + if eeprom_raw is None: + return None + + for i in range(0, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + return True + + def __validate_eeprom_qsfp(self): + checksum_test = 0 + eeprom_raw = self.read_eeprom(128, 96) + if eeprom_raw is None: + return None + + for i in range(0, 63): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[63]: + return False + + checksum_test = 0 + for i in range(64, 95): + checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF + else: + if checksum_test != eeprom_raw[95]: + return False + + api = self.get_xcvr_api() + if api is None: + return False + + if api.is_flat_memory(): + return True + + return True + + def validate_eeprom(self): + id_byte_raw = self.read_eeprom(0, 1) + if id_byte_raw is None: + return None + + id = id_byte_raw[0] + if id in self.QSFP_TYPE_CODE_LIST: + return self.__validate_eeprom_qsfp() + elif id in self.SFP_TYPE_CODE_LIST: + return self.__validate_eeprom_sfp() + else: + return False + + def validate_temperature(self): + temperature = self.get_temperature() + if temperature is None: + return None + + threshold_dict = self.get_transceiver_threshold_info() + if threshold_dict is None: + return None + + if isinstance(temperature, float) is not True: + return True + + if isinstance(threshold_dict['temphighalarm'], float) is not True: + return True + + return threshold_dict['temphighalarm'] > temperature + + def __get_error_description(self): + if not self.get_presence(): + return self.SFP_STATUS_UNPLUGGED + + err_stat = self.SFP_STATUS_BIT_INSERTED + + status = self.validate_eeprom() + if status is not True: + err_stat = (err_stat | self.SFP_ERROR_BIT_BAD_EEPROM) + + status = self.validate_temperature() + if status is not True: + err_stat = (err_stat | self.SFP_ERROR_BIT_HIGH_TEMP) + + if err_stat is self.SFP_STATUS_BIT_INSERTED: + return self.SFP_STATUS_OK + else: + err_desc = '' + cnt = 0 + for key in self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT: + if (err_stat & key) != 0: + if cnt > 0: + err_desc = err_desc + "|" + cnt = cnt + 1 + err_desc = err_desc + self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT[key] + + return err_desc + + def get_reset_status(self): + if self.sfp_type == "QSFP28": + return super().get_reset_status() + return False + + def reset(self): + if self.sfp_type == "QSFP28": + return super().reset() + return False + + def get_error_description(self): + """ + Retrives the error descriptions of the SFP module + Returns: + String that represents the current error descriptions of vendor specific errors + In case there are multiple errors, they should be joined by '|', + like: "Bad EEPROM|Unsupported cable" + """ + if self.sfp_type != "SFP28" and self.sfp_type != "QSFP28": + return "Not implemented" + try: + ret = super().get_error_description() + if ret is not None: + return ret + except NotImplementedError: + pass + return self.__get_error_description() + diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/thermal.py index 77d6ec7ae8..3dd096567e 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/thermal.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/sonic_platform/thermal.py @@ -3,10 +3,55 @@ try: from sonic_platform_pddf_base.pddf_thermal import PddfThermal + from .helper import DeviceThreshold except ImportError as e: raise ImportError(str(e) + "- required module not found") +NOT_AVAILABLE = DeviceThreshold.NOT_AVAILABLE +HIGH_THRESHOLD = DeviceThreshold.HIGH_THRESHOLD +LOW_THRESHOLD = DeviceThreshold.LOW_THRESHOLD +HIGH_CRIT_THRESHOLD = DeviceThreshold.HIGH_CRIT_THRESHOLD +LOW_CRIT_THRESHOLD = DeviceThreshold.LOW_CRIT_THRESHOLD + +DEFAULT_THRESHOLD = { + 'Temp sensor 1' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'Temp sensor 2' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'Temp sensor 3' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'Temp sensor 4' : { + HIGH_THRESHOLD : '71.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : '91.0', + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-1 temp sensor 1' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + }, + 'PSU-2 temp sensor 1' : { + HIGH_THRESHOLD : '80.0', + LOW_THRESHOLD : NOT_AVAILABLE, + HIGH_CRIT_THRESHOLD : NOT_AVAILABLE, + LOW_CRIT_THRESHOLD : NOT_AVAILABLE + } +} class Thermal(PddfThermal): """PDDF Platform-Specific Thermal class""" @@ -14,4 +59,196 @@ class Thermal(PddfThermal): def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0): PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data, is_psu_thermal, psu_index) + # Threshold Configuration + self.__conf = DeviceThreshold(self.get_name()) + # Default threshold. + self.__default_threshold = DEFAULT_THRESHOLD[self.get_name()] + self.min_temperature = None + self.max_temperature = None + # Provide the functions/variables below for which implementation is to be overwritten + def get_name(self): + if self.is_psu_thermal: + return "PSU-{0} temp sensor 1".format(self.thermals_psu_index) + else: + return "Temp sensor {0}".format(self.thermal_index) + + def get_status(self): + get_temp=self.get_temperature() + + if get_temp is not None: + return True if get_temp else False + + def get_temperature(self): + current = super().get_temperature() + + if self.min_temperature is None or \ + current < self.min_temperature: + self.min_temperature = current + + if self.max_temperature is None or \ + current > self.max_temperature: + self.max_temperature = current + + return current + + def set_high_threshold(self, temperature): + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be more than the default value. + default_value = self.__default_threshold[HIGH_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value > float(default_value): + return False + + try: + self.__conf.set_high_threshold(str(value)) + except Exception: + return False + + return True + + def get_high_threshold(self): + value = self.__conf.get_high_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[HIGH_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def set_low_threshold(self, temperature): + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be less than the default value. + default_value = self.__default_threshold[LOW_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value < float(default_value): + return False + + try: + self.__conf.set_low_threshold(str(value)) + except Exception: + return False + + return True + + def get_low_threshold(self): + value = self.__conf.get_low_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[LOW_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def set_high_critical_threshold(self, temperature): + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be more than the default value. + default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value > float(default_value): + return False + + try: + self.__conf.set_high_critical_threshold(str(value)) + except Exception: + return False + + return True + + def get_high_critical_threshold(self): + value = self.__conf.get_high_critical_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def set_low_critical_threshold(self, temperature): + try: + value = float(temperature) + except Exception: + return False + + # The new value can not be less than the default value. + default_value = self.__default_threshold[LOW_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + if value < float(default_value): + return False + + try: + self.__conf.set_low_critical_threshold(str(value)) + except Exception: + return False + + return True + + def get_low_critical_threshold(self): + value = self.__conf.get_low_critical_threshold() + if value != NOT_AVAILABLE: + return float(value) + + default_value = self.__default_threshold[LOW_CRIT_THRESHOLD] + if default_value != NOT_AVAILABLE: + return float(default_value) + + raise NotImplementedError + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + Returns: + string: Model/part number of device + """ + + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + Returns: + string: Serial number of device + """ + return "N/A" + + def get_minimum_recorded(self): + """ + Retrieves the minimum recorded temperature of thermal + Returns: + A float number, the minimum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.min_temperature is None: + self.get_temperature() + + return self.min_temperature + + def get_maximum_recorded(self): + """ + Retrieves the maximum recorded temperature of thermal + Returns: + A float number, the maximum recorded temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + if self.max_temperature is None: + self.get_temperature() + + return self.max_temperature diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/udev/70-persistent-net.rules b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/udev/70-persistent-net.rules new file mode 100644 index 0000000000..438ec0b42a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/udev/70-persistent-net.rules @@ -0,0 +1,3 @@ +ACTION=="add", SUBSYSTEM=="net", DRIVERS=="ixgbe", KERNELS=="0000:08:00.0", NAME:="eth0" +ACTION=="add", SUBSYSTEM=="net", DRIVERS=="ixgbe", KERNELS=="0000:06:00.1", NAME:="eth1" +ACTION=="add", SUBSYSTEM=="net", DRIVERS=="ixgbe", KERNELS=="0000:06:00.0", NAME:="eth3" diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py index b954da8726..0c55036ddf 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/accton_as4630_54pe_util.py @@ -16,21 +16,30 @@ # along with this program. If not, see . """ -Usage: %(scriptName)s [options] command object -options: - -h | --help : this help message - -d | --debug : run with debug mode - -f | --force : ignore error during installation or clean -command: - install : install drivers and generate related sysfs nodes - clean : uninstall drivers and remove related sysfs nodes +usage: accton_as4630_54pe_util.py [-h] [-d] [-f] {install,clean,api,api_clean,threshold} ... + +AS4630-54PE Platform Utility + +optional arguments: + -h, --help show this help message and exit + -d, --debug run with debug mode + -f, --force ignore error during installation or clean + +Utility Command: + {install,clean,api,api_clean,threshold} + install : install drivers and generate related sysfs nodes + clean : uninstall drivers and remove related sysfs nodes + api : install SONiC platform API + api_clean : uninstall SONiC platform API + threshold : modify thermal threshold """ import subprocess -import getopt import sys import logging import time import os +import argparse +from sonic_py_common.general import getstatusoutput_noshell PROJECT_NAME = 'as4630_54pe' version = '0.0.1' @@ -97,40 +106,48 @@ def main(): global DEBUG global args global FORCE + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH + + util_parser = argparse.ArgumentParser(description="AS4630-54PE Platform Utility") + util_parser.add_argument("-d", "--debug", dest='debug', action='store_true', default=False, + help="run with debug mode") + util_parser.add_argument("-f", "--force", dest='force', action='store_true', default=False, + help="ignore error during installation or clean") + subcommand = util_parser.add_subparsers(dest='cmd', title='Utility Command', required=True) + subcommand.add_parser('install', help=': install drivers and generate related sysfs nodes') + subcommand.add_parser('clean', help=': uninstall drivers and remove related sysfs nodes') + subcommand.add_parser('api', help=': install SONiC platform API') + subcommand.add_parser('api_clean', help=': uninstall SONiC platform API') + threshold_parser = subcommand.add_parser('threshold', help=': modify thermal threshold') + threshold_parser.add_argument("-l", dest='list', action='store_true', default=False, + help="list avaliable thermal") + threshold_parser.add_argument("-t", dest='thermal', type=str, metavar='THERMAL_NAME', + help="thermal name, ex: -t 'Temp sensor 1'") + threshold_parser.add_argument("-ht", dest='high_threshold', type=restricted_float, + metavar='THRESHOLD_VALUE', + help="high threshold: %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + threshold_parser.add_argument("-hct", dest='high_crit_threshold', type=restricted_float, + metavar='THRESHOLD_VALUE', + help="high critical threshold : %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + args = util_parser.parse_args() - if len(sys.argv)<2: - show_help() - - options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', - 'debug', - 'force', - ]) if DEBUG == True: - print(options) print(args) print(len(sys.argv)) - for opt, arg in options: - if opt in ('-h', '--help'): - show_help() - elif opt in ('-d', '--debug'): - DEBUG = True - logging.basicConfig(level=logging.INFO) - elif opt in ('-f', '--force'): - FORCE = 1 - else: - logging.info('no option') - for arg in args: - if arg == 'install': - do_install() - elif arg == 'clean': - do_uninstall() - elif arg == 'api': - do_sonic_platform_install() - elif arg == 'api_clean': - do_sonic_platform_clean() - else: - show_help() + DEBUG = args.debug + FORCE = 1 if args.force else 0 + + if args.cmd == 'install': + do_install() + elif args.cmd == 'clean': + do_uninstall() + elif args.cmd == 'api': + do_sonic_platform_install() + elif args.cmd == 'api_clean': + do_sonic_platform_clean() + elif args.cmd == 'threshold': + do_threshold() return 0 @@ -382,5 +399,162 @@ def device_exist(): ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0) return not(ret1 or ret2) +THRESHOLD_RANGE_LOW = 30.0 +THRESHOLD_RANGE_HIGH = 110.0 +# Code to initialize chassis object +init_chassis_code = \ + "import sonic_platform.platform\n"\ + "platform = sonic_platform.platform.Platform()\n"\ + "chassis = platform.get_chassis()\n\n" + +# Looking for thermal +looking_for_thermal_code = \ + "thermal = None\n"\ + "all_thermals = chassis.get_all_thermals()\n"\ + "for psu in chassis.get_all_psus():\n"\ + " all_thermals += psu.get_all_thermals()\n"\ + "for tmp in all_thermals:\n"\ + " if '{}' == tmp.get_name():\n"\ + " thermal = tmp\n"\ + " break\n"\ + "if thermal == None:\n"\ + " print('{} not found!')\n"\ + " exit(1)\n\n" + +def avaliable_thermals(): + global init_chassis_code + + get_all_thermal_name_code = \ + "thermal_list = []\n"\ + "all_thermals = chassis.get_all_thermals()\n"\ + "for psu in chassis.get_all_psus():\n"\ + " all_thermals += psu.get_all_thermals()\n"\ + "for tmp in all_thermals:\n"\ + " thermal_list.append(tmp.get_name())\n"\ + "print(str(thermal_list)[1:-1])\n" + + all_code = "{}{}".format(init_chassis_code, get_all_thermal_name_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status != 0: + return "" + return output + +def restricted_float(x): + global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH + + try: + x = float(x) + except ValueError: + raise argparse.ArgumentTypeError("%r not a floating-point literal" % (x,)) + + if x < THRESHOLD_RANGE_LOW or x > THRESHOLD_RANGE_HIGH: + raise argparse.ArgumentTypeError("%r not in range [%.1f ~ %.1f]" % + (x, THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH)) + + return x + +def get_high_threshold(name): + global init_chassis_code, looking_for_thermal_code + + get_high_threshold_code = \ + "try:\n"\ + " print(thermal.get_high_threshold())\n"\ + " exit(0)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the get_high_threshold method!')\n"\ + " exit(1)" + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name), + get_high_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status == 1: + return None + + return float(output) + +def get_high_crit_threshold(name): + global init_chassis_code, looking_for_thermal_code + + get_high_crit_threshold_code = \ + "try:\n"\ + " print(thermal.get_high_critical_threshold())\n"\ + " exit(0)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the get_high_critical_threshold method!')\n"\ + " exit(1)" + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name), + get_high_crit_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + if status == 1: + return None + + return float(output) + +def do_threshold(): + global args, init_chassis_code, looking_for_thermal_code + + if args.list: + print("Thermals: " + avaliable_thermals()) + return + + if args.thermal is None: + print("The following arguments are required: -t") + return + + set_threshold_code = "" + if args.high_threshold is not None: + if args.high_crit_threshold is not None and \ + args.high_threshold >= args.high_crit_threshold: + print("Invalid Threshold!(High threshold can not be more than " \ + "or equal to high critical threshold.)") + exit(1) + + high_crit = get_high_crit_threshold(args.thermal) + if high_crit is not None and \ + args.high_threshold >= high_crit: + print("Invalid Threshold!(High threshold can not be more than " \ + "or equal to high critical threshold.)") + exit(1) + + set_threshold_code += \ + "try:\n"\ + " if thermal.set_high_threshold({}) is False:\n"\ + " print('{}: set_high_threshold failure!')\n"\ + " exit(1)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the set_high_threshold method!')\n"\ + "print('Apply the new high threshold successfully.')\n"\ + "\n".format(args.high_threshold, args.thermal) + + if args.high_crit_threshold is not None: + high = get_high_threshold(args.thermal) + if high is not None and \ + args.high_crit_threshold <= high: + print("Invalid Threshold!(High critical threshold can not " \ + "be less than or equal to high threshold.)") + exit(1) + + set_threshold_code += \ + "try:\n"\ + " if thermal.set_high_critical_threshold({}) is False:\n"\ + " print('{}: set_high_critical_threshold failure!')\n"\ + " exit(1)\n"\ + "except NotImplementedError:\n"\ + " print('Not implement the set_high_critical_threshold method!')\n"\ + "print('Apply the new high critical threshold successfully.')\n"\ + "\n".format(args.high_crit_threshold, args.thermal) + + if set_threshold_code == "": + return + + all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(args.thermal, args.thermal), set_threshold_code) + + status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code]) + print(output) + if __name__ == "__main__": main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/handle_mgmt_interface.sh b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/handle_mgmt_interface.sh index e1acd16a01..19eae1716d 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/handle_mgmt_interface.sh +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/handle_mgmt_interface.sh @@ -1,9 +1,7 @@ #!/bin/bash -#Due to the hardware design, as4630-54pe use "eth2" instead of "eth0" as management interface. -#Rename netdev "eth0" and "eth2" to swap original "eth2" to "eth0". - -ifconfig eth0 down -ip link set eth0 name eth3 -ip link set eth2 name eth0 -ifconfig eth0 up +# Re-install the igb and ixgbe again to make the NIC sequence follow the udev rule +modprobe -r igb +modprobe -r ixgbe +modprobe igb +modprobe ixgbe diff --git a/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/restart_ixgbe.sh b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/restart_ixgbe.sh new file mode 100755 index 0000000000..de38f4ee60 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as4630-54pe/utils/restart_ixgbe.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +/etc/init.d/netfilter-persistent stop +modprobe -r ixgbe +udevadm control --reload-rules +udevadm trigger +modprobe ixgbe +/etc/init.d/netfilter-persistent start + diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as4630-54pe.postinst b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as4630-54pe.postinst index 23bebd3b29..0ed1fd80ea 100644 --- a/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as4630-54pe.postinst +++ b/platform/broadcom/sonic-platform-modules-accton/debian/sonic-platform-accton-as4630-54pe.postinst @@ -6,3 +6,6 @@ systemctl enable pddf-platform-init.service systemctl start pddf-platform-init.service systemctl enable as4630-54pe-pddf-platform-monitor.service systemctl start as4630-54pe-pddf-platform-monitor.service +systemctl enable as4630-54pe-platform-handle-mgmt-interface.service +systemctl start as4630-54pe-platform-handle-mgmt-interface.service +/usr/local/bin/restart_ixgbe.sh