Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1744896imu; Wed, 28 Nov 2018 14:30:56 -0800 (PST) X-Google-Smtp-Source: AFSGD/UA+nGkh4ZhgTBzOUS9KLWZm1dC+dCoxU5Ks4JIzdnPrCY+DIY5e2g0gb/fWGAwYafcoCMP X-Received: by 2002:a63:5518:: with SMTP id j24mr34195149pgb.208.1543444256624; Wed, 28 Nov 2018 14:30:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543444256; cv=none; d=google.com; s=arc-20160816; b=YYk+NibNLOrKEBEkySERKnVY8zMYrgwXDzIAiLGXResAcxfK+YkhPBB3FvPz2JfJ0V 2e85CziY704GB7SOqFUHC9PaBMArJgo2O85lio2NCgg6LR1v5WW3Mz2alVV+9cAvPiBR eu6faoaVhsimzDKK8QaBGlOBWTXRnxucS5ACOVY8023Lri84qaSxXeRTN5tFoBUCEytk HToaeMzolM5bbCLj8ubnqJMx6EpDFNBDZw2+RAKx3IPA0IU/YxebpfGON1t4gdFcruri F5eD1mdl2K19h/8tPnnY7Cc/gsYEzz4J38RaMZgJU6BFeJBZr/oWUZdobtvaaxDV/pG7 1/LA== 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 :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject; bh=ez6XoTTTM5rXiCjXPXofigAtAIEZOVIthHse3HXfz2c=; b=hVqQpFQjYhzYw3RyOxMumN6ild2zkHO2mHLBpcI05VSsx3CRVuj47T86siJOL03iNo kNCMx1mXrEZsYO/rB+zaFrKQXtuNUUvCAVw9ui8S8DchuLPCs/rw+UV0s2wEQZCnYxMP wGCfgPYAohleHQSd5X8Is/8cuT7JQbcOyIxgeS8T3QP4v1eh6j1x2ihl+viDLl8P6Ht+ n7QfSny7dt/RtPevMnhe4k2UX4Vfk/1rzaDUt8k7bvTvWXPiecii6dGbWUxOrTc0anLG rpwdYqfG88pkPOhpGANAZqCCsX/jAF75eByxFn/dYDN5x58+iBBsNAEba/1MHeeAJQFr MSjw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p5si8229873pga.352.2018.11.28.14.30.41; Wed, 28 Nov 2018 14:30:56 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726628AbeK2JdQ (ORCPT + 99 others); Thu, 29 Nov 2018 04:33:16 -0500 Received: from mga05.intel.com ([192.55.52.43]:34010 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726485AbeK2JdQ (ORCPT ); Thu, 29 Nov 2018 04:33:16 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Nov 2018 14:30:06 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,292,1539673200"; d="scan'208";a="93726054" Received: from yoojae-mobl1.amr.corp.intel.com (HELO [10.122.32.196]) ([10.122.32.196]) by orsmga007.jf.intel.com with ESMTP; 28 Nov 2018 14:30:04 -0800 Subject: Re: [PATCH i2c-next v9 5/5] i2c: aspeed: Add bus idle waiting logic for multi-master use cases To: Wolfram Sang Cc: Brendan Higgins , Rob Herring , Joel Stanley , Benjamin Herrenschmidt , Mark Rutland , Andrew Jeffery , linux-i2c@vger.kernel.org, openbmc@lists.ozlabs.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org, Jarkko Nikula , James Feist , Vernon Mauery References: <20181030210917.32711-1-jae.hyun.yoo@linux.intel.com> <20181030210917.32711-6-jae.hyun.yoo@linux.intel.com> <20181128215434.GA1666@kunai> From: Jae Hyun Yoo Message-ID: <2772b86e-6ffb-e289-40f2-f96d11b82349@linux.intel.com> Date: Wed, 28 Nov 2018 16:30:03 -0600 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <20181128215434.GA1666@kunai> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 11/28/2018 3:54 PM, Wolfram Sang wrote: > On Tue, Oct 30, 2018 at 02:09:16PM -0700, Jae Hyun Yoo wrote: >> In multi-master environment, this driver's master cannot know >> exactly when a peer master sends data to this driver's slave so a >> case can be happened that this master tries to send data through >> the master_xfer function but slave data from peer master is still >> being processed by this driver. > > So, that I get this correct: your IP core cannot detect a bus busy state > when its own slave address is acessed? Well, I know HW can have bugs, > but I still wonder because a bus is busy as soon as another START has > been detected, independent of which device is going to be accessed. > > Even if so, why can't you use a mutex to prevent any master_xfer while > slave_xfer is ongoing? > > Shouldn't that be enough according to the above description? Why do you > need the delay? I might be missing something... > This IP has a bus busy state bit which can cover master and slave operations but in case of slave operation, the bit is cleared little bit earlier than its actual completion so it's the reason why I made this patch. I agree with you that it still has a weak point since the bus can be changed to busy state immediately just after finishing the busy waiting delay. As you suggested, I'll try to implement it using a mutex instead of using delay. Thanks a lot for your comment. Jae >> To prevent any state corruption in the case, this patch adds >> checking code if any slave operation is ongoing and it waits up to >> the bus timeout duration before starting a master_xfer operation. >> >> Signed-off-by: Jae Hyun Yoo >> Reviewed-by: Brendan Higgins >> --- >> drivers/i2c/busses/i2c-aspeed.c | 55 ++++++++++++++++++++++++--------- >> 1 file changed, 40 insertions(+), 15 deletions(-) >> >> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c >> index 833b6b6a4c7e..30c3ab3a4844 100644 >> --- a/drivers/i2c/busses/i2c-aspeed.c >> +++ b/drivers/i2c/busses/i2c-aspeed.c >> @@ -12,6 +12,7 @@ >> >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -115,6 +116,9 @@ >> /* 0x18 : I2CD Slave Device Address Register */ >> #define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0) >> >> +/* Busy checking */ >> +#define ASPEED_I2C_BUS_BUSY_CHECK_INTERVAL_US (10 * 1000) >> + >> enum aspeed_i2c_master_state { >> ASPEED_I2C_MASTER_INACTIVE, >> ASPEED_I2C_MASTER_START, >> @@ -156,6 +160,8 @@ struct aspeed_i2c_bus { >> int cmd_err; >> /* Protected only by i2c_lock_bus */ >> int master_xfer_result; >> + /* Multi-master */ >> + bool multi_master; >> #if IS_ENABLED(CONFIG_I2C_SLAVE) >> struct i2c_client *slave; >> enum aspeed_i2c_slave_state slave_state; >> @@ -596,27 +602,44 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id) >> return irq_remaining ? IRQ_NONE : IRQ_HANDLED; >> } >> >> +static int aspeed_i2c_check_bus_busy(struct aspeed_i2c_bus *bus) >> +{ >> + unsigned long timeout; >> + >> + if (bus->multi_master) { >> + might_sleep(); >> + /* Initialize it only when multi_master is set */ >> + timeout = jiffies + bus->adap.timeout; >> + } >> + >> + for (;;) { >> + if (!(readl(bus->base + ASPEED_I2C_CMD_REG) & >> + ASPEED_I2CD_BUS_BUSY_STS)) >> +#if IS_ENABLED(CONFIG_I2C_SLAVE) >> + if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) >> +#endif >> + return 0; >> + if (!bus->multi_master) >> + break; >> + if (time_after(jiffies, timeout)) >> + break; >> + usleep_range((ASPEED_I2C_BUS_BUSY_CHECK_INTERVAL_US >> 2) + 1, >> + ASPEED_I2C_BUS_BUSY_CHECK_INTERVAL_US); >> + } >> + >> + return aspeed_i2c_recover_bus(bus); >> +} >> + >> static int aspeed_i2c_master_xfer(struct i2c_adapter *adap, >> struct i2c_msg *msgs, int num) >> { >> struct aspeed_i2c_bus *bus = i2c_get_adapdata(adap); >> unsigned long time_left, flags; >> - int ret = 0; >> >> - spin_lock_irqsave(&bus->lock, flags); >> - bus->cmd_err = 0; >> - >> - /* If bus is busy, attempt recovery. We assume a single master >> - * environment. >> - */ >> - if (readl(bus->base + ASPEED_I2C_CMD_REG) & ASPEED_I2CD_BUS_BUSY_STS) { >> - spin_unlock_irqrestore(&bus->lock, flags); >> - ret = aspeed_i2c_recover_bus(bus); >> - if (ret) >> - return ret; >> - spin_lock_irqsave(&bus->lock, flags); >> - } >> + if (aspeed_i2c_check_bus_busy(bus)) >> + return -EAGAIN; >> >> + spin_lock_irqsave(&bus->lock, flags); >> bus->cmd_err = 0; >> bus->msgs = msgs; >> bus->msgs_index = 0; >> @@ -827,7 +850,9 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus, >> if (ret < 0) >> return ret; >> >> - if (!of_property_read_bool(pdev->dev.of_node, "multi-master")) >> + if (of_property_read_bool(pdev->dev.of_node, "multi-master")) >> + bus->multi_master = true; >> + else >> fun_ctrl_reg |= ASPEED_I2CD_MULTI_MASTER_DIS; >> >> /* Enable Master Mode */ >> -- >> 2.19.1 >>