[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 8 Aug 2016 14:28:39 +0200
From: Wolfgang Grandegger <wg@...ndegger.com>
To: Andreas Werner <andreas.werner@....de>
Cc: mkl@...gutronix.de, linux-can@...r.kernel.org,
netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
davem@...emloft.net, jthumshirn@...e.de, andy@...nerandy.de,
michael.miehling@....de
Subject: Re: [PATCH RESEND] net: can: Introduce MEN 16Z192-00 CAN controller
driver
Hello,
Am 08.08.2016 um 13:39 schrieb Andreas Werner:
> On Mon, Aug 08, 2016 at 11:27:25AM +0200, Wolfgang Grandegger wrote:
>> Hello Andreas,
>>
>> a first quick review....
>>
>> Am 26.07.2016 um 11:16 schrieb Andreas Werner:
>>> This CAN Controller is found on MEN Chameleon FPGAs.
>>>
>>> The driver/device supports the CAN2.0 specification.
>>> There are 255 RX and 255 Tx buffer within the IP. The
>>> pointer for the buffer are handled by HW to make the
>>> access from within the driver as simple as possible.
>>>
>>> The driver also supports parameters to configure the
>>> buffer level interrupt for RX/TX as well as a RX timeout
>>> interrupt.
>>>
>>> With this configuration options, the driver/device
>>> provides flexibility for different types of usecases.
>>>
>>> Signed-off-by: Andreas Werner <andreas.werner@....de>
>>> ---
>>> drivers/net/can/Kconfig | 10 +
>>> drivers/net/can/Makefile | 1 +
>>> drivers/net/can/men_z192_can.c | 989 +++++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 1000 insertions(+)
>>> create mode 100644 drivers/net/can/men_z192_can.c
---snip---
>>> +/* Buffer level control values */
>>> +#define MEN_Z192_MIN_BUF_LVL 0
>>> +#define MEN_Z192_MAX_BUF_LVL 254
>>> +#define MEN_Z192_RX_BUF_LVL_DEF 5
>>> +#define MEN_Z192_TX_BUF_LVL_DEF 5
>>> +#define MEN_Z192_RX_TOUT_MIN 0
>>> +#define MEN_Z192_RX_TOUT_MAX 65535
>>> +#define MEN_Z192_RX_TOUT_DEF 1000
>>> +
>>> +static int txlvl = MEN_Z192_TX_BUF_LVL_DEF;
>>> +module_param(txlvl, int, S_IRUGO);
>>> +MODULE_PARM_DESC(txlvl, "TX IRQ trigger level (in frames) 0-254, default="
>>> + __MODULE_STRING(MEN_Z192_TX_BUF_LVL_DEF) ")");
>>> +
>>> +static int rxlvl = MEN_Z192_RX_BUF_LVL_DEF;
>>> +module_param(rxlvl, int, S_IRUGO);
>>> +MODULE_PARM_DESC(rxlvl, "RX IRQ trigger level (in frames) 0-254, default="
>>> + __MODULE_STRING(MEN_Z192_RX_BUF_LVL_DEF) ")");
>>> +
>>
>> What impact does the level have on the latency? Could you please add some
>> comments.
>
> It has a impact on the latency.
> rxlvl = 0 -> if one frame got received, a IRQ will be generated
> rxlvl = 254 -> if 255 frames got received, a IRQ will be generated
Well, what's your usecase for rxlvl > 0? For me it's not obvious what it
can be good for. The application usually wants the message as soon as
possible. Anyway, the default should be *0*. For RX and TX.
>>> +static int rx_timeout = MEN_Z192_RX_TOUT_DEF;
>>> +module_param(rx_timeout, int, S_IRUGO);
>>> +MODULE_PARM_DESC(rx_timeout, "RX IRQ timeout (in 100usec steps), default="
>>> + __MODULE_STRING(MEN_Z192_RX_TOUT_DEF) ")");
>>
>> Ditto. What is "rx_timeout" good for.
>>
>
> The rx timeout is used im combination with the rxlvl to assert the
> if the buffer level is not reached within this timeout.
What event will the application receive in case of a timeout.
> Both, the timeout and the level are used to give the user as much
> control over the latency and the IRQ handling as possible.
> With this two options, the driver can be configured for different
> use cases.
>
> I will add this as the comment to make it more clear.
Even a bit more would be appreciated.
---snip---
>>> +static int men_z192_read_frame(struct net_device *ndev, unsigned int frame_nr)
>>> +{
>>> + struct net_device_stats *stats = &ndev->stats;
>>> + struct men_z192 *priv = netdev_priv(ndev);
>>> + struct men_z192_cf_buf __iomem *cf_buf;
>>> + struct can_frame *cf;
>>> + struct sk_buff *skb;
>>> + u32 cf_offset;
>>> + u32 length;
>>> + u32 data;
>>> + u32 id;
>>> +
>>> + skb = alloc_can_skb(ndev, &cf);
>>> + if (unlikely(!skb)) {
>>> + stats->rx_dropped++;
>>> + return 0;
>>> + }
>>> +
>>> + cf_offset = sizeof(struct men_z192_cf_buf) * frame_nr;
>>> +
>>> + cf_buf = priv->dev_base + MEN_Z192_RX_BUF_START + cf_offset;
>>> + length = readl(&cf_buf->length) & MEN_Z192_CFBUF_LEN;
>>> + id = readl(&cf_buf->can_id);
>>> +
>>> + if (id & MEN_Z192_CFBUF_IDE) {
>>> + /* Extended frame */
>>> + cf->can_id = (id & MEN_Z192_CFBUF_ID1) >> 3;
>>> + cf->can_id |= (id & MEN_Z192_CFBUF_ID2) >>
>>> + MEN_Z192_CFBUF_ID2_SHIFT;
>>> +
>>> + cf->can_id |= CAN_EFF_FLAG;
>>> +
>>> + if (id & MEN_Z192_CFBUF_E_RTR)
>>> + cf->can_id |= CAN_RTR_FLAG;
>>> + } else {
>>> + /* Standard frame */
>>> + cf->can_id = (id & MEN_Z192_CFBUF_ID1) >>
>>> + MEN_Z192_CFBUF_ID1_SHIFT;
>>> +
>>> + if (id & MEN_Z192_CFBUF_S_RTR)
>>> + cf->can_id |= CAN_RTR_FLAG;
>>> + }
>>> +
>>> + cf->can_dlc = get_can_dlc(length);
>>> +
>>> + /* remote transmission request frame
>>> + * contains no data field even if the
>>> + * data length is set to a value > 0
>>> + */
>>> + if (!(cf->can_id & CAN_RTR_FLAG)) {
>>> + if (cf->can_dlc > 0) {
>>> + data = readl(&cf_buf->data[0]);
>>> + *(__be32 *)cf->data = cpu_to_be32(data);
>>
>> Do you really need the extra copy?
>>
>>> + }
>>> + if (cf->can_dlc > 4) {
>>> + data = readl(&cf_buf->data[1]);
>>> + *(__be32 *)(cf->data + 4) = cpu_to_be32(data);
>>
>> Ditto.
>
> No its not really needed. I thought its more clean and more readable than
> putting this in one line withouth the copy.
It should be fast in the first place.
>>
>>> + }
>>> + }
>>> +
>>> + stats->rx_bytes += cf->can_dlc;
>>> + stats->rx_packets++;
>>> + netif_receive_skb(skb);
>>> +
>>> + return 1;
>>
>>> +}
---snip---
>>> +static int men_z192_xmit(struct sk_buff *skb, struct net_device *ndev)
>>> +{
>>> + struct can_frame *cf = (struct can_frame *)skb->data;
>>> + struct men_z192 *priv = netdev_priv(ndev);
>>> + struct men_z192_regs __iomem *regs = priv->regs;
>>> + struct net_device_stats *stats = &ndev->stats;
>>> + struct men_z192_cf_buf __iomem *cf_buf;
>>> + u32 data[2] = {0, 0};
>>> + int status;
>>> + u32 id;
>>> +
>>> + if (can_dropped_invalid_skb(ndev, skb))
>>> + return NETDEV_TX_OK;
>>> +
>>> + status = readl(®s->rx_tx_sts);
>>> +
>>> + if (MEN_Z192_TX_BUF_CNT(status) >= 255) {
>>> + netif_stop_queue(ndev);
>>> + netdev_err(ndev, "not enough space in TX buffer\n");
>>> +
>>> + return NETDEV_TX_BUSY;
>>> + }
>>
>> Please try to avoid NETDEV_TX_BUSY by stopping the queue earlier (if buf_cnt
>> == 254).
>>
>
> Agree with you, will fix that.
>
>>> + cf_buf = priv->dev_base + MEN_Z192_TX_BUF_START;
>>> +
>>> + if (cf->can_id & CAN_EFF_FLAG) {
>>> + /* Extended frame */
>>> + id = ((cf->can_id & CAN_EFF_MASK) <<
>>> + MEN_Z192_CFBUF_ID2_SHIFT) & MEN_Z192_CFBUF_ID2;
>>> +
>>> + id |= (((cf->can_id & CAN_EFF_MASK) >>
>>> + (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS)) <<
>>> + MEN_Z192_CFBUF_ID1_SHIFT) & MEN_Z192_CFBUF_ID1;
>>> +
>>> + id |= MEN_Z192_CFBUF_IDE;
>>> + id |= MEN_Z192_CFBUF_SRR;
>>> +
>>> + if (cf->can_id & CAN_RTR_FLAG)
>>> + id |= MEN_Z192_CFBUF_E_RTR;
>>> + } else {
>>> + /* Standard frame */
>>> + id = ((cf->can_id & CAN_SFF_MASK) <<
>>> + MEN_Z192_CFBUF_ID1_SHIFT) & MEN_Z192_CFBUF_ID1;
>>> +
>>> + if (cf->can_id & CAN_RTR_FLAG)
>>> + id |= MEN_Z192_CFBUF_S_RTR;
>>> + }
>>> +
>>> + if (cf->can_dlc > 0)
>>> + data[0] = be32_to_cpup((__be32 *)(cf->data));
>>> + if (cf->can_dlc > 3)
>>> + data[1] = be32_to_cpup((__be32 *)(cf->data + 4));
>>
>> Not necessary if RTR.
>>
>
> Argh, right...
>
>>> + writel(id, &cf_buf->can_id);
>>> + writel(cf->can_dlc, &cf_buf->length);
>>> +
>>> + if (!(cf->can_id & CAN_RTR_FLAG)) {
>>> + writel(data[0], &cf_buf->data[0]);
>>> + writel(data[1], &cf_buf->data[1]);
>>
>> Why do you not check cf->can_dlc here as well. And is the extra copy
>> necessary.
>>
>
> Yes, I agree with you. The extra copy could be also avoided.
>
>>> +
>>> + stats->tx_bytes += cf->can_dlc;
>>> + }
>>
>> If I look to other drivers, they write the data even in case of RTR.
>>
>
> But why?
>
> A RTR does not have any data, therefore there is no need to write the data.
> Only the length is required as the request size.
Yes; I'm wondering as well.
>
> If there is a reason behind writing the data of a RTR frame, I can
> change that, but for now there is no reason.
Yep.
>
>>> + /* be sure everything is written to the
>>> + * device before acknowledge the data.
>>> + */
>>> + mmiowb();
>>> +
>>> + /* trigger the transmission */
>>> + men_z192_ack_tx_pkg(priv, 1);
>>> +
>>> + stats->tx_packets++;
>>> +
>>> + kfree_skb(skb);
>>> +
>>> + return NETDEV_TX_OK;
>>> +}
>>> +
>>> +static void men_z192_err_interrupt(struct net_device *ndev, u32 status)
>>> +{
>>> + struct net_device_stats *stats = &ndev->stats;
>>> + struct men_z192 *priv = netdev_priv(ndev);
>>> + struct can_berr_counter bec;
>>> + struct can_frame *cf;
>>> + struct sk_buff *skb;
>>> + enum can_state rx_state = 0, tx_state = 0;
>>> +
>>> + skb = alloc_can_err_skb(ndev, &cf);
>>> + if (unlikely(!skb))
>>> + return;
>>> +
>>> + /* put the rx/tx error counter to
>>> + * the additional controller specific
>>> + * section of the error frame.
>>> + */
>>> + men_z192_get_berr_counter(ndev, &bec);
>>> + cf->data[6] = bec.txerr;
>>> + cf->data[7] = bec.rxerr;
>>> +
>>> + /* overrun interrupt */
>>> + if (status & MEN_Z192_RFLG_OVRF) {
>>> + cf->can_id |= CAN_ERR_CRTL;
>>> + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
>>> + stats->rx_over_errors++;
>>> + stats->rx_errors++;
>>> + }
>>> +
>>> + /* bus change interrupt */
>>> + if (status & MEN_Z192_RFLG_CSCIF) {
>>> + rx_state = bus_state_map[MEN_Z192_GET_RSTATE(status)];
>>> + tx_state = bus_state_map[MEN_Z192_GET_TSTATE(status)];
>>> + can_change_state(ndev, cf, tx_state, rx_state);
>>> +
>>> + if (priv->can.state == CAN_STATE_BUS_OFF)
>>> + can_bus_off(ndev);
>>> + }
>>
>> Does the controller only provide state change events? What about other
>> errors?
>>
>
> I thought that somebody will ask. The controller does only the state change events
> and the overrun error. Nothing more.
>
> I saw the error flags in many other drivers, but they are not existing
> in my controller.
No problem. Just to be sure.
>
>>> +
>>> + stats->rx_packets++;
>>> + stats->rx_bytes += cf->can_dlc;
>>> + netif_receive_skb(skb);
>>> +}
---snip---
>>> +void men_z192_set_can_state(struct net_device *ndev)
>>> +{
>>> + struct men_z192 *priv = netdev_priv(ndev);
>>> + struct men_z192_regs __iomem *regs = priv->regs;
>>> + enum can_state rx_state, tx_state;
>>> + u32 status;
>>> +
>>> + status = readl(®s->rx_tx_sts);
>>> +
>>> + rx_state = bus_state_map[MEN_Z192_GET_RSTATE(status)];
>>> + tx_state = bus_state_map[MEN_Z192_GET_TSTATE(status)];
>>> +
>>> + priv->can.state = max(tx_state, rx_state);
>>> +}
>>> +
>>> +static int men_z192_start(struct net_device *ndev)
>>> +{
>>> + struct men_z192 *priv = netdev_priv(ndev);
>>> + int ret;
>>> +
>>> + ret = men_z192_req_init_mode(priv);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + ret = men_z192_set_bittiming(ndev);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + ret = men_z192_req_run_mode(priv);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + men_z192_init_idac(ndev);
>>> +
>>> + /* The 16z192 CAN IP does not reset the can bus state
>>> + * if we enter the init mode. There is also
>>> + * no software reset to reset the state machine.
>>> + * We need to read the current state, and
>>> + * inform the upper layer about the current state.
>>> + */
>>> + men_z192_set_can_state(ndev);
>>
>> Hm, the application expected the state to be reset. Calling
>> "can_change_state()" in "men_z192_set_can_state()" does make sense.
>>
>
> Hm yes, but the IP is saving the state, this cannot be avoided.
> can_change_state() makes sense yes, I will add it.
>
>>> +
>>> + men_z192_set_int(priv, MEN_Z192_CAN_EN);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int men_z192_set_mode(struct net_device *ndev, enum can_mode mode)
>>> +{
>>> + int ret;
>>> +
>>> + switch (mode) {
>>> + case CAN_MODE_START:
>>> + ret = men_z192_start(ndev);
>>> + if (ret)
>>> + return ret;
>>
>> "if (ret)" means always an error. Therefore s/ret/err/ is clearer. Here and
>> in many other places.
>>
>
> Yes and no. I think its a general question about the naming of those variables.
> I will check all the variables in the driver if it really makes sense
> to rename it.
>
> For my opinion, "ret" is more generic. But you are right, "err" would be more
> readable in some places.
if (err)
makes immediately clear that it's an error case. ret is more general,
e.g. for the return value of read/write:
if (ret < 0)
error-case
else if (ret == 0)
end-of-file
else
btyes-read
Just my personal preference to make the code more readable.
>>> +
>>> + netif_wake_queue(ndev);
>>> + break;
>>> + default:
>>> + return -EOPNOTSUPP;
>>> + }
>>> +
>>> + return 0;
>>> +static int men_z192_probe(struct mcb_device *mdev,
>>> + const struct mcb_device_id *id)
>>> +{
>>> + struct device *dev = &mdev->dev;
>>> + struct men_z192 *priv;
>>> + struct net_device *ndev;
>>> + void __iomem *dev_base;
>>> + struct resource *mem;
>>> + u32 timebase;
>>> + int ret = 0;
>>> + int irq;
>>> +
>>> + mem = mcb_request_mem(mdev, dev_name(dev));
>>> + if (IS_ERR(mem)) {
>>> + dev_err(dev, "failed to request device memory");
>>> + return PTR_ERR(mem);
>>> + }
>>> +
>>> + dev_base = ioremap(mem->start, resource_size(mem));
>>> + if (!dev_base) {
>>> + dev_err(dev, "failed to ioremap device memory");
>>> + ret = -ENXIO;
>>> + goto out_release;
>>> + }
>>> +
>>> + irq = mcb_get_irq(mdev);
>>> + if (irq <= 0) {
>>> + ret = -ENODEV;
>>> + goto out_unmap;
>>> + }
>>> +
>>> + ndev = alloc_candev(sizeof(struct men_z192), 1);
>>
>> You specify here one echo_skb but it's not used anywhere. Local loopback
>> seems not to be implemented.
>>
>
> Agree with you, will set it to "0".
No, the local loopback is mandetory!
Wolfgang.
Powered by blists - more mailing lists