-
Notifications
You must be signed in to change notification settings - Fork 177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CMIS] Add lane_mask parameter to set_loopback_mode() to enable setti… #490
Changes from 5 commits
36a0294
b2ac81c
6801fa0
7105a22
dd39936
9faee1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1115,50 +1115,216 @@ def get_loopback_capability(self): | |
loopback_capability['media_side_output_loopback_supported'] = bool((allowed_loopback_result >> 0) & 0x1) | ||
return loopback_capability | ||
|
||
def set_loopback_mode(self, loopback_mode): | ||
def set_host_input_loopback(self, lane_mask, enable): | ||
''' | ||
This function sets the module loopback mode. | ||
Loopback mode has to be one of the five: | ||
1. "none" (default) | ||
2. "host-side-input" | ||
3. "host-side-output" | ||
4. "media-side-input" | ||
5. "media-side-output" | ||
The function will look at 13h:128 to check advertized loopback capabilities. | ||
Return True if the provision succeeds, False if it fails | ||
Sets the host-side input loopback mode for specified lanes. | ||
|
||
Args: | ||
lane_mask (int): A bitmask indicating which lanes to enable/disable loopback. | ||
- 0xFF: Enable loopback on all lanes. | ||
- Individual bits represent corresponding lanes. | ||
enable (bool): True to enable loopback, False to disable. | ||
|
||
Returns: | ||
bool: True if the operation succeeds, False otherwise. | ||
''' | ||
loopback_capability = self.get_loopback_capability() | ||
if loopback_capability is None: | ||
logger.info('Failed to get loopback capabilities') | ||
return False | ||
if loopback_mode == 'none': | ||
status_host_input = self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0) | ||
status_host_output = self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0) | ||
status_media_input = self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0) | ||
status_media_output = self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0) | ||
return all([status_host_input, status_host_output, status_media_input, status_media_output]) | ||
elif loopback_mode == 'host-side-input': | ||
if loopback_capability['host_side_input_loopback_supported']: | ||
return self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0xff) | ||
else: | ||
return False | ||
elif loopback_mode == 'host-side-output': | ||
if loopback_capability['host_side_output_loopback_supported']: | ||
return self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0xff) | ||
else: | ||
|
||
if loopback_capability['host_side_input_loopback_supported'] is False: | ||
logger.error('Host input loopback is not supported') | ||
return False | ||
|
||
if loopback_capability['per_lane_host_loopback_supported'] is False and lane_mask != 0xff: | ||
logger.error('Per-lane host input loopback is not supported, lane_mask:%#x', lane_mask) | ||
return False | ||
|
||
if loopback_capability['simultaneous_host_media_loopback_supported'] is False: | ||
media_input_val = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) | ||
media_output_val = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) | ||
if media_input_val or media_output_val: | ||
txt = 'Simultaneous host media loopback is not supported\n' | ||
txt += f'media_input_val:{media_input_val:#x}, media_output_val:{media_output_val:#x}' | ||
logger.error(txt) | ||
return False | ||
elif loopback_mode == 'media-side-input': | ||
if loopback_capability['media_side_input_loopback_supported']: | ||
return self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0xff) | ||
else: | ||
|
||
host_input_val = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) | ||
if enable: | ||
return self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, host_input_val | lane_mask) | ||
else: | ||
return self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, host_input_val & ~lane_mask) | ||
|
||
def set_host_output_loopback(self, lane_mask, enable): | ||
''' | ||
Sets the host-side output loopback mode for specified lanes. | ||
|
||
Args: | ||
lane_mask (int): A bitmask indicating which lanes to enable/disable loopback. | ||
- 0xFF: Enable loopback on all lanes. | ||
- Individual bits represent corresponding lanes. | ||
enable (bool): True to enable loopback, False to disable. | ||
|
||
Returns: | ||
bool: True if the operation succeeds, False otherwise. | ||
''' | ||
loopback_capability = self.get_loopback_capability() | ||
if loopback_capability is None: | ||
logger.info('Failed to get loopback capabilities') | ||
return False | ||
|
||
if loopback_capability['host_side_output_loopback_supported'] is False: | ||
logger.error('Host output loopback is not supported') | ||
return False | ||
|
||
if loopback_capability['per_lane_host_loopback_supported'] is False and lane_mask != 0xff: | ||
logger.error('Per-lane host output loopback is not supported, lane_mask:%#x', lane_mask) | ||
return False | ||
|
||
if loopback_capability['simultaneous_host_media_loopback_supported'] is False: | ||
media_input_val = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) | ||
media_output_val = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) | ||
if media_input_val or media_output_val: | ||
txt = 'Simultaneous host media loopback is not supported\n' | ||
txt += f'media_input_val:{media_input_val:x}, media_output_val:{media_output_val:#x}' | ||
logger.error(txt) | ||
return False | ||
elif loopback_mode == 'media-side-output': | ||
if loopback_capability['media_side_output_loopback_supported']: | ||
return self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0xff) | ||
else: | ||
|
||
host_output_val = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) | ||
if enable: | ||
return self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, host_output_val | lane_mask) | ||
else: | ||
return self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, host_output_val & ~lane_mask) | ||
|
||
def set_media_input_loopback(self, lane_mask, enable): | ||
''' | ||
Sets the media-side input loopback mode for specified lanes. | ||
|
||
Args: | ||
lane_mask (int): A bitmask indicating which lanes to enable/disable loopback. | ||
- 0xFF: Enable loopback on all lanes. | ||
- Individual bits represent corresponding lanes. | ||
enable (bool): True to enable loopback, False to disable. | ||
|
||
Returns: | ||
bool: True if the operation succeeds, False otherwise. | ||
''' | ||
loopback_capability = self.get_loopback_capability() | ||
if loopback_capability is None: | ||
logger.info('Failed to get loopback capabilities') | ||
return False | ||
|
||
if loopback_capability['media_side_input_loopback_supported'] is False: | ||
logger.error('Media input loopback is not supported') | ||
return False | ||
|
||
if loopback_capability['per_lane_media_loopback_supported'] is False and lane_mask != 0xff: | ||
logger.error('Per-lane media input loopback is not supported, lane_mask:%#x', lane_mask) | ||
return False | ||
|
||
if loopback_capability['simultaneous_host_media_loopback_supported'] is False: | ||
host_input_val = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) | ||
host_output_val = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) | ||
if host_input_val or host_output_val: | ||
txt = 'Simultaneous host media loopback is not supported\n' | ||
txt += f'host_input_val:{host_input_val:#x}, host_output_val:{host_output_val:#x}' | ||
logger.error(txt) | ||
return False | ||
|
||
media_input_val = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) | ||
if enable: | ||
return self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, media_input_val | lane_mask) | ||
else: | ||
return self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, media_input_val & ~lane_mask) | ||
|
||
def set_media_output_loopback(self, lane_mask, enable): | ||
''' | ||
Sets the media-side output loopback mode for specified lanes. | ||
|
||
Args: | ||
lane_mask (int): A bitmask indicating which lanes to enable/disable loopback. | ||
- 0xFF: Enable loopback on all lanes. | ||
- Individual bits represent corresponding lanes. | ||
enable (bool): True to enable loopback, False to disable. | ||
|
||
Returns: | ||
bool: True if the operation succeeds, False otherwise. | ||
''' | ||
loopback_capability = self.get_loopback_capability() | ||
if loopback_capability is None: | ||
logger.info('Failed to get loopback capabilities') | ||
return False | ||
|
||
if loopback_capability['media_side_output_loopback_supported'] is False: | ||
logger.error('Media output loopback is not supported') | ||
return False | ||
|
||
if loopback_capability['per_lane_media_loopback_supported'] is False and lane_mask != 0xff: | ||
logger.error('Per-lane media output loopback is not supported, lane_mask:%#x', lane_mask) | ||
return False | ||
|
||
if loopback_capability['simultaneous_host_media_loopback_supported'] is False: | ||
host_input_val = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) | ||
host_output_val = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) | ||
if host_input_val or host_output_val: | ||
txt = 'Simultaneous host media loopback is not supported\n' | ||
txt += f'host_input_val:{host_input_val:#x}, host_output_val:{host_output_val:#x}' | ||
logger.error(txt) | ||
return False | ||
|
||
media_output_val = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) | ||
if enable: | ||
return self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, media_output_val | lane_mask) | ||
else: | ||
return self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, media_output_val & ~lane_mask) | ||
|
||
def set_loopback_mode(self, loopback_mode, lane_mask = 0xff): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @xinyulin can you add an argument |
||
''' | ||
This function sets the module loopback mode. | ||
|
||
Args: | ||
- loopback_mode (str): Specifies the loopback mode. It must be one of the following: | ||
1. "none" | ||
2. "host-side-input-none" | ||
3. "host-side-output-none" | ||
4. "media-side-input-none" | ||
5. "media-side-output-none" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @xinyulin please see my comments below. if you add one argument There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
6. "host-side-input" | ||
7. "host-side-output" | ||
8. "media-side-input" | ||
9. "media-side-output" | ||
- lane_mask (int): A bitmask representing the lanes to which the loopback mode should | ||
be applied. Default 0xFF applies to all lanes. | ||
Returns: | ||
- bool: True if the operation succeeds, False otherwise. | ||
''' | ||
loopback_functions = { | ||
'host-side-input-none': (self.set_host_input_loopback, False), | ||
'host-side-output-none': (self.set_host_output_loopback, False), | ||
'media-side-input-none': (self.set_media_input_loopback, False), | ||
'media-side-output-none': (self.set_media_output_loopback, False), | ||
'host-side-input': (self.set_host_input_loopback, True), | ||
'host-side-output': (self.set_host_output_loopback, True), | ||
'media-side-input': (self.set_media_input_loopback, True), | ||
'media-side-output': (self.set_media_output_loopback, True) | ||
} | ||
|
||
if loopback_mode == 'none': | ||
return all([ | ||
self.set_host_input_loopback(0xff, False), | ||
self.set_host_output_loopback(0xff, False), | ||
self.set_media_input_loopback(0xff, False), | ||
self.set_media_output_loopback(0xff, False) | ||
]) | ||
|
||
if loopback_mode in loopback_functions: | ||
func, enable = loopback_functions[loopback_mode] | ||
return func(lane_mask, enable) | ||
|
||
logger.error('Invalid loopback mode:%s, lane_mask:%#x', loopback_mode, lane_mask) | ||
return False | ||
|
||
def get_vdm(self, field_option=None): | ||
''' | ||
This function returns all the VDM items, including real time monitor value, threholds and flags | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xinyulin As part of clearing the loopback (line 1136-1140), can we make sure that the loopback is cleared only for the lane_mask lanes rather than all lanes?
Also, should we check if the module advertises per lane loopback support and then use
lane_mask
accordingly. This will be helpful to clear loopback on all lanes if per lane loopback is not supported.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
none
mode, we will need to have two lane masks (host_lane_mask
andmedia_lane_mask
for host and media individually) because the host and media lane masks might not be identical (e.g., host_lane_mask = 0x3, media_lane_mask = 0x1).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xinyulin
For
2.
, we can expectloopback_mode
to include the type of loopback to be cleared i.e. havehost-side-input-none
,host-side-output-none
etc. In this case, the caller can pass the lane_mask accordingly.For
3.
, I think we should configure entire physical port and display a message. @prgeor Can you please confirm the expected behavior in this case?For
4.
, Yes, I think it is helpful to log messages in reject cases.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mihirpat1 Thanks for the comments. I've updated it accordingly. Let's check if Prince has any comments on the changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xinyulin I discussed with @prgeor regarding
3.
and concluded to reject the config if per lane loopback is not supported (i.e. we should not configure unrelated lanes when loopback is intended to configure specific lanes).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mihirpat1 Thanks for the confirmation. It has been updated!