-
Notifications
You must be signed in to change notification settings - Fork 206
optoe: Add CMIS Bank support for transceivers with >8 lanes #473
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
base: master
Are you sure you want to change the base?
Changes from all commits
837f305
e3a8551
37eb33b
50d0308
9a42eb0
053afe8
424ec6c
194d44a
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 | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,361 @@ | ||||||
| From baef70561c79d0e34d79bfc011edfbec585e5d24 Mon Sep 17 00:00:00 2001 | ||||||
| From: Wataru Ishida <wataru.ishid@gmail.com> | ||||||
| Date: Sun, 15 Feb 2026 22:34:29 +0900 | ||||||
| Subject: [PATCH] optoe: Add CMIS Bank support for transceivers with >8 lanes | ||||||
|
|
||||||
| This patch adds CMIS Bank support to the 'optoe3' device class in order | ||||||
| to enable access to CMIS transceivers with more than 8 lanes (e.g., OSFP-XD, CPO OEs). | ||||||
|
|
||||||
| - Bank support can be enabled only for the 'optoe3' dev class. | ||||||
| - 'bank_size' sysfs entry is added to enable and configure the size of the bank. | ||||||
| - By default, bank size is set to 0. | ||||||
|
|
||||||
| Signed-off-by: Wataru Ishida <wataru.ishid@gmail.com> | ||||||
|
|
||||||
| --- | ||||||
| drivers/misc/eeprom/optoe.c | 198 +++++++++++++++++++++++++++++++----- | ||||||
| 1 file changed, 171 insertions(+), 27 deletions(-) | ||||||
|
|
||||||
| diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c | ||||||
| index ba4ca17..0d575aa 100644 | ||||||
| --- a/drivers/misc/eeprom/optoe.c | ||||||
| +++ b/drivers/misc/eeprom/optoe.c | ||||||
| @@ -101,9 +101,50 @@ | ||||||
| * considerably more pages (at least to page 0xAF), which this driver | ||||||
| * supports. | ||||||
| * | ||||||
| - * NOTE: This version of the driver ONLY SUPPORTS BANK 0 PAGES on CMIS | ||||||
| - * devices. | ||||||
| + * For CMIS transceivers that support Banked Pages, access to these pages | ||||||
| + * is also supported. To access the banked pages, set the number of banks | ||||||
| + * to access via the `bank_size` sysfs entry. | ||||||
| + * By default, `bank_size` is set to 0, which disables this feature. | ||||||
|
Contributor
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. @ishidawataru We probably don't need this. see my comments above. |
||||||
| * | ||||||
| + * The maximum number of banks supported in this version is 8. | ||||||
| + * | ||||||
| + * When access to the Banked Pages is enabled, they are mapped into a linear | ||||||
| + * address space. The mapping starts right after the Non-Banked Page area, | ||||||
| + * as shown below. | ||||||
| + * | ||||||
| + * Note that support for memory pages varies by device. If the device does not | ||||||
| + * support a requested page, it should overwrite the PageSelect register to 0 and | ||||||
| + * return the data from page 0 following the behavior defined in CMIS 5.3 8.2.15. | ||||||
| + * | ||||||
| + * Since this driver does not validate the PageSelect register value after each | ||||||
| + * write, applications should verify page and bank support through device | ||||||
| + * advertisement registers or the datasheet. | ||||||
| + * | ||||||
| + * +-------------------------------+ | ||||||
| + * | Lower Page | | ||||||
| + * +-------------------------------+ | ||||||
| + * | Upper Page (Bank 0, Page 0h) | | ||||||
| + * +-------------------------------+ | ||||||
| + * | Upper Page (Bank 0, Page 1h) | | ||||||
| + * +-------------------------------+ | ||||||
| + * | ... | | ||||||
| + * +-------------------------------+ | ||||||
| + * | Upper Page (Bank 0, Page FFh) | | ||||||
| + * +-------------------------------+ | ||||||
| + * | Upper Page (Bank 1, Page 0h) | | ||||||
| + * +-------------------------------+ | ||||||
| + * | ... | | ||||||
| + * +-------------------------------+ | ||||||
| + * | Upper Page (Bank 1, Page FFh) | | ||||||
| + * +-------------------------------+ | ||||||
| + * | Upper Page (Bank 2, Page 0h) | | ||||||
| + * +-------------------------------+ | ||||||
| + * | ... | | ||||||
| + * +-------------------------------+ | ||||||
| + * | Upper Page (Bank 2, Page FFh) | | ||||||
| + * +-------------------------------+ | ||||||
| + * | ... | | ||||||
| + * (continued for more banks) | ||||||
| **/ | ||||||
|
|
||||||
| /* #define DEBUG 1 */ | ||||||
| @@ -150,6 +191,17 @@ struct optoe_platform_data { | ||||||
|
|
||||||
| /* fundamental unit of addressing for EEPROM */ | ||||||
| #define OPTOE_PAGE_SIZE 128 | ||||||
| + | ||||||
| +/* | ||||||
| + * By default, banked pages are not supported (bank_size = 0), which limits | ||||||
| + * the maximum linear address space to 256 pages (32KB). When bank_size is | ||||||
| + * greater than 0, the driver supports access to additional banked pages, with | ||||||
| + * the total address space increasing by 256 pages (32KB) for each additional bank. | ||||||
| + * The maximum supported bank size in this version is 8. | ||||||
| + */ | ||||||
| +#define OPTOE_DEFAULT_BANK_SIZE 0 | ||||||
|
Contributor
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. @ishidawataru the default bank is 0, which means modules that support 8 lanes, the bank size = 1?
Contributor
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. @ishidawataru This probably can be removed if we implement full range of linear address for all bank pages. See my comments below |
||||||
| +#define OPTOE_MAX_SUPPORTED_BANK_SIZE 8 | ||||||
| + | ||||||
| /* | ||||||
| * Single address devices (eg QSFP) have 256 pages, plus the unpaged | ||||||
| * low 128 bytes. If the device does not support paging, it is | ||||||
| @@ -168,6 +220,7 @@ struct optoe_platform_data { | ||||||
| #define TWO_ADDR_NO_0X51_SIZE (2 * OPTOE_PAGE_SIZE) | ||||||
|
|
||||||
| /* a few constants to find our way around the EEPROM */ | ||||||
| +#define OPTOE_BANK_SELECT_REG 0x7E | ||||||
| #define OPTOE_PAGE_SELECT_REG 0x7F | ||||||
| #define ONE_ADDR_PAGEABLE_REG 0x02 | ||||||
| #define QSFP_NOT_PAGEABLE (1<<2) | ||||||
| @@ -195,6 +248,13 @@ struct optoe_data { | ||||||
| u8 *writebuf; | ||||||
| unsigned int write_max; | ||||||
| unsigned int write_timeout; | ||||||
| + unsigned int bank_size; /* 0 means bank is not supported */ | ||||||
| + | ||||||
| + /* Indicates if page restore has failed. | ||||||
| + * If true, the driver doesn't skip writing to page select register | ||||||
| + * even for acesses to page 0. | ||||||
|
||||||
| + * even for acesses to page 0. | |
| + * even for accesses to page 0. |
Copilot
AI
Feb 15, 2026
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.
Use C-style comment syntax /* / instead of C++ style //. Kernel code should use C-style comments for inline code comments. The comment should be: / 256 * 128 = 32KB */
| + const size_t bytes_per_bank = OPTOE_ARCH_PAGES * OPTOE_PAGE_SIZE; // 256 * 128 = 32KB | |
| + const size_t bytes_per_bank = OPTOE_ARCH_PAGES * OPTOE_PAGE_SIZE; /* 256 * 128 = 32KB */ |
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.
@ishidawataru The computation does not consider full range of linear address for all banks. Its OK to use all page address for bank 0 i.e Assume that page 0x10, 0x11, 0x12... 0xFF exist for Bank 0 as well.
So that the getaddr() can be implemented as follows:-
def getaddr(self, bank=0, page, offset, page_size=128):
return ((uint32_t)bank * PAGES_PER_BANK + page) * page_size + offset;
In your case you are not wasting the address space for OPTOE_NON_BANKED_PAGE_SIZE but its OK to loose those many address range to keep the use space implementation of getaddr() simple
Here is the simple decoding of the above linear address that optoe needs to do:-
static uint8_t optoe_translate_offset(struct optoe_data *optoe,
loff_t *offset, struct i2c_client **client, uint8_t *bank)
{
unsigned int page = 0;
*bank = *offset / (PAGES_PER_BANK * PAGE_SIZE);
page = ((*offset / PAGE_SIZE) % PAGES_PER_BANK) - 1;
*offset = PAGE_SIZE + linear_address % PAGE_SIZE;
return page;
}
Assumption here is the user application will provide only the valid pages and the module will return IO error if incorrect Page address is selected.
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.
@prgeor This is the linear address map of the current implementation.
Are you suggesting to change it like below?
Returning I/O errors for the grayed-out area will prevent us from using cat on the EEPROM file as shown below.
admin@sonic:~$ hexdump /sys/class/i2c-dev/i2c-1/device/1-0050/eeprom
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
001e880
I suggest keeping the current implementation or returning the value from bank 0, rather than returning I/O errors.
What do you think?
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.
@ishidawataru I am not sure if hexdump will be user friendly to read so many pages across multiple banks for the user to scroll and look for. Alternatively, one can use the userspace tools like sfputil to dump only relavant page from a particular bank.
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.
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.
@ishidawataru would it be good to have the sanity check to validate the bank value to what the module supports? Page 01h, Byte 142
ishidawataru marked this conversation as resolved.
Show resolved
Hide resolved
ishidawataru marked this conversation as resolved.
Show resolved
Hide resolved
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.
If this restore fails, the module's bank/page registers remain pointing to the last accessed bank/page (not reset to 0). If the next write is intended to be for page/bank 0 in optoe_eeprom_update_client, it will skip the optoe_eeprom_write and actually be read from the wrong page/bank. ( due to the if page/bank > 0 check)
If the restore fails, we shouldn't skip the optoe_eeprom_write
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.
fixed by 9a42eb0
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.
@ishidawataru do we need this? What is the usecase? I thought the number of banks is already advertised so the optoe driver can read the advertisement and cache the value? Are you considering a case where the module is swapped?
Copilot
AI
Feb 15, 2026
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.
Use C-style comment syntax /* / instead of C++ style //. Kernel code should use C-style comments for inline code comments. The comment should be: / setting bank size is only supported for the CMIS device */
| + // setting bank size is only supported for the CMIS device | |
| + /* setting bank size is only supported for the CMIS device */ |


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.
It’d be great if you could add a paragraph how to verify/test this to the commit message too.