From patchwork Wed Jan 23 21:20:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ren=C3=A9_van_Dorst?= X-Patchwork-Id: 1030194 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=vdorst.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=vdorst.com header.i=@vdorst.com header.b="QpMUONq0"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43lJB12lJBz9s55 for ; Thu, 24 Jan 2019 08:21:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726986AbfAWVVL (ORCPT ); Wed, 23 Jan 2019 16:21:11 -0500 Received: from mail.0dd.nl ([5.2.79.48]:45960 "EHLO mail.0dd.nl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726953AbfAWVVL (ORCPT ); Wed, 23 Jan 2019 16:21:11 -0500 Received: from mail.vdorst.com (mail.vdorst.com [IPv6:fd01::250]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.0dd.nl (Postfix) with ESMTPS id 9C3055FC0F; Wed, 23 Jan 2019 22:21:09 +0100 (CET) Received: from pc-rene.vdorst.com (unknown [IPv6:2a02:a453:deab:1:da50:e6ff:fed1:4a04]) by mail.vdorst.com (Postfix) with ESMTPA id 62F2513DA897; Wed, 23 Jan 2019 22:21:09 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.vdorst.com 62F2513DA897 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vdorst.com; s=default; t=1548278469; bh=9GFybOlzf+ulgz99WzECXhi4Q2Y6fKsvaSz8RsP5mRg=; h=From:To:Cc:Subject:Date:From; b=QpMUONq06OTd/kmdQaTk1+SwLTv2NmrTPi9a/Wk/p7v7/0A7n9cSd6pfT+4LCYLcn S/lg6EOfWEFvXDsGUdlaTs/uDjzqSLMnmoiN/hmYD6/+bQt/bSqAh+q98J7T7if/QW 2wpM6Fd4eU7tz0SJPbsMMjZFBUHyO0yb9aTXOjA+hfuVAQfGJ44PxXXYD5TnMzSVsu Iz90qsasIVIxRuvbSQ8VlfAJRiCA4YgiC9nDJ3eQMxUC9OGuSsQ+PGluwMwl8B3OwA kQL6x2hVEGoi1vO31EES4GK2paMvderKKam2REhClhPagZmkr2/3CpWNsnx+JSyC3x 7ygTtX08iR6gQ== From: =?utf-8?q?Ren=C3=A9_van_Dorst?= To: Andrew Lunn , Florian Fainelli , Heiner Kallweit , "David S. Miller" , netdev@vger.kernel.org Cc: =?utf-8?q?Ren=C3=A9_van_Dorst?= Subject: [PATCH] sfp: sfp_read: split-up request when hw rx buffer is too small. Date: Wed, 23 Jan 2019 22:20:46 +0100 Message-Id: <20190123212046.13020-1-opensource@vdorst.com> X-Mailer: git-send-email 2.19.1 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Without this patch sfp code retries to read the full struct sfp_eeprom_id id out of the SFP eeprom. Sizeof(id) is 96 bytes. My i2c hardware, Mediatek mt7621, has a rx buffer of 64 bytes. So sfp_read gets -NOSUPPORTED back on his turn return -EAGAIN. Same issue is with the SFP_EXT_STATUS data which is 92 bytes. By split-up the request in multiple smaller requests with a max size of i2c max_read_len, we can readout the SFP module successfully. Tested with MT7621 and two Fiberstore modules SFP-GB-GE-T and SFP-GE-BX. Signed-off-by: René van Dorst --- drivers/net/phy/sfp.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index fd8bb998ae52..1352a19571cd 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -367,7 +367,28 @@ static void sfp_set_state(struct sfp *sfp, unsigned int state) static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) { - return sfp->read(sfp, a2, addr, buf, len); + const struct i2c_adapter_quirks *q = sfp->i2c->quirks; + int ret; + size_t rx_bytes = 0; + + /* Many i2c hw have limited rx buffers, split-up request when needed. */ + while ((q->max_read_len) && (len > q->max_read_len)) { + ret = sfp->read(sfp, a2, addr, buf, q->max_read_len); + if (ret < 0) + return ret; + rx_bytes += ret; + addr += q->max_read_len; + buf += q->max_read_len; + len -= q->max_read_len; + } + + ret = sfp->read(sfp, a2, addr, buf, len); + if (ret < 0) + return ret; + + rx_bytes += ret; + + return rx_bytes; } static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)