From patchwork Fri Feb 3 14:36:21 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: sjur.brandeland@stericsson.com X-Patchwork-Id: 139385 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id D2472104792 for ; Sat, 4 Feb 2012 01:36:45 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756729Ab2BCOgm (ORCPT ); Fri, 3 Feb 2012 09:36:42 -0500 Received: from mail-lpp01m010-f46.google.com ([209.85.215.46]:39416 "EHLO mail-lpp01m010-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756726Ab2BCOgk (ORCPT ); Fri, 3 Feb 2012 09:36:40 -0500 Received: by lagu2 with SMTP id u2so1877418lag.19 for ; Fri, 03 Feb 2012 06:36:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=/DvDk3x/amg1+E0eyJuSkccWwWiJpQWrHllaZJjR9Ok=; b=pil5RV4PqkhGIANyXvz88vCUAl1hj4FTmvbSsCDy6eo+XIR9CLA8WoHI6ByOWhbQNk WJaxnDREy5Q40Yga6c6sfDECZtOaJMFK5pThK+SIdHkmqO6VYC5llCls0upEi1SGplme 4tNBWchdIoxRu8vTvva+1u+x+9lXlk8qZJaEo= Received: by 10.152.128.133 with SMTP id no5mr3441215lab.31.1328279799105; Fri, 03 Feb 2012 06:36:39 -0800 (PST) Received: from localhost.localdomain ([212.4.57.94]) by mx.google.com with ESMTPS id od2sm3870556lab.11.2012.02.03.06.36.37 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 03 Feb 2012 06:36:38 -0800 (PST) From: =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= To: netdev@vger.kernel.org, davem@davemloft.net Cc: sjurbren@gmail.com, =?UTF-8?q?Sjur=20Br=C3=A6ndeland?= Subject: [PATCH 3/3] caif-hsi: Add RX flip buffer Date: Fri, 3 Feb 2012 15:36:21 +0100 Message-Id: <1328279781-4745-3-git-send-email-sjur.brandeland@stericsson.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1328279781-4745-1-git-send-email-sjur.brandeland@stericsson.com> References: <1328279781-4745-1-git-send-email-sjur.brandeland@stericsson.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Implement RX flip buffer in the cfhsi_rx_done function, piggy-backed frames is also supported. This gives a significant performance gain for CAIF over HSI. Signed-off-by: Sjur Brændeland --- drivers/net/caif/caif_hsi.c | 145 ++++++++++++++++++++++++++++++------------ include/net/caif/caif_hsi.h | 1 + 2 files changed, 104 insertions(+), 42 deletions(-) diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c index 0a4fc62..c8afd62 100644 --- a/drivers/net/caif/caif_hsi.c +++ b/drivers/net/caif/caif_hsi.c @@ -426,6 +426,35 @@ static int cfhsi_rx_desc(struct cfhsi_desc *desc, struct cfhsi *cfhsi) return xfer_sz; } +static int cfhsi_rx_desc_len(struct cfhsi_desc *desc) +{ + int xfer_sz = 0; + int nfrms = 0; + u16 *plen; + + if ((desc->header & ~CFHSI_PIGGY_DESC) || + (desc->offset > CFHSI_MAX_EMB_FRM_SZ)) { + + pr_err("Invalid descriptor. %x %x\n", desc->header, + desc->offset); + return -EPROTO; + } + + /* Calculate transfer length. */ + plen = desc->cffrm_len; + while (nfrms < CFHSI_MAX_PKTS && *plen) { + xfer_sz += *plen; + plen++; + nfrms++; + } + + if (xfer_sz % 4) { + pr_err("Invalid payload len: %d, ignored.\n", xfer_sz); + return -EPROTO; + } + return xfer_sz; +} + static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi) { int rx_sz = 0; @@ -517,8 +546,10 @@ static int cfhsi_rx_pld(struct cfhsi_desc *desc, struct cfhsi *cfhsi) static void cfhsi_rx_done(struct cfhsi *cfhsi) { int res; - int desc_pld_len = 0; + int desc_pld_len = 0, rx_len, rx_state; struct cfhsi_desc *desc = NULL; + u8 *rx_ptr, *rx_buf; + struct cfhsi_desc *piggy_desc = NULL; desc = (struct cfhsi_desc *)cfhsi->rx_buf; @@ -534,65 +565,71 @@ static void cfhsi_rx_done(struct cfhsi *cfhsi) spin_unlock_bh(&cfhsi->lock); if (cfhsi->rx_state.state == CFHSI_RX_STATE_DESC) { - desc_pld_len = cfhsi_rx_desc(desc, cfhsi); - if (desc_pld_len == -ENOMEM) - goto restart; - if (desc_pld_len == -EPROTO) + desc_pld_len = cfhsi_rx_desc_len(desc); + + if (desc_pld_len < 0) goto out_of_sync; + + rx_buf = cfhsi->rx_buf; + rx_len = desc_pld_len; + if (desc_pld_len > 0 && (desc->header & CFHSI_PIGGY_DESC)) + rx_len += CFHSI_DESC_SZ; + if (desc_pld_len == 0) + rx_buf = cfhsi->rx_flip_buf; } else { - int pld_len; + rx_buf = cfhsi->rx_flip_buf; - if (!cfhsi->rx_state.piggy_desc) { - pld_len = cfhsi_rx_pld(desc, cfhsi); - if (pld_len == -ENOMEM) - goto restart; - if (pld_len == -EPROTO) - goto out_of_sync; - cfhsi->rx_state.pld_len = pld_len; - } else { - pld_len = cfhsi->rx_state.pld_len; - } + rx_len = CFHSI_DESC_SZ; + if (cfhsi->rx_state.pld_len > 0 && + (desc->header & CFHSI_PIGGY_DESC)) { - if ((pld_len > 0) && (desc->header & CFHSI_PIGGY_DESC)) { - struct cfhsi_desc *piggy_desc; piggy_desc = (struct cfhsi_desc *) (desc->emb_frm + CFHSI_MAX_EMB_FRM_SZ + - pld_len); + cfhsi->rx_state.pld_len); + cfhsi->rx_state.piggy_desc = true; - /* Extract piggy-backed descriptor. */ - desc_pld_len = cfhsi_rx_desc(piggy_desc, cfhsi); - if (desc_pld_len == -ENOMEM) - goto restart; + /* Extract payload len from piggy-backed descriptor. */ + desc_pld_len = cfhsi_rx_desc_len(piggy_desc); + if (desc_pld_len < 0) + goto out_of_sync; + + if (desc_pld_len > 0) + rx_len = desc_pld_len; + + if (desc_pld_len > 0 && + (piggy_desc->header & CFHSI_PIGGY_DESC)) + rx_len += CFHSI_DESC_SZ; /* * Copy needed information from the piggy-backed * descriptor to the descriptor in the start. */ - memcpy((u8 *)desc, (u8 *)piggy_desc, + memcpy(rx_buf, (u8 *)piggy_desc, CFHSI_DESC_SHORT_SZ); - + /* Mark no embedded frame here */ + piggy_desc->offset = 0; if (desc_pld_len == -EPROTO) goto out_of_sync; } } - memset(&cfhsi->rx_state, 0, sizeof(cfhsi->rx_state)); if (desc_pld_len) { - cfhsi->rx_state.state = CFHSI_RX_STATE_PAYLOAD; - cfhsi->rx_ptr = cfhsi->rx_buf + CFHSI_DESC_SZ; - cfhsi->rx_len = desc_pld_len; + rx_state = CFHSI_RX_STATE_PAYLOAD; + rx_ptr = rx_buf + CFHSI_DESC_SZ; } else { - cfhsi->rx_state.state = CFHSI_RX_STATE_DESC; - cfhsi->rx_ptr = cfhsi->rx_buf; - cfhsi->rx_len = CFHSI_DESC_SZ; + rx_state = CFHSI_RX_STATE_DESC; + rx_ptr = rx_buf; + rx_len = CFHSI_DESC_SZ; } + /* Initiate next read */ if (test_bit(CFHSI_AWAKE, &cfhsi->bits)) { /* Set up new transfer. */ dev_dbg(&cfhsi->ndev->dev, "%s: Start RX.\n", - __func__); - res = cfhsi->dev->cfhsi_rx(cfhsi->rx_ptr, cfhsi->rx_len, + __func__); + + res = cfhsi->dev->cfhsi_rx(rx_ptr, rx_len, cfhsi->dev); if (WARN_ON(res < 0)) { dev_err(&cfhsi->ndev->dev, "%s: RX error %d.\n", @@ -601,16 +638,32 @@ static void cfhsi_rx_done(struct cfhsi *cfhsi) cfhsi->ndev->stats.rx_dropped++; } } - return; -restart: - if (++cfhsi->rx_state.retries > CFHSI_MAX_RX_RETRIES) { - dev_err(&cfhsi->ndev->dev, "%s: No memory available " - "in %d iterations.\n", - __func__, CFHSI_MAX_RX_RETRIES); - BUG(); + if (cfhsi->rx_state.state == CFHSI_RX_STATE_DESC) { + /* Extract payload from descriptor */ + if (cfhsi_rx_desc(desc, cfhsi) < 0) + goto out_of_sync; + } else { + /* Extract payload */ + if (cfhsi_rx_pld(desc, cfhsi) < 0) + goto out_of_sync; + if (piggy_desc) { + /* Extract any payload in piggyback descriptor. */ + if (cfhsi_rx_desc(piggy_desc, cfhsi) < 0) + goto out_of_sync; + } } - mod_timer(&cfhsi->rx_slowpath_timer, jiffies + 1); + + /* Update state info */ + memset(&cfhsi->rx_state, 0, sizeof(cfhsi->rx_state)); + cfhsi->rx_state.state = rx_state; + cfhsi->rx_ptr = rx_ptr; + cfhsi->rx_len = rx_len; + cfhsi->rx_state.pld_len = desc_pld_len; + cfhsi->rx_state.piggy_desc = desc->header & CFHSI_PIGGY_DESC; + + if (rx_buf != cfhsi->rx_buf) + swap(cfhsi->rx_buf, cfhsi->rx_flip_buf); return; out_of_sync: @@ -1040,6 +1093,12 @@ int cfhsi_probe(struct platform_device *pdev) goto err_alloc_rx; } + cfhsi->rx_flip_buf = kzalloc(CFHSI_BUF_SZ_RX, GFP_KERNEL); + if (!cfhsi->rx_flip_buf) { + res = -ENODEV; + goto err_alloc_rx_flip; + } + /* Pre-calculate inactivity timeout. */ if (inactivity_timeout != -1) { cfhsi->inactivity_timeout = @@ -1138,6 +1197,8 @@ int cfhsi_probe(struct platform_device *pdev) err_activate: destroy_workqueue(cfhsi->wq); err_create_wq: + kfree(cfhsi->rx_flip_buf); + err_alloc_rx_flip: kfree(cfhsi->rx_buf); err_alloc_rx: kfree(cfhsi->tx_buf); diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h index 8d55251..6db8ecf 100644 --- a/include/net/caif/caif_hsi.h +++ b/include/net/caif/caif_hsi.h @@ -138,6 +138,7 @@ struct cfhsi { u8 *rx_ptr; u8 *tx_buf; u8 *rx_buf; + u8 *rx_flip_buf; spinlock_t lock; int flow_off_sent; u32 q_low_mark;