From ac8340ce62a7b7ea83a59dbd572f881aa588ff13 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Wed, 2 Apr 2025 07:21:31 +0000 Subject: [PATCH 1/9] optoe: Add CMIS Bank support for transceivers with >8 lanes Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 280 ++++++++++++++++++ patches-sonic/series | 1 + 2 files changed, 281 insertions(+) create mode 100644 patches-sonic/driver-support-optoe-bank-support.patch diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch new file mode 100644 index 000000000..b97846e88 --- /dev/null +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -0,0 +1,280 @@ +From b1a63f047615b56c271e6d41e50112045fd6a978 Mon Sep 17 00:00:00 2001 +From: Wataru Ishida +Date: Wed, 2 Apr 2025 07:10:10 +0000 +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. +- When enabling bank by setting a value greater than 1, the 'write_max' value is + automatically updated to 2 to comply with CMIS requirements, + which mandate that both bank and page values be updated in a single WRITE operation. +- If the 'write_max' value is already greater than 2, this module keeps the value as is. + +Signed-off-by: Wataru Ishida +--- + drivers/misc/eeprom/optoe.c | 124 ++++++++++++++++++++++++++++++------ + 1 file changed, 103 insertions(+), 21 deletions(-) + +diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c +index 22d2c0cd4..71bd90204 100644 +--- a/drivers/misc/eeprom/optoe.c ++++ b/drivers/misc/eeprom/optoe.c +@@ -150,6 +150,12 @@ struct optoe_platform_data { + + /* fundamental unit of addressing for EEPROM */ + #define OPTOE_PAGE_SIZE 128 ++ ++#define OPTOE_DEFAULT_BANK_SIZE 0 ++#define OPTOE_MAX_SUPPORTED_BANK_SIZE 8 ++#define OPTOE_NON_BANKED_PAGE_SIZE 16 /* page 00h-0Fh are not banked */ ++#define OPTOE_BANKED_PAGE_SIZE 240 /* page 10h-FFh are banked */ ++ + /* + * 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 +174,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 +202,7 @@ struct optoe_data { + u8 *writebuf; + unsigned int write_max; + unsigned int write_timeout; ++ unsigned int bank_size; /* 0 means bank is not supported */ + + unsigned int num_addresses; + +@@ -245,13 +253,19 @@ static const struct i2c_device_id optoe_ids[] = { + }; + MODULE_DEVICE_TABLE(i2c, optoe_ids); + ++static uint32_t one_addr_eeprom_size_with_bank(uint32_t bank_size) ++{ ++ bank_size = bank_size == 0 ? 1 : bank_size; ++ return (bank_size * OPTOE_BANKED_PAGE_SIZE + OPTOE_NON_BANKED_PAGE_SIZE + 1) * OPTOE_PAGE_SIZE; ++} ++ + /*-------------------------------------------------------------------------*/ + /* + * This routine computes the addressing information to be used for + * a given r/w request. + * + * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), +- * the page, and the offset. ++ * the bank, the page, and the offset. + * + * Handles both single address (eg QSFP) and two address (eg SFP). + * For SFP, offset 0-255 are on client[0], >255 is on client[1] +@@ -274,7 +288,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); + */ + + static uint8_t optoe_translate_offset(struct optoe_data *optoe, +- loff_t *offset, struct i2c_client **client) ++ loff_t *offset, struct i2c_client **client, uint8_t *bank) + { + unsigned int page = 0; + +@@ -301,8 +315,9 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, + page = (*offset >> 7)-1; + /* 0x80 places the offset in the top half, offset is last 7 bits */ + *offset = OPTOE_PAGE_SIZE + (*offset & 0x7f); +- +- return page; /* note also returning client and offset */ ++ *bank = page < OPTOE_PAGE_SIZE ? 0 : (page - OPTOE_NON_BANKED_PAGE_SIZE) / OPTOE_BANKED_PAGE_SIZE; ++ page = page - *bank * OPTOE_BANKED_PAGE_SIZE; ++ return page; /* note also returning client, bank and offset */ + } + + static ssize_t optoe_eeprom_read(struct optoe_data *optoe, +@@ -511,21 +526,38 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, + { + struct i2c_client *client; + ssize_t retval = 0; +- uint8_t page = 0; ++ uint8_t page = 0, bank = 0; + loff_t phy_offset = off; + int ret = 0; + +- page = optoe_translate_offset(optoe, &phy_offset, &client); ++ page = optoe_translate_offset(optoe, &phy_offset, &client, &bank); + dev_dbg(&client->dev, +- "%s off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", +- __func__, off, page, phy_offset, (long int) count, opcode); ++ "%s off %lld bank:%d page:%d phy_offset:%lld, count:%ld, opcode:%d\n", ++ __func__, off, bank, page, phy_offset, (long int) count, opcode); + if (page > 0) { +- ret = optoe_eeprom_write(optoe, client, &page, +- OPTOE_PAGE_SELECT_REG, 1); ++ /* ++ * CMIS 5.3 8.2.15 Page Mapping ++ * ++ * For an arbitrary Page Address change or for just a Bank Index change, ++ * a host must write both BankSelect and PageSelect in one WRITE access, ++ * even if the PageSelect value does not change. ++ * The module does not begin processing the BankSelect value until after the PageSelect register has been written. ++ * ++ * For just a Page Index change (mapping another Page in the current Bank), ++ * or for mapping an arbitrary unbanked Page to Upper Memory, a host may WRITE only the PageSelect Byte. ++ */ ++ if (bank > 0) { ++ char buf[2] = {bank, page}; ++ ret = optoe_eeprom_write(optoe, client, buf, ++ OPTOE_BANK_SELECT_REG, 2); ++ } else { ++ ret = optoe_eeprom_write(optoe, client, &page, ++ OPTOE_PAGE_SELECT_REG, 1); ++ } + if (ret < 0) { + dev_dbg(&client->dev, +- "Write page register for page %d failed ret:%d!\n", +- page, ret); ++ "Write page register for bank %d, page %d failed ret:%d!\n", ++ bank, page, ret); + return ret; + } + } +@@ -553,13 +585,18 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, + + + if (page > 0) { +- /* return the page register to page 0 (why?) */ +- page = 0; +- ret = optoe_eeprom_write(optoe, client, &page, +- OPTOE_PAGE_SELECT_REG, 1); ++ if (bank > 0) { ++ char buf[2] = {0, 0}; ++ ret = optoe_eeprom_write(optoe, client, buf, ++ OPTOE_BANK_SELECT_REG, 2); ++ } else { ++ page = 0; ++ ret = optoe_eeprom_write(optoe, client, &page, ++ OPTOE_PAGE_SELECT_REG, 1); ++ } + if (ret < 0) { + dev_err(&client->dev, +- "Restore page register to 0 failed:%d!\n", ret); ++ "Restore bank, page register to (0, 0) failed:%d!\n", ret); + /* error only if nothing has been transferred */ + if (retval == 0) + retval = ret; +@@ -622,8 +659,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, + /* if no pages needed, we're good */ + if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) + return len; ++ ++ maxlen = one_addr_eeprom_size_with_bank(optoe->bank_size); + /* if offset exceeds possible pages, we're not good */ +- if (off >= ONE_ADDR_EEPROM_SIZE) ++ if (off >= maxlen) + return OPTOE_EOF; + /* in between, are pages supported? */ + status = optoe_eeprom_read(optoe, client, ®val, +@@ -665,7 +704,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, + maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; + } else { + /* Pages supported, trim len to the end of pages */ +- maxlen = ONE_ADDR_EEPROM_SIZE - off; ++ maxlen = maxlen - off; + } + len = (len > maxlen) ? maxlen : len; + dev_dbg(&client->dev, +@@ -995,6 +1034,47 @@ static ssize_t set_port_name(struct device *dev, + return count; + } + ++static ssize_t show_bank_size(struct device *dev, ++ struct device_attribute *dattr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ ssize_t count; ++ ++ mutex_lock(&optoe->lock); ++ count = sprintf(buf, "%u\n", optoe->bank_size); ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ ++static ssize_t set_bank_size(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ unsigned int bank_size; ++ ++ // setting bank size is only supported for the CMIS device ++ if (optoe->dev_class != CMIS_ADDR) { ++ return -EINVAL; ++ } ++ ++ if (kstrtouint(buf, 0, &bank_size) != 0 || ++ bank_size < 0 || bank_size > OPTOE_MAX_SUPPORTED_BANK_SIZE) ++ return -EINVAL; ++ ++ mutex_lock(&optoe->lock); ++ optoe->bank_size = bank_size; ++ if (optoe->bank_size > 0 && optoe->write_max == 1) { ++ optoe->write_max = 2; ++ } ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ + static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); + #endif /* if NOT defined EEPROM_CLASS, the common case */ + +@@ -1003,6 +1083,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, + static DEVICE_ATTR(write_max, 0644, show_dev_write_max_size, + set_dev_write_max_size); + static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); ++static DEVICE_ATTR(bank_size, 0644, show_bank_size, set_bank_size); + + static struct attribute *optoe_attrs[] = { + #ifndef EEPROM_CLASS +@@ -1011,6 +1092,7 @@ static struct attribute *optoe_attrs[] = { + &dev_attr_write_timeout.attr, + &dev_attr_write_max.attr, + &dev_attr_dev_class.attr, ++ &dev_attr_bank_size.attr, + NULL, + }; + +@@ -1027,7 +1109,6 @@ static int optoe_probe(struct i2c_client *client, + struct optoe_data *optoe; + int num_addresses = 0; + char port_name[MAX_PORT_NAME_LEN]; +- + if (client->addr != 0x50) { + dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", + client->addr); +@@ -1108,7 +1189,7 @@ static int optoe_probe(struct i2c_client *client, + } else if (strcmp(client->name, "optoe3") == 0) { + /* CMIS spec */ + optoe->dev_class = CMIS_ADDR; +- chip.byte_len = ONE_ADDR_EEPROM_SIZE; ++ chip.byte_len = one_addr_eeprom_size_with_bank(OPTOE_MAX_SUPPORTED_BANK_SIZE); + num_addresses = 1; + } else { /* those were the only choices */ + err = -EINVAL; +@@ -1120,6 +1201,7 @@ static int optoe_probe(struct i2c_client *client, + optoe->chip = chip; + optoe->num_addresses = num_addresses; + optoe->write_timeout = OPTOE_DEFAULT_WRITE_TIMEOUT; ++ optoe->bank_size = OPTOE_DEFAULT_BANK_SIZE; + memcpy(optoe->port_name, port_name, MAX_PORT_NAME_LEN); + + /* +-- +2.25.1 + diff --git a/patches-sonic/series b/patches-sonic/series index 6aad6c5f0..ab545756e 100644 --- a/patches-sonic/series +++ b/patches-sonic/series @@ -34,6 +34,7 @@ driver-support-optoe-oneaddr-pageable.patch driver-support-optoe-update-to-linux-6.1.patch driver-support-optoe-dynamic-write-timeout.patch driver-support-optoe-update-to-linux-6.10.patch +driver-support-optoe-bank-support.patch driver-net-tg3-add-param-short-preamble-and-reset.patch driver-net-tg3-change-dma-mask-for-57766.patch 0004-dt-bindings-hwmon-Add-missing-documentation-for-lm75.patch From e43e49d280e9c9fa65875c76ad5765e771512d9b Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Tue, 22 Apr 2025 01:25:46 +0000 Subject: [PATCH 2/9] fix(optoe): add explanation for bank page support Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 89 ++++++++++++++----- 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch index b97846e88..377e9dc9a 100644 --- a/patches-sonic/driver-support-optoe-bank-support.patch +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -1,4 +1,4 @@ -From b1a63f047615b56c271e6d41e50112045fd6a978 Mon Sep 17 00:00:00 2001 +From aa39d1af8ae72a7a3f6f5337266d69f720a39086 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Wed, 2 Apr 2025 07:10:10 +0000 Subject: [PATCH] optoe: Add CMIS Bank support for transceivers with >8 lanes @@ -16,18 +16,67 @@ to enable access to CMIS transceivers with more than 8 lanes (e.g., OSFP-XD, CPO Signed-off-by: Wataru Ishida --- - drivers/misc/eeprom/optoe.c | 124 ++++++++++++++++++++++++++++++------ - 1 file changed, 103 insertions(+), 21 deletions(-) + drivers/misc/eeprom/optoe.c | 165 +++++++++++++++++++++++++++++++----- + 1 file changed, 142 insertions(+), 23 deletions(-) diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c -index 22d2c0cd4..71bd90204 100644 +index 22d2c0cd4..a4def4986 100644 --- a/drivers/misc/eeprom/optoe.c +++ b/drivers/misc/eeprom/optoe.c -@@ -150,6 +150,12 @@ struct optoe_platform_data { +@@ -101,9 +101,42 @@ + * 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. + * ++ * 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. ++ * ++ * +-------------------------------+ ++ * | 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 10h) | ++ * +-------------------------------+ ++ * | ... | ++ * +-------------------------------+ ++ * | Upper Page (Bank 1, Page FFh) | ++ * +-------------------------------+ ++ * | Upper Page (Bank 2, Page 10h) | ++ * +-------------------------------+ ++ * | ... | ++ * +-------------------------------+ ++ * | Upper Page (Bank 2, Page FFh) | ++ * +-------------------------------+ ++ * | ... | ++ * (continued for more banks) + **/ + + /* #define DEBUG 1 */ +@@ -150,6 +183,16 @@ struct optoe_platform_data { /* fundamental unit of addressing for EEPROM */ #define OPTOE_PAGE_SIZE 128 + ++/* ++ * ++ * ++ */ +#define OPTOE_DEFAULT_BANK_SIZE 0 +#define OPTOE_MAX_SUPPORTED_BANK_SIZE 8 +#define OPTOE_NON_BANKED_PAGE_SIZE 16 /* page 00h-0Fh are not banked */ @@ -36,7 +85,7 @@ index 22d2c0cd4..71bd90204 100644 /* * 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 +174,7 @@ struct optoe_platform_data { +@@ -168,6 +211,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 */ @@ -44,7 +93,7 @@ index 22d2c0cd4..71bd90204 100644 #define OPTOE_PAGE_SELECT_REG 0x7F #define ONE_ADDR_PAGEABLE_REG 0x02 #define QSFP_NOT_PAGEABLE (1<<2) -@@ -195,6 +202,7 @@ struct optoe_data { +@@ -195,6 +239,7 @@ struct optoe_data { u8 *writebuf; unsigned int write_max; unsigned int write_timeout; @@ -52,7 +101,7 @@ index 22d2c0cd4..71bd90204 100644 unsigned int num_addresses; -@@ -245,13 +253,19 @@ static const struct i2c_device_id optoe_ids[] = { +@@ -245,13 +290,19 @@ static const struct i2c_device_id optoe_ids[] = { }; MODULE_DEVICE_TABLE(i2c, optoe_ids); @@ -73,7 +122,7 @@ index 22d2c0cd4..71bd90204 100644 * * Handles both single address (eg QSFP) and two address (eg SFP). * For SFP, offset 0-255 are on client[0], >255 is on client[1] -@@ -274,7 +288,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); +@@ -274,7 +325,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); */ static uint8_t optoe_translate_offset(struct optoe_data *optoe, @@ -82,7 +131,7 @@ index 22d2c0cd4..71bd90204 100644 { unsigned int page = 0; -@@ -301,8 +315,9 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, +@@ -301,8 +352,9 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, page = (*offset >> 7)-1; /* 0x80 places the offset in the top half, offset is last 7 bits */ *offset = OPTOE_PAGE_SIZE + (*offset & 0x7f); @@ -94,7 +143,7 @@ index 22d2c0cd4..71bd90204 100644 } static ssize_t optoe_eeprom_read(struct optoe_data *optoe, -@@ -511,21 +526,38 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -511,21 +563,38 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, { struct i2c_client *client; ssize_t retval = 0; @@ -141,7 +190,7 @@ index 22d2c0cd4..71bd90204 100644 return ret; } } -@@ -553,13 +585,18 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -553,13 +622,18 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, if (page > 0) { @@ -165,7 +214,7 @@ index 22d2c0cd4..71bd90204 100644 /* error only if nothing has been transferred */ if (retval == 0) retval = ret; -@@ -622,8 +659,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -622,8 +696,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, /* if no pages needed, we're good */ if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) return len; @@ -177,7 +226,7 @@ index 22d2c0cd4..71bd90204 100644 return OPTOE_EOF; /* in between, are pages supported? */ status = optoe_eeprom_read(optoe, client, ®val, -@@ -665,7 +704,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -665,7 +741,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; } else { /* Pages supported, trim len to the end of pages */ @@ -186,7 +235,7 @@ index 22d2c0cd4..71bd90204 100644 } len = (len > maxlen) ? maxlen : len; dev_dbg(&client->dev, -@@ -995,6 +1034,47 @@ static ssize_t set_port_name(struct device *dev, +@@ -995,6 +1071,47 @@ static ssize_t set_port_name(struct device *dev, return count; } @@ -234,7 +283,7 @@ index 22d2c0cd4..71bd90204 100644 static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); #endif /* if NOT defined EEPROM_CLASS, the common case */ -@@ -1003,6 +1083,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, +@@ -1003,6 +1120,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, static DEVICE_ATTR(write_max, 0644, show_dev_write_max_size, set_dev_write_max_size); static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); @@ -242,7 +291,7 @@ index 22d2c0cd4..71bd90204 100644 static struct attribute *optoe_attrs[] = { #ifndef EEPROM_CLASS -@@ -1011,6 +1092,7 @@ static struct attribute *optoe_attrs[] = { +@@ -1011,6 +1129,7 @@ static struct attribute *optoe_attrs[] = { &dev_attr_write_timeout.attr, &dev_attr_write_max.attr, &dev_attr_dev_class.attr, @@ -250,7 +299,7 @@ index 22d2c0cd4..71bd90204 100644 NULL, }; -@@ -1027,7 +1109,6 @@ static int optoe_probe(struct i2c_client *client, +@@ -1027,7 +1146,6 @@ static int optoe_probe(struct i2c_client *client, struct optoe_data *optoe; int num_addresses = 0; char port_name[MAX_PORT_NAME_LEN]; @@ -258,7 +307,7 @@ index 22d2c0cd4..71bd90204 100644 if (client->addr != 0x50) { dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", client->addr); -@@ -1108,7 +1189,7 @@ static int optoe_probe(struct i2c_client *client, +@@ -1108,7 +1226,7 @@ static int optoe_probe(struct i2c_client *client, } else if (strcmp(client->name, "optoe3") == 0) { /* CMIS spec */ optoe->dev_class = CMIS_ADDR; @@ -267,7 +316,7 @@ index 22d2c0cd4..71bd90204 100644 num_addresses = 1; } else { /* those were the only choices */ err = -EINVAL; -@@ -1120,6 +1201,7 @@ static int optoe_probe(struct i2c_client *client, +@@ -1120,6 +1238,7 @@ static int optoe_probe(struct i2c_client *client, optoe->chip = chip; optoe->num_addresses = num_addresses; optoe->write_timeout = OPTOE_DEFAULT_WRITE_TIMEOUT; From a6eb49e7adb5f16479217a7b086aba066e223d8b Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 22:57:37 +0900 Subject: [PATCH 3/9] fix(optoe): rebased onto master Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch index 377e9dc9a..c4bb586da 100644 --- a/patches-sonic/driver-support-optoe-bank-support.patch +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -1,6 +1,6 @@ -From aa39d1af8ae72a7a3f6f5337266d69f720a39086 Mon Sep 17 00:00:00 2001 +From 6088f7f169e0676a0184e73991f2d0f925763f71 Mon Sep 17 00:00:00 2001 From: Wataru Ishida -Date: Wed, 2 Apr 2025 07:10:10 +0000 +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 @@ -9,18 +9,15 @@ to enable access to CMIS transceivers with more than 8 lanes (e.g., OSFP-XD, CPO - 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. -- When enabling bank by setting a value greater than 1, the 'write_max' value is - automatically updated to 2 to comply with CMIS requirements, - which mandate that both bank and page values be updated in a single WRITE operation. -- If the 'write_max' value is already greater than 2, this module keeps the value as is. Signed-off-by: Wataru Ishida ---- + +-- drivers/misc/eeprom/optoe.c | 165 +++++++++++++++++++++++++++++++----- 1 file changed, 142 insertions(+), 23 deletions(-) diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c -index 22d2c0cd4..a4def4986 100644 +index ba4ca17..087b093 100644 --- a/drivers/misc/eeprom/optoe.c +++ b/drivers/misc/eeprom/optoe.c @@ -101,9 +101,42 @@ @@ -74,7 +71,7 @@ index 22d2c0cd4..a4def4986 100644 #define OPTOE_PAGE_SIZE 128 + +/* -+ * ++ * + * + */ +#define OPTOE_DEFAULT_BANK_SIZE 0 @@ -299,15 +296,15 @@ index 22d2c0cd4..a4def4986 100644 NULL, }; -@@ -1027,7 +1146,6 @@ static int optoe_probe(struct i2c_client *client, - struct optoe_data *optoe; +@@ -1027,7 +1146,6 @@ static int optoe_probe(struct i2c_client *client) + const struct i2c_device_id *id; int num_addresses = 0; char port_name[MAX_PORT_NAME_LEN]; - if (client->addr != 0x50) { dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", client->addr); -@@ -1108,7 +1226,7 @@ static int optoe_probe(struct i2c_client *client, +@@ -1109,7 +1227,7 @@ static int optoe_probe(struct i2c_client *client) } else if (strcmp(client->name, "optoe3") == 0) { /* CMIS spec */ optoe->dev_class = CMIS_ADDR; @@ -316,7 +313,7 @@ index 22d2c0cd4..a4def4986 100644 num_addresses = 1; } else { /* those were the only choices */ err = -EINVAL; -@@ -1120,6 +1238,7 @@ static int optoe_probe(struct i2c_client *client, +@@ -1121,6 +1239,7 @@ static int optoe_probe(struct i2c_client *client) optoe->chip = chip; optoe->num_addresses = num_addresses; optoe->write_timeout = OPTOE_DEFAULT_WRITE_TIMEOUT; From c8d1fc0b8b8aeebaac7475bbe16b97a097e6adab Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 23:00:05 +0900 Subject: [PATCH 4/9] fix(optoe): update the mapping of banked pages as suggested Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 81 ++++++++++++------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch index c4bb586da..66e2c23fe 100644 --- a/patches-sonic/driver-support-optoe-bank-support.patch +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -1,4 +1,4 @@ -From 6088f7f169e0676a0184e73991f2d0f925763f71 Mon Sep 17 00:00:00 2001 +From c11b89d58982c2561212f9659d9761399460263a Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 22:34:29 +0900 Subject: [PATCH] optoe: Add CMIS Bank support for transceivers with >8 lanes @@ -12,15 +12,15 @@ to enable access to CMIS transceivers with more than 8 lanes (e.g., OSFP-XD, CPO Signed-off-by: Wataru Ishida --- - drivers/misc/eeprom/optoe.c | 165 +++++++++++++++++++++++++++++++----- - 1 file changed, 142 insertions(+), 23 deletions(-) +--- + drivers/misc/eeprom/optoe.c | 183 +++++++++++++++++++++++++++++++----- + 1 file changed, 157 insertions(+), 26 deletions(-) diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c -index ba4ca17..087b093 100644 +index ba4ca17..97bde31 100644 --- a/drivers/misc/eeprom/optoe.c +++ b/drivers/misc/eeprom/optoe.c -@@ -101,9 +101,42 @@ +@@ -101,9 +101,50 @@ * considerably more pages (at least to page 0xAF), which this driver * supports. * @@ -37,6 +37,14 @@ index ba4ca17..087b093 100644 + * 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 | + * +-------------------------------+ @@ -48,13 +56,13 @@ index ba4ca17..087b093 100644 + * +-------------------------------+ + * | Upper Page (Bank 0, Page FFh) | + * +-------------------------------+ -+ * | Upper Page (Bank 1, Page 10h) | ++ * | Upper Page (Bank 1, Page 0h) | + * +-------------------------------+ + * | ... | + * +-------------------------------+ + * | Upper Page (Bank 1, Page FFh) | + * +-------------------------------+ -+ * | Upper Page (Bank 2, Page 10h) | ++ * | Upper Page (Bank 2, Page 0h) | + * +-------------------------------+ + * | ... | + * +-------------------------------+ @@ -65,7 +73,7 @@ index ba4ca17..087b093 100644 **/ /* #define DEBUG 1 */ -@@ -150,6 +183,16 @@ struct optoe_platform_data { +@@ -150,6 +191,16 @@ struct optoe_platform_data { /* fundamental unit of addressing for EEPROM */ #define OPTOE_PAGE_SIZE 128 @@ -82,7 +90,7 @@ index ba4ca17..087b093 100644 /* * 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 +211,7 @@ struct optoe_platform_data { +@@ -168,6 +219,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 */ @@ -90,7 +98,7 @@ index ba4ca17..087b093 100644 #define OPTOE_PAGE_SELECT_REG 0x7F #define ONE_ADDR_PAGEABLE_REG 0x02 #define QSFP_NOT_PAGEABLE (1<<2) -@@ -195,6 +239,7 @@ struct optoe_data { +@@ -195,6 +247,7 @@ struct optoe_data { u8 *writebuf; unsigned int write_max; unsigned int write_timeout; @@ -98,14 +106,14 @@ index ba4ca17..087b093 100644 unsigned int num_addresses; -@@ -245,13 +290,19 @@ static const struct i2c_device_id optoe_ids[] = { +@@ -245,13 +298,19 @@ static const struct i2c_device_id optoe_ids[] = { }; MODULE_DEVICE_TABLE(i2c, optoe_ids); +static uint32_t one_addr_eeprom_size_with_bank(uint32_t bank_size) +{ + bank_size = bank_size == 0 ? 1 : bank_size; -+ return (bank_size * OPTOE_BANKED_PAGE_SIZE + OPTOE_NON_BANKED_PAGE_SIZE + 1) * OPTOE_PAGE_SIZE; ++ return (bank_size * OPTOE_ARCH_PAGES + 1) * OPTOE_PAGE_SIZE; +} + /*-------------------------------------------------------------------------*/ @@ -119,7 +127,7 @@ index ba4ca17..087b093 100644 * * Handles both single address (eg QSFP) and two address (eg SFP). * For SFP, offset 0-255 are on client[0], >255 is on client[1] -@@ -274,7 +325,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); +@@ -274,7 +333,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); */ static uint8_t optoe_translate_offset(struct optoe_data *optoe, @@ -128,19 +136,30 @@ index ba4ca17..087b093 100644 { unsigned int page = 0; -@@ -301,8 +352,9 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, - page = (*offset >> 7)-1; - /* 0x80 places the offset in the top half, offset is last 7 bits */ - *offset = OPTOE_PAGE_SIZE + (*offset & 0x7f); -- +@@ -297,12 +356,17 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, + if (*offset < OPTOE_PAGE_SIZE) + return page; + +- /* note, page will always be positive since *offset >= 128 */ +- page = (*offset >> 7)-1; +- /* 0x80 places the offset in the top half, offset is last 7 bits */ +- *offset = OPTOE_PAGE_SIZE + (*offset & 0x7f); ++ /* ++ * Calculate bank, page, and physical offset for paged EEPROM access. ++ * Memory layout: multiple banks, each containing 256 pages of 128 bytes. ++ */ ++ loff_t offset_in_paged_area = *offset - OPTOE_PAGE_SIZE; ++ const size_t bytes_per_bank = OPTOE_ARCH_PAGES * OPTOE_PAGE_SIZE; // 256 * 128 = 32KB ++ *bank = offset_in_paged_area / bytes_per_bank; ++ page = (offset_in_paged_area / OPTOE_PAGE_SIZE) % OPTOE_ARCH_PAGES; ++ *offset = OPTOE_PAGE_SIZE + (offset_in_paged_area % OPTOE_PAGE_SIZE); + - return page; /* note also returning client and offset */ -+ *bank = page < OPTOE_PAGE_SIZE ? 0 : (page - OPTOE_NON_BANKED_PAGE_SIZE) / OPTOE_BANKED_PAGE_SIZE; -+ page = page - *bank * OPTOE_BANKED_PAGE_SIZE; + return page; /* note also returning client, bank and offset */ } static ssize_t optoe_eeprom_read(struct optoe_data *optoe, -@@ -511,21 +563,38 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -511,21 +575,38 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, { struct i2c_client *client; ssize_t retval = 0; @@ -187,7 +206,7 @@ index ba4ca17..087b093 100644 return ret; } } -@@ -553,13 +622,18 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -553,13 +634,18 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, if (page > 0) { @@ -211,7 +230,7 @@ index ba4ca17..087b093 100644 /* error only if nothing has been transferred */ if (retval == 0) retval = ret; -@@ -622,8 +696,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -622,8 +708,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, /* if no pages needed, we're good */ if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) return len; @@ -223,7 +242,7 @@ index ba4ca17..087b093 100644 return OPTOE_EOF; /* in between, are pages supported? */ status = optoe_eeprom_read(optoe, client, ®val, -@@ -665,7 +741,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -665,7 +753,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; } else { /* Pages supported, trim len to the end of pages */ @@ -232,7 +251,7 @@ index ba4ca17..087b093 100644 } len = (len > maxlen) ? maxlen : len; dev_dbg(&client->dev, -@@ -995,6 +1071,47 @@ static ssize_t set_port_name(struct device *dev, +@@ -995,6 +1083,47 @@ static ssize_t set_port_name(struct device *dev, return count; } @@ -280,7 +299,7 @@ index ba4ca17..087b093 100644 static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); #endif /* if NOT defined EEPROM_CLASS, the common case */ -@@ -1003,6 +1120,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, +@@ -1003,6 +1132,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, static DEVICE_ATTR(write_max, 0644, show_dev_write_max_size, set_dev_write_max_size); static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); @@ -288,7 +307,7 @@ index ba4ca17..087b093 100644 static struct attribute *optoe_attrs[] = { #ifndef EEPROM_CLASS -@@ -1011,6 +1129,7 @@ static struct attribute *optoe_attrs[] = { +@@ -1011,6 +1141,7 @@ static struct attribute *optoe_attrs[] = { &dev_attr_write_timeout.attr, &dev_attr_write_max.attr, &dev_attr_dev_class.attr, @@ -296,7 +315,7 @@ index ba4ca17..087b093 100644 NULL, }; -@@ -1027,7 +1146,6 @@ static int optoe_probe(struct i2c_client *client) +@@ -1027,7 +1158,6 @@ static int optoe_probe(struct i2c_client *client) const struct i2c_device_id *id; int num_addresses = 0; char port_name[MAX_PORT_NAME_LEN]; @@ -304,7 +323,7 @@ index ba4ca17..087b093 100644 if (client->addr != 0x50) { dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", client->addr); -@@ -1109,7 +1227,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1109,7 +1239,7 @@ static int optoe_probe(struct i2c_client *client) } else if (strcmp(client->name, "optoe3") == 0) { /* CMIS spec */ optoe->dev_class = CMIS_ADDR; @@ -313,7 +332,7 @@ index ba4ca17..087b093 100644 num_addresses = 1; } else { /* those were the only choices */ err = -EINVAL; -@@ -1121,6 +1239,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1121,6 +1251,7 @@ static int optoe_probe(struct i2c_client *client) optoe->chip = chip; optoe->num_addresses = num_addresses; optoe->write_timeout = OPTOE_DEFAULT_WRITE_TIMEOUT; From 4f9d28da9a0b222a373b5166e75dbc276a64de66 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 23:02:03 +0900 Subject: [PATCH 5/9] fix(optoe): don't skip page selection when page restore is failed Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch index 66e2c23fe..f4c49d540 100644 --- a/patches-sonic/driver-support-optoe-bank-support.patch +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -1,4 +1,4 @@ -From c11b89d58982c2561212f9659d9761399460263a Mon Sep 17 00:00:00 2001 +From 526a41f1fc717ddb6cfd600c899254d582735523 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 22:34:29 +0900 Subject: [PATCH] optoe: Add CMIS Bank support for transceivers with >8 lanes @@ -13,11 +13,11 @@ to enable access to CMIS transceivers with more than 8 lanes (e.g., OSFP-XD, CPO Signed-off-by: Wataru Ishida --- - drivers/misc/eeprom/optoe.c | 183 +++++++++++++++++++++++++++++++----- - 1 file changed, 157 insertions(+), 26 deletions(-) + drivers/misc/eeprom/optoe.c | 194 +++++++++++++++++++++++++++++++----- + 1 file changed, 167 insertions(+), 27 deletions(-) diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c -index ba4ca17..97bde31 100644 +index ba4ca17..8ba71ef 100644 --- a/drivers/misc/eeprom/optoe.c +++ b/drivers/misc/eeprom/optoe.c @@ -101,9 +101,50 @@ @@ -98,15 +98,21 @@ index ba4ca17..97bde31 100644 #define OPTOE_PAGE_SELECT_REG 0x7F #define ONE_ADDR_PAGEABLE_REG 0x02 #define QSFP_NOT_PAGEABLE (1<<2) -@@ -195,6 +247,7 @@ struct optoe_data { +@@ -195,6 +247,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. ++ */ ++ bool page_restore_failed; unsigned int num_addresses; -@@ -245,13 +298,19 @@ static const struct i2c_device_id optoe_ids[] = { +@@ -245,13 +304,19 @@ static const struct i2c_device_id optoe_ids[] = { }; MODULE_DEVICE_TABLE(i2c, optoe_ids); @@ -127,7 +133,7 @@ index ba4ca17..97bde31 100644 * * Handles both single address (eg QSFP) and two address (eg SFP). * For SFP, offset 0-255 are on client[0], >255 is on client[1] -@@ -274,7 +333,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); +@@ -274,7 +339,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); */ static uint8_t optoe_translate_offset(struct optoe_data *optoe, @@ -136,7 +142,7 @@ index ba4ca17..97bde31 100644 { unsigned int page = 0; -@@ -297,12 +356,17 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, +@@ -297,12 +362,17 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, if (*offset < OPTOE_PAGE_SIZE) return page; @@ -159,7 +165,7 @@ index ba4ca17..97bde31 100644 } static ssize_t optoe_eeprom_read(struct optoe_data *optoe, -@@ -511,21 +575,38 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -511,23 +581,41 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, { struct i2c_client *client; ssize_t retval = 0; @@ -173,11 +179,12 @@ index ba4ca17..97bde31 100644 dev_dbg(&client->dev, - "%s off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - __func__, off, page, phy_offset, (long int) count, opcode); -+ "%s off %lld bank:%d page:%d phy_offset:%lld, count:%ld, opcode:%d\n", -+ __func__, off, bank, page, phy_offset, (long int) count, opcode); - if (page > 0) { +- if (page > 0) { - ret = optoe_eeprom_write(optoe, client, &page, - OPTOE_PAGE_SELECT_REG, 1); ++ "%s off %lld bank:%d page:%d phy_offset:%lld, count:%ld, opcode:%d\n", ++ __func__, off, bank, page, phy_offset, (long int) count, opcode); ++ if (optoe->page_restore_failed || page > 0) { + /* + * CMIS 5.3 8.2.15 Page Mapping + * @@ -205,8 +212,11 @@ index ba4ca17..97bde31 100644 + bank, page, ret); return ret; } ++ optoe->page_restore_failed = false; } -@@ -553,13 +634,18 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, + + while (count) { +@@ -553,13 +641,20 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, if (page > 0) { @@ -227,10 +237,12 @@ index ba4ca17..97bde31 100644 dev_err(&client->dev, - "Restore page register to 0 failed:%d!\n", ret); + "Restore bank, page register to (0, 0) failed:%d!\n", ret); ++ optoe->page_restore_failed = true; ++ /* error only if nothing has been transferred */ if (retval == 0) retval = ret; -@@ -622,8 +708,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -622,8 +717,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, /* if no pages needed, we're good */ if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) return len; @@ -242,7 +254,7 @@ index ba4ca17..97bde31 100644 return OPTOE_EOF; /* in between, are pages supported? */ status = optoe_eeprom_read(optoe, client, ®val, -@@ -665,7 +753,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -665,7 +762,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; } else { /* Pages supported, trim len to the end of pages */ @@ -251,7 +263,7 @@ index ba4ca17..97bde31 100644 } len = (len > maxlen) ? maxlen : len; dev_dbg(&client->dev, -@@ -995,6 +1083,47 @@ static ssize_t set_port_name(struct device *dev, +@@ -995,6 +1092,47 @@ static ssize_t set_port_name(struct device *dev, return count; } @@ -299,7 +311,7 @@ index ba4ca17..97bde31 100644 static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); #endif /* if NOT defined EEPROM_CLASS, the common case */ -@@ -1003,6 +1132,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, +@@ -1003,6 +1141,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, static DEVICE_ATTR(write_max, 0644, show_dev_write_max_size, set_dev_write_max_size); static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); @@ -307,7 +319,7 @@ index ba4ca17..97bde31 100644 static struct attribute *optoe_attrs[] = { #ifndef EEPROM_CLASS -@@ -1011,6 +1141,7 @@ static struct attribute *optoe_attrs[] = { +@@ -1011,6 +1150,7 @@ static struct attribute *optoe_attrs[] = { &dev_attr_write_timeout.attr, &dev_attr_write_max.attr, &dev_attr_dev_class.attr, @@ -315,7 +327,7 @@ index ba4ca17..97bde31 100644 NULL, }; -@@ -1027,7 +1158,6 @@ static int optoe_probe(struct i2c_client *client) +@@ -1027,7 +1167,6 @@ static int optoe_probe(struct i2c_client *client) const struct i2c_device_id *id; int num_addresses = 0; char port_name[MAX_PORT_NAME_LEN]; @@ -323,7 +335,7 @@ index ba4ca17..97bde31 100644 if (client->addr != 0x50) { dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", client->addr); -@@ -1109,7 +1239,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1109,7 +1248,7 @@ static int optoe_probe(struct i2c_client *client) } else if (strcmp(client->name, "optoe3") == 0) { /* CMIS spec */ optoe->dev_class = CMIS_ADDR; @@ -332,7 +344,7 @@ index ba4ca17..97bde31 100644 num_addresses = 1; } else { /* those were the only choices */ err = -EINVAL; -@@ -1121,6 +1251,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1121,6 +1260,7 @@ static int optoe_probe(struct i2c_client *client) optoe->chip = chip; optoe->num_addresses = num_addresses; optoe->write_timeout = OPTOE_DEFAULT_WRITE_TIMEOUT; From 0dafa0bad1955eb63c00abcbb7b8ff666c820760 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 23:03:22 +0900 Subject: [PATCH 6/9] fix(optoe): ensure page and bank select is written in one WRITE access Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch index f4c49d540..8f0ac9c48 100644 --- a/patches-sonic/driver-support-optoe-bank-support.patch +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -1,4 +1,4 @@ -From 526a41f1fc717ddb6cfd600c899254d582735523 Mon Sep 17 00:00:00 2001 +From 0020c4e2164d6b645ce571dc20137266c195012f Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 22:34:29 +0900 Subject: [PATCH] optoe: Add CMIS Bank support for transceivers with >8 lanes @@ -13,11 +13,11 @@ to enable access to CMIS transceivers with more than 8 lanes (e.g., OSFP-XD, CPO Signed-off-by: Wataru Ishida --- - drivers/misc/eeprom/optoe.c | 194 +++++++++++++++++++++++++++++++----- - 1 file changed, 167 insertions(+), 27 deletions(-) + drivers/misc/eeprom/optoe.c | 197 +++++++++++++++++++++++++++++++----- + 1 file changed, 170 insertions(+), 27 deletions(-) diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c -index ba4ca17..8ba71ef 100644 +index ba4ca17..14b60d9 100644 --- a/drivers/misc/eeprom/optoe.c +++ b/drivers/misc/eeprom/optoe.c @@ -101,9 +101,50 @@ @@ -165,7 +165,7 @@ index ba4ca17..8ba71ef 100644 } static ssize_t optoe_eeprom_read(struct optoe_data *optoe, -@@ -511,23 +581,41 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -511,23 +581,44 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, { struct i2c_client *client; ssize_t retval = 0; @@ -198,8 +198,11 @@ index ba4ca17..8ba71ef 100644 + */ + if (bank > 0) { + char buf[2] = {bank, page}; ++ unsigned int write_max_orig = optoe->write_max; ++ optoe->write_max = 2; /* ensure both bank and page are written together */ + ret = optoe_eeprom_write(optoe, client, buf, + OPTOE_BANK_SELECT_REG, 2); ++ optoe->write_max = write_max_orig; + } else { + ret = optoe_eeprom_write(optoe, client, &page, + OPTOE_PAGE_SELECT_REG, 1); @@ -216,7 +219,7 @@ index ba4ca17..8ba71ef 100644 } while (count) { -@@ -553,13 +641,20 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -553,13 +644,23 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, if (page > 0) { @@ -226,8 +229,11 @@ index ba4ca17..8ba71ef 100644 - OPTOE_PAGE_SELECT_REG, 1); + if (bank > 0) { + char buf[2] = {0, 0}; ++ unsigned int write_max_orig = optoe->write_max; ++ optoe->write_max = 2; /* ensure both bank and page are written together */ + ret = optoe_eeprom_write(optoe, client, buf, + OPTOE_BANK_SELECT_REG, 2); ++ optoe->write_max = write_max_orig; + } else { + page = 0; + ret = optoe_eeprom_write(optoe, client, &page, @@ -242,7 +248,7 @@ index ba4ca17..8ba71ef 100644 /* error only if nothing has been transferred */ if (retval == 0) retval = ret; -@@ -622,8 +717,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -622,8 +723,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, /* if no pages needed, we're good */ if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) return len; @@ -254,7 +260,7 @@ index ba4ca17..8ba71ef 100644 return OPTOE_EOF; /* in between, are pages supported? */ status = optoe_eeprom_read(optoe, client, ®val, -@@ -665,7 +762,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -665,7 +768,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; } else { /* Pages supported, trim len to the end of pages */ @@ -263,7 +269,7 @@ index ba4ca17..8ba71ef 100644 } len = (len > maxlen) ? maxlen : len; dev_dbg(&client->dev, -@@ -995,6 +1092,47 @@ static ssize_t set_port_name(struct device *dev, +@@ -995,6 +1098,44 @@ static ssize_t set_port_name(struct device *dev, return count; } @@ -300,9 +306,6 @@ index ba4ca17..8ba71ef 100644 + + mutex_lock(&optoe->lock); + optoe->bank_size = bank_size; -+ if (optoe->bank_size > 0 && optoe->write_max == 1) { -+ optoe->write_max = 2; -+ } + mutex_unlock(&optoe->lock); + + return count; @@ -311,7 +314,7 @@ index ba4ca17..8ba71ef 100644 static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); #endif /* if NOT defined EEPROM_CLASS, the common case */ -@@ -1003,6 +1141,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, +@@ -1003,6 +1144,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, static DEVICE_ATTR(write_max, 0644, show_dev_write_max_size, set_dev_write_max_size); static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); @@ -319,7 +322,7 @@ index ba4ca17..8ba71ef 100644 static struct attribute *optoe_attrs[] = { #ifndef EEPROM_CLASS -@@ -1011,6 +1150,7 @@ static struct attribute *optoe_attrs[] = { +@@ -1011,6 +1153,7 @@ static struct attribute *optoe_attrs[] = { &dev_attr_write_timeout.attr, &dev_attr_write_max.attr, &dev_attr_dev_class.attr, @@ -327,7 +330,7 @@ index ba4ca17..8ba71ef 100644 NULL, }; -@@ -1027,7 +1167,6 @@ static int optoe_probe(struct i2c_client *client) +@@ -1027,7 +1170,6 @@ static int optoe_probe(struct i2c_client *client) const struct i2c_device_id *id; int num_addresses = 0; char port_name[MAX_PORT_NAME_LEN]; @@ -335,7 +338,7 @@ index ba4ca17..8ba71ef 100644 if (client->addr != 0x50) { dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", client->addr); -@@ -1109,7 +1248,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1109,7 +1251,7 @@ static int optoe_probe(struct i2c_client *client) } else if (strcmp(client->name, "optoe3") == 0) { /* CMIS spec */ optoe->dev_class = CMIS_ADDR; @@ -344,7 +347,7 @@ index ba4ca17..8ba71ef 100644 num_addresses = 1; } else { /* those were the only choices */ err = -EINVAL; -@@ -1121,6 +1260,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1121,6 +1263,7 @@ static int optoe_probe(struct i2c_client *client) optoe->chip = chip; optoe->num_addresses = num_addresses; optoe->write_timeout = OPTOE_DEFAULT_WRITE_TIMEOUT; From 49e67a997bcb40818574f71f137b49fad575a1d1 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 23:52:08 +0900 Subject: [PATCH 7/9] fix(optoe): remove unused constant and redundant value check Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch index 8f0ac9c48..d55749655 100644 --- a/patches-sonic/driver-support-optoe-bank-support.patch +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -1,4 +1,4 @@ -From 0020c4e2164d6b645ce571dc20137266c195012f Mon Sep 17 00:00:00 2001 +From 4973f14cf8ff39f5c5091b3ebf3ca907a3b256c9 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 22:34:29 +0900 Subject: [PATCH] optoe: Add CMIS Bank support for transceivers with >8 lanes @@ -13,11 +13,11 @@ to enable access to CMIS transceivers with more than 8 lanes (e.g., OSFP-XD, CPO Signed-off-by: Wataru Ishida --- - drivers/misc/eeprom/optoe.c | 197 +++++++++++++++++++++++++++++++----- - 1 file changed, 170 insertions(+), 27 deletions(-) + drivers/misc/eeprom/optoe.c | 195 +++++++++++++++++++++++++++++++----- + 1 file changed, 168 insertions(+), 27 deletions(-) diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c -index ba4ca17..14b60d9 100644 +index ba4ca17..42dd27c 100644 --- a/drivers/misc/eeprom/optoe.c +++ b/drivers/misc/eeprom/optoe.c @@ -101,9 +101,50 @@ @@ -73,7 +73,7 @@ index ba4ca17..14b60d9 100644 **/ /* #define DEBUG 1 */ -@@ -150,6 +191,16 @@ struct optoe_platform_data { +@@ -150,6 +191,14 @@ struct optoe_platform_data { /* fundamental unit of addressing for EEPROM */ #define OPTOE_PAGE_SIZE 128 @@ -84,13 +84,11 @@ index ba4ca17..14b60d9 100644 + */ +#define OPTOE_DEFAULT_BANK_SIZE 0 +#define OPTOE_MAX_SUPPORTED_BANK_SIZE 8 -+#define OPTOE_NON_BANKED_PAGE_SIZE 16 /* page 00h-0Fh are not banked */ -+#define OPTOE_BANKED_PAGE_SIZE 240 /* page 10h-FFh are banked */ + /* * 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 +219,7 @@ struct optoe_platform_data { +@@ -168,6 +217,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 */ @@ -98,7 +96,7 @@ index ba4ca17..14b60d9 100644 #define OPTOE_PAGE_SELECT_REG 0x7F #define ONE_ADDR_PAGEABLE_REG 0x02 #define QSFP_NOT_PAGEABLE (1<<2) -@@ -195,6 +247,13 @@ struct optoe_data { +@@ -195,6 +245,13 @@ struct optoe_data { u8 *writebuf; unsigned int write_max; unsigned int write_timeout; @@ -112,7 +110,7 @@ index ba4ca17..14b60d9 100644 unsigned int num_addresses; -@@ -245,13 +304,19 @@ static const struct i2c_device_id optoe_ids[] = { +@@ -245,13 +302,19 @@ static const struct i2c_device_id optoe_ids[] = { }; MODULE_DEVICE_TABLE(i2c, optoe_ids); @@ -133,7 +131,7 @@ index ba4ca17..14b60d9 100644 * * Handles both single address (eg QSFP) and two address (eg SFP). * For SFP, offset 0-255 are on client[0], >255 is on client[1] -@@ -274,7 +339,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); +@@ -274,7 +337,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); */ static uint8_t optoe_translate_offset(struct optoe_data *optoe, @@ -142,7 +140,7 @@ index ba4ca17..14b60d9 100644 { unsigned int page = 0; -@@ -297,12 +362,17 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, +@@ -297,12 +360,17 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, if (*offset < OPTOE_PAGE_SIZE) return page; @@ -165,7 +163,7 @@ index ba4ca17..14b60d9 100644 } static ssize_t optoe_eeprom_read(struct optoe_data *optoe, -@@ -511,23 +581,44 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -511,23 +579,44 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, { struct i2c_client *client; ssize_t retval = 0; @@ -219,7 +217,7 @@ index ba4ca17..14b60d9 100644 } while (count) { -@@ -553,13 +644,23 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -553,13 +642,23 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, if (page > 0) { @@ -248,7 +246,7 @@ index ba4ca17..14b60d9 100644 /* error only if nothing has been transferred */ if (retval == 0) retval = ret; -@@ -622,8 +723,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -622,8 +721,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, /* if no pages needed, we're good */ if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) return len; @@ -260,7 +258,7 @@ index ba4ca17..14b60d9 100644 return OPTOE_EOF; /* in between, are pages supported? */ status = optoe_eeprom_read(optoe, client, ®val, -@@ -665,7 +768,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -665,7 +766,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; } else { /* Pages supported, trim len to the end of pages */ @@ -269,7 +267,7 @@ index ba4ca17..14b60d9 100644 } len = (len > maxlen) ? maxlen : len; dev_dbg(&client->dev, -@@ -995,6 +1098,44 @@ static ssize_t set_port_name(struct device *dev, +@@ -995,6 +1096,44 @@ static ssize_t set_port_name(struct device *dev, return count; } @@ -301,7 +299,7 @@ index ba4ca17..14b60d9 100644 + } + + if (kstrtouint(buf, 0, &bank_size) != 0 || -+ bank_size < 0 || bank_size > OPTOE_MAX_SUPPORTED_BANK_SIZE) ++ bank_size > OPTOE_MAX_SUPPORTED_BANK_SIZE) + return -EINVAL; + + mutex_lock(&optoe->lock); @@ -314,7 +312,7 @@ index ba4ca17..14b60d9 100644 static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); #endif /* if NOT defined EEPROM_CLASS, the common case */ -@@ -1003,6 +1144,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, +@@ -1003,6 +1142,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, static DEVICE_ATTR(write_max, 0644, show_dev_write_max_size, set_dev_write_max_size); static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); @@ -322,7 +320,7 @@ index ba4ca17..14b60d9 100644 static struct attribute *optoe_attrs[] = { #ifndef EEPROM_CLASS -@@ -1011,6 +1153,7 @@ static struct attribute *optoe_attrs[] = { +@@ -1011,6 +1151,7 @@ static struct attribute *optoe_attrs[] = { &dev_attr_write_timeout.attr, &dev_attr_write_max.attr, &dev_attr_dev_class.attr, @@ -330,7 +328,7 @@ index ba4ca17..14b60d9 100644 NULL, }; -@@ -1027,7 +1170,6 @@ static int optoe_probe(struct i2c_client *client) +@@ -1027,7 +1168,6 @@ static int optoe_probe(struct i2c_client *client) const struct i2c_device_id *id; int num_addresses = 0; char port_name[MAX_PORT_NAME_LEN]; @@ -338,7 +336,7 @@ index ba4ca17..14b60d9 100644 if (client->addr != 0x50) { dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", client->addr); -@@ -1109,7 +1251,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1109,7 +1249,7 @@ static int optoe_probe(struct i2c_client *client) } else if (strcmp(client->name, "optoe3") == 0) { /* CMIS spec */ optoe->dev_class = CMIS_ADDR; @@ -347,7 +345,7 @@ index ba4ca17..14b60d9 100644 num_addresses = 1; } else { /* those were the only choices */ err = -EINVAL; -@@ -1121,6 +1263,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1121,6 +1261,7 @@ static int optoe_probe(struct i2c_client *client) optoe->chip = chip; optoe->num_addresses = num_addresses; optoe->write_timeout = OPTOE_DEFAULT_WRITE_TIMEOUT; From 85d8fe04a0fd9a8267b8cad2b40e3270c737ed90 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Mon, 16 Feb 2026 00:01:45 +0900 Subject: [PATCH 8/9] fix(optoe): add missing comments to bank related constants Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch index d55749655..565935940 100644 --- a/patches-sonic/driver-support-optoe-bank-support.patch +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -1,4 +1,4 @@ -From 4973f14cf8ff39f5c5091b3ebf3ca907a3b256c9 Mon Sep 17 00:00:00 2001 +From baef70561c79d0e34d79bfc011edfbec585e5d24 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sun, 15 Feb 2026 22:34:29 +0900 Subject: [PATCH] optoe: Add CMIS Bank support for transceivers with >8 lanes @@ -13,11 +13,11 @@ to enable access to CMIS transceivers with more than 8 lanes (e.g., OSFP-XD, CPO Signed-off-by: Wataru Ishida --- - drivers/misc/eeprom/optoe.c | 195 +++++++++++++++++++++++++++++++----- - 1 file changed, 168 insertions(+), 27 deletions(-) + 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..42dd27c 100644 +index ba4ca17..0d575aa 100644 --- a/drivers/misc/eeprom/optoe.c +++ b/drivers/misc/eeprom/optoe.c @@ -101,9 +101,50 @@ @@ -73,14 +73,17 @@ index ba4ca17..42dd27c 100644 **/ /* #define DEBUG 1 */ -@@ -150,6 +191,14 @@ struct optoe_platform_data { +@@ -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 +#define OPTOE_MAX_SUPPORTED_BANK_SIZE 8 @@ -88,7 +91,7 @@ index ba4ca17..42dd27c 100644 /* * 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 +217,7 @@ struct optoe_platform_data { +@@ -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 */ @@ -96,7 +99,7 @@ index ba4ca17..42dd27c 100644 #define OPTOE_PAGE_SELECT_REG 0x7F #define ONE_ADDR_PAGEABLE_REG 0x02 #define QSFP_NOT_PAGEABLE (1<<2) -@@ -195,6 +245,13 @@ struct optoe_data { +@@ -195,6 +248,13 @@ struct optoe_data { u8 *writebuf; unsigned int write_max; unsigned int write_timeout; @@ -110,7 +113,7 @@ index ba4ca17..42dd27c 100644 unsigned int num_addresses; -@@ -245,13 +302,19 @@ static const struct i2c_device_id optoe_ids[] = { +@@ -245,13 +305,19 @@ static const struct i2c_device_id optoe_ids[] = { }; MODULE_DEVICE_TABLE(i2c, optoe_ids); @@ -131,7 +134,7 @@ index ba4ca17..42dd27c 100644 * * Handles both single address (eg QSFP) and two address (eg SFP). * For SFP, offset 0-255 are on client[0], >255 is on client[1] -@@ -274,7 +337,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); +@@ -274,7 +340,7 @@ MODULE_DEVICE_TABLE(i2c, optoe_ids); */ static uint8_t optoe_translate_offset(struct optoe_data *optoe, @@ -140,7 +143,7 @@ index ba4ca17..42dd27c 100644 { unsigned int page = 0; -@@ -297,12 +360,17 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, +@@ -297,12 +363,17 @@ static uint8_t optoe_translate_offset(struct optoe_data *optoe, if (*offset < OPTOE_PAGE_SIZE) return page; @@ -163,7 +166,7 @@ index ba4ca17..42dd27c 100644 } static ssize_t optoe_eeprom_read(struct optoe_data *optoe, -@@ -511,23 +579,44 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -511,23 +582,44 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, { struct i2c_client *client; ssize_t retval = 0; @@ -217,7 +220,7 @@ index ba4ca17..42dd27c 100644 } while (count) { -@@ -553,13 +642,23 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, +@@ -553,13 +645,23 @@ static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, if (page > 0) { @@ -246,7 +249,7 @@ index ba4ca17..42dd27c 100644 /* error only if nothing has been transferred */ if (retval == 0) retval = ret; -@@ -622,8 +721,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -622,8 +724,10 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, /* if no pages needed, we're good */ if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) return len; @@ -258,7 +261,7 @@ index ba4ca17..42dd27c 100644 return OPTOE_EOF; /* in between, are pages supported? */ status = optoe_eeprom_read(optoe, client, ®val, -@@ -665,7 +766,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, +@@ -665,7 +769,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe, maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; } else { /* Pages supported, trim len to the end of pages */ @@ -267,7 +270,7 @@ index ba4ca17..42dd27c 100644 } len = (len > maxlen) ? maxlen : len; dev_dbg(&client->dev, -@@ -995,6 +1096,44 @@ static ssize_t set_port_name(struct device *dev, +@@ -995,6 +1099,44 @@ static ssize_t set_port_name(struct device *dev, return count; } @@ -312,7 +315,7 @@ index ba4ca17..42dd27c 100644 static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); #endif /* if NOT defined EEPROM_CLASS, the common case */ -@@ -1003,6 +1142,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, +@@ -1003,6 +1145,7 @@ static DEVICE_ATTR(write_timeout, 0644, show_dev_write_timeout_size, static DEVICE_ATTR(write_max, 0644, show_dev_write_max_size, set_dev_write_max_size); static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); @@ -320,7 +323,7 @@ index ba4ca17..42dd27c 100644 static struct attribute *optoe_attrs[] = { #ifndef EEPROM_CLASS -@@ -1011,6 +1151,7 @@ static struct attribute *optoe_attrs[] = { +@@ -1011,6 +1154,7 @@ static struct attribute *optoe_attrs[] = { &dev_attr_write_timeout.attr, &dev_attr_write_max.attr, &dev_attr_dev_class.attr, @@ -328,7 +331,7 @@ index ba4ca17..42dd27c 100644 NULL, }; -@@ -1027,7 +1168,6 @@ static int optoe_probe(struct i2c_client *client) +@@ -1027,7 +1171,6 @@ static int optoe_probe(struct i2c_client *client) const struct i2c_device_id *id; int num_addresses = 0; char port_name[MAX_PORT_NAME_LEN]; @@ -336,7 +339,7 @@ index ba4ca17..42dd27c 100644 if (client->addr != 0x50) { dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", client->addr); -@@ -1109,7 +1249,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1109,7 +1252,7 @@ static int optoe_probe(struct i2c_client *client) } else if (strcmp(client->name, "optoe3") == 0) { /* CMIS spec */ optoe->dev_class = CMIS_ADDR; @@ -345,7 +348,7 @@ index ba4ca17..42dd27c 100644 num_addresses = 1; } else { /* those were the only choices */ err = -EINVAL; -@@ -1121,6 +1261,7 @@ static int optoe_probe(struct i2c_client *client) +@@ -1121,6 +1264,7 @@ static int optoe_probe(struct i2c_client *client) optoe->chip = chip; optoe->num_addresses = num_addresses; optoe->write_timeout = OPTOE_DEFAULT_WRITE_TIMEOUT; From 6af9b8efe58a84f84dd9ada68007182dd8d4774a Mon Sep 17 00:00:00 2001 From: Prince George <45705344+prgeor@users.noreply.github.com> Date: Wed, 22 Apr 2026 20:52:11 -0700 Subject: [PATCH 9/9] fix(optoe): apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Wataru Ishida --- .../driver-support-optoe-bank-support.patch | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/patches-sonic/driver-support-optoe-bank-support.patch b/patches-sonic/driver-support-optoe-bank-support.patch index 565935940..41ff5f019 100644 --- a/patches-sonic/driver-support-optoe-bank-support.patch +++ b/patches-sonic/driver-support-optoe-bank-support.patch @@ -107,7 +107,7 @@ index ba4ca17..0d575aa 100644 + + /* 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 accesses to page 0. + */ + bool page_restore_failed; @@ -296,7 +296,7 @@ index ba4ca17..0d575aa 100644 + struct optoe_data *optoe = i2c_get_clientdata(client); + unsigned int bank_size; + -+ // setting bank size is only supported for the CMIS device ++ /* setting bank size is only supported for the CMIS device */ + if (optoe->dev_class != CMIS_ADDR) { + return -EINVAL; + } @@ -331,14 +331,6 @@ index ba4ca17..0d575aa 100644 NULL, }; -@@ -1027,7 +1171,6 @@ static int optoe_probe(struct i2c_client *client) - const struct i2c_device_id *id; - int num_addresses = 0; - char port_name[MAX_PORT_NAME_LEN]; -- - if (client->addr != 0x50) { - dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", - client->addr); @@ -1109,7 +1252,7 @@ static int optoe_probe(struct i2c_client *client) } else if (strcmp(client->name, "optoe3") == 0) { /* CMIS spec */