diff --git a/patch/driver-support-optoe.patch b/patch/driver-support-optoe.patch new file mode 100644 index 000000000..e87e99e2d --- /dev/null +++ b/patch/driver-support-optoe.patch @@ -0,0 +1,1202 @@ +From 280cea4bd2b98b15382a730a3697f95994544381 Mon Sep 17 00:00:00 2001 + +From: Don Bollinger + +Subject: [PATCH] drivers/misc/eeprom: Add optoe driver (SFP/QSFP EEPROM + Read/Write) + +* Add the optoe driver, copied from github.com/opencomputeproject/oom +* Update Makefile to build optoe +* Update Kconfig to configure optoe + +Signed-off-by: Don Bollinger +--- + debian/build/build_amd64_none_amd64/.config | 1 + drivers/misc/eeprom/Kconfig | 18 + drivers/misc/eeprom/Makefile | 1 + drivers/misc/eeprom/optoe.c | 1126 +++++++++++++++++++++++++++ + 4 files changed, 1146 insertions(+) + create mode 100644 drivers/misc/eeprom/optoe.c + +diff --git a/debian/build/build_amd64_none_amd64/.config b/debian/build/build_amd64_none_amd64/.config +index ae681ac..6bd2b13 100644 +--- a/debian/build/build_amd64_none_amd64/.config ++++ b/debian/build/build_amd64_none_amd64/.config +@@ -1787,6 +1787,7 @@ CONFIG_EEPROM_MAX6875=m + CONFIG_EEPROM_93CX6=m + # CONFIG_EEPROM_93XX46 is not set + CONFIG_EEPROM_SFF_8436=m ++CONFIG_EEPROM_OPTOE=m + CONFIG_CB710_CORE=m + # CONFIG_CB710_DEBUG is not set + CONFIG_CB710_DEBUG_ASSUMPTIONS=y +diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig +index 484e3e1..33e4030 100644 +--- a/drivers/misc/eeprom/Kconfig ++++ b/drivers/misc/eeprom/Kconfig +@@ -108,6 +108,24 @@ config EEPROM_SFF_8436 + This driver can also be built as a module. If so, the module + will be called sff_8436. + ++config EEPROM_OPTOE ++ tristate "read/write access to SFP* & QSFP* EEPROMs" ++ depends on I2C && SYSFS ++ help ++ If you say yes here you get support for read and write access to ++ the EEPROM of SFP and QSFP type optical and copper transceivers. ++ Includes all devices which conform to the sff-8436 and sff-8472 ++ spec including SFP, SFP+, SFP28, SFP-DWDM, QSFP, QSFP+, QSFP28 ++ or later. These devices are usually found in network switches. ++ ++ This driver only manages read/write access to the EEPROM, all ++ other features should be accessed via i2c-dev. ++ ++ This driver can also be built as a module. If so, the module ++ will be called optoe. ++ ++ If unsure, say N. ++ + config EEPROM_SUNXI_SID + tristate "Allwinner sunxi security ID support" + depends on ARCH_SUNXI && SYSFS +diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile +index 235b5cc..2a95beb 100644 +--- a/drivers/misc/eeprom/Makefile ++++ b/drivers/misc/eeprom/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o + obj-$(CONFIG_EEPROM_SUNXI_SID) += sunxi_sid.o + obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o + obj-$(CONFIG_EEPROM_SFF_8436) += sff_8436_eeprom.o ++obj-$(CONFIG_EEPROM_OPTOE) += optoe.o +diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c +new file mode 100644 +index 0000000..7425bf6 +--- /dev/null ++++ b/drivers/misc/eeprom/optoe.c +@@ -0,0 +1,1126 @@ ++/* ++ * optoe.c - A driver to read and write the EEPROM on optical transceivers ++ * (SFP, QSFP and similar I2C based devices) ++ * ++ * Copyright (C) 2014 Cumulus networks Inc. ++ * Copyright (C) 2017 Finisar Corp. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Freeoftware Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++/* ++ * Description: ++ * a) Optical transceiver EEPROM read/write transactions are just like ++ * the at24 eeproms managed by the at24.c i2c driver ++ * b) The register/memory layout is up to 256 128 byte pages defined by ++ * a "pages valid" register and switched via a "page select" ++ * register as explained in below diagram. ++ * c) 256 bytes are mapped at a time. 'Lower page 00h' is the first 128 ++ * bytes of address space, and always references the same ++ * location, independent of the page select register. ++ * All mapped pages are mapped into the upper 128 bytes ++ * (offset 128-255) of the i2c address. ++ * d) Devices with one I2C address (eg QSFP) use I2C address 0x50 ++ * (A0h in the spec), and map all pages in the upper 128 bytes ++ * of that address. ++ * e) Devices with two I2C addresses (eg SFP) have 256 bytes of data ++ * at I2C address 0x50, and 256 bytes of data at I2C address ++ * 0x51 (A2h in the spec). Page selection and paged access ++ * only apply to this second I2C address (0x51). ++ * e) The address space is presented, by the driver, as a linear ++ * address space. For devices with one I2C client at address ++ * 0x50 (eg QSFP), offset 0-127 are in the lower ++ * half of address 50/A0h/client[0]. Offset 128-255 are in ++ * page 0, 256-383 are page 1, etc. More generally, offset ++ * 'n' resides in page (n/128)-1. ('page -1' is the lower ++ * half, offset 0-127). ++ * f) For devices with two I2C clients at address 0x50 and 0x51 (eg SFP), ++ * the address space places offset 0-127 in the lower ++ * half of 50/A0/client[0], offset 128-255 in the upper ++ * half. Offset 256-383 is in the lower half of 51/A2/client[1]. ++ * Offset 384-511 is in page 0, in the upper half of 51/A2/... ++ * Offset 512-639 is in page 1, in the upper half of 51/A2/... ++ * Offset 'n' is in page (n/128)-3 (for n > 383) ++ * ++ * One I2c addressed (eg QSFP) Memory Map ++ * ++ * 2-Wire Serial Address: 1010000x ++ * ++ * Lower Page 00h (128 bytes) ++ * ===================== ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * |Page Select Byte(127)| ++ * ===================== ++ * | ++ * | ++ * | ++ * | ++ * V ++ * ------------------------------------------------------------ ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * V V V V ++ * ------------ -------------- --------------- -------------- ++ * | | | | | | | | ++ * | Upper | | Upper | | Upper | | Upper | ++ * | Page 00h | | Page 01h | | Page 02h | | Page 03h | ++ * | | | (Optional) | | (Optional) | | (Optional | ++ * | | | | | | | for Cable | ++ * | | | | | | | Assemblies) | ++ * | ID | | AST | | User | | | ++ * | Fields | | Table | | EEPROM Data | | | ++ * | | | | | | | | ++ * | | | | | | | | ++ * | | | | | | | | ++ * ------------ -------------- --------------- -------------- ++ * ++ * The SFF 8436 (QSFP) spec only defines the 4 pages described above. ++ * In anticipation of future applications and devices, this driver ++ * supports access to the full architected range, 256 pages. ++ * ++ **/ ++ ++/* #define DEBUG 1 */ ++ ++#undef EEPROM_CLASS ++#ifdef CONFIG_EEPROM_CLASS ++#define EEPROM_CLASS ++#endif ++#ifdef CONFIG_EEPROM_CLASS_MODULE ++#define EEPROM_CLASS ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef EEPROM_CLASS ++#include ++#endif ++ ++#include ++ ++/* The maximum length of a port name */ ++#define MAX_PORT_NAME_LEN 20 ++ ++struct optoe_platform_data { ++ u32 byte_len; /* size (sum of all addr) */ ++ u16 page_size; /* for writes */ ++ u8 flags; ++ void *dummy1; /* backward compatibility */ ++ void *dummy2; /* backward compatibility */ ++ ++#ifdef EEPROM_CLASS ++ struct eeprom_platform_data *eeprom_data; ++#endif ++ char port_name[MAX_PORT_NAME_LEN]; ++}; ++ ++/* fundamental unit of addressing for EEPROM */ ++#define OPTOE_PAGE_SIZE 128 ++/* ++ * Single address devices (eg QSFP) have 256 pages, plus the unpaged ++ * low 128 bytes. If the device does not support paging, it is ++ * only 2 'pages' long. ++ */ ++#define OPTOE_ARCH_PAGES 256 ++#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) ++#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE) ++/* ++ * Dual address devices (eg SFP) have 256 pages, plus the unpaged ++ * low 128 bytes, plus 256 bytes at 0x50. If the device does not ++ * support paging, it is 4 'pages' long. ++ */ ++#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) ++#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE) ++ ++/* 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 TWO_ADDR_PAGEABLE_REG 0x40 ++#define TWO_ADDR_PAGEABLE (1<<4) ++#define OPTOE_ID_REG 0 ++#define OPTOE_READ_OP 0 ++#define OPTOE_WRITE_OP 1 ++ ++struct optoe_data { ++ struct optoe_platform_data chip; ++ int use_smbus; ++ char port_name[MAX_PORT_NAME_LEN]; ++ ++ /* ++ * Lock protects against activities from other Linux tasks, ++ * but not from changes by other I2C masters. ++ */ ++ struct mutex lock; ++ struct bin_attribute bin; ++ struct attribute_group attr_group; ++ ++ u8 *writebuf; ++ unsigned int write_max; ++ ++ unsigned int num_addresses; ++ ++#ifdef EEPROM_CLASS ++ struct eeprom_device *eeprom_dev; ++#endif ++ ++ /* dev_class: ONE_ADDR (QSFP) or TWO_ADDR (SFP) */ ++ int dev_class; ++ ++ struct i2c_client *client[]; ++}; ++ ++ ++/* ++ * This parameter is to help this driver avoid blocking other drivers out ++ * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C ++ * clock, one 256 byte read takes about 1/43 second which is excessive; ++ * but the 1/170 second it takes at 400 kHz may be quite reasonable; and ++ * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. ++ * ++ * This value is forced to be a power of two so that writes align on pages. ++ */ ++static unsigned int io_limit = OPTOE_PAGE_SIZE; ++ ++/* ++ * specs often allow 5 msec for a page write, sometimes 20 msec; ++ * it's important to recover from write timeouts. ++ */ ++static unsigned int write_timeout = 25; ++ ++/* ++ * flags to distinguish one-address (QSFP family) from two-address (SFP family) ++ * If the family is not known, figure it out when the device is accessed ++ */ ++#define ONE_ADDR 1 ++#define TWO_ADDR 2 ++ ++static const struct i2c_device_id optoe_ids[] = { ++ { "optoe1", ONE_ADDR }, ++ { "optoe2", TWO_ADDR }, ++ { "sff8436", ONE_ADDR }, ++ { "24c04", TWO_ADDR }, ++ { /* END OF LIST */ } ++}; ++MODULE_DEVICE_TABLE(i2c, optoe_ids); ++ ++/*-------------------------------------------------------------------------*/ ++/* ++ * 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. ++ * ++ * 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] ++ * Offset 256-383 are on the lower half of client[1] ++ * Pages are accessible on the upper half of client[1]. ++ * Offset >383 are in 128 byte pages mapped into the upper half ++ * ++ * For QSFP, all offsets are on client[0] ++ * offset 0-127 are on the lower half of client[0] (no paging) ++ * Pages are accessible on the upper half of client[1]. ++ * Offset >127 are in 128 byte pages mapped into the upper half ++ * ++ * Callers must not read/write beyond the end of a client or a page ++ * without recomputing the client/page. Hence offset (within page) ++ * plus length must be less than or equal to 128. (Note that this ++ * routine does not have access to the length of the call, hence ++ * cannot do the validity check.) ++ * ++ * Offset within Lower Page 00h and Upper Page 00h are not recomputed ++ */ ++ ++static uint8_t optoe_translate_offset(struct optoe_data *optoe, ++ loff_t *offset, struct i2c_client **client) ++{ ++ unsigned int page = 0; ++ ++ *client = optoe->client[0]; ++ ++ /* if SFP style, offset > 255, shift to i2c addr 0x51 */ ++ if (optoe->dev_class == TWO_ADDR) { ++ if (*offset > 255) { ++ /* like QSFP, but shifted to client[1] */ ++ *client = optoe->client[1]; ++ *offset -= 256; ++ } ++ } ++ ++ /* ++ * if offset is in the range 0-128... ++ * page doesn't matter (using lower half), return 0. ++ * offset is already correct (don't add 128 to get to paged area) ++ */ ++ 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); ++ ++ return page; /* note also returning client and offset */ ++} ++ ++static ssize_t optoe_eeprom_read(struct optoe_data *optoe, ++ struct i2c_client *client, ++ char *buf, unsigned int offset, size_t count) ++{ ++ struct i2c_msg msg[2]; ++ u8 msgbuf[2]; ++ unsigned long timeout, read_time; ++ int status, i; ++ ++ memset(msg, 0, sizeof(msg)); ++ ++ switch (optoe->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /*smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* ++ * When we have a better choice than SMBus calls, use a ++ * combined I2C message. Write address; then read up to ++ * io_limit data bytes. msgbuf is u8 and will cast to our ++ * needs. ++ */ ++ i = 0; ++ msgbuf[i++] = offset; ++ ++ msg[0].addr = client->addr; ++ msg[0].buf = msgbuf; ++ msg[0].len = i; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = buf; ++ msg[1].len = count; ++ } ++ ++ /* ++ * Reads fail if the previous write didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ read_time = jiffies; ++ ++ switch (optoe->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_read_i2c_block_data(client, offset, ++ count, buf); ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ status = i2c_smbus_read_word_data(client, offset); ++ if (status >= 0) { ++ buf[0] = status & 0xff; ++ if (count == 2) ++ buf[1] = status >> 8; ++ status = count; ++ } ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_read_byte_data(client, offset); ++ if (status >= 0) { ++ buf[0] = status; ++ status = count; ++ } ++ break; ++ default: ++ status = i2c_transfer(client->adapter, msg, 2); ++ if (status == 2) ++ status = count; ++ } ++ ++ dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", ++ count, offset, status, jiffies); ++ ++ if (status == count) /* happy path */ ++ return count; ++ ++ if (status == -ENXIO) /* no module present */ ++ return status; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ usleep_range(1000, 2000); ++ } while (time_before(read_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static ssize_t optoe_eeprom_write(struct optoe_data *optoe, ++ struct i2c_client *client, ++ const char *buf, ++ unsigned int offset, size_t count) ++{ ++ struct i2c_msg msg; ++ ssize_t status; ++ unsigned long timeout, write_time; ++ unsigned int next_page_start; ++ int i = 0; ++ ++ /* write max is at most a page ++ * (In this driver, write_max is actually one byte!) ++ */ ++ if (count > optoe->write_max) ++ count = optoe->write_max; ++ ++ /* shorten count if necessary to avoid crossing page boundary */ ++ next_page_start = roundup(offset + 1, OPTOE_PAGE_SIZE); ++ if (offset + count > next_page_start) ++ count = next_page_start - offset; ++ ++ switch (optoe->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /*smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* If we'll use I2C calls for I/O, set up the message */ ++ msg.addr = client->addr; ++ msg.flags = 0; ++ ++ /* msg.buf is u8 and casts will mask the values */ ++ msg.buf = optoe->writebuf; ++ ++ msg.buf[i++] = offset; ++ memcpy(&msg.buf[i], buf, count); ++ msg.len = i + count; ++ break; ++ } ++ ++ /* ++ * Reads fail if the previous write didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ write_time = jiffies; ++ ++ switch (optoe->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_write_i2c_block_data(client, ++ offset, count, buf); ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ if (count == 2) { ++ status = i2c_smbus_write_word_data(client, ++ offset, (u16)((buf[0])|(buf[1] << 8))); ++ } else { ++ /* count = 1 */ ++ status = i2c_smbus_write_byte_data(client, ++ offset, buf[0]); ++ } ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_write_byte_data(client, offset, ++ buf[0]); ++ if (status == 0) ++ status = count; ++ break; ++ default: ++ status = i2c_transfer(client->adapter, &msg, 1); ++ if (status == 1) ++ status = count; ++ break; ++ } ++ ++ dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", ++ count, offset, (long int) status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ usleep_range(1000, 2000); ++ } while (time_before(write_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++ ++static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, ++ char *buf, loff_t off, ++ size_t count, int opcode) ++{ ++ struct i2c_client *client; ++ ssize_t retval = 0; ++ uint8_t page = 0; ++ loff_t phy_offset = off; ++ int ret = 0; ++ ++ page = optoe_translate_offset(optoe, &phy_offset, &client); ++ 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); ++ if (page > 0) { ++ 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); ++ return ret; ++ } ++ } ++ ++ while (count) { ++ ssize_t status; ++ ++ if (opcode == OPTOE_READ_OP) { ++ status = optoe_eeprom_read(optoe, client, ++ buf, phy_offset, count); ++ } else { ++ status = optoe_eeprom_write(optoe, client, ++ buf, phy_offset, count); ++ } ++ if (status <= 0) { ++ if (retval == 0) ++ retval = status; ++ break; ++ } ++ buf += status; ++ phy_offset += status; ++ count -= status; ++ retval += status; ++ } ++ ++ ++ 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 (ret < 0) { ++ dev_err(&client->dev, ++ "Restore page register to 0 failed:%d!\n", ret); ++ /* error only if nothing has been transferred */ ++ if (retval == 0) ++ retval = ret; ++ } ++ } ++ return retval; ++} ++ ++/* ++ * Figure out if this access is within the range of supported pages. ++ * Note this is called on every access because we don't know if the ++ * module has been replaced since the last call. ++ * If/when modules support more pages, this is the routine to update ++ * to validate and allow access to additional pages. ++ * ++ * Returns updated len for this access: ++ * - entire access is legal, original len is returned. ++ * - access begins legal but is too long, len is truncated to fit. ++ * - initial offset exceeds supported pages, return -EINVAL ++ */ ++static ssize_t optoe_page_legal(struct optoe_data *optoe, ++ loff_t off, size_t len) ++{ ++ struct i2c_client *client = optoe->client[0]; ++ u8 regval; ++ int status; ++ size_t maxlen; ++ ++ if (off < 0) ++ return -EINVAL; ++ if (optoe->dev_class == TWO_ADDR) { ++ /* SFP case */ ++ /* if no pages needed, we're good */ ++ if ((off + len) <= TWO_ADDR_EEPROM_UNPAGED_SIZE) ++ return len; ++ /* if offset exceeds possible pages, we're not good */ ++ if (off >= TWO_ADDR_EEPROM_SIZE) ++ return -EINVAL; ++ /* in between, are pages supported? */ ++ status = optoe_eeprom_read(optoe, client, ®val, ++ TWO_ADDR_PAGEABLE_REG, 1); ++ if (status < 0) ++ return status; /* error out (no module?) */ ++ if (regval & TWO_ADDR_PAGEABLE) { ++ /* Pages supported, trim len to the end of pages */ ++ maxlen = TWO_ADDR_EEPROM_SIZE - off; ++ } else { ++ /* pages not supported, trim len to unpaged size */ ++ if (off >= TWO_ADDR_EEPROM_UNPAGED_SIZE) ++ return -EINVAL; ++ maxlen = TWO_ADDR_EEPROM_UNPAGED_SIZE - off; ++ } ++ len = (len > maxlen) ? maxlen : len; ++ dev_dbg(&client->dev, ++ "page_legal, SFP, off %lld len %ld\n", ++ off, (long int) len); ++ } else { ++ /* QSFP case */ ++ /* if no pages needed, we're good */ ++ if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) ++ return len; ++ /* if offset exceeds possible pages, we're not good */ ++ if (off >= ONE_ADDR_EEPROM_SIZE) ++ return -EINVAL; ++ /* in between, are pages supported? */ ++ status = optoe_eeprom_read(optoe, client, ®val, ++ ONE_ADDR_PAGEABLE_REG, 1); ++ if (status < 0) ++ return status; /* error out (no module?) */ ++ if (regval & ONE_ADDR_NOT_PAGEABLE) { ++ /* pages not supported, trim len to unpaged size */ ++ if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE) ++ return -EINVAL; ++ maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; ++ } else { ++ /* Pages supported, trim len to the end of pages */ ++ maxlen = ONE_ADDR_EEPROM_SIZE - off; ++ } ++ len = (len > maxlen) ? maxlen : len; ++ dev_dbg(&client->dev, ++ "page_legal, QSFP, off %lld len %ld\n", ++ off, (long int) len); ++ } ++ return len; ++} ++ ++static ssize_t optoe_read_write(struct optoe_data *optoe, ++ char *buf, loff_t off, size_t len, int opcode) ++{ ++ struct i2c_client *client = optoe->client[0]; ++ int chunk; ++ int status = 0; ++ ssize_t retval; ++ size_t pending_len = 0, chunk_len = 0; ++ loff_t chunk_offset = 0, chunk_start_offset = 0; ++ ++ dev_dbg(&client->dev, ++ "%s: off %lld len:%ld, opcode:%s\n", ++ __func__, off, (long int) len, ++ (opcode == OPTOE_READ_OP) ? "r" : "w"); ++ if (unlikely(!len)) ++ return len; ++ ++ /* ++ * Read data from chip, protecting against concurrent updates ++ * from this host, but not from other I2C masters. ++ */ ++ mutex_lock(&optoe->lock); ++ ++ /* ++ * Confirm this access fits within the device suppored addr range ++ */ ++ status = optoe_page_legal(optoe, off, len); ++ if (status < 0) ++ goto err; ++ len = status; ++ ++ /* ++ * For each (128 byte) chunk involved in this request, issue a ++ * separate call to sff_eeprom_update_client(), to ++ * ensure that each access recalculates the client/page ++ * and writes the page register as needed. ++ * Note that chunk to page mapping is confusing, is different for ++ * QSFP and SFP, and never needs to be done. Don't try! ++ */ ++ pending_len = len; /* amount remaining to transfer */ ++ retval = 0; /* amount transferred */ ++ for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { ++ ++ /* ++ * Compute the offset and number of bytes to be read/write ++ * ++ * 1. start at offset 0 (within the chunk), and read/write ++ * the entire chunk ++ * 2. start at offset 0 (within the chunk) and read/write less ++ * than entire chunk ++ * 3. start at an offset not equal to 0 and read/write the rest ++ * of the chunk ++ * 4. start at an offset not equal to 0 and read/write less than ++ * (end of chunk - offset) ++ */ ++ chunk_start_offset = chunk * OPTOE_PAGE_SIZE; ++ ++ if (chunk_start_offset < off) { ++ chunk_offset = off; ++ if ((off + pending_len) < (chunk_start_offset + ++ OPTOE_PAGE_SIZE)) ++ chunk_len = pending_len; ++ else ++ chunk_len = OPTOE_PAGE_SIZE - off; ++ } else { ++ chunk_offset = chunk_start_offset; ++ if (pending_len > OPTOE_PAGE_SIZE) ++ chunk_len = OPTOE_PAGE_SIZE; ++ else ++ chunk_len = pending_len; ++ } ++ ++ dev_dbg(&client->dev, ++ "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", ++ off, (long int) len, chunk_start_offset, chunk_offset, ++ (long int) chunk_len, (long int) pending_len); ++ ++ /* ++ * note: chunk_offset is from the start of the EEPROM, ++ * not the start of the chunk ++ */ ++ status = optoe_eeprom_update_client(optoe, buf, ++ chunk_offset, chunk_len, opcode); ++ if (status != chunk_len) { ++ /* This is another 'no device present' path */ ++ dev_dbg(&client->dev, ++ "o_u_c: chunk %d c_offset %lld c_len %ld failed %d!\n", ++ chunk, chunk_offset, (long int) chunk_len, status); ++ goto err; ++ } ++ buf += status; ++ pending_len -= status; ++ retval += status; ++ } ++ mutex_unlock(&optoe->lock); ++ ++ return retval; ++ ++err: ++ mutex_unlock(&optoe->lock); ++ ++ return status; ++} ++ ++static ssize_t optoe_bin_read(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(container_of(kobj, ++ struct device, kobj)); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ ++ return optoe_read_write(optoe, buf, off, count, OPTOE_READ_OP); ++} ++ ++ ++static ssize_t optoe_bin_write(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(container_of(kobj, ++ struct device, kobj)); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ ++ return optoe_read_write(optoe, buf, off, count, OPTOE_WRITE_OP); ++} ++ ++static int optoe_remove(struct i2c_client *client) ++{ ++ struct optoe_data *optoe; ++ int i; ++ ++ optoe = i2c_get_clientdata(client); ++ sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); ++ sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); ++ ++ for (i = 1; i < optoe->num_addresses; i++) ++ i2c_unregister_device(optoe->client[i]); ++ ++#ifdef EEPROM_CLASS ++ eeprom_device_unregister(optoe->eeprom_dev); ++#endif ++ ++ kfree(optoe->writebuf); ++ kfree(optoe); ++ return 0; ++} ++ ++static ssize_t show_dev_class(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, "%d\n", optoe->dev_class); ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ ++static ssize_t set_dev_class(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); ++ int dev_class; ++ ++ /* ++ * dev_class is actually the number of i2c addresses used, thus ++ * legal values are "1" (QSFP class) and "2" (SFP class) ++ */ ++ ++ if (kstrtoint(buf, 0, &dev_class) != 0 || ++ dev_class < 1 || dev_class > 2) ++ return -EINVAL; ++ ++ mutex_lock(&optoe->lock); ++ optoe->dev_class = dev_class; ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ ++/* ++ * if using the EEPROM CLASS driver, we don't report a port_name, ++ * the EEPROM CLASS drive handles that. Hence all this code is ++ * only compiled if we are NOT using the EEPROM CLASS driver. ++ */ ++#ifndef EEPROM_CLASS ++ ++static ssize_t show_port_name(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, "%s\n", optoe->port_name); ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ ++static ssize_t set_port_name(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); ++ char port_name[MAX_PORT_NAME_LEN]; ++ ++ /* no checking, this value is not used except by show_port_name */ ++ ++ if (sscanf(buf, "%19s", port_name) != 1) ++ return -EINVAL; ++ ++ mutex_lock(&optoe->lock); ++ strcpy(optoe->port_name, port_name); ++ 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 */ ++ ++static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); ++ ++static struct attribute *optoe_attrs[] = { ++#ifndef EEPROM_CLASS ++ &dev_attr_port_name.attr, ++#endif ++ &dev_attr_dev_class.attr, ++ NULL, ++}; ++ ++static struct attribute_group optoe_attr_group = { ++ .attrs = optoe_attrs, ++}; ++ ++static int optoe_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int err; ++ int use_smbus = 0; ++ struct optoe_platform_data chip; ++ 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); ++ err = -EINVAL; ++ goto exit; ++ } ++ ++ if (client->dev.platform_data) { ++ chip = *(struct optoe_platform_data *)client->dev.platform_data; ++ /* take the port name from the supplied platform data */ ++#ifdef EEPROM_CLASS ++ strncpy(port_name, chip.eeprom_data->label, MAX_PORT_NAME_LEN); ++#else ++ memcpy(port_name, chip.port_name, MAX_PORT_NAME_LEN); ++#endif ++ dev_dbg(&client->dev, ++ "probe, chip provided, flags:0x%x; name: %s\n", ++ chip.flags, client->name); ++ } else { ++ if (!id->driver_data) { ++ err = -ENODEV; ++ goto exit; ++ } ++ dev_dbg(&client->dev, "probe, building chip\n"); ++ strcpy(port_name, "unitialized"); ++ chip.flags = 0; ++#ifdef EEPROM_CLASS ++ chip.eeprom_data = NULL; ++#endif ++ } ++ ++ /* Use I2C operations unless we're stuck with SMBus extensions. */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { ++ use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; ++ } else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_WORD_DATA)) { ++ use_smbus = I2C_SMBUS_WORD_DATA; ++ } else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_BYTE_DATA)) { ++ use_smbus = I2C_SMBUS_BYTE_DATA; ++ } else { ++ err = -EPFNOSUPPORT; ++ goto exit; ++ } ++ } ++ ++ ++ /* ++ * Make room for two i2c clients ++ */ ++ num_addresses = 2; ++ ++ optoe = kzalloc(sizeof(struct optoe_data) + ++ num_addresses * sizeof(struct i2c_client *), ++ GFP_KERNEL); ++ if (!optoe) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ mutex_init(&optoe->lock); ++ ++ /* determine whether this is a one-address or two-address module */ ++ if ((strcmp(client->name, "optoe1") == 0) || ++ (strcmp(client->name, "sff8436") == 0)) { ++ /* one-address (eg QSFP) family */ ++ optoe->dev_class = ONE_ADDR; ++ chip.byte_len = ONE_ADDR_EEPROM_SIZE; ++ num_addresses = 1; ++ } else if ((strcmp(client->name, "optoe2") == 0) || ++ (strcmp(client->name, "24c04") == 0)) { ++ /* SFP family */ ++ optoe->dev_class = TWO_ADDR; ++ chip.byte_len = TWO_ADDR_EEPROM_SIZE; ++ } else { /* those were the only two choices */ ++ err = -EINVAL; ++ goto exit; ++ } ++ ++ dev_dbg(&client->dev, "dev_class: %d\n", optoe->dev_class); ++ optoe->use_smbus = use_smbus; ++ optoe->chip = chip; ++ optoe->num_addresses = num_addresses; ++ memcpy(optoe->port_name, port_name, MAX_PORT_NAME_LEN); ++ ++ /* ++ * Export the EEPROM bytes through sysfs, since that's convenient. ++ * By default, only root should see the data (maybe passwords etc) ++ */ ++ sysfs_bin_attr_init(&optoe->bin); ++ optoe->bin.attr.name = "eeprom"; ++ optoe->bin.attr.mode = 0444; ++ optoe->bin.read = optoe_bin_read; ++ optoe->bin.size = chip.byte_len; ++ ++ if (!use_smbus || ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_WORD_DATA) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { ++ /* ++ * NOTE: AN-2079 ++ * Finisar recommends that the host implement 1 byte writes ++ * only since this module only supports 32 byte page boundaries. ++ * 2 byte writes are acceptable for PE and Vout changes per ++ * Application Note AN-2071. ++ */ ++ unsigned int write_max = 1; ++ ++ optoe->bin.write = optoe_bin_write; ++ optoe->bin.attr.mode |= 0200; ++ ++ if (write_max > io_limit) ++ write_max = io_limit; ++ if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) ++ write_max = I2C_SMBUS_BLOCK_MAX; ++ optoe->write_max = write_max; ++ ++ /* buffer (data + address at the beginning) */ ++ optoe->writebuf = kmalloc(write_max + 2, GFP_KERNEL); ++ if (!optoe->writebuf) { ++ err = -ENOMEM; ++ goto exit_kfree; ++ } ++ } else { ++ dev_warn(&client->dev, ++ "cannot write due to controller restrictions."); ++ } ++ ++ optoe->client[0] = client; ++ ++ /* SFF-8472 spec requires that the second I2C address be 0x51 */ ++ if (num_addresses == 2) { ++ optoe->client[1] = i2c_new_dummy(client->adapter, 0x51); ++ if (!optoe->client[1]) { ++ dev_err(&client->dev, "address 0x51 unavailable\n"); ++ err = -EADDRINUSE; ++ goto err_struct; ++ } ++ } ++ ++ /* create the sysfs eeprom file */ ++ err = sysfs_create_bin_file(&client->dev.kobj, &optoe->bin); ++ if (err) ++ goto err_struct; ++ ++ optoe->attr_group = optoe_attr_group; ++ ++ err = sysfs_create_group(&client->dev.kobj, &optoe->attr_group); ++ if (err) { ++ dev_err(&client->dev, "failed to create sysfs attribute group.\n"); ++ goto err_struct; ++ } ++ ++#ifdef EEPROM_CLASS ++ optoe->eeprom_dev = eeprom_device_register(&client->dev, ++ chip.eeprom_data); ++ if (IS_ERR(optoe->eeprom_dev)) { ++ dev_err(&client->dev, "error registering eeprom device.\n"); ++ err = PTR_ERR(optoe->eeprom_dev); ++ goto err_sysfs_cleanup; ++ } ++#endif ++ ++ i2c_set_clientdata(client, optoe); ++ ++ dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", ++ optoe->bin.size, client->name, ++ optoe->bin.write ? "read/write" : "read-only"); ++ ++ if (use_smbus == I2C_SMBUS_WORD_DATA || ++ use_smbus == I2C_SMBUS_BYTE_DATA) { ++ dev_notice(&client->dev, ++ "Falling back to %s reads, performance will suffer\n", ++ use_smbus == I2C_SMBUS_WORD_DATA ? "word" : "byte"); ++ } ++ ++ return 0; ++ ++#ifdef EEPROM_CLASS ++err_sysfs_cleanup: ++ sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); ++ sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); ++#endif ++ ++err_struct: ++ if (num_addresses == 2) { ++ if (optoe->client[1]) ++ i2c_unregister_device(optoe->client[1]); ++ } ++ ++ kfree(optoe->writebuf); ++exit_kfree: ++ kfree(optoe); ++exit: ++ dev_dbg(&client->dev, "probe error %d\n", err); ++ ++ return err; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct i2c_driver optoe_driver = { ++ .driver = { ++ .name = "optoe", ++ .owner = THIS_MODULE, ++ }, ++ .probe = optoe_probe, ++ .remove = optoe_remove, ++ .id_table = optoe_ids, ++}; ++ ++static int __init optoe_init(void) ++{ ++ ++ if (!io_limit) { ++ pr_err("optoe: io_limit must not be 0!\n"); ++ return -EINVAL; ++ } ++ ++ io_limit = rounddown_pow_of_two(io_limit); ++ return i2c_add_driver(&optoe_driver); ++} ++module_init(optoe_init); ++ ++static void __exit optoe_exit(void) ++{ ++ i2c_del_driver(&optoe_driver); ++} ++module_exit(optoe_exit); ++ ++MODULE_DESCRIPTION("Driver for optical transceiver (SFP, QSFP, ...) EEPROMs"); ++MODULE_AUTHOR("DON BOLLINGER "); ++MODULE_LICENSE("GPL"); diff --git a/patch/series b/patch/series index 6f5e4672b..0c77cf35a 100644 --- a/patch/series +++ b/patch/series @@ -32,3 +32,4 @@ bridge-per-port-multicast-broadcast-flood-flags.patch driver-support-tun-config-carrier-enable.patch driver-i2c-bus-ismt-i801-support-intel-denverton.patch driver-hwmon-max31790.patch +driver-support-optoe.patch