Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp566ybz; Thu, 30 Apr 2020 15:15:41 -0700 (PDT) X-Google-Smtp-Source: APiQypJXN+6oFMs8/WSK6YDdWdHfqttage3KEP+86oJdi59cddIJ5D5D1N+bdASXMdGQn7BIOxou X-Received: by 2002:a17:906:7ac8:: with SMTP id k8mr580071ejo.235.1588284941096; Thu, 30 Apr 2020 15:15:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588284941; cv=none; d=google.com; s=arc-20160816; b=OBWricvTbZG9qOBoxW0Ga6M4juWbtDqoFEN8OIiZE1xSEqwnBD3FJ61DwCe2HfDenj GFEthBB3dAFSMtz4v1Vfd9OsUAALD7Gw0qlFXYMfG7IVgTw+aQXNn9e4YRa8e0TiCDIS fZCbJjYW27MAEzxng6SytOVbb5YeXdS2u1CP5BIdSWvmH9OlRpIyji7TPru8kxz9kMxG 7C1HrS/F2EHRUQdZKtDcXPGR7xC/uRL3SGniwBgwZG23XbeqWUnMlc4pJFZg6mrxFB8M k/VGUMFyTjouo6y63xlwzLtW+qzwJP0tR0jNXtuigEs6k6lcso+NzEz7aMc2r/Mf6WNZ mPjw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=gN/TqDhg8bNL/QeGTI+szQXKqV9fUbqEbuIp2Eu9bQs=; b=NG80vDt58tE9eir8HY7RQVPuZdfyEM1ZDGPxxEWth8L6Ttcqy4NaFlOj5A3ug0oqHK QJagJw8wtZhhdzB8oHNuGF9AoYiCFPtKuWuBxv08IxO3f9W4YUjSpdm6Ll7GSKUpLhNQ yIVwG5XhXk1bbwsUp76c1Y7QcbkzmgZdhGDbbNB49Dgo3duU2nzhGNgoupqbLK9tG+2D 0mVd0SIinodahfeFKXXhE+CBoVItNZnHBRXV4A00ckcp43ehN9S749Op1TkG8bZN4tnW 6jBaFKBv9hvnNP2pFEffIeGjbDYAeToU561hQqttyYqwV2g/W70cBVSfh8h2iyeYY67R eR4g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=efQJcaoa; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id dk10si573106edb.3.2020.04.30.15.15.18; Thu, 30 Apr 2020 15:15:41 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=efQJcaoa; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727931AbgD3WNj (ORCPT + 99 others); Thu, 30 Apr 2020 18:13:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727865AbgD3WNd (ORCPT ); Thu, 30 Apr 2020 18:13:33 -0400 Received: from mail-qk1-x744.google.com (mail-qk1-x744.google.com [IPv6:2607:f8b0:4864:20::744]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85EC6C035495 for ; Thu, 30 Apr 2020 15:13:33 -0700 (PDT) Received: by mail-qk1-x744.google.com with SMTP id 23so7571231qkf.0 for ; Thu, 30 Apr 2020 15:13:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=gN/TqDhg8bNL/QeGTI+szQXKqV9fUbqEbuIp2Eu9bQs=; b=efQJcaoasuYbZGC9B1Cx8MFELGozCD/WNm7f4tVvAxGMZbLr5cQowkmZoWV8bT33aa V+8vumksqodYEmlLzoPh9MvJBtSuJ19WPed3OYWZdoVaJtNF9ILpLbShTGjhiJurVbZS ZFtGEMFF4bs4XMlq6hG2XanW6HJICjTYTkljQ/qI7dWwgeg09VTX7aJYS9qiaudiM0x0 +QUhsE1kg1TEdxICFtVFmprmr3gVjgjVvs9o0NHi3sKaUSsOpJSXDNhMGoHnALu3g33g N7i0wHbn0whEjzqsVPtWA837n0VOU6AJWgwwxtrRvycCbaJgQCz8YaEMOP3Vl8OQ+Pfk 0Xxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gN/TqDhg8bNL/QeGTI+szQXKqV9fUbqEbuIp2Eu9bQs=; b=t3uacbqC4jbVKyy9VnLWn62QE3maHTXntTRA0AySr1/OWuNjzJec+sCtCMF9Ld2nSf v3ad3x8IxERqAWuN6nF8ke9E2yoZ4jRF8+4ByANJZVQuZxHV5f5rNQ8lOkNkTVVKmRK/ pXBdkbd+069sBEcTVMaZWlVv6YxmiAHU+KDXZ7vcrq9rVzr6vE86ASWiB31+yG8Gpjjt qw366NdQCL8yriyDlPZDk3WH6E+e7kw08OjX4tsvH7M0OGbjgql+qGNoWWGPBJ6wCaIB gQ8X9c64sY7CLIc7N//WSgqVeIrAX458+/kzdxXbt2+73lJ+5eSFAC2KjMnrBdBiwmMj Qzkg== X-Gm-Message-State: AGi0PuZqPVC6oeTOE/wBXE71qoVM6+rAPK/L35NUEMh4Wwgq7Bvbn2j/ saXIX6p86iUaI6f4qoaN5lcfnE/1sn0= X-Received: by 2002:a37:bd81:: with SMTP id n123mr717459qkf.57.1588284812686; Thu, 30 Apr 2020 15:13:32 -0700 (PDT) Received: from beast.localdomain (c-73-185-129-58.hsd1.mn.comcast.net. [73.185.129.58]) by smtp.gmail.com with ESMTPSA id w42sm957028qtj.63.2020.04.30.15.13.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Apr 2020 15:13:32 -0700 (PDT) From: Alex Elder To: davem@davemloft.net Cc: evgreen@chromium.org.net, subashab@codeaurora.org, cpratapa@codeaurora.org, bjorn.andersson@linaro.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 2/2] net: ipa: do not cache channel state Date: Thu, 30 Apr 2020 17:13:23 -0500 Message-Id: <20200430221323.5449-3-elder@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200430221323.5449-1-elder@linaro.org> References: <20200430221323.5449-1-elder@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org It is possible for a GSI channel's state to be changed as a result of an action by a different execution environment. Specifically, the modem is able to issue a GSI generic command that causes a state change on a GSI channel associated with the AP. A channel's state only needs to be known when a channel is allocated or deallocaed, started or stopped, or reset. So there is little value in caching the state anyway. Stop recording a copy of the channel's last known state, and instead fetch the true state from hardware whenever it's needed. In such cases, *do* record the state in a local variable, in case an error message reports it (so the value reported is the value seen). Signed-off-by: Alex Elder --- drivers/net/ipa/gsi.c | 87 +++++++++++++++++++++++++++---------------- drivers/net/ipa/gsi.h | 3 +- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index 6946c39b664a..8184d34124b7 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -415,7 +415,7 @@ static void gsi_evt_ring_de_alloc_command(struct gsi *gsi, u32 evt_ring_id) evt_ring->state); } -/* Return the hardware's notion of the current state of a channel */ +/* Fetch the current state of a channel from hardware */ static enum gsi_channel_state gsi_channel_state(struct gsi_channel *channel) { u32 channel_id = gsi_channel_id(channel); @@ -433,16 +433,18 @@ gsi_channel_command(struct gsi_channel *channel, enum gsi_ch_cmd_opcode opcode) { struct completion *completion = &channel->completion; u32 channel_id = gsi_channel_id(channel); + struct gsi *gsi = channel->gsi; u32 val; val = u32_encode_bits(channel_id, CH_CHID_FMASK); val |= u32_encode_bits(opcode, CH_OPCODE_FMASK); - if (gsi_command(channel->gsi, GSI_CH_CMD_OFFSET, val, completion)) + if (gsi_command(gsi, GSI_CH_CMD_OFFSET, val, completion)) return 0; /* Success! */ - dev_err(channel->gsi->dev, "GSI command %u to channel %u timed out " - "(state is %u)\n", opcode, channel_id, channel->state); + dev_err(gsi->dev, + "GSI command %u to channel %u timed out (state is %u)\n", + opcode, channel_id, gsi_channel_state(channel)); return -ETIMEDOUT; } @@ -451,18 +453,21 @@ gsi_channel_command(struct gsi_channel *channel, enum gsi_ch_cmd_opcode opcode) static int gsi_channel_alloc_command(struct gsi *gsi, u32 channel_id) { struct gsi_channel *channel = &gsi->channel[channel_id]; + enum gsi_channel_state state; int ret; /* Get initial channel state */ - channel->state = gsi_channel_state(channel); - - if (channel->state != GSI_CHANNEL_STATE_NOT_ALLOCATED) + state = gsi_channel_state(channel); + if (state != GSI_CHANNEL_STATE_NOT_ALLOCATED) return -EINVAL; ret = gsi_channel_command(channel, GSI_CH_ALLOCATE); - if (!ret && channel->state != GSI_CHANNEL_STATE_ALLOCATED) { + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (!ret && state != GSI_CHANNEL_STATE_ALLOCATED) { dev_err(gsi->dev, "bad channel state (%u) after alloc\n", - channel->state); + state); ret = -EIO; } @@ -472,18 +477,21 @@ static int gsi_channel_alloc_command(struct gsi *gsi, u32 channel_id) /* Start an ALLOCATED channel */ static int gsi_channel_start_command(struct gsi_channel *channel) { - enum gsi_channel_state state = channel->state; + enum gsi_channel_state state; int ret; + state = gsi_channel_state(channel); if (state != GSI_CHANNEL_STATE_ALLOCATED && state != GSI_CHANNEL_STATE_STOPPED) return -EINVAL; ret = gsi_channel_command(channel, GSI_CH_START); - if (!ret && channel->state != GSI_CHANNEL_STATE_STARTED) { + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (!ret && state != GSI_CHANNEL_STATE_STARTED) { dev_err(channel->gsi->dev, - "bad channel state (%u) after start\n", - channel->state); + "bad channel state (%u) after start\n", state); ret = -EIO; } @@ -493,23 +501,27 @@ static int gsi_channel_start_command(struct gsi_channel *channel) /* Stop a GSI channel in STARTED state */ static int gsi_channel_stop_command(struct gsi_channel *channel) { - enum gsi_channel_state state = channel->state; + enum gsi_channel_state state; int ret; + state = gsi_channel_state(channel); if (state != GSI_CHANNEL_STATE_STARTED && state != GSI_CHANNEL_STATE_STOP_IN_PROC) return -EINVAL; ret = gsi_channel_command(channel, GSI_CH_STOP); - if (ret || channel->state == GSI_CHANNEL_STATE_STOPPED) + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (ret || state == GSI_CHANNEL_STATE_STOPPED) return ret; /* We may have to try again if stop is in progress */ - if (channel->state == GSI_CHANNEL_STATE_STOP_IN_PROC) + if (state == GSI_CHANNEL_STATE_STOP_IN_PROC) return -EAGAIN; - dev_err(channel->gsi->dev, "bad channel state (%u) after stop\n", - channel->state); + dev_err(channel->gsi->dev, + "bad channel state (%u) after stop\n", state); return -EIO; } @@ -517,41 +529,49 @@ static int gsi_channel_stop_command(struct gsi_channel *channel) /* Reset a GSI channel in ALLOCATED or ERROR state. */ static void gsi_channel_reset_command(struct gsi_channel *channel) { + enum gsi_channel_state state; int ret; msleep(1); /* A short delay is required before a RESET command */ - if (channel->state != GSI_CHANNEL_STATE_STOPPED && - channel->state != GSI_CHANNEL_STATE_ERROR) { + state = gsi_channel_state(channel); + if (state != GSI_CHANNEL_STATE_STOPPED && + state != GSI_CHANNEL_STATE_ERROR) { dev_err(channel->gsi->dev, - "bad channel state (%u) before reset\n", - channel->state); + "bad channel state (%u) before reset\n", state); return; } ret = gsi_channel_command(channel, GSI_CH_RESET); - if (!ret && channel->state != GSI_CHANNEL_STATE_ALLOCATED) + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (!ret && state != GSI_CHANNEL_STATE_ALLOCATED) dev_err(channel->gsi->dev, - "bad channel state (%u) after reset\n", - channel->state); + "bad channel state (%u) after reset\n", state); } /* Deallocate an ALLOCATED GSI channel */ static void gsi_channel_de_alloc_command(struct gsi *gsi, u32 channel_id) { struct gsi_channel *channel = &gsi->channel[channel_id]; + enum gsi_channel_state state; int ret; - if (channel->state != GSI_CHANNEL_STATE_ALLOCATED) { - dev_err(gsi->dev, "bad channel state (%u) before dealloc\n", - channel->state); + state = gsi_channel_state(channel); + if (state != GSI_CHANNEL_STATE_ALLOCATED) { + dev_err(gsi->dev, + "bad channel state (%u) before dealloc\n", state); return; } ret = gsi_channel_command(channel, GSI_CH_DE_ALLOC); - if (!ret && channel->state != GSI_CHANNEL_STATE_NOT_ALLOCATED) - dev_err(gsi->dev, "bad channel state (%u) after dealloc\n", - channel->state); + + /* Channel state will normally have been updated */ + state = gsi_channel_state(channel); + if (!ret && state != GSI_CHANNEL_STATE_NOT_ALLOCATED) + dev_err(gsi->dev, + "bad channel state (%u) after dealloc\n", state); } /* Ring an event ring doorbell, reporting the last entry processed by the AP. @@ -778,6 +798,7 @@ int gsi_channel_start(struct gsi *gsi, u32 channel_id) int gsi_channel_stop(struct gsi *gsi, u32 channel_id) { struct gsi_channel *channel = &gsi->channel[channel_id]; + enum gsi_channel_state state; u32 retries; int ret; @@ -787,7 +808,8 @@ int gsi_channel_stop(struct gsi *gsi, u32 channel_id) * STOP command timed out. We won't stop a channel if stopping it * was successful previously (so we still want the freeze above). */ - if (channel->state == GSI_CHANNEL_STATE_STOPPED) + state = gsi_channel_state(channel); + if (state == GSI_CHANNEL_STATE_STOPPED) return 0; /* RX channels might require a little time to enter STOPPED state */ @@ -941,7 +963,6 @@ static void gsi_isr_chan_ctrl(struct gsi *gsi) channel_mask ^= BIT(channel_id); channel = &gsi->channel[channel_id]; - channel->state = gsi_channel_state(channel); complete(&channel->completion); } diff --git a/drivers/net/ipa/gsi.h b/drivers/net/ipa/gsi.h index 0698ff1ae7a6..19471017fadf 100644 --- a/drivers/net/ipa/gsi.h +++ b/drivers/net/ipa/gsi.h @@ -113,8 +113,7 @@ struct gsi_channel { u16 tre_count; u16 event_count; - struct completion completion; /* signals channel state changes */ - enum gsi_channel_state state; + struct completion completion; /* signals channel command completion */ struct gsi_ring tre_ring; u32 evt_ring_id; -- 2.20.1