Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp1227421imm; Wed, 6 Jun 2018 12:28:47 -0700 (PDT) X-Google-Smtp-Source: ADUXVKL8aTBS9g7dKnKi+DXi5awgDkRZKEFOmUbgPfMteHoxeU2vWmoL2UcDzPDbqxE+oqEOhZlO X-Received: by 2002:a17:902:ac89:: with SMTP id h9-v6mr4424614plr.311.1528313327689; Wed, 06 Jun 2018 12:28:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528313327; cv=none; d=google.com; s=arc-20160816; b=cmfSwsi5pglhtgA7ya8/1ACFSOY0BrI9qGutYeeL9NZRg+TLCBldPylZuGOIORS8oh hkUJg4rX+qkKGWn0BxOu7jZvX3RI3+B2az7wkYtSdJnJMsSiQJNXWptKYHo8REgw2bZf mAVwRhMZpCMz7qHPvYoeoV2iiNvslhmqzW3gswpvblFVIYmcmJIJPpfufO8ZRcyVbsck dek4cAv2n64qERClqr7cwnS5x8QCCdVxrHw6vYydvlhzphiI7Y6/i/bWIUslHIrH60KP vz1RiT/OBq4U+wHpNxTGxbm60ZJRcP/hoIOx9XQ3sATWwLXHh60J3bH9ZfWHxd3O47ss p7GQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=qvL/jDlxesf39k4pOPdP0JrNueyVHErx/kO9gom9v90=; b=qzBcU7mS29+KXoSyFvl9ffhrQ+umKvP+ik8Py1KTYClWsq9KZHHlRBI7PtSfNjACdm nCx5mr2aNMkpFewPMjGUAM3D4AkzKWgHjbUerE8amc7pwr0i/9U6aVQcYoey8vsp3ZSv 9Hq/yIlvV5VXoUYXd7JW2i6+wd1SQVdmAl03/sgPy8v5pNpGnUD1VsddMTVycNYp76Vw ZXLBUOr2UgTHQf50VWIO1xhDcYVnzfss50rv4RLISOnEo+TObtuwiEUbAfOtiajpq+mC uYg5aZcJ/Tbx8yDznoW3Ty2LCtl/KRl8Hn9OM/votVrAYclmza7iEGxAZQuP4U43/TWL GDLg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=gdOty5cm; 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=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a64-v6si53154249pla.530.2018.06.06.12.28.33; Wed, 06 Jun 2018 12:28:47 -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=@gmail.com header.s=20161025 header.b=gdOty5cm; 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=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932449AbeFFSru (ORCPT + 99 others); Wed, 6 Jun 2018 14:47:50 -0400 Received: from mail-qk0-f196.google.com ([209.85.220.196]:44892 "EHLO mail-qk0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932334AbeFFSrs (ORCPT ); Wed, 6 Jun 2018 14:47:48 -0400 Received: by mail-qk0-f196.google.com with SMTP id 185-v6so4635762qkk.11; Wed, 06 Jun 2018 11:47:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=qvL/jDlxesf39k4pOPdP0JrNueyVHErx/kO9gom9v90=; b=gdOty5cm/mcYS7SPhsZjn4OOnOMYyQnON2Fk7HB1TpDJMVAfTE0aYN6YKAJRW0rd4T DcOqyUYWFfDBKXBFM9CLD2o5wjq3ci2tlwywQtsI5xCyWBBJsxAn++2xIvP5lz1glq/8 pGnzA6VX6xHOEgeQCHXIU7gYnA1II037alATKKgUtYPyglDtaJ77UKWVPcp8lWLs5EtB MW08wY2pV8QJzGWodfcpdHpwsJyEzo+Kog1nIcklyCN0MIYr7M6mvf1deEasSVjPzLf5 dm5cWbdm3n1mmBhghGekPKl+dz9bAnDyGEinpO46uG73Mr8TxIBhoeGAQMbuOYwLYk0c mUgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=qvL/jDlxesf39k4pOPdP0JrNueyVHErx/kO9gom9v90=; b=C7r5wpl/2280yojdH5+IcpG5VcxSpnMqMf50qnA4EuqTlriODFqdT4HL3GTAQWhmOd IN0+q8mvVysERYOYLMTgISGN+5nFAnOWI1n+vHavKz8gOpTHGsU1PI4g4A57QhP3utpr ho72J6AQoEWut8Ia3J49c5Ke3+iBBQdSPprij6Nkr+Upof5m3WyE3YNEQUoD9Ud4Q6sb 0ITrQf4sK6g2GuxQuekBG56cD0ea32mkQh59LbTSsaK4c0lI37UioNU/H6fC7GlrZYvG +SAHwO5VsElO4FWM133RswMhLlg0uoYqiXxa8tHNVt74yNnJlr45D07KefbHopR38dYk 4Rmw== X-Gm-Message-State: APt69E1UN1cmUITDOLsKi+AGfGRv10k1AsQ370kjJTZIzl/8JXyj9uJx FtfaFwc/eOasn5ocP2Bi0slFk0i93HYkR1qUeTU= X-Received: by 2002:a37:ddce:: with SMTP id u75-v6mr3575358qku.147.1528310867293; Wed, 06 Jun 2018 11:47:47 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a0c:98f9:0:0:0:0:0 with HTTP; Wed, 6 Jun 2018 11:47:46 -0700 (PDT) In-Reply-To: <1528224240-30786-3-git-send-email-mark.jonas@de.bosch.com> References: <1528224240-30786-1-git-send-email-mark.jonas@de.bosch.com> <1528224240-30786-3-git-send-email-mark.jonas@de.bosch.com> From: Andy Shevchenko Date: Wed, 6 Jun 2018 21:47:46 +0300 Message-ID: Subject: Re: [PATCH 2/5] spi: implement companion-spi driver To: Mark Jonas Cc: Wolfgang Grandegger , Marc Kleine-Budde , linux-can@vger.kernel.org, netdev , Linux Kernel Mailing List , Heiko Schocher , Zhu Yi Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Jun 5, 2018 at 9:43 PM, Mark Jonas wrote: > The low level companion-spi driver encapsulates the communication > details with the companion processor, and provides interface for > the upper level drivers to access. > +int companion_do_io_tx(struct device *parent, > + const char __user *buf, > + size_t count) > +{ > + struct companion_spi_priv *priv = dev_get_drvdata(parent); > + unsigned int copied; > + int error; > + struct companion_packet p; > + > + /*TODO: support mutiple packets in one write in future*/ Hmm... Either fix this, or remove comment? > + if (copy_from_user(p.data, buf, sizeof(p)) == 0) { > + if (is_can_type(&p)) > + return -EINVAL; > + } else { > + dev_info(parent, "copy from user not succeed in one call\n"); Shouldn't it return immediately? > + } > + > + error = qm_io_txq_in(&priv->pm.qm, buf, count, &copied); ...what the point to call if we got garbage from user space? > + if (!error) { The usual pattern is to check for errors first. > + wake_up_interruptible(&priv->wait); > + priv->pm.stats.io_tx++; > + return copied; > + } else { > + priv->pm.stats.io_tx_overflows++; > + } > + return error; > +} > + ... qm_io_rxq_out(&priv->pm.qm, buf, count, &copied); > + ... pm_can_data_tx(&priv->pm, port, prio, cf); Oh, oh, oh. These namespaces are too generic, moreover pm is kinda occupied by power management. You bring a lot of confusion here, I think. > + err = pm_can_get_txq_status(pm, port); > + if (!err) { if (err) return err; > + } > + return err; > + int ret, value; > + > + ret = sscanf(buf, "%d", &value); > + if (ret != 1) { > + } You have to be consistent in your code. I've already noticed err error and now ret Choose one and stick with it. Also check your entire patch series' code for consistency. > +static DEVICE_ATTR(dump_packets, S_IRUGO | S_IWUSR, > + show_dump_packets, store_dump_packets); We have helpers, like DEVICE_ATTR_RW(). > + ret = snprintf(buf + pos, PAGE_SIZE - pos, > + "\ntx: %u, rx: %u, err: %u\n\n", > + total, > + priv->pm.stats.can_rx_overflows[i], > + priv->pm.stats.can_err_overflows[i]); Please, avoid leading '\n'. > + gpio_set_value(priv->cs_gpios, priv->cs_gpios_assert); > + gpio_set_value(priv->cs_gpios, !priv->cs_gpios_assert); Can you switch to GPIO descriptor API? > + unsigned int count = READY_POLL_US / READY_POLL_US_GRAN; > + while (count--) { For counting like this better to have do { } while (--count); The rationale, reader at first glance will know that the loop will iterate at least once. > + if (slave_is_not_busy(priv)) > + return 0; > + > + udelay(READY_POLL_US_GRAN); Should it be atomic? Can it use read_poll_* type of helpers instead? > + } Above comments applicable to entire code you have. > +static void companion_spi_cpu_to_be32(char *buf) > +{ > + u32 *buf32 = (u32*)buf; > + int i; > + > + for (i = 0; i < (BCP_PACKET_SIZE / sizeof(u32)); i++, buf32++) > + *buf32 = cpu_to_be32(*buf32); > +} This entire function should be replaced by one of the helpers from include/linux/byteorder/generic.h I guess cpu_to_be32_array() is a right one. > +static void companion_spi_be32_to_cpu(char *buf) > +{ > + u32 *buf32 = (u32*)buf; > + int i; > + > + for (i = 0; i < (BCP_PACKET_SIZE / sizeof(u32)); i++, buf32++) > + *buf32 = be32_to_cpu(*buf32); > +} Ditto. Recommendation: check your code against existing helpers. > + p = (const struct companion_packet*)transfer->tx_buf; > + companion_spi_cpu_to_be32((char*)transfer->tx_buf); If tx_buf is type of void * all these castings are redundant. Also looking at the function, did you consider to use whatever SPI core provides, like CS handling, messages handling and so on? > +static int companion_spi_thread(void *data) > +{ > + struct companion_spi_priv *priv = data; > + struct companion_packet tx_packet; > + struct companion_packet rx_packet; > + struct spi_message message; > + struct spi_transfer transfer; > + > + memset(&transfer, 0, sizeof(transfer)); > + transfer.tx_buf = tx_packet.data; > + transfer.rx_buf = rx_packet.data; > + transfer.len = sizeof(struct companion_packet); > + transfer.cs_change = 0; Redundant. > + transfer.bits_per_word = 32; > + > + for (;;) { Infinite loops are evil in most of the cases. I see here do { } while (kthread_should_stop()); > + if (wait_event_interruptible(priv->wait, > + kthread_should_stop() || > + slave_has_request(priv) || > + qm_has_tx_data(&priv->pm.qm))) > + continue; > + > + if (kthread_should_stop()) > + break; > + > + pm_prepare_tx(&priv->pm, &tx_packet); > + companion_spi_transceive(priv, &message, &transfer); > + pm_on_tx_done(&priv->pm); > + pm_on_rx_done(&priv->pm, &rx_packet); > + } > + > + return 0; > +} > +static const struct of_device_id companion_spi_of_match[] = { > + { .compatible = DRIVER_NAME, .data = NULL, }, > + { /* sentinel */ }, terminators better without commas. > +}; > +static struct spi_driver companion_spi_driver = { > + .driver = { > + .name = DRIVER_NAME, > + .owner = THIS_MODULE, This is redundant, macro you are using below sets that. > + .of_match_table = of_match_ptr(companion_spi_of_match), > + }, > + .probe = companion_spi_probe, > + .remove = companion_spi_remove, > +}; > +module_spi_driver(companion_spi_driver); > +static void io_process(struct companion_protocol_manager *pm, > + const struct companion_packet *p) Something wrong with indentation in this file. > +#define CHECK_SIZE(x) BUILD_BUG_ON(sizeof(struct companion_packet) != \ > + sizeof(x)) Better to split like _SIZE(x) \ BUILD_BUG_ON() > +void pm_init(struct companion_protocol_manager *pm) Unfortunately, horrible name for the function. Namespace is kinda occupied, name itself way too generic. > + if (ctrl & CAN_CTRLMODE_LISTENONLY) > + p.mode = BCP_CAN_MODE_LISTEN; > + else > + return -EOPNOTSUPP; if (!(cond)) return -ERRNO; ? > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. Do you still need this text? > + * TODO: add more statistics fields and export to sysfs Do it or remove the comment? > + * TODO: re-think the data structure for handle CAN response Ditto. > +/** > + * BCP status field definitions > + */ > +#define BCP_STATUS_SUCCESS 0x00u > +#define BCP_STATUS_UNKNOWN 0x01u > +#define BCP_STATUS_OTHER 0x02u BIT() ? > +struct companion_packet { > + __u8 data[BCP_PACKET_SIZE]; > +}; Is it going from / to user space? Otherwise why __ kind of type? > +#define CAN_MAX_IN_A_ROW 8 > + > + > + Too many blank lines. > +int companion_do_can_err(struct device *parent, > + u8 port, > + struct can_berr_counter *bec, > + u8 *state, > + u8 *code); + blank line here. > +#define COMPANION_CAN_STATE_WARNING 0x01u > +#define COMPANION_CAN_STATE_PASSIVE 0x02u > +#define COMPANION_CAN_STATE_BUS_OFF 0x04u > +#define COMPANION_CAN_ERROR_STUFF 0x01u > +#define COMPANION_CAN_ERROR_FORM 0x02u > +#define COMPANION_CAN_ERROR_ACK 0x04u > +#define COMPANION_CAN_ERROR_BIT1 0x08u > +#define COMPANION_CAN_ERROR_BIT0 0x10u > +#define COMPANION_CAN_ERROR_CRC 0x20u > +#define COMPANION_CAN_ERROR_RXOV 0x80u BIT() ? -- With Best Regards, Andy Shevchenko