Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp796996ybl; Wed, 4 Dec 2019 11:03:37 -0800 (PST) X-Google-Smtp-Source: APXvYqxf+5Ks/aDdW1iytAwiF4lqfA34BHcN/oyJPUft61wqhfzl5+R6ipzjUI5v0M7FQayoGVlX X-Received: by 2002:aca:dbc3:: with SMTP id s186mr3927228oig.130.1575486217249; Wed, 04 Dec 2019 11:03:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1575486217; cv=none; d=google.com; s=arc-20160816; b=VRCmuGppke0G2iatQ9VlUO4JPJSDTsAFcEgKkbUIkspn0t90kjCdlms1maOeU8Ilcg 9/mcns7YSwkv8eC15vAxEro6kwVQXojELvmac1XwaY77337kLIWLli1W5/ORMa346+U/ RgzVhRnLVPJlSvwpE4dDWKbH58Y6ESxZKmZs7/m8hMMmJt39Q0ikoir1PCLDs4aKHVjF h65NT273aMdwzOKWFTWQ9FA8Sdz4IceCHZPNYAu3TwndqzqjlY+lLES7ulkVxh2Gt/Fw IvaLmUvjhzX+W+xwJ2RQbmRLpYncsPVM1uPhWaAqxblfTlbyJ5hJYcrTHdqt8/lYPpM7 DrhQ== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=fFFdppuju1fo+f+Q1eRNOVBKmq7aqWWaw/YEtqDRMA8=; b=c2ioBQ8cHXuAAH5BIIFJzXcOeQXw/d/gq7DhuZVbG5wzkrqbEZpMBjY7lNtEvE3TSD o4nztpGtcmCs02rqk48uzroEie9G4JHTWJZPBirefpUNLLt3eU//FoyxYL72LT16FT1n ZhwAHlEicfbsLs5pxb3piuAQEJriy52ve5YRXpzbYiPmt3cAD1+S/xpxBNC3/F4iKxqO SMIlf742CinNgtDDD6hFEvf6EBYBVTpdIQfSBARGvPqpktEmNNzYNhmJwjG1FO56BFbo 5OqCWtWmLTfkm8mbG+HXWMKr9hlSnm/38vw6XVPqvNuLud6e52So72ubHLJx6mQeqYzL zpuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lGC1I8aW; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l5si3695306otn.40.2019.12.04.11.03.24; Wed, 04 Dec 2019 11:03:37 -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; dkim=pass header.i=@kernel.org header.s=default header.b=lGC1I8aW; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729210AbfLDSBl (ORCPT + 99 others); Wed, 4 Dec 2019 13:01:41 -0500 Received: from mail.kernel.org ([198.145.29.99]:42480 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729637AbfLDSBj (ORCPT ); Wed, 4 Dec 2019 13:01:39 -0500 Received: from localhost (unknown [217.68.49.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 331FB20865; Wed, 4 Dec 2019 18:01:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1575482498; bh=H8r+7YXvCx8T/EUb3d20nJKxVG4s6oZ/bYM374HNWV4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lGC1I8aWTRb+FUZaUt64T71AInacdLwze6wnv/NMutaFGNZsj5mRCF6V7C4IFw86j KwjFDh9DpT1DabhRF8APXJrrGpTibkd1MVWyiTOLiZhGVnu8YQXbqLLPk3hNdKK2ih QRHdvk8tXQywkqpbCE1CYmqbnKgA47phtNBUZpVY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Marc Kleine-Budde , Sasha Levin Subject: [PATCH 4.14 020/209] can: rx-offload: can_rx_offload_offload_one(): use ERR_PTR() to propagate error value in case of errors Date: Wed, 4 Dec 2019 18:53:52 +0100 Message-Id: <20191204175322.908327664@linuxfoundation.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191204175321.609072813@linuxfoundation.org> References: <20191204175321.609072813@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Marc Kleine-Budde [ Upstream commit d763ab3044f0bf50bd0e6179f6b2cf1c125d1d94 ] Before this patch can_rx_offload_offload_one() returns a pointer to a skb containing the read CAN frame or a NULL pointer. However the meaning of the NULL pointer is ambiguous, it can either mean the requested mailbox is empty or there was an error. This patch fixes this situation by returning: - pointer to skb on success - NULL pointer if mailbox is empty - ERR_PTR() in case of an error All users of can_rx_offload_offload_one() have been adopted, no functional change intended. Signed-off-by: Marc Kleine-Budde Signed-off-by: Sasha Levin --- drivers/net/can/rx-offload.c | 86 ++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/drivers/net/can/rx-offload.c b/drivers/net/can/rx-offload.c index b068e2320c794..840aef094f208 100644 --- a/drivers/net/can/rx-offload.c +++ b/drivers/net/can/rx-offload.c @@ -116,39 +116,95 @@ static int can_rx_offload_compare(struct sk_buff *a, struct sk_buff *b) return cb_b->timestamp - cb_a->timestamp; } -static struct sk_buff *can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n) +/** + * can_rx_offload_offload_one() - Read one CAN frame from HW + * @offload: pointer to rx_offload context + * @n: number of mailbox to read + * + * The task of this function is to read a CAN frame from mailbox @n + * from the device and return the mailbox's content as a struct + * sk_buff. + * + * If the struct can_rx_offload::skb_queue exceeds the maximal queue + * length (struct can_rx_offload::skb_queue_len_max) or no skb can be + * allocated, the mailbox contents is discarded by reading it into an + * overflow buffer. This way the mailbox is marked as free by the + * driver. + * + * Return: A pointer to skb containing the CAN frame on success. + * + * NULL if the mailbox @n is empty. + * + * ERR_PTR() in case of an error + */ +static struct sk_buff * +can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n) { - struct sk_buff *skb = NULL; + struct sk_buff *skb = NULL, *skb_error = NULL; struct can_rx_offload_cb *cb; struct can_frame *cf; int ret; - /* If queue is full or skb not available, read to discard mailbox */ if (likely(skb_queue_len(&offload->skb_queue) < - offload->skb_queue_len_max)) + offload->skb_queue_len_max)) { skb = alloc_can_skb(offload->dev, &cf); + if (unlikely(!skb)) + skb_error = ERR_PTR(-ENOMEM); /* skb alloc failed */ + } else { + skb_error = ERR_PTR(-ENOBUFS); /* skb_queue is full */ + } - if (!skb) { + /* If queue is full or skb not available, drop by reading into + * overflow buffer. + */ + if (unlikely(skb_error)) { struct can_frame cf_overflow; u32 timestamp; ret = offload->mailbox_read(offload, &cf_overflow, ×tamp, n); - if (ret) { - offload->dev->stats.rx_dropped++; - offload->dev->stats.rx_fifo_errors++; - } - return NULL; + /* Mailbox was empty. */ + if (unlikely(!ret)) + return NULL; + + /* Mailbox has been read and we're dropping it or + * there was a problem reading the mailbox. + * + * Increment error counters in any case. + */ + offload->dev->stats.rx_dropped++; + offload->dev->stats.rx_fifo_errors++; + + /* There was a problem reading the mailbox, propagate + * error value. + */ + if (unlikely(ret < 0)) + return ERR_PTR(ret); + + return skb_error; } cb = can_rx_offload_get_cb(skb); ret = offload->mailbox_read(offload, cf, &cb->timestamp, n); - if (!ret) { + + /* Mailbox was empty. */ + if (unlikely(!ret)) { kfree_skb(skb); return NULL; } + /* There was a problem reading the mailbox, propagate error value. */ + if (unlikely(ret < 0)) { + kfree_skb(skb); + + offload->dev->stats.rx_dropped++; + offload->dev->stats.rx_fifo_errors++; + + return ERR_PTR(ret); + } + + /* Mailbox was read. */ return skb; } @@ -168,7 +224,7 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, u64 pen continue; skb = can_rx_offload_offload_one(offload, i); - if (!skb) + if (IS_ERR_OR_NULL(skb)) break; __skb_queue_add_sort(&skb_queue, skb, can_rx_offload_compare); @@ -199,7 +255,11 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload) struct sk_buff *skb; int received = 0; - while ((skb = can_rx_offload_offload_one(offload, 0))) { + while (1) { + skb = can_rx_offload_offload_one(offload, 0); + if (IS_ERR_OR_NULL(skb)) + break; + skb_queue_tail(&offload->skb_queue, skb); received++; } -- 2.20.1