Skip to content

Commit

Permalink
Update optoe driver to add CMIS (QSFP-DD, OSFP, ...) support (#96)
Browse files Browse the repository at this point in the history
* Update to optoe driver to improve EOF handling

	Added patch: 'driver-support-optoe-EOF_fix.patch' to patch directory
	Added the patch to 'series

Signed-off-by: Don Bollinger

* Patch to add support for CMIS (QSFP-DD, OSFP, ...) class devices
to optoe driver.  Backward compatible, still supports SFP*, QSFP*
  • Loading branch information
donboll authored and lguohan committed Aug 8, 2019
1 parent 1d9c69f commit 15f8651
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
149 changes: 149 additions & 0 deletions patch/driver-support-optoe-QSFP_DD.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
From 3e212b8886a21fad8df621992b00b6bd1f5a7f16 Mon Sep 17 00:00:00 2001
From: Don Bollinger <don@thebollingers.org>
Date: Sat, 3 Aug 2019 12:06:05 -0700
Subject: [PATCH] drivers/misc/eeprom: Support QSFP-DD (CMIS) type
devices

Add support for CMIS devices (QSFP-DD, OSFP, etc) to optoe driver
Backward compatible, still supports SFP* and QSFP* devices
Note: CMIS devices are 'optoe3' (SFP remain optoe2, QSFP optoe1)

Signed-off-by: Don Bollinger <don@thebollingers.org>
---
drivers/misc/eeprom/optoe.c | 61 +++++++++++++++++++++++++++++++++++++----
1 file changed, 56 insertions(+), 5 deletions(-)

diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c
index c22b92a..16287fd 100644
--- a/drivers/misc/eeprom/optoe.c
+++ b/drivers/misc/eeprom/optoe.c
@@ -97,6 +97,13 @@
* In anticipation of future applications and devices, this driver
* supports access to the full architected range, 256 pages.
*
+ * The CMIS (Common Management Interface Specification) defines use of
+ * 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.
+ *
**/

/* #define DEBUG 1 */
@@ -163,7 +170,8 @@ struct optoe_platform_data {
/* a few constants to find our way around the EEPROM */
#define OPTOE_PAGE_SELECT_REG 0x7F
#define ONE_ADDR_PAGEABLE_REG 0x02
-#define ONE_ADDR_NOT_PAGEABLE (1<<2)
+#define QSFP_NOT_PAGEABLE (1<<2)
+#define CMIS_NOT_PAGEABLE (1<<7)
#define TWO_ADDR_PAGEABLE_REG 0x40
#define TWO_ADDR_PAGEABLE (1<<4)
#define TWO_ADDR_0X51_REG 92
@@ -225,10 +233,12 @@ static unsigned int write_timeout = 25;
*/
#define ONE_ADDR 1
#define TWO_ADDR 2
+#define CMIS_ADDR 3

static const struct i2c_device_id optoe_ids[] = {
{ "optoe1", ONE_ADDR },
{ "optoe2", TWO_ADDR },
+ { "optoe3", CMIS_ADDR },
{ "sff8436", ONE_ADDR },
{ "24c04", TWO_ADDR },
{ /* END OF LIST */ }
@@ -575,6 +585,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe,
{
struct i2c_client *client = optoe->client[0];
u8 regval;
+ int not_pageable;
int status;
size_t maxlen;

@@ -622,7 +633,7 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe,
"page_legal, SFP, off %lld len %ld\n",
off, (long int) len);
} else {
- /* QSFP case */
+ /* QSFP case, CMIS case */
/* if no pages needed, we're good */
if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE)
return len;
@@ -634,7 +645,17 @@ static ssize_t optoe_page_legal(struct optoe_data *optoe,
ONE_ADDR_PAGEABLE_REG, 1);
if (status < 0)
return status; /* error out (no module?) */
- if (regval & ONE_ADDR_NOT_PAGEABLE) {
+
+ if (optoe->dev_class == ONE_ADDR) {
+ not_pageable = QSFP_NOT_PAGEABLE;
+ } else {
+ not_pageable = CMIS_NOT_PAGEABLE;
+ }
+ dev_dbg(&client->dev,
+ "Paging Register: 0x%x; not_pageable mask: 0x%x\n",
+ regval, not_pageable);
+
+ if (regval & not_pageable) {
/* pages not supported, trim len to unpaged size */
if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE)
return OPTOE_EOF;
@@ -826,13 +847,37 @@ static ssize_t set_dev_class(struct device *dev,
/*
* dev_class is actually the number of i2c addresses used, thus
* legal values are "1" (QSFP class) and "2" (SFP class)
+ * And... CMIS spec is 1 i2c address, but puts the pageable
+ * bit in a different location, so CMIS devices are "3"
*/

if (kstrtoint(buf, 0, &dev_class) != 0 ||
- dev_class < 1 || dev_class > 2)
+ dev_class < 1 || dev_class > 3)
return -EINVAL;

mutex_lock(&optoe->lock);
+ if (dev_class == TWO_ADDR) {
+ /* SFP family */
+ /* if it doesn't exist, create 0x51 i2c address */
+ if (!optoe->client[1]) {
+ optoe->client[1] = i2c_new_dummy(client->adapter, 0x51);
+ if (!optoe->client[1]) {
+ dev_err(&client->dev,
+ "address 0x51 unavailable\n");
+ mutex_unlock(&optoe->lock);
+ return -EADDRINUSE;
+ }
+ }
+ optoe->bin.size = TWO_ADDR_EEPROM_SIZE;
+ optoe->num_addresses = 2;
+ } else {
+ /* one-address (eg QSFP) and CMIS family */
+ /* if it exists, remove 0x51 i2c address */
+ if (optoe->client[1])
+ i2c_unregister_device(optoe->client[1]);
+ optoe->bin.size = ONE_ADDR_EEPROM_SIZE;
+ optoe->num_addresses = 1;
+ }
optoe->dev_class = dev_class;
mutex_unlock(&optoe->lock);

@@ -983,7 +1028,13 @@ static int optoe_probe(struct i2c_client *client,
/* SFP family */
optoe->dev_class = TWO_ADDR;
chip.byte_len = TWO_ADDR_EEPROM_SIZE;
- } else { /* those were the only two choices */
+ num_addresses = 2;
+ } else if (strcmp(client->name, "optoe3") == 0) {
+ /* CMIS spec */
+ optoe->dev_class = CMIS_ADDR;
+ chip.byte_len = ONE_ADDR_EEPROM_SIZE;
+ num_addresses = 1;
+ } else { /* those were the only choices */
err = -EINVAL;
goto exit;
}
--
2.16.2

1 change: 1 addition & 0 deletions patch/series
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ driver-support-tun-config-carrier-enable.patch
driver-support-optoe.patch
driver-support-optoe-EOF_fix.patch
driver-support-optoe-chunk-offset-fix.patch
driver-support-optoe-QSFP_DD.patch
bridge-add-per-port-broadcast-flood-flag.patch
driver-net-tg3-add-param-short-preamble-and-reset.patch
config-dell-s6000.patch
Expand Down

0 comments on commit 15f8651

Please sign in to comment.