linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Wolfgang Grandegger <wg@grandegger.com>
To: Stefano Babic <sbabic@denx.de>, linux-can@vger.kernel.org
Cc: socketcan@hartkopp.net, Marc Kleine-Budde <mkl@pengutronix.de>
Subject: Re: [PATCH v2 3/3] CAN: CAN driver to support multiple CAN bus on SPI interface
Date: Mon, 07 Apr 2014 11:34:51 +0200	[thread overview]
Message-ID: <5342713B.4000605@grandegger.com> (raw)
In-Reply-To: <534261D0.8060802@denx.de>

On 04/07/2014 10:29 AM, Stefano Babic wrote:
> Hi Wolfgang,
> 
> On 06/04/2014 17:20, Wolfgang Grandegger wrote:
>> Hi Stefan,
>>
>> sorry for jumping in late...
> 
> No problem..but you picked up V2. Some of the issues you see are already
> solved in V3, some not, and some are new. I add here some comments when
> there are still unsolved issues.

My bad. I picked an old version.

>> This driver is rather special in various
>> respects. As I see it, it does not support:
>>
>>   - loopback (echo_skbs)
>>   - error state handling
>>   - any error reporting (CAN error messages)
>>   - any error counting (net and CAN stats)
>>   - recovery from bus-off
>>
>> Any chance to improve on that? At least some kind of error reporting
>> would be nice otherwise the app does not realize any problems. Or how
>> does your app handle error cases.
> 
> About IFF_ECHO: in my understanding, by enabling IFF_ECHO the driver
> should sent messages back to the upper layer as fast as these messages
> are put on the bus. As I see in most drivers, can_put_echo() is called
> directly into the ISR for most drivers.

Yes, actually when TX is done.

http://lxr.linux.no/#linux+v2.6.37/Documentation/networking/can.txt#L176

> This driver implements a sort of "remote CAN". I do not know when
> messages are really put on the bus, because this is done by the
> microcontroller and not by the Main Controller. There is always a
> latency due to the fact that I can only enqueue messages on the SPI Bus
> using the SPI framework, letting the microcontroller doing the rest.
> Because I do not know when messages are really sent, I thought it makes
> little sense to implement echo_skbs. I did it during the development
> (you have found tracks of it), but I dropped later. IMHO this driver
> should not turn on IFF_ECHO.

To get that working the firmware must send some notification when TX is
done... which will be delayed, of course. It's still regarded to be
better than the loopback done by the protocol layer anyway. The GS_USB
driver does it for example. But I understand your concerns. Also the TX
done notification requires resources and bandwidth especially when the
firmware must handle 5 CAN buses concurrently.  It would reduce the TX
rate for sure.
BTW: does the work-queue handling limit the maximum TX rate? If yes,
threaded interrupts might be the better solution.

> Agree that it should be nice to have some error reporting from the
> microcontroller. However, it seeems quite difficult for the firmware
> developers to get it. There is currently no error reporting to the main
> controller, and if I do something in this direction, it remains untested
> because I cannot get the related firmware. I will really prefer to let
> the driver in, even if this feature is not implemented, and add it later
> when there is a use case for it.

OK, thinking more about it, a simple state handling is more important
than error reporting and it should be rather simple to implement in
firmware. It also does not require a lot of resources.

>>> +/* Default Values */
>>> +static struct can_bittiming_const spi_can_bittiming_const = {
>>> +	.name = DRV_NAME,
>>> +	.tseg1_min = 4,
>>> +	.tseg1_max = 16,
>>> +	.tseg2_min = 2,
>>> +	.tseg2_max = 8,
>>> +	.sjw_max = 4,
>>> +	.brp_min = 1,
>>> +	.brp_max = 64,
>>> +	.brp_inc = 1,
>>> +};
>>
>> Hm, this is specific to the hardware and should not be set globally. Do
>> you need/use it at all. Typically CAN handled by firmware does use
>> rather fixed bit timing parameters. Just the bit-rate can usually be
>> specified.
> 
> Changed in V3, but with the goal in V4 to query the microcontroller at
> the start for the timing.

There is no need for that. Just the bit-rate should be reported properly.

...

>>> +static int spi_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
>>> +{
>>> +	struct spi_can_priv *priv = netdev_priv(dev);
>>> +	struct spi_can_data	*spi_priv = priv->spi_priv;
>>> +	struct msg_queue_tx *tx_pkt;
>>> +	unsigned long flags;
>>> +
>>> +	if (can_dropped_invalid_skb(dev, skb))
>>> +		return NETDEV_TX_OK;
>>> +
>>> +	tx_pkt = kzalloc(sizeof(struct msg_queue_tx), GFP_KERNEL);
>>> +	tx_pkt->channel = priv->channel;
>>> +	tx_pkt->skb = skb;
>>> +	tx_pkt->type = SPI_MSG_SEND_DATA;
>>> +	INIT_LIST_HEAD(&(tx_pkt->list));
>>> +
>>> +	/* Add the incoming message to the end of the list */
>>> +	spin_lock_irqsave(&spi_priv->lock, flags);
>>> +	list_add_tail(&(tx_pkt->list), &(spi_priv->msgtx.list));
>>> +	spi_priv->messages_in_queue++;
>>
>> You probabley may want to limit the number of TX messages to be queued.
>> Otherwise the system may even run out of memory... if I understand the
>> code correctly
> 
> You understand right. In my tests, I observed the evolution of
> messages_in_queue to be sure that it does not increase indefinetely
> under heavier bus load, without setting a limit. Agree we need a higher
> limit, I will do it.

Should be rather simple to implement.

>>> +static void spi_can_process_single_frame(struct spi_can_data *spi_data,
>>> +	u32 index)
>>> +{
>>> +	struct list_head *pos;
>>> +	struct msg_queue_rx *msg;
>>> +	u32 found = 0, freed;
>>
>> Why is "int" not just fine.
> 
> For what ? Both are used as boolean, unsigned is right.

Yes, but there is no need for "u32". "unsigned int" should just be fine.
I use the u32 and friends only when the size is fixed, e.g. due to
hardware requirements. In all other cases I use "[unsigned] int" or
"long". But maybe that's also debatable.

...

>>> +static int spi_can_probe(struct spi_device *spi)
>>> +{
>>> +	struct net_device *dev;
>>> +	struct spi_can_platform_data *pdata = spi->dev.platform_data;
>>> +	int ret = -ENODEV;
>>> +	struct spi_can_data *spi_data;
>>> +	struct spi_can_priv *priv;
>>> +	int index, i;
>>> +	u32 can_channels;
>>> +	u32 active = GPIO_ACTIVE_LOW;
>>> +	int data_gpio;
>>> +	u32 flags;
>>> +
>>> +	if (spi->dev.of_node) {
>>> +		if (of_property_read_u32(spi->dev.of_node,
>>> +			    "channels", &can_channels))
>>> +			return -ENODEV;
>>> +		if (!slow_freq) {
>>> +			of_property_read_u32(spi->dev.of_node,
>>> +			    "slowfreq", &slow_freq);
>>> +		}
>>> +		if (!freq) {
>>> +			of_property_read_u32(spi->dev.of_node,
>>> +			    "freq", &freq);
>>> +		}
>>> +		data_gpio = of_get_gpio_flags(spi->dev.of_node,
>>> +				0, &flags);
>>> +		active = (flags & GPIO_ACTIVE_LOW) ? 0 : 1;
>>> +	} else {
>>> +		if (!pdata || (pdata->can_channels < 0) ||
>>> +			(pdata->can_channels > MAX_CAN_CHANNELS))
>>> +			return -ENODEV;
>>> +		if (pdata->slow_freq)
>>> +			slow_freq = pdata->slow_freq;
>>> +		data_gpio = pdata->gpio;
>>> +		active = pdata->active;
>>> +		can_channels = pdata->can_channels;
>>> +	}
>>> +
>>> +	if (!gpio_is_valid(data_gpio)) {
>>> +		dev_err(&spi->dev,
>>> +			"Wrong data valid GPIO: %d\n",
>>> +			data_gpio);
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	dev_info(&spi->dev, "Channels: %d, gpio %d active %s\n",
>>> +				can_channels,
>>> +				data_gpio,
>>> +				active ? "high" : "low");
>>> +	/* It is possible to adjust frequency at loading time
>>> +	 * if the driver is compiled as module
>>> +	 */
>>> +	if (freq) {
>>> +		if (freq > spi->max_speed_hz) {
>>> +			dev_err(&spi->dev,
>>> +				"Frequency too high: %d Hz > %d Hz. Falling back to %d\n",
>>> +				freq,
>>> +				spi->max_speed_hz,
>>> +				spi->max_speed_hz);
>>> +			freq = spi->max_speed_hz;
>>> +		}
>>> +	}
>>> +
>>> +	/* Check if the supervisor frequency is passed as parameter
>>> +	 * Fallback to 1 Mhz
>>> +	 */
>>> +	if (!slow_freq)
>>> +		slow_freq = SLAVE_SUPERVISOR_FREQ;
>>> +
>>> +	if ((freq && (slow_freq > freq)) ||
>>> +		(slow_freq > SLAVE_SUPERVISOR_FREQ)) {
>>> +		dev_err(&spi->dev,
>>> +			"Supervisor frequency too high: %d Hz > %d Hz. Falling back to %d\n",
>>> +			slow_freq,
>>> +			min(freq, SLAVE_SUPERVISOR_FREQ),
>>> +			min(freq, SLAVE_SUPERVISOR_FREQ));
>>> +			slow_freq = min(freq, SLAVE_SUPERVISOR_FREQ);
>>> +	}
>>> +
>>> +	ret = gpio_request(data_gpio, "spican-irq");
>>> +	if (ret) {
>>> +		dev_err(&spi->dev,
>>> +			"gpio %d cannot be acquired\n",
>>> +			data_gpio);
>>> +		return -ENODEV;
>>
>> Please use goto for cleanup...
> 
> I can do it. Anyway, at this level in probe I have not yet reserved any
> resource, and returning with an error is not wrong. I have nothing to
> free in the cleanup at this point.

You are right. I thought free_irq() or free_gpio() is missing. Maybe
that was some lines later.

Wolfgang.


  reply	other threads:[~2014-04-07  9:35 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-25 14:30 [PATCH v2 0/3] Adding support for CAN busses via SPI interface Stefano Babic
2014-03-25 14:30 ` [PATCH v2 1/3] Add documentation for SPI to CAN driver Stefano Babic
2014-03-25 18:14   ` Oliver Hartkopp
2014-03-26  8:07     ` Stefano Babic
2014-03-25 14:30 ` [PATCH v2 2/3] CAN: moved SPI drivers into a separate directory Stefano Babic
2014-03-25 18:56   ` Oliver Hartkopp
2014-04-01 21:08   ` Marc Kleine-Budde
2014-03-25 14:30 ` [PATCH v2 3/3] CAN: CAN driver to support multiple CAN bus on SPI interface Stefano Babic
2014-03-25 18:54   ` Oliver Hartkopp
2014-03-26  9:01     ` Stefano Babic
2014-04-06 15:20   ` Wolfgang Grandegger
2014-04-06 19:01     ` Oliver Hartkopp
2014-04-06 19:22       ` Wolfgang Grandegger
2014-04-06 19:42         ` Oliver Hartkopp
2014-04-07  8:29     ` Stefano Babic
2014-04-07  9:34       ` Wolfgang Grandegger [this message]
2014-04-07 10:24         ` Stefano Babic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5342713B.4000605@grandegger.com \
    --to=wg@grandegger.com \
    --cc=linux-can@vger.kernel.org \
    --cc=mkl@pengutronix.de \
    --cc=sbabic@denx.de \
    --cc=socketcan@hartkopp.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).