From 931c6ea6f4ab4521dc2fc441975536f0b5073f19 Mon Sep 17 00:00:00 2001 From: Xinyu Lin Date: Wed, 16 Feb 2022 03:52:47 +0800 Subject: [PATCH] [Y-Cable][Credo] add theading locker to support thread-safe calling, add SKU check for download_firmware API. (#222) * [Y-Cable][Credo] fix racing issue of VSC releated APIs The VSC protocol didn't allow user to send two or more vsc command to the module simultaneously, otherwise unexpected error might occurred. To avoid this issue, we can simply to update the download_firmware_status in the the following functions. This could help the helper to know vsc is in progress or not. * get_firmware_version() * download_firmware() * activate_firmware() * rollback_firmware() This PR also does add SKU check for download_firmware API. * [Y-Cable][Credo] add firmware ID checker to avoid update the wrong firmware Signed-off-by: xinyu --- sonic_y_cable/credo/y_cable_credo.py | 1652 +++++++++++++++----------- 1 file changed, 964 insertions(+), 688 deletions(-) diff --git a/sonic_y_cable/credo/y_cable_credo.py b/sonic_y_cable/credo/y_cable_credo.py index 3a888f727665..81a1a54174f6 100644 --- a/sonic_y_cable/credo/y_cable_credo.py +++ b/sonic_y_cable/credo/y_cable_credo.py @@ -7,6 +7,9 @@ import math import time import struct +import threading +from contextlib import contextmanager + from ctypes import c_int8 from sonic_y_cable.y_cable_base import YCableBase @@ -15,6 +18,18 @@ except ImportError as e: pass +class RLocker(): + ACQUIRE_LOCK_TIMEOUT = 15 + + def __init__(self): + self.rlock = threading.RLock() + + @contextmanager + def acquire_timeout(self, timeout): + result = self.rlock.acquire(timeout=timeout) + yield result + if result: + self.rlock.release() class YCable(YCableBase): # definitions of the offset with width accommodated for values @@ -120,6 +135,7 @@ class YCable(YCableBase): EYE_TIMEOUT_SECS = 1 GET_DEBUG_MODE_TIMEOUT_SECS = 1 EXTEND_SWITCH_CNT_TIMEOUT_SECS = 1 + FWUPD_UART_XFER_TIMEOUT_SECS = 120 # error code of EEPROM EEPROM_READ_DATA_INVALID = -1 @@ -179,6 +195,7 @@ def __init__(self, port, main_logger): YCableBase.__init__(self, port, main_logger) self.platform_chassis = None + self.rlock = RLocker() try: self.platform_chassis = sonic_platform.platform.Platform().get_chassis() @@ -502,7 +519,12 @@ def toggle_mux_to_tor_a(self): curr_offset = YCable.OFFSET_SWITCH_MUX_DIRECTION if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + else: + self.log_error('acquire lock timeout, failed to toggle mux to TOR A') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to toggle mux to TOR A") return YCable.EEPROM_ERROR @@ -527,7 +549,12 @@ def toggle_mux_to_tor_b(self): curr_offset = YCable.OFFSET_SWITCH_MUX_DIRECTION if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + else: + self.log_error('acquire lock timeout, failed to toggle mux to TOR B') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to toggle mux to TOR B") return YCable.EEPROM_ERROR @@ -553,7 +580,12 @@ def get_read_side(self): curr_offset = YCable.OFFSET_DETERMINE_CABLE_READ_SIDE if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + else: + self.log_error('acquire lock timeout, failed to check read side') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to check read side") return YCable.EEPROM_ERROR @@ -608,10 +640,15 @@ def get_mux_direction(self): curr_offset = YCable.OFFSET_MUX_DIRECTION if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + else: + self.log_error('acquire lock timeout, failed to get mux direction') + return YCableBase.EEPROM_ERROR else: self.log_error( - "platform_chassis is not loaded, failed to check Active Linked and routing TOR side") + "platform_chassis is not loaded, failed to get mux direction") return YCable.EEPROM_ERROR if result is not None: @@ -661,7 +698,12 @@ def get_active_linked_tor_side(self): curr_offset = YCable.OFFSET_ACTIVE_TOR_INDICATOR if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + else: + self.log_error('acquire lock timeout, failed to check Active Linked and routing TOR side') + return YCableBase.EEPROM_ERROR else: self.log_error( "platform_chassis is not loaded, failed to check Active Linked and routing TOR side") @@ -717,7 +759,12 @@ def is_link_active(self, target): curr_offset = YCable.OFFSET_CHECK_LINK_ACTIVE if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + else: + self.log_error('acquire lock timeout, failed to check if link is Active on target side') + return YCableBase.EEPROM_ERROR else: self.log_error( "platform_chassis is not loaded, failed to check if link is Active on target side") @@ -772,39 +819,44 @@ def get_eye_heights(self, target): eye_result = [] if self.platform_chassis is not None: - buffer = bytearray([target]) - curr_offset = YCable.OFFSET_TARGET - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - - buffer = bytearray([0]) - curr_offset = YCable.OFFSET_INITIATE_EYE_MEASUREMENT - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - - time_start = time.time() - while(True): - done = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - time_now = time.time() - time_diff = time_now - time_start - if done[0] == 1: - break - elif time_diff >= YCable.EYE_TIMEOUT_SECS: - return YCable.EEPROM_TIMEOUT_ERROR - - idx = 0 - for lane in range(YCable.MAX_NUM_LANES): - curr_offset = YCable.OFFSET_LANE_1_EYE_RESULT - msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + idx, 1) - lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + idx + 1, 1) - - lane_result = (msb_result[0] << 8 | lsb_result[0]) - eye_result.append(lane_result) - idx += 2 + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + buffer = bytearray([target]) + curr_offset = YCable.OFFSET_TARGET + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + + buffer = bytearray([0]) + curr_offset = YCable.OFFSET_INITIATE_EYE_MEASUREMENT + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + + time_start = time.time() + while(True): + done = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + time_now = time.time() + time_diff = time_now - time_start + if done[0] == 1: + break + elif time_diff >= YCable.EYE_TIMEOUT_SECS: + return YCable.EEPROM_TIMEOUT_ERROR + + idx = 0 + for lane in range(YCable.MAX_NUM_LANES): + curr_offset = YCable.OFFSET_LANE_1_EYE_RESULT + msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + idx, 1) + lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + idx + 1, 1) + + lane_result = (msb_result[0] << 8 | lsb_result[0]) + eye_result.append(lane_result) + idx += 2 + else: + self.log_error('acquire lock timeout, failed to get eye height') + return YCableBase.EEPROM_ERROR else: - self.log_error("platform_chassis is not loaded, failed to configure the PRBS type") + self.log_error("platform_chassis is not loaded, failed to get eye height") return YCable.EEPROM_ERROR return eye_result @@ -823,7 +875,12 @@ def get_vendor(self): curr_offset = YCable.OFFSET_VENDOR_NAME if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 16) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 16) + else: + self.log_error('acquire lock timeout, failed to get vendor name') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get Vendor name") return YCable.EEPROM_ERROR @@ -845,7 +902,12 @@ def get_part_number(self): curr_offset = YCable.OFFSET_PART_NUMBER if self.platform_chassis is not None: - part_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 16) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + part_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 16) + else: + self.log_error('acquire lock timeout, failed to get part number') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get part number") return YCable.EEPROM_ERROR @@ -867,9 +929,14 @@ def get_serial_number(self): curr_offset = YCable.OFFSET_SERIAL_NUMBER if self.platform_chassis is not None: - part_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 16) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + part_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 16) + else: + self.log_error('acquire lock timeout, failed to get serial number') + return YCableBase.EEPROM_ERROR else: - self.log_error("platform_chassis is not loaded, failed to get part number") + self.log_error("platform_chassis is not loaded, failed to get serial number") return YCable.EEPROM_ERROR part_number = str(part_result.decode()) @@ -896,32 +963,40 @@ def get_switch_count_total(self, switch_count_type, clear_on_read=False): count = 0 - if switch_count_type == YCableBase.SWITCH_COUNT_MANUAL: - count = self.get_switch_count_tor_a(clear_on_read) + self.get_switch_count_tor_b(clear_on_read) - elif switch_count_type == YCableBase.SWITCH_COUNT_AUTO: - curr_offset = YCable.OFFSET_AUTO_SWITCH_COUNT - - if self.platform_chassis is not None: - msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - msb_result_1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 1, 1) - msb_result_2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 2, 1) - lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+3, 1) - count = (msb_result[0] << 24 | msb_result_1[0] << 16 | msb_result_2[0] << 8 | lsb_result[0]) + if self.platform_chassis is not None: + if switch_count_type == YCableBase.SWITCH_COUNT_MANUAL: + count = self.get_switch_count_tor_a(clear_on_read) + self.get_switch_count_tor_b(clear_on_read) + elif switch_count_type == YCableBase.SWITCH_COUNT_AUTO: + curr_offset = YCable.OFFSET_AUTO_SWITCH_COUNT + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + msb_result_1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 1, 1) + msb_result_2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 2, 1) + lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 3, 1) + count = (msb_result[0] << 24 | msb_result_1[0] << 16 | msb_result_2[0] << 8 | lsb_result[0]) + else: + self.log_error('acquire lock timeout, failed to get switch count') + return YCableBase.EEPROM_ERROR else: - self.log_error("platform_chassis is not loaded, failed to get manual switch count") + self.log_error("not a valid switch_count_type, failed to get switch count") return YCable.EEPROM_ERROR - else: - self.log_error("not a valid switch_count_type, failed to get switch count") - return YCable.EEPROM_ERROR - if clear_on_read: - if switch_count_type == YCableBase.SWITCH_COUNT_AUTO: - curr_offset = YCable.OFFSET_AUTO_SWITCH_COUNT - buffer = bytearray([6]) - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return YCable.EEPROM_ERROR + if clear_on_read: + if switch_count_type == YCableBase.SWITCH_COUNT_AUTO: + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_AUTO_SWITCH_COUNT + buffer = bytearray([6]) + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return YCable.EEPROM_ERROR + else: + self.log_error('acquire lock timeout, failed to clear switch count') + return YCableBase.EEPROM_ERROR + else: + self.log_error("platform_chassis is not loaded, failed to get switch count") + return YCable.EEPROM_ERROR return count @@ -946,23 +1021,26 @@ def get_switch_count_tor_a(self, clear_on_read=False): count = 0 if self.platform_chassis is not None: - msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - msb_result_1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 1, 1) - msb_result_2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 2, 1) - lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+3, 1) - count = (msb_result[0] << 24 | msb_result_1[0] << 16 | msb_result_2[0] << 8 | lsb_result[0]) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + msb_result_1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 1, 1) + msb_result_2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 2, 1) + lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+3, 1) + count = (msb_result[0] << 24 | msb_result_1[0] << 16 | msb_result_2[0] << 8 | lsb_result[0]) + + buffer = bytearray([4]) + curr_offset = YCable.OFFSET_CLEAR_SWITCH_COUNT + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return YCable.EEPROM_ERROR + else: + self.log_error('acquire lock timeout, failed to get switch count (tor A)') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get manual switch count") return YCable.EEPROM_ERROR - if clear_on_read: - buffer = bytearray([4]) - curr_offset = YCable.OFFSET_CLEAR_SWITCH_COUNT - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return YCable.EEPROM_ERROR - return count def get_switch_count_tor_b(self, clear_on_read=False): @@ -986,23 +1064,27 @@ def get_switch_count_tor_b(self, clear_on_read=False): count = 0 if self.platform_chassis is not None: - msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - msb_result_1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 1, 1) - msb_result_2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 2, 1) - lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+3, 1) - count = (msb_result[0] << 24 | msb_result_1[0] << 16 | msb_result_2[0] << 8 | lsb_result[0]) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + msb_result_1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 1, 1) + msb_result_2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 2, 1) + lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+3, 1) + count = (msb_result[0] << 24 | msb_result_1[0] << 16 | msb_result_2[0] << 8 | lsb_result[0]) + + if clear_on_read: + buffer = bytearray([5]) + curr_offset = YCable.OFFSET_CLEAR_SWITCH_COUNT + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return YCable.EEPROM_ERROR + else: + self.log_error('acquire lock timeout, failed to get switch count (tor B)') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get manual switch count") return YCable.EEPROM_ERROR - if clear_on_read: - buffer = bytearray([5]) - curr_offset = YCable.OFFSET_CLEAR_SWITCH_COUNT - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return YCable.EEPROM_ERROR - return count def get_switch_count_target(self, switch_count_type, target, clear_on_read=False): @@ -1052,33 +1134,36 @@ def get_switch_count_target(self, switch_count_type, target, clear_on_read=False return YCable.EEPROM_ERROR if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return YCable.EEPROM_ERROR - time_start = time.time() - while(True): - done = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - time_now = time.time() - time_diff = time_now - time_start - if done[0] & 0x80: - break - elif time_diff >= YCable.EXTEND_SWITCH_CNT_TIMEOUT_SECS: - return YCable.EEPROM_TIMEOUT_ERROR - - curr_offset = YCable.OFFSET_EXTEND_SWITCH_COUNT - msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 3, 1) - msb_result_1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 2, 1) - msb_result_2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 1, 1) - lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - count = (msb_result[0] << 24 | msb_result_1[0] << 16 | msb_result_2[0] << 8 | lsb_result[0]) - - if clear_on_read: - curr_offset = YCable.OFFSET_CLEAR_SWITCH_COUNT - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return YCable.EEPROM_ERROR + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return YCable.EEPROM_ERROR + time_start = time.time() + while(True): + done = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + time_now = time.time() + time_diff = time_now - time_start + if done[0] & 0x80: + break + elif time_diff >= YCable.EXTEND_SWITCH_CNT_TIMEOUT_SECS: + return YCable.EEPROM_TIMEOUT_ERROR + + curr_offset = YCable.OFFSET_EXTEND_SWITCH_COUNT + msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 3, 1) + msb_result_1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 2, 1) + msb_result_2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + 1, 1) + lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + count = (msb_result[0] << 24 | msb_result_1[0] << 16 | msb_result_2[0] << 8 | lsb_result[0]) + + if clear_on_read: + curr_offset = YCable.OFFSET_CLEAR_SWITCH_COUNT + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return YCable.EEPROM_ERROR + else: + self.log_error('acquire lock timeout, failed to get switch count target') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get switch count target") return YCable.EEPROM_ERROR @@ -1112,16 +1197,21 @@ def get_target_cursor_values(self, lane, target): result = [] if self.platform_chassis is not None: - pre1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5, 1) - result.append(c_int8(pre1[0]).value) - pre2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5 + 1, 1) - result.append(c_int8(pre2[0]).value) - main = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5 + 2, 1) - result.append(c_int8(main[0]).value) - post1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5 + 3, 1) - result.append(c_int8(post1[0]).value) - post2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5 + 4, 1) - result.append(c_int8(post2[0]).value) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + pre1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5, 1) + result.append(c_int8(pre1[0]).value) + pre2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5 + 1, 1) + result.append(c_int8(pre2[0]).value) + main = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5 + 2, 1) + result.append(c_int8(main[0]).value) + post1 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5 + 3, 1) + result.append(c_int8(post1[0]).value) + post2 = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset + (target)*20 + (lane-1)*5 + 4, 1) + result.append(c_int8(post2[0]).value) + else: + self.log_error('acquire lock timeout, failed to get target cursor values') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get target cursor values") return YCable.EEPROM_ERROR @@ -1155,12 +1245,17 @@ def set_target_cursor_values(self, lane, cursor_values, target): curr_offset = YCable.OFFSET_NIC_CURSOR_VALUES idx = 0 if self.platform_chassis is not None: - for data in cursor_values: - data = data & 0xFF - buffer = bytearray([data]) - self.platform_chassis.get_sfp(self.port).write_eeprom( - curr_offset + (target)*20 + (lane-1)*5 + idx, 1, buffer) - idx += 1 + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + for data in cursor_values: + data = data & 0xFF + buffer = bytearray([data]) + self.platform_chassis.get_sfp(self.port).write_eeprom( + curr_offset + (target)*20 + (lane-1)*5 + idx, 1, buffer) + idx += 1 + else: + self.log_error('acquire lock timeout, failed to set target cursor values') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get target cursor values") return YCable.EEPROM_ERROR @@ -1186,20 +1281,28 @@ def get_firmware_version(self, target): and their corresponding values """ - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_GET_INFO - self.send_vsc(vsc_req_form) - - data = bytearray(YCable.FIRMWARE_INFO_PAYLOAD_SIZE) - if self.platform_chassis is not None: - for byte_idx in range(0, YCable.FIRMWARE_INFO_PAYLOAD_SIZE): - curr_offset = 0xfc * 128 + 128 + byte_idx - read_out = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - data[byte_idx] = read_out[0] + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_GET_INFO + status = self.send_vsc(vsc_req_form) + + if status != YCable.MCU_EC_NO_ERROR: + self.log_error('Get firmware version error (error code:0x%04X)' % (status)) + return None + + data = bytearray(YCable.FIRMWARE_INFO_PAYLOAD_SIZE) + for byte_idx in range(0, YCable.FIRMWARE_INFO_PAYLOAD_SIZE): + curr_offset = 0xfc * 128 + 128 + byte_idx + read_out = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + data[byte_idx] = read_out[0] + else: + self.log_error('acquire lock timeout, failed to get firmware version') + return None else: - self.log_error("platform_chassis is not loaded, failed to get NIC lanes active") + self.log_error("platform_chassis is not loaded, failed to get firmware version") return YCable.EEPROM_ERROR result = {} @@ -1274,24 +1377,37 @@ def download_firmware(self, fwfile): """ if self.platform_chassis is not None: - inFile = open(fwfile, 'rb') fwImage = bytearray(inFile.read()) inFile.close() + bin_pid = struct.unpack_from('>B', fwImage[5 : 6])[0] + mcu_pid = self.read_mmap(0xFB, 187) + + if bin_pid != mcu_pid: + self.log_error('Firmware binary ID Mismatched Bin[%d] MCU[%d]' % (bin_pid, mcu_pid)) + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_INPROGRESS ''' Firmware update start ''' - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_START - status = self.send_vsc(vsc_req_form) - if status != YCable.MCU_EC_NO_ERROR: - self.log_error(YCable.MCU_ERROR_CODE_STRING[status]) - self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED - return YCableBase.FIRMWARE_DOWNLOAD_FAILURE + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_START + status = self.send_vsc(vsc_req_form) + if status != YCable.MCU_EC_NO_ERROR: + self.log_error(YCable.MCU_ERROR_CODE_STRING[status]) + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE + else: + self.log_error('acquire lock timeout, failed to start firmware update') + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE ''' Transfer firmwre image to local side MCU @@ -1300,99 +1416,111 @@ def download_firmware(self, fwfile): chunk_idx = 0 retry_count = 0 while chunk_idx < total_chunk: - checksum = 0 - fw_img_offset = chunk_idx * YCable.VSC_BUFF_SIZE - for byte_offset in range(YCable.VSC_BUFF_SIZE): - checksum += fwImage[fw_img_offset] - fw_img_offset += 1 - if (((byte_offset + 1) % YCable.VSC_BLOCK_WRITE_LENGTH) == 0): - page = YCable.MIS_PAGE_FC + byte_offset // 128 - byte = 128 + ((byte_offset + 1) - YCable.VSC_BLOCK_WRITE_LENGTH) % 128 - self.write_mmap(page, byte, bytearray( - fwImage[fw_img_offset - YCable.VSC_BLOCK_WRITE_LENGTH: fw_img_offset]), YCable.VSC_BLOCK_WRITE_LENGTH) - - fw_img_offset = chunk_idx * YCable.VSC_BUFF_SIZE - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_LOCAL_XFER - vsc_req_form[YCable.VSC_BYTE_ADDR0] = (fw_img_offset >> 0) & 0xFF - vsc_req_form[YCable.VSC_BYTE_ADDR1] = (fw_img_offset >> 8) & 0xFF - vsc_req_form[YCable.VSC_BYTE_ADDR2] = (fw_img_offset >> 16) & 0xFF - vsc_req_form[YCable.VSC_BYTE_ADDR3] = (fw_img_offset >> 24) & 0xFF - vsc_req_form[YCable.VSC_BYTE_CHKSUM_MSB] = (checksum >> 8) & 0xFF - vsc_req_form[YCable.VSC_BYTE_CHKSUM_LSB] = (checksum >> 0) & 0xFF - status = self.send_vsc(vsc_req_form) - - if status == YCable.MCU_EC_NO_ERROR: - chunk_idx += 1 - retry_count = 0 - else: - self.log_error('Firmware binary transfer error (error code:%04X)' % (status)) - - if retry_count == 3: - self.log_error('Retry Xfer Fw Bin Error, abort firmware update') + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + checksum = 0 + fw_img_offset = chunk_idx * YCable.VSC_BUFF_SIZE + for byte_offset in range(YCable.VSC_BUFF_SIZE): + checksum += fwImage[fw_img_offset] + fw_img_offset += 1 + if (((byte_offset + 1) % YCable.VSC_BLOCK_WRITE_LENGTH) == 0): + page = YCable.MIS_PAGE_FC + byte_offset // 128 + byte = 128 + ((byte_offset + 1) - YCable.VSC_BLOCK_WRITE_LENGTH) % 128 + self.write_mmap(page, byte, bytearray( + fwImage[fw_img_offset - YCable.VSC_BLOCK_WRITE_LENGTH: fw_img_offset]), YCable.VSC_BLOCK_WRITE_LENGTH) + + fw_img_offset = chunk_idx * YCable.VSC_BUFF_SIZE + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_LOCAL_XFER + vsc_req_form[YCable.VSC_BYTE_ADDR0] = (fw_img_offset >> 0) & 0xFF + vsc_req_form[YCable.VSC_BYTE_ADDR1] = (fw_img_offset >> 8) & 0xFF + vsc_req_form[YCable.VSC_BYTE_ADDR2] = (fw_img_offset >> 16) & 0xFF + vsc_req_form[YCable.VSC_BYTE_ADDR3] = (fw_img_offset >> 24) & 0xFF + vsc_req_form[YCable.VSC_BYTE_CHKSUM_MSB] = (checksum >> 8) & 0xFF + vsc_req_form[YCable.VSC_BYTE_CHKSUM_LSB] = (checksum >> 0) & 0xFF + status = self.send_vsc(vsc_req_form) + + if status == YCable.MCU_EC_NO_ERROR: + chunk_idx += 1 + retry_count = 0 + else: + self.log_error('Firmware binary transfer error (error code:%04X)' % (status)) + + if retry_count == 3: + self.log_error('Retry Xfer Fw Bin Error, abort firmware update') + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE + retry_count += 1 + else: + self.log_error('acquire lock timeout, failed to xfer firmware') self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED return YCableBase.FIRMWARE_DOWNLOAD_FAILURE - retry_count += 1 ''' Complete the local side firmware transferring ''' - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_LOCAL_XFER_COMPLETE - status = self.send_vsc(vsc_req_form) - if status != YCable.MCU_EC_NO_ERROR: - self.log_error('Veriyf firmware binary error (error code:0x%04X)' % (status)) - self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED - return YCableBase.FIRMWARE_DOWNLOAD_FAILURE + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_LOCAL_XFER_COMPLETE + status = self.send_vsc(vsc_req_form) + if status != YCable.MCU_EC_NO_ERROR: + self.log_error('Veriyf firmware binary error (error code:0x%04X)' % (status)) + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE + else: + self.log_error('acquire lock timeout, failed to complete firmware xfer') + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE ''' transfer firmware image from local side MCU to the other two via UART ''' - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_UART_XFER - status = self.send_vsc(vsc_req_form) - if status != YCable.MCU_EC_NO_ERROR: - self.log_error('Firmware binary UART transfer error (error code:0x%04X)' % (status)) - self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED - return YCableBase.FIRMWARE_DOWNLOAD_FAILURE - - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_UART_XFER_STATUS - status = self.send_vsc(vsc_req_form) - if status != YCable.MCU_EC_NO_ERROR: - self.log_error( - 'Get firmware binary UART transfer status error (error code:0x%04X)' % (status)) - self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED - return YCableBase.FIRMWARE_DOWNLOAD_FAILURE - - busy = self.read_mmap(YCable.MIS_PAGE_FC, 128) - self.read_mmap(YCable.MIS_PAGE_FC, 129) - self.read_mmap(YCable.MIS_PAGE_FC, 130) - self.read_mmap(YCable.MIS_PAGE_FC, 131) - - while busy != 0: - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_UART_XFER_STATUS - status = self.send_vsc(vsc_req_form) - if status != YCable.MCU_EC_NO_ERROR: - self.log_error( - 'Get firmware binary UART transfer status error (error code:0x%04X)' % (status)) - + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_UART_XFER + status = self.send_vsc(vsc_req_form) + if status != YCable.MCU_EC_NO_ERROR: + self.log_error('Firmware binary UART transfer error (error code:0x%04X)' % (status)) + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE + else: + self.log_error('acquire lock timeout, failed to uart xfer') self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED return YCableBase.FIRMWARE_DOWNLOAD_FAILURE - time.sleep(0.2) - busy = self.read_mmap(YCable.MIS_PAGE_FC, 128) - self.read_mmap(YCable.MIS_PAGE_FC, 129) - self.read_mmap(YCable.MIS_PAGE_FC, 130) - self.read_mmap(YCable.MIS_PAGE_FC, 131) - - self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_NOT_INITIATED_OR_FINISHED + uartXferStartTime = time.time() + while True: + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_UART_XFER_STATUS + status = self.send_vsc(vsc_req_form) + + busy = self.read_mmap(YCable.MIS_PAGE_FC, 128) + self.read_mmap(YCable.MIS_PAGE_FC, 129) + self.read_mmap(YCable.MIS_PAGE_FC, 130) + self.read_mmap(YCable.MIS_PAGE_FC, 131) + + if busy == 0: + break + + if (time.time() - uartXferStartTime) > YCable.FWUPD_UART_XFER_TIMEOUT_SECS: + self.log_error( + 'Get firmware binary UART transfer status error (error code:0x%04X)' % (status)) + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE + + time.sleep(1) + else: + self.log_error('acquire lock timeout, failed to get uart xfer status') + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_DOWNLOAD_FAILURE else: self.log_error("platform_chassis is not loaded, failed to download firmware") return YCable.EEPROM_ERROR @@ -1438,27 +1566,38 @@ def activate_firmware(self, fwfile=None, hitless=False): """ if self.platform_chassis is not None: if fwfile is None: - side = 0x7 - - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_COMMIT - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_ADDR0] = side - status = self.send_vsc(vsc_req_form) - if status != YCable.MCU_EC_NO_ERROR: - self.log_error(YCable.MCU_ERROR_CODE_STRING[status]) - return YCableBase.FIRMWARE_ACTIVATE_FAILURE - - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_RUN - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_ADDR0] = side - vsc_req_form[YCable.VSC_BYTE_ADDR1] = hitless - status = self.send_vsc(vsc_req_form) - time.sleep(5) - if status != YCable.MCU_EC_NO_ERROR: - self.log_error(YCable.MCU_ERROR_CODE_STRING[status]) - return YCableBase.FIRMWARE_ACTIVATE_FAILURE + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_INPROGRESS + side = 0x7 + + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_COMMIT + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_ADDR0] = side + status = self.send_vsc(vsc_req_form) + if status != YCable.MCU_EC_NO_ERROR: + self.log_error(YCable.MCU_ERROR_CODE_STRING[status]) + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_ACTIVATE_FAILURE + + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_RUN + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_ADDR0] = side + vsc_req_form[YCable.VSC_BYTE_ADDR1] = hitless + status = self.send_vsc(vsc_req_form) + time.sleep(5) + if status != YCable.MCU_EC_NO_ERROR: + self.log_error(YCable.MCU_ERROR_CODE_STRING[status]) + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_ACTIVATE_FAILURE + + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_NOT_INITIATED_OR_FINISHED + else: + self.log_error('acquire lock timeout, failed to activate firmware') + self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_FAILED + return YCableBase.FIRMWARE_ACTIVATE_FAILURE else: inFile = open(fwfile, 'rb') fwImage = bytearray(inFile.read()) @@ -1477,10 +1616,6 @@ def activate_firmware(self, fwfile=None, hitless=False): return YCableBase.FIRMWARE_ACTIVATE_SUCCESS elif fwVer['version_inactive'] == version_build_file: return self.activate_firmware(hitless=hitless) - else: - if self.download_firmware(fwfile) != YCableBase.FIRMWARE_DOWNLOAD_SUCCESS: - return YCableBase.FIRMWARE_ACTIVATE_FAILURE - return self.activate_firmware(fwfile, hitless) else: self.log_error("platform_chassis is not loaded, failed to activate firmware") return YCable.EEPROM_ERROR @@ -1558,10 +1693,14 @@ def set_switching_mode(self, mode): curr_offset = YCable.OFFSET_ENABLE_AUTO_SWITCH if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + else: + self.log_error('acquire lock timeout, failed to set switching mode') + return YCableBase.EEPROM_ERROR else: - self.log_error("platform_chassis is not loaded, failed to do a switch target") + self.log_error("platform_chassis is not loaded, failed to set switching mode") return YCable.EEPROM_ERROR return result @@ -1581,16 +1720,22 @@ def get_switching_mode(self): curr_offset = YCable.OFFSET_ENABLE_AUTO_SWITCH if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp( - self.port).read_eeprom(curr_offset, 1) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + + if result[0] == 1: + return YCableBase.SWITCHING_MODE_AUTO + else: + return YCableBase.SWITCHING_MODE_MANUAL + else: + self.log_error('acquire lock timeout, failed to get the switch mode') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get the switch mode") return YCable.EEPROM_ERROR - if result[0] == 1: - return YCableBase.SWITCHING_MODE_AUTO - else: - return YCableBase.SWITCHING_MODE_MANUAL + def get_nic_temperature(self): """ @@ -1605,8 +1750,13 @@ def get_nic_temperature(self): curr_offset = YCable.OFFSET_NIC_TEMPERATURE if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - temp = result[0] + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + temp = result[0] + else: + self.log_error('acquire lock timeout, failed to get NIC temp') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get NIC temp") return -1 @@ -1626,8 +1776,13 @@ def get_local_temperature(self): curr_offset = YCable.OFFSET_INTERNAL_TEMPERATURE if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - temp = result[0] + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + temp = result[0] + else: + self.log_error('acquire lock timeout, failed to get local temp') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get local temp") return YCable.EEPROM_ERROR @@ -1646,10 +1801,15 @@ def get_nic_voltage(self): """ if self.platform_chassis is not None: - curr_offset = YCable.OFFSET_NIC_VOLTAGE - msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+1, 1) - voltage = (((msb_result[0] << 8) | lsb_result[0]) * 0.0001) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_NIC_VOLTAGE + msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+1, 1) + voltage = (((msb_result[0] << 8) | lsb_result[0]) * 0.0001) + else: + self.log_error('acquire lock timeout, failed to get NIC voltage') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get NIC voltage") return -1 @@ -1668,10 +1828,15 @@ def get_local_voltage(self): """ if self.platform_chassis is not None: - curr_offset = YCable.OFFSET_INTERNAL_VOLTAGE - msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+1, 1) - voltage = (((msb_result[0] << 8) | lsb_result[0]) * 0.0001) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_INTERNAL_VOLTAGE + msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+1, 1) + voltage = (((msb_result[0] << 8) | lsb_result[0]) * 0.0001) + else: + self.log_error('acquire lock timeout, failed to get local voltage') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get local voltage") return YCable.EEPROM_ERROR @@ -1691,16 +1856,21 @@ def get_alive_status(self): """ if self.platform_chassis is not None: - curr_offset = YCable.OFFSET_NIC_SIGNAL_DETECTION - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 6) - if result is False: - return result - - for idx in range(6): - if result[idx] == 0: - return False + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_NIC_SIGNAL_DETECTION + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 6) + if result is False: + return result + + for idx in range(6): + if result[idx] == 0: + return False + else: + self.log_error('acquire lock timeout, failed to get active status') + return YCableBase.EEPROM_ERROR else: - self.log_error("platform_chassis is not loaded, failed to get anlt") + self.log_error("platform_chassis is not loaded, failed to get active status") return YCable.EEPROM_ERROR return True @@ -1731,21 +1901,26 @@ def reset(self, target): self.log_error("reset: unsupported target") return False - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_RUN - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD - vsc_req_form[YCable.VSC_BYTE_ADDR0] = (1 << target) - vsc_req_form[YCable.VSC_BYTE_ADDR1] = 0 - status = self.send_vsc(vsc_req_form) - - if target == YCableBase.TARGET_NIC: - time.sleep(4) - else: - time.sleep(2) - - if status != YCable.MCU_EC_NO_ERROR: - self.log_error("unable to reset the module") - return False + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.FWUPD_OPTION_RUN + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_FWUPD + vsc_req_form[YCable.VSC_BYTE_ADDR0] = (1 << target) + vsc_req_form[YCable.VSC_BYTE_ADDR1] = 0 + status = self.send_vsc(vsc_req_form) + + if status != YCable.MCU_EC_NO_ERROR: + self.log_error("unable to reset the module") + return False + + if target == YCableBase.TARGET_NIC: + time.sleep(4) + else: + time.sleep(2) + else: + self.log_error('acquire lock timeout, failed to reset') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to reset") return YCable.EEPROM_ERROR @@ -1795,25 +1970,30 @@ def create_port(self, speed, fec_mode_tor = YCableBase.FEC_MODE_NONE, fec_mode_n """ if self.platform_chassis is not None: - mode = 0 - if speed == 50000: - mode |= (0 << 6) - elif speed == 100000: - mode |= (1 << 6) - else: - self.log_error("create port: unsupported speed:%d" % (speed)) - return False - - mode |= (1 << 0) if anlt_nic else (0 << 0) - mode |= (1 << 1) if anlt_tor else (0 << 1) - mode |= (1 << 3) if fec_mode_nic == YCableBase.FEC_MODE_RS else (0 << 3) - mode |= (1 << 4) if fec_mode_tor == YCableBase.FEC_MODE_RS else (0 << 4) - - curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION - buffer = bytearray([mode]) - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + mode = 0 + if speed == 50000: + mode |= (0 << 6) + elif speed == 100000: + mode |= (1 << 6) + else: + self.log_error("create port: unsupported speed:%d" % (speed)) + return False + + mode |= (1 << 0) if anlt_nic else (0 << 0) + mode |= (1 << 1) if anlt_tor else (0 << 1) + mode |= (1 << 3) if fec_mode_nic == YCableBase.FEC_MODE_RS else (0 << 3) + mode |= (1 << 4) if fec_mode_tor == YCableBase.FEC_MODE_RS else (0 << 4) + + curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION + buffer = bytearray([mode]) + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + else: + self.log_error('acquire lock timeout, failed to create port') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to create port") return YCable.EEPROM_ERROR @@ -1837,16 +2017,21 @@ def get_speed(self): speed = 0 if self.platform_chassis is not None: - curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION - mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - - if (mode[0] >> 6) == 0: - speed = 50000 - elif (mode[0] >> 6) == 1: - speed = 100000 - else: - self.log_error("unsupported speed") - return -1 + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION + mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + + if (mode[0] >> 6) == 0: + speed = 50000 + elif (mode[0] >> 6) == 1: + speed = 100000 + else: + self.log_error("unsupported speed") + return -1 + else: + self.log_error('acquire lock timeout, failed to get speed') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get speed") return YCable.EEPROM_ERROR @@ -1877,22 +2062,27 @@ def set_fec_mode(self, fec_mode, target): """ if self.platform_chassis is not None: - curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION - mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - - if target == YCableBase.TARGET_NIC: - mode[0] &= ~(1 << 3) - mode[0] |= (1 << 3) if fec_mode == YCableBase.FEC_MODE_RS else (0 << 3) - elif target == YCableBase.TARGET_TOR_A or target == YCableBase.TARGET_TOR_B: - mode[0] &= ~(1 << 4) - mode[0] |= (1 << 4) if fec_mode == YCableBase.FEC_MODE_RS else (0 << 4) - else: - self.log_error("set fec mode: unsupported target") - return False - - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, mode) - if result is False: - return result + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION + mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + + if target == YCableBase.TARGET_NIC: + mode[0] &= ~(1 << 3) + mode[0] |= (1 << 3) if fec_mode == YCableBase.FEC_MODE_RS else (0 << 3) + elif target == YCableBase.TARGET_TOR_A or target == YCableBase.TARGET_TOR_B: + mode[0] &= ~(1 << 4) + mode[0] |= (1 << 4) if fec_mode == YCableBase.FEC_MODE_RS else (0 << 4) + else: + self.log_error("set fec mode: unsupported target") + return False + + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, mode) + if result is False: + return result + else: + self.log_error('acquire lock timeout, failed to set fec mode') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to set fec mode") return YCable.EEPROM_ERROR @@ -1921,17 +2111,22 @@ def get_fec_mode(self, target): fec_mode = YCableBase.FEC_MODE_NONE if self.platform_chassis is not None: - curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION - mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - - if target == YCableBase.TARGET_NIC: - if mode[0] & (1 << 3): - fec_mode = YCableBase.FEC_MODE_RS - elif target == YCableBase.TARGET_TOR_A or target == YCableBase.TARGET_TOR_B: - if mode[0] & (1 << 4): - fec_mode = YCableBase.FEC_MODE_RS - else: - self.log_error("get fec mode: unsupported target") + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION + mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + + if target == YCableBase.TARGET_NIC: + if mode[0] & (1 << 3): + fec_mode = YCableBase.FEC_MODE_RS + elif target == YCableBase.TARGET_TOR_A or target == YCableBase.TARGET_TOR_B: + if mode[0] & (1 << 4): + fec_mode = YCableBase.FEC_MODE_RS + else: + self.log_error("get fec mode: unsupported target") + else: + self.log_error('acquire lock timeout, failed to get fec mode') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get fec mode") return YCable.EEPROM_ERROR @@ -1960,22 +2155,27 @@ def set_anlt(self, enable, target): """ if self.platform_chassis is not None: - curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION - mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - - if target == YCableBase.TARGET_NIC: - mode[0] &= ~(1 << 0) - mode[0] |= (1 << 0) if enable else (0 << 0) - elif target == YCableBase.TARGET_TOR_A or target == YCableBase.TARGET_TOR_B: - mode[0] &= ~(1 << 1) - mode[0] |= (1 << 1) if enable else (0 << 1) - else: - self.log_error("set anlt: unsupported target") - return False - - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, mode) - if result is False: - return result + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION + mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + + if target == YCableBase.TARGET_NIC: + mode[0] &= ~(1 << 0) + mode[0] |= (1 << 0) if enable else (0 << 0) + elif target == YCableBase.TARGET_TOR_A or target == YCableBase.TARGET_TOR_B: + mode[0] &= ~(1 << 1) + mode[0] |= (1 << 1) if enable else (0 << 1) + else: + self.log_error("set anlt: unsupported target") + return False + + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, mode) + if result is False: + return result + else: + self.log_error('acquire lock timeout, failed to set anlt') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to set anlt") return YCable.EEPROM_ERROR @@ -2001,18 +2201,23 @@ def get_anlt(self, target): anlt_mode = False if self.platform_chassis is not None: - curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION - mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - - if target == YCableBase.TARGET_NIC: - if mode[0] & (1 << 0): - anlt_mode = True - - elif target == YCableBase.TARGET_TOR_A or target == YCableBase.TARGET_TOR_B: - if mode[0] & (1 << 1): - anlt_mode = True - else: - self.log_error("get anlt: unsupported target") + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + curr_offset = YCable.OFFSET_NIC_MODE_CONFIGURATION + mode = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + + if target == YCableBase.TARGET_NIC: + if mode[0] & (1 << 0): + anlt_mode = True + + elif target == YCableBase.TARGET_TOR_A or target == YCableBase.TARGET_TOR_B: + if mode[0] & (1 << 1): + anlt_mode = True + else: + self.log_error("get anlt: unsupported target") + else: + self.log_error('acquire lock timeout, failed to get anlt') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get anlt") return YCable.EEPROM_ERROR @@ -2038,10 +2243,19 @@ def get_event_log(self, clear_on_read=False): if self.platform_chassis is not None: if (clear_on_read): - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_EVENTLOG - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.EVENTLOG_OPTION_CLEAR - self.send_vsc(vsc_req_form) + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) + vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_EVENTLOG + vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.EVENTLOG_OPTION_CLEAR + status = self.send_vsc(vsc_req_form) + + if status != YCable.MCU_EC_NO_ERROR: + self.log_error("clear event log error(error code:%04X)" % (status)) + return YCable.EEPROM_ERROR + else: + self.log_error("acquire lock timeout, failed to clear event log") + return YCable.EEPROM_ERROR last_read_id = -1 @@ -2061,52 +2275,57 @@ def get_event_log(self, clear_on_read=False): } while (True): - vsc_req_form = [None] * (YCable.VSC_CMD_ATTRIBUTE_LENGTH) - vsc_req_form[YCable.VSC_BYTE_OPCODE] = YCable.VSC_OPCODE_EVENTLOG - vsc_req_form[YCable.VSC_BYTE_OPTION] = YCable.EVENTLOG_OPTION_DUMP - vsc_req_form[YCable.VSC_BYTE_ADDR0] = (last_read_id >> 0) & 0xFF - vsc_req_form[YCable.VSC_BYTE_ADDR1] = (last_read_id >> 8) & 0xFF - vsc_req_form[YCable.VSC_BYTE_ADDR2] = (last_read_id >> 16) & 0xFF - vsc_req_form[YCable.VSC_BYTE_ADDR3] = (last_read_id >> 24) & 0xFF - status = self.send_vsc(vsc_req_form) - - if status == YCable.MCU_EC_NO_ERROR: - fetch_cnt = self.read_mmap(YCable.MIS_PAGE_VSC, 134) - if (fetch_cnt == 0): - break - else: - self.log_error("download event log error(error code:%04X)" % (status)) - return None - - event_data = bytearray(YCable.EVENTLOG_PAYLOAD_SIZE * fetch_cnt) - - for byte_offset in range(0, YCable.EVENTLOG_PAYLOAD_SIZE * fetch_cnt): - byte_data = self.read_mmap(YCable.MIS_PAGE_FC, 128 + byte_offset) - event_data[byte_offset] = byte_data - - for curr_idx in range(0, fetch_cnt): - byte_offset = curr_idx * YCable.EVENTLOG_PAYLOAD_SIZE - event_id = struct.unpack_from('> 0) & 0xFF + vsc_req_form[YCable.VSC_BYTE_ADDR1] = (last_read_id >> 8) & 0xFF + vsc_req_form[YCable.VSC_BYTE_ADDR2] = (last_read_id >> 16) & 0xFF + vsc_req_form[YCable.VSC_BYTE_ADDR3] = (last_read_id >> 24) & 0xFF + status = self.send_vsc(vsc_req_form) + + if status == YCable.MCU_EC_NO_ERROR: + fetch_cnt = self.read_mmap(YCable.MIS_PAGE_VSC, 134) + if (fetch_cnt == 0): + break + else: + self.log_error("download event log error(error code:%04X)" % (status)) + return YCable.EEPROM_ERROR + + event_data = bytearray(YCable.EVENTLOG_PAYLOAD_SIZE * fetch_cnt) + + for byte_offset in range(0, YCable.EVENTLOG_PAYLOAD_SIZE * fetch_cnt): + byte_data = self.read_mmap(YCable.MIS_PAGE_FC, 128 + byte_offset) + event_data[byte_offset] = byte_data + + for curr_idx in range(0, fetch_cnt): + byte_offset = curr_idx * YCable.EVENTLOG_PAYLOAD_SIZE + event_id = struct.unpack_from('> 8) & 0xFF, lt_tx1 & 0xFF, (lt_tx2 >> 8) & 0xFF, lt_tx2 & 0xFF] + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + an_sm = 0 + if target == YCableBase.TARGET_NIC: + an_sm = self.reg_read(0x0048) + lanes=[0,4] + elif target == YCableBase.TARGET_TOR_A: + an_sm = self.reg_read(0x5448) + lanes=[12,16] + elif target == YCableBase.TARGET_TOR_B: + an_sm = self.reg_read(0x5C48) + lanes=[20,24] + else: + self.log_error("get anlt stats: unsupported target") + + anlt_stat['AN_StateMachine'] = an_sm + + for idx, ln in enumerate(range(lanes[0], lanes[1])): + lt_tx1 = self.reg_read(0xB3 | 0x200 * ln) + lt_tx2 = self.reg_read(0xB4 | 0x200 * ln) + anlt_stat['LT_TX_lane%d' % idx] = [(lt_tx1 >> 8) & 0xFF, lt_tx1 & 0xFF, (lt_tx2 >> 8) & 0xFF, lt_tx2 & 0xFF] + else: + self.log_error('acquire lock timeout, failed to get anlt stat') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get anlt stats") return YCable.EEPROM_ERROR @@ -2450,26 +2698,30 @@ def enable_prbs_mode(self, target, mode_value, lane_mask, direction=YCableBase.P curr_offset = YCable.OFFSET_TARGET if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - - buffer = bytearray([0]) - curr_offset = YCable.OFFSET_ENABLE_PRBS - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - - buffer = bytearray([mode_value]) - curr_offset = YCable.OFFSET_CONFIGURE_PRBS_TYPE - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - - buffer = bytearray([lane_mask]) - curr_offset = YCable.OFFSET_ENABLE_PRBS - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + + buffer = bytearray([0]) + curr_offset = YCable.OFFSET_ENABLE_PRBS + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + + buffer = bytearray([mode_value]) + curr_offset = YCable.OFFSET_CONFIGURE_PRBS_TYPE + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + + buffer = bytearray([lane_mask]) + curr_offset = YCable.OFFSET_ENABLE_PRBS + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + else: + self.log_error('acquire lock timeout, failed to enable the PRBS mode') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to enable the PRBS mode") return YCable.EEPROM_ERROR @@ -2503,15 +2755,17 @@ def disable_prbs_mode(self, target, direction): curr_offset = YCable.OFFSET_TARGET if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - buffer = bytearray([0]) - curr_offset = YCable.OFFSET_ENABLE_PRBS - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + buffer = bytearray([0]) + curr_offset = YCable.OFFSET_ENABLE_PRBS + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + else: + self.log_error('acquire lock timeout, failed to disable the PRBS mode') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to disable the PRBS mode") return YCable.EEPROM_ERROR @@ -2551,15 +2805,17 @@ def enable_loopback_mode(self, target, lane_mask, mode=YCableBase.LOOPBACK_MODE_ curr_offset = YCable.OFFSET_TARGET if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - buffer = bytearray([lane_mask]) - curr_offset = YCable.OFFSET_ENABLE_LOOPBACK - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + buffer = bytearray([lane_mask]) + curr_offset = YCable.OFFSET_ENABLE_LOOPBACK + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + else: + self.log_error('acquire lock timeout, failed to enable the loopback mode') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to enable the loopback mode") return YCable.EEPROM_ERROR @@ -2588,17 +2844,19 @@ def disable_loopback_mode(self, target): curr_offset = YCable.OFFSET_TARGET if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - buffer = bytearray([0]) - curr_offset = YCable.OFFSET_ENABLE_LOOPBACK - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + buffer = bytearray([0]) + curr_offset = YCable.OFFSET_ENABLE_LOOPBACK + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + else: + self.log_error('acquire lock timeout, failed to disable loopback mode') + return YCableBase.EEPROM_ERROR else: - self.log_error("platform_chassis is not loaded, failed to disable the loopback mode") + self.log_error("platform_chassis is not loaded, failed to disable loopback mode") return YCable.EEPROM_ERROR return result @@ -2626,33 +2884,38 @@ def get_loopback_mode(self, target): """ if self.platform_chassis is not None: - buffer = bytearray([target]) - curr_offset = YCable.OFFSET_TARGET - - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return -1 - - buffer = bytearray([0]) - curr_offset = YCable.OFFSET_SYNC_DEBUG_MODE - result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return -1 - time_start = time.time() - while(True): - done = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - time_now = time.time() - time_diff = time_now - time_start - if done[0] == 1: - break - elif time_diff >= YCable.GET_DEBUG_MODE_TIMEOUT_SECS: - return YCable.EEPROM_TIMEOUT_ERROR - - curr_offset = YCable.OFFSET_ENABLE_LOOPBACK - result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - - if result[0]: - return YCableBase.LOOPBACK_MODE_NEAR_END + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + buffer = bytearray([target]) + curr_offset = YCable.OFFSET_TARGET + + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return -1 + + buffer = bytearray([0]) + curr_offset = YCable.OFFSET_SYNC_DEBUG_MODE + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return -1 + time_start = time.time() + while(True): + done = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + time_now = time.time() + time_diff = time_now - time_start + if done[0] == 1: + break + elif time_diff >= YCable.GET_DEBUG_MODE_TIMEOUT_SECS: + return YCable.EEPROM_TIMEOUT_ERROR + + curr_offset = YCable.OFFSET_ENABLE_LOOPBACK + result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + + if result[0]: + return YCableBase.LOOPBACK_MODE_NEAR_END + else: + self.log_error('acquire lock timeout, failed to get loopback mode') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get loopback mode") return YCable.EEPROM_ERROR @@ -2682,34 +2945,38 @@ def get_ber_info(self, target): ber_result = [] if self.platform_chassis is not None: - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - buffer = bytearray([0]) - curr_offset = YCable.OFFSET_INITIATE_BER_MEASUREMENT - result = self.platform_chassis.get_sfp( - self.port).write_eeprom(curr_offset, 1, buffer) - if result is False: - return result - time_start = time.time() - while(True): - done = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) - time_now = time.time() - time_diff = time_now - time_start - if done[0] == 1: - break - elif time_diff >= YCable.BER_TIMEOUT_SECS: - return YCable.EEPROM_TIMEOUT_ERROR - - idx = 0 - curr_offset = YCable.OFFSET_LANE_1_BER_RESULT - for lane in range(YCable.MAX_NUM_LANES): - msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+idx, 1) - lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+1+idx, 1) - lane_result = msb_result[0] * math.pow(10, (lsb_result[0]-24)) - ber_result.append(lane_result) - idx += 2 + with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: + if lock_status: + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + buffer = bytearray([0]) + curr_offset = YCable.OFFSET_INITIATE_BER_MEASUREMENT + result = self.platform_chassis.get_sfp( + self.port).write_eeprom(curr_offset, 1, buffer) + if result is False: + return result + time_start = time.time() + while(True): + done = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + time_now = time.time() + time_diff = time_now - time_start + if done[0] == 1: + break + elif time_diff >= YCable.BER_TIMEOUT_SECS: + return YCable.EEPROM_TIMEOUT_ERROR + + idx = 0 + curr_offset = YCable.OFFSET_LANE_1_BER_RESULT + for lane in range(YCable.MAX_NUM_LANES): + msb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+idx, 1) + lsb_result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset+1+idx, 1) + lane_result = msb_result[0] * math.pow(10, (lsb_result[0]-24)) + ber_result.append(lane_result) + idx += 2 + else: + self.log_error('acquire lock timeout, failed to get ber info') + return YCableBase.EEPROM_ERROR else: self.log_error("platform_chassis is not loaded, failed to get ber info") return YCable.EEPROM_ERROR @@ -2740,42 +3007,46 @@ def debug_dump_registers(self, option=None): which would help diagnose the cable for proper functioning """ if self.platform_chassis is not None: - result = {} - result['pn'] = self.get_part_number() - result['sn'] = self.get_serial_number() - result['uart_stat'] = self.get_uart_stat() - result['nic_temp'] = self.get_nic_temperature() - result['nic_voltage'] = self.get_nic_voltage() - result['fw_init_status'] = self.get_dsp_fw_init_stat() - result['serdes_detect'] = self.get_dsp_link_Dect() - - lanes = [0,1,2,3,12,13,14,15,20,21,22,23] - - for ln in list(lanes): - data = self.get_serdes_params(ln) - serdes = {} - serdes['ch_est'] = struct.unpack_from('