Received: by 10.192.165.148 with SMTP id m20csp1726821imm; Sat, 28 Apr 2018 04:16:34 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqaSoQs3/3OWHrZuitqOjn4o4rJ/t23o8biZJd1WivS/xkAMiLiTpKFMD5XaQmU+ACoE0t7 X-Received: by 2002:a63:5f0d:: with SMTP id t13-v6mr4968475pgb.145.1524914194235; Sat, 28 Apr 2018 04:16:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524914194; cv=none; d=google.com; s=arc-20160816; b=vAabiZSzB/Npk3CxYmS8Y99kRfvc5ixdXXYQ+5uSZTRaFjgwrURH18SPzMgTQ/8Ca9 RgIFuOmCKCj2PXtaLQoN8MvwQK3d9XSVfAhJL6YFpc78NjDDXF0ZKMc1z0bcm7WRD0dA Wp232QeUODp99qvxJJv/1P+yACRXWjh0koLyLi4jftpNYN00d4JZ8xJvgJTbx+cKM22b 4H0nbY0VKUhKIu8/bDXckbx6OC/A+9ObhX6HbV4U8zom9ROPj88XMtnpXBJYizHCv9W+ WeOSE4R8fBl/h+6KoCzg5OWzPzc+3myijmB36QKaUQUNqJCH9C2T1WW+1W50O5HzWt2D 3whA== 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:dkim-signature :arc-authentication-results; bh=oLMV9FII00kViZnxLUN/xqJfCDTUNXdSQ5gEauqXq+E=; b=zheI4dAPkKUwtlQrJ6meiIolB7rdD7mbxahJnzfB4+bDWFc9osQIxX56yHcJv/JW3z BPQUHoehxA4t8l2SnNtR/lgD+oEZ7CPW1te8EWj0B2Whwev4ZcqF0cZPtOeKC3QSLooV nirh5jV2jb8Q1qDqN6tfirHwOc0zW8QQ/KoYOudjHmxkjQX18CyQs6sgqdOvUJXO4V2P r2VvVMPIQ5uLRzjOLMOLnyWBuGhq8MG148FjOsMpeE4uqjniEKzjsRVIBQNxSr9KG+mQ ESU2SX8iRmtQWdDzUJUPGtO3z0LYnjn5M/mBYEaDHwY5uxY6R2Pe/l5p47ywCna5raWp LFvA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GSJ7Fr5Y; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v17-v6si2920563pgb.380.2018.04.28.04.15.45; Sat, 28 Apr 2018 04:16:34 -0700 (PDT) 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; dkim=pass header.i=@linaro.org header.s=google header.b=GSJ7Fr5Y; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759890AbeD1LM7 (ORCPT + 99 others); Sat, 28 Apr 2018 07:12:59 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:36006 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759871AbeD1LMz (ORCPT ); Sat, 28 Apr 2018 07:12:55 -0400 Received: by mail-wm0-f68.google.com with SMTP id n10so7021903wmc.1 for ; Sat, 28 Apr 2018 04:12:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=oLMV9FII00kViZnxLUN/xqJfCDTUNXdSQ5gEauqXq+E=; b=GSJ7Fr5Y6LMhnEkSdEJBK9se7yZ5FPpxlRklWWjDPjNao3RmUuOCLJWmhCXjH2Ls91 v+7cWzHDuYENnVq+YyPo5Yly7eUUW1yaR+zku5hP3n3ibBE2mX1chM5g+U0Y9e7DrWeZ 7hlO9Bz4K8dRAHj6/UsYNfZbWLDDsKNwz5vZI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=oLMV9FII00kViZnxLUN/xqJfCDTUNXdSQ5gEauqXq+E=; b=GCkWewL0uIqH73qiJsMBwIDVx8YEH7KnLmTjN+LoUQz8nAjhPUr1Ucv5dxUc8LhRyU 1YCN3H1hh9v32pNSPKb4LjMs5Q2Rd0wYtKONA1tPk/lF8KM5AXlVDqUCOegI61haZ2ru /kOHdAPrhpHVsisVYVXlQ7ZiIXqQUEFRdv4CWJvG/XtCyiIc1V9Lxurpo+4aTj45PkUy g/5IJFDP+nw+Rd6qi32Q4P9sMTNNPulcKV6Z1TsUR/+40u+hFoxWEKhDd+QtsdzQJmBq lofgjfHhRCSHJF5iVXJsImd3xuyUjGDzp2SY0z/l8k6IUlHSgNjBtV7Vv74rvnbUidWC wQiA== X-Gm-Message-State: ALQs6tABFJekrYjibl5VC5XrPFzdbvfV/O/Y02zSXmIa9kfT2DT10z6M yz60yO7Pis8rp08W0l3456OO3w== X-Received: by 2002:a50:f0c7:: with SMTP id a7-v6mr7866129edm.90.1524913973694; Sat, 28 Apr 2018 04:12:53 -0700 (PDT) Received: from [192.168.0.12] (cpc90716-aztw32-2-0-cust92.18-1.cable.virginm.net. [86.26.100.93]) by smtp.googlemail.com with ESMTPSA id q19-v6sm1964035edd.39.2018.04.28.04.12.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 28 Apr 2018 04:12:53 -0700 (PDT) Subject: Re: [PATCH v6 02/24] soc: qcom: Add APR bus driver To: Bjorn Andersson Cc: andy.gross@linaro.org, broonie@kernel.org, linux-arm-msm@vger.kernel.org, alsa-devel@alsa-project.org, robh+dt@kernel.org, bgoswami@codeaurora.org, gregkh@linuxfoundation.org, david.brown@linaro.org, mark.rutland@arm.com, lgirdwood@gmail.com, plai@codeaurora.org, tiwai@suse.com, perex@perex.cz, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rohkumar@qti.qualcomm.com, spatakok@qti.qualcomm.com References: <20180426094606.4775-1-srinivas.kandagatla@linaro.org> <20180426094606.4775-3-srinivas.kandagatla@linaro.org> <20180428045155.GA491@tuxbook-pro> From: Srinivas Kandagatla Message-ID: Date: Sat, 28 Apr 2018 12:12:51 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: <20180428045155.GA491@tuxbook-pro> 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 Thanks Bjorn for the review comments. On 28/04/18 05:51, Bjorn Andersson wrote: > On Thu 26 Apr 02:45 PDT 2018, Srinivas Kandagatla wrote: >> diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c > [..] >> +int apr_send_pkt(struct apr_device *adev, void *buf) > > Sorry, but I think we have discussed this before? > Yes, I did mention that I would give it a try and see, This change was pretty intrusive when I last looked at this. I agree with you on asymmetry! I will change this and add struc apr_pkt which would apr_hdr followed by payload. This should also work for callback as well. > "buf" isn't some random buffer to be sent, it is a apr_hdr followed by > some data. As such I think you should make this type struct apr_hdr *, > or if you think that doesn't imply there's payload make a type apr_pkt > that has a payload[] at the end. > > It will make it obvious for both future readers and the compiler what > kind of data we're passing here. > > > This comment also applies to functions calling functions that calls > apr_send_pkt() as they too lug around a void *. > >> +{ >> + struct apr *apr = dev_get_drvdata(adev->dev.parent); >> + struct apr_hdr *hdr; >> + unsigned long flags; >> + int ret; >> + >> + spin_lock_irqsave(&adev->lock, flags); >> + >> + hdr = (struct apr_hdr *)buf; >> + hdr->src_domain = APR_DOMAIN_APPS; >> + hdr->src_svc = adev->svc_id; >> + hdr->dest_domain = adev->domain_id; >> + hdr->dest_svc = adev->svc_id; >> + >> + ret = rpmsg_trysend(apr->ch, buf, hdr->pkt_size); >> + if (ret) { >> + dev_err(&adev->dev, "Unable to send APR pkt %d\n", >> + hdr->pkt_size); > > Afaict all callers of this function will print an error message, > sometimes on more than one level in the stack. And if some code path > does retry sending you will get a printout for each attempt, even though > the caller is fine with it. > > I would recommend unlocking the spinlock and then do: I can do that !! > > return ret ? : hdr->pkt_size; > >> + } else { >> + ret = hdr->pkt_size; >> + } >> + >> + spin_unlock_irqrestore(&adev->lock, flags); >> + >> + return ret; >> +} >> +EXPORT_SYMBOL_GPL(apr_send_pkt); >> + >> + >> +static int apr_callback(struct rpmsg_device *rpdev, void *buf, >> + int len, void *priv, u32 addr) >> +{ >> + struct apr *apr = dev_get_drvdata(&rpdev->dev); >> + struct apr_client_message data; >> + struct apr_device *p, *c_svc = NULL; >> + struct apr_driver *adrv = NULL; >> + struct apr_hdr *hdr; >> + unsigned long flags; >> + uint16_t hdr_size; >> + uint16_t msg_type; >> + uint16_t ver; >> + uint16_t svc; >> + >> + if (len <= APR_HDR_SIZE) { >> + dev_err(apr->dev, "APR: Improper apr pkt received:%p %d\n", >> + buf, len); >> + return -EINVAL; >> + } >> + >> + hdr = buf; >> + ver = APR_HDR_FIELD_VER(hdr->hdr_field); >> + if (ver > APR_PKT_VER + 1) >> + return -EINVAL; >> + >> + hdr_size = APR_HDR_FIELD_SIZE_BYTES(hdr->hdr_field); >> + if (hdr_size < APR_HDR_SIZE) { >> + dev_err(apr->dev, "APR: Wrong hdr size:%d\n", hdr_size); >> + return -EINVAL; >> + } >> + >> + if (hdr->pkt_size < APR_HDR_SIZE) { > > I think it would be nice to make sure that hdr->pkt_size is < len as > well, to reject messages that larger than the incoming buffer. > > The pkt_size should be in the ballpark of len, could this check be > changed to hdr->pkt_size != len? Yep, It makes sense, I can add that check here. > >> + dev_err(apr->dev, "APR: Wrong paket size\n"); >> + return -EINVAL; >> + } >> + >> + msg_type = APR_HDR_FIELD_MT(hdr->hdr_field); >> + if (msg_type >= APR_MSG_TYPE_MAX && msg_type != APR_BASIC_RSP_RESULT) { >> + dev_err(apr->dev, "APR: Wrong message type: %d\n", msg_type); >> + return -EINVAL; >> + } >> + >> + if (hdr->src_domain >= APR_DOMAIN_MAX || >> + hdr->dest_domain >= APR_DOMAIN_MAX || >> + hdr->src_svc >= APR_SVC_MAX || >> + hdr->dest_svc >= APR_SVC_MAX) { >> + dev_err(apr->dev, "APR: Wrong APR header\n"); >> + return -EINVAL; >> + } >> + >> + svc = hdr->dest_svc; >> + spin_lock_irqsave(&apr->svcs_lock, flags); >> + list_for_each_entry(p, &apr->svcs, node) { > > Rather than doing a O(n) search for the svc with svc_id you could use a > idr or a radix_tree to keep the id -> svc mapping. Am not 100% sure idr is correct thing here, as the svc_ids are static and the list we are talking here in worst case would be max of 13 entires, in audio case it is just 4 services. I think using radix_tree would be over do. > >> + if (svc == p->svc_id) { >> + c_svc = p; >> + if (c_svc->dev.driver) >> + adrv = to_apr_driver(c_svc->dev.driver); >> + break; >> + } >> + } >> + spin_unlock_irqrestore(&apr->svcs_lock, flags); >> + >> + if (!adrv) { >> + dev_err(apr->dev, "APR: service is not registered\n"); >> + return -EINVAL; >> + } >> + >> + data.payload_size = hdr->pkt_size - hdr_size; >> + data.opcode = hdr->opcode; >> + data.src_port = hdr->src_port; >> + data.dest_port = hdr->dest_port; >> + data.token = hdr->token; >> + data.msg_type = msg_type; >> + >> + if (data.payload_size > 0) >> + data.payload = buf + hdr_size; >> + > > Making a verbatim copy of parts of the hdr and then passing that to the > APR devices creates an asymmetry in the send/callback API, without a > whole lot of benefits. I would prefer that you introduce the apr_pkt, as > described above, and once you have validated the size et al and found > the service you just pass it along. Okay, this would be a big rework, I will do it in next version. > >> + adrv->callback(c_svc, &data); >> + >> + return 0; >> +} > [..] >> +static int apr_uevent(struct device *dev, struct kobj_uevent_env *env) >> +{ >> + struct apr_device *adev = to_apr_device(dev); >> + int ret; >> + >> + ret = of_device_uevent_modalias(dev, env); >> + if (ret != -ENODEV) >> + return ret; >> + >> + return add_uevent_var(env, "MODALIAS= apr:%s", adev->name); > > No space between '=' and "apr". > Yep. >> +} >> + >> +struct bus_type aprbus = { >> + .name = "aprbus", > > Most busses doesn't have "bus" in the name. > Yep, just "apr" make sense. >> + .match = apr_device_match, >> + .probe = apr_device_probe, >> + .uevent = apr_uevent, >> + .remove = apr_device_remove, >> +}; >> +EXPORT_SYMBOL_GPL(aprbus); >> + >> +static int apr_add_device(struct device *dev, struct device_node *np, >> + const struct apr_device_id *id) >> +{ >> + struct apr *apr = dev_get_drvdata(dev); >> + struct apr_device *adev = NULL; >> + >> + adev = kzalloc(sizeof(*adev), GFP_KERNEL); >> + if (!adev) >> + return -ENOMEM; >> + >> + spin_lock_init(&adev->lock); >> + >> + adev->svc_id = id->svc_id; >> + adev->domain_id = id->domain_id; >> + adev->version = id->svc_version; >> + if (np) >> + strncpy(adev->name, np->name, APR_NAME_SIZE); >> + else >> + strncpy(adev->name, id->name, APR_NAME_SIZE); >> + >> + dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, >> + id->domain_id, id->svc_id); >> + >> + adev->dev.bus = &aprbus; >> + adev->dev.parent = dev; >> + adev->dev.of_node = np; >> + adev->dev.release = apr_dev_release; >> + adev->dev.driver = NULL; >> + >> + spin_lock(&apr->svcs_lock); >> + list_add_tail(&adev->node, &apr->svcs); >> + spin_unlock(&apr->svcs_lock); >> + >> + dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev)); >> + >> + return device_register(&adev->dev); > > If this fails you must call put_device(&adev->dev); > Agree!! >> +} >> + >> +static void of_register_apr_devices(struct device *dev) >> +{ >> + struct apr *apr = dev_get_drvdata(dev); >> + struct device_node *node; >> + >> + for_each_child_of_node(dev->of_node, node) { >> + struct apr_device_id id = { {0} }; >> + >> + if (of_property_read_u32(node, "reg", &id.svc_id)) >> + continue; >> + >> + id.domain_id = apr->dest_domain_id; >> + >> + if (apr_add_device(dev, node, &id)) >> + dev_err(dev, "Failed to add arp %d svc\n", id.svc_id); >> + } >> +} > [..] >> + >> +static int __init apr_init(void) >> +{ >> + int ret; >> + >> + ret = bus_register(&aprbus); >> + if (!ret) >> + ret = register_rpmsg_driver(&apr_driver); > > bus_unregister() if ret here. > Yep. Thanks, srini >> + >> + return ret; >> +} >> + > > Regards, > Bjorn >