Received: by 2002:a05:7208:c250:b0:86:f851:443 with SMTP id w16csp938711rbd; Thu, 13 Jun 2024 01:46:49 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWwao4SGbu1h2wr0pLZfRWNCqaBBYhScl2TBad2GzKZy+gUn+ZnRTiKj6YXW0sJz+AZ4JYmSO05n4amx/AzpaSM3Ua4SxuOzs7Yngvr9w== X-Google-Smtp-Source: AGHT+IE3AQhW4ZK8s+GuaBz9yHb5nWfp1vVJJx4moYN3TLhGMsx91FV6cIcXf5K0wZ7HcwqvShJe X-Received: by 2002:a17:90a:e14d:b0:2c2:db82:c06a with SMTP id 98e67ed59e1d1-2c4a76f585amr4337057a91.35.1718268408701; Thu, 13 Jun 2024 01:46:48 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1718268408; cv=pass; d=google.com; s=arc-20160816; b=AsTTKmJGLo7A3wBIs/piv2hEtYfPr9jJswxuR03RX4fPhfVaAqv0/ZES7uPB52vJ9n 3/LUiBHAl67fx5rogK4iBUaPeeEXd52lxabcc+6Gk4r/jRta16kDlaG7ahKz8FXUJVM4 q8GO9okxudtN9//EvY9JPUhPnkjBdbGJ4ZBpF7NnQpd2wUTZCiUXXm43GVFaiZExptjm kmjPs4K6iq0QYM9DFa1A1unfXbX+QAZpNt82j0sW+gWqYqb8oOz/LlR8/oMkKRmYqikc HJF+ufD83Dtmsi24nFwiZbUJWELvR75yKGE9AeXsF/v6XWRzDYdeXr5XuHnW4fXsx5Z0 aYQg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:list-unsubscribe:list-subscribe:list-id:precedence :references:message-id:in-reply-to:subject:cc:to:date:from :dkim-signature; bh=D6QX1IUYLsz6zn3aeKSp0MiM+JW20UhL2RQhP7RA5ME=; fh=l6ginnCGrmvvZF0AxP3GM6UABnTEV9eURThsgEFF6OY=; b=fAbqusqvuxMzrJVBTJzSuO261WMVXYztSheXYVv07kE2VrhMH8PU1Zp9f0Qw2q5pTu bgDDka7G5yUr03DvMZ9wqFODP6aRBFKHqqWrnsmROCj17QMhwQwa5b4EDuuYIIxSUlY9 wUH8dP5B8q6iFaSP/ZVRrtL0kIbLd9J2OaBM3HEJpO6QH7gjm+59fPyisLCF3dBzugZQ brbgHLYPdeTTlYZ3gIxsj2ypqUdyQvKpUi0sfzYSO+tzTqw8VF6n0LM0Gd/ran4Grycb RWEC9HmvAFNrhDkaT22w0Dch1gmXJNxreA5MxJE0bpljG8or6p7B/mj0b4D3h4Mo6U0a +vSQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=OdnUOSVg; arc=pass (i=1 dkim=pass dkdomain=intel.com dmarc=pass fromdomain=linux.intel.com); spf=pass (google.com: domain of linux-kernel+bounces-212705-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-212705-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id 98e67ed59e1d1-2c4c4624e3fsi1017307a91.67.2024.06.13.01.46.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Jun 2024 01:46:48 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-212705-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=OdnUOSVg; arc=pass (i=1 dkim=pass dkdomain=intel.com dmarc=pass fromdomain=linux.intel.com); spf=pass (google.com: domain of linux-kernel+bounces-212705-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-212705-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 702902890E2 for ; Thu, 13 Jun 2024 07:30:53 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 75BDE13C83A; Thu, 13 Jun 2024 07:30:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="OdnUOSVg" Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B1E2C13B5B0; Thu, 13 Jun 2024 07:30:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.13 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718263834; cv=none; b=UMKhHL/cV4wYpWiYvIi9n/DIIdHZpvGNJ7+wpnUWsfyBCaIWS/X5j1kmCZBTan0HtRQmxE4w3AbX/iaajL6N1RTCKKd4cVoWZb/bOPqoVaEOeJkpj5l6ctJu/p8HgVNU5sHV4FsAMQrilSJF806QNx6cWvsKO69HBRtbxOufFKg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718263834; c=relaxed/simple; bh=dsetrFdITEMBuE/dVKeYsPlIhzXBWBSLjWq5b239AhQ=; h=From:Date:To:cc:Subject:In-Reply-To:Message-ID:References: MIME-Version:Content-Type; b=BsQNGfRHmAqcnu3lNLRFWKJjCuyIuh+aIfuHhu3hcMMnz2lXtRGK6Y0KSTxGtO2e5FiyZqv/F3Paji4bShJNnOTsDZ1Bb2TqA21zS2tvcLBSs/53/bdCc1tXRV/3LqqTgJhVWrIArgml5XP3WcPCyw19BDVczhpA30jGY2PE+zo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=OdnUOSVg; arc=none smtp.client-ip=198.175.65.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1718263833; x=1749799833; h=from:date:to:cc:subject:in-reply-to:message-id: references:mime-version; bh=dsetrFdITEMBuE/dVKeYsPlIhzXBWBSLjWq5b239AhQ=; b=OdnUOSVgKZV6gDw/hR5ODOC5kIACpRsIZYntY13NY9F6qEFlsb1vsa2b oO6OK9tyUIyX+5Ex1HPH4hiJ0TZQGfV28uvcE6IKW7DrPRbLBJArCr05r TYTPXCZU0V51a/FuJxXZUjAbPK2D4IzA/7GgawwAlNWxuR12p0PLibcPu ZbAeH3hFIPB3RvyA0egLrDWj7bJ7iBZne50geqwfkii68/Eu0IFKW0vMU Pnl3LBx9Fnavv/s0f2AYDrX2eDzdDpIYo3Os7uQAOt0G3ZgdHoXoLEz9V icu+mcZDOWvfx/Tlq0rjhSZ8Dk4FAIKwVBij7xkT9VxixyenwIyLqL9Nv A==; X-CSE-ConnectionGUID: G3ag7TxFR5uqrnerMtBqZQ== X-CSE-MsgGUID: THdUdd6cTDOddWcFhiIFlA== X-IronPort-AV: E=McAfee;i="6700,10204,11101"; a="26179761" X-IronPort-AV: E=Sophos;i="6.08,234,1712646000"; d="scan'208";a="26179761" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Jun 2024 00:30:31 -0700 X-CSE-ConnectionGUID: VZ2GH6DcRz6lt7rN8CLZrA== X-CSE-MsgGUID: 1/G27uvSQ02EkRRYgnBJrA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,234,1712646000"; d="scan'208";a="40118770" Received: from ijarvine-desk1.ger.corp.intel.com (HELO localhost) ([10.245.247.209]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Jun 2024 00:30:26 -0700 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Thu, 13 Jun 2024 10:30:23 +0300 (EEST) To: Dmitry Baryshkov cc: Sebastian Reichel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Bjorn Andersson , Hans de Goede , Bryan O'Donoghue , Heikki Krogerus , Greg Kroah-Hartman , Konrad Dybcio , linux-pm@vger.kernel.org, devicetree@vger.kernel.org, LKML , platform-driver-x86@vger.kernel.org, linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org, Nikita Travkin Subject: Re: [PATCH v6 3/6] usb: typec: ucsi: add Lenovo Yoga C630 glue driver In-Reply-To: <20240612-yoga-ec-driver-v6-3-8e76ba060439@linaro.org> Message-ID: References: <20240612-yoga-ec-driver-v6-0-8e76ba060439@linaro.org> <20240612-yoga-ec-driver-v6-3-8e76ba060439@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII On Wed, 12 Jun 2024, Dmitry Baryshkov wrote: > The Lenovo Yoga C630 WOS laptop provides implements UCSI interface in > the onboard EC. Add glue driver to interface the platform's UCSI > implementation. > > Reviewed-by: Bryan O'Donoghue > Reviewed-by: Heikki Krogerus > Signed-off-by: Dmitry Baryshkov > --- > +static int yoga_c630_ucsi_read(struct ucsi *ucsi, unsigned int offset, > + void *val, size_t val_len) > +{ > + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); > + u8 buf[YOGA_C630_UCSI_READ_SIZE]; > + int ret; > + > + ret = yoga_c630_ec_ucsi_read(uec->ec, buf); > + if (ret) > + return ret; > + > + if (offset == UCSI_VERSION) { > + memcpy(val, &uec->version, min(val_len, sizeof(uec->version))); > + return 0; > + } > + > + if (offset == UCSI_CCI) > + memcpy(val, buf, min(val_len, YOGA_C630_UCSI_CCI_SIZE)); > + else if (offset == UCSI_MESSAGE_IN) > + memcpy(val, buf + YOGA_C630_UCSI_CCI_SIZE, > + min(val_len, YOGA_C630_UCSI_DATA_SIZE)); > + else > + return -EINVAL; > + > + return 0; Hmm, the inconsistency when to do return 0 is a bit odd. Also, using switch (offset) would probably be better here anyway to replace all the ifs. > +} > + > +static int yoga_c630_ucsi_async_write(struct ucsi *ucsi, unsigned int offset, > + const void *val, size_t val_len) > +{ > + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); > + > + if (offset != UCSI_CONTROL || > + val_len != YOGA_C630_UCSI_WRITE_SIZE) > + return -EINVAL; > + > + return yoga_c630_ec_ucsi_write(uec->ec, val); > +} > + > +static int yoga_c630_ucsi_sync_write(struct ucsi *ucsi, unsigned int offset, > + const void *val, size_t val_len) > +{ > + struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); > + bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI; > + int ret; > + > + if (ack) > + set_bit(UCSI_C630_ACK_PENDING, &uec->flags); > + else > + set_bit(UCSI_C630_COMMAND_PENDING, &uec->flags); > + > + reinit_completion(&uec->complete); > + > + ret = yoga_c630_ucsi_async_write(ucsi, offset, val, val_len); > + if (ret) > + goto out_clear_bit; > + > + if (!wait_for_completion_timeout(&uec->complete, 5 * HZ)) > + ret = -ETIMEDOUT; > + > +out_clear_bit: > + if (ack) > + clear_bit(UCSI_C630_ACK_PENDING, &uec->flags); > + else > + clear_bit(UCSI_C630_COMMAND_PENDING, &uec->flags); > + > + return ret; > +} > + > +const struct ucsi_operations yoga_c630_ucsi_ops = { > + .read = yoga_c630_ucsi_read, > + .sync_write = yoga_c630_ucsi_sync_write, > + .async_write = yoga_c630_ucsi_async_write, > +}; > + > +static void yoga_c630_ucsi_notify_ucsi(struct yoga_c630_ucsi *uec, u32 cci) > +{ > + if (UCSI_CCI_CONNECTOR(cci)) > + ucsi_connector_change(uec->ucsi, UCSI_CCI_CONNECTOR(cci)); > + > + if (cci & UCSI_CCI_ACK_COMPLETE && > + test_bit(UCSI_C630_ACK_PENDING, &uec->flags)) > + complete(&uec->complete); > + > + if (cci & UCSI_CCI_COMMAND_COMPLETE && > + test_bit(UCSI_C630_COMMAND_PENDING, &uec->flags)) > + complete(&uec->complete); Is this racy? Can another command start after an ACK in between these two ifs and complete() is called prematurely for the new command? (Or will different value in cci protect against that?) > +} > + > +static int yoga_c630_ucsi_notify(struct notifier_block *nb, > + unsigned long action, void *data) > +{ > + struct yoga_c630_ucsi *uec = container_of(nb, struct yoga_c630_ucsi, nb); > + u32 cci; > + int ret; > + > + switch (action) { > + case LENOVO_EC_EVENT_USB: > + case LENOVO_EC_EVENT_HPD: > + ucsi_connector_change(uec->ucsi, 1); > + return NOTIFY_OK; > + > + case LENOVO_EC_EVENT_UCSI: > + ret = uec->ucsi->ops->read(uec->ucsi, UCSI_CCI, &cci, sizeof(cci)); > + if (ret) > + return NOTIFY_DONE; > + > + yoga_c630_ucsi_notify_ucsi(uec, cci); > + > + return NOTIFY_OK; > + > + default: > + return NOTIFY_DONE; > + } > +} > + > +static int yoga_c630_ucsi_probe(struct auxiliary_device *adev, > + const struct auxiliary_device_id *id) > +{ > + struct yoga_c630_ec *ec = adev->dev.platform_data; > + struct yoga_c630_ucsi *uec; > + int ret; > + > + uec = devm_kzalloc(&adev->dev, sizeof(*uec), GFP_KERNEL); > + if (!uec) > + return -ENOMEM; > + > + uec->ec = ec; > + init_completion(&uec->complete); > + uec->nb.notifier_call = yoga_c630_ucsi_notify; > + > + uec->ucsi = ucsi_create(&adev->dev, &yoga_c630_ucsi_ops); > + if (IS_ERR(uec->ucsi)) > + return PTR_ERR(uec->ucsi); > + > + ucsi_set_drvdata(uec->ucsi, uec); > + > + uec->version = yoga_c630_ec_ucsi_get_version(uec->ec); > + > + auxiliary_set_drvdata(adev, uec); > + > + ret = yoga_c630_ec_register_notify(ec, &uec->nb); > + if (ret) > + return ret; > + > + return ucsi_register(uec->ucsi); > +} > + > +static void yoga_c630_ucsi_remove(struct auxiliary_device *adev) > +{ > + struct yoga_c630_ucsi *uec = auxiliary_get_drvdata(adev); > + > + yoga_c630_ec_unregister_notify(uec->ec, &uec->nb); > + ucsi_unregister(uec->ucsi); Usually, the remove should tear down in reverse order than the probe side. Is the divergence from that here intentional? -- i.