Read my comment again. I never mentioned err vs. ret.if (err) {Opened Eclipse, searched for "if (err != 0)" in the kernel code. 290
matches. For "if (ret != 0)" I found now 1970 matches.
I am asking to replace "if (err != 0)" by "if (err)". We are not
using MISRA and there is no concept of essential boolean type here.
You can pass an integer to an if ().
I do not use eclipse, but git can give a few relevant statistics:
$ git grep "if (err != 0)" | wc -l
277
$ git grep "if (err)" | wc -l
34307
And while this is not the topic, "ret" is more popular than "err":
$ git grep "if (ret != 0)" | wc -l
1956
$ git grep "if (ret)" | wc -l
67927
but both are well established usage so I do not really care which one
of "ret" or "err" you use.
...+ /* Not expected to happen */
+ dev_err(dev, "%s(): virtqueue_add_sgs() failed\n", __func__);
+ }
+
+ if (!virtqueue_kick(vq)) {
+ /* Not expected to happen */
+ dev_err(dev, "%s(): Kick failed\n", __func__);
+ }
+
+ while (!virtqueue_get_buf(vq, &len) && !virtqueue_is_broken(vq))
+ wait_for_completion(&priv->ctrl_done);
+
+ mutex_unlock(&priv->ctrl_lock);
+
+ return priv->cpkt_in.result;
+}
Ooopsy on my side. sgs is an array of pointers so the above is not equivalent.+static netdev_tx_t virtio_can_start_xmit(struct sk_buff *skb,Instead declaring two times an array of 1, can we do:
+ struct net_device *dev)
+{
+ struct virtio_can_priv *priv = netdev_priv(dev);
+ struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+ struct virtio_can_tx *can_tx_msg;
+ struct virtqueue *vq = priv->vqs[VIRTIO_CAN_QUEUE_TX];
+ struct scatterlist sg_out[1];
+ struct scatterlist sg_in[1];
+ struct scatterlist *sgs[2];
struct scatterlist sgs[2];
And doing this:
struct scatterlist *sgs[2];
Would be problematic as the memory of the two elements would not be allocated.
ACK. My second example does that:and then use sgs[0] for out and sgs[1] for in?Makes thing worse. I'm not even sure whether this is a null change only
Or, if you really want to keep sg_out and sg_in, at least do:
struct scatterlist sg_out, sg_in;
struct scatterlist *sgs[] = {&sg_out, &sg_in};
N.B. The same comment also applies to the other places where you are
doing some sg[1] declarations.
or introduces a problem.
virtio strictly separates devices readable and device writeable data.
Therefore I want really to have here 2 separate definitions. The one is
data to the device, the other is data from the device.
struct scatterlist sg_out, sg_in;
struct scatterlist *sgs[] = {&sg_out, &sg_in};
ACK. Checked this also now, saw &foo[0] once or so.If this had any advantage, I could separate the data further. Forsg_out and sg_in are only passed to one function: sg_init_one(). And
example I could separate the payload from the preceding data. In this
case I had struct scatterlist sg_out[2]. As long as the payload is
small the memcpy for the payload can be justified and [1] is good. In
fact, those are still arrays even if by coincident now the number of
elements is 1.
as the name suggests, sg_init_one expects a single scatterlist, not an
array.
A look at:
$ git grep sg_init_one
show me that doing as "sg_init_one(&foo[0], ...)" is not a popular
solution. The majority does sg_init_one(&foo, ...).
I do get that sgs is an array of arrays. I am just not comfortableI missed here to update the number of dropped messages.
with sg_out and sg_in being declared as arrays because these never get
used as such.
+ unsigned long flags;
+ u32 can_flags;
+ int err;
+ int putidx;
+ netdev_tx_t xmit_ret = NETDEV_TX_OK;
+ const unsigned int hdr_size = offsetof(struct virtio_can_tx_out, sdu);
+
+ if (can_dev_dropped_skb(dev, skb))
+ goto kick; /* No way to return NET_XMIT_DROP here */
+
+ /* No local check for CAN_RTR_FLAG or FD frame against negotiated
+ * features. The device will reject those anyway if not supported.
+ */
+
+ can_tx_msg = kzalloc(sizeof(*can_tx_msg), GFP_ATOMIC);
+ if (!can_tx_msg)
+ goto kick; /* No way to return NET_XMIT_DROP here */
Yes, and you can use the ERR_PTR() to turn your int into an error pointer.%pe does not do that. It works for an error coded in a pointer. I have+ida_alloc_range() can also return -ENOMEM. So the error is not
+ can_tx_msg->tx_out.msg_type = cpu_to_le16(VIRTIO_CAN_TX);
+ can_flags = 0;
+
+ if (cf->can_id & CAN_EFF_FLAG) {
+ can_flags |= VIRTIO_CAN_FLAGS_EXTENDED;
+ can_tx_msg->tx_out.can_id = cpu_to_le32(cf->can_id & CAN_EFF_MASK);
+ } else {
+ can_tx_msg->tx_out.can_id = cpu_to_le32(cf->can_id & CAN_SFF_MASK);
+ }
+ if (cf->can_id & CAN_RTR_FLAG)
+ can_flags |= VIRTIO_CAN_FLAGS_RTR;
+ else
+ memcpy(can_tx_msg->tx_out.sdu, cf->data, cf->len);
+ if (can_is_canfd_skb(skb))
+ can_flags |= VIRTIO_CAN_FLAGS_FD;
+
+ can_tx_msg->tx_out.flags = cpu_to_le32(can_flags);
+ can_tx_msg->tx_out.length = cpu_to_le16(cf->len);
+
+ /* Prepare sending of virtio message */
+ sg_init_one(&sg_out[0], &can_tx_msg->tx_out, hdr_size + cf->len);
+ sg_init_one(&sg_in[0], &can_tx_msg->tx_in, sizeof(can_tx_msg->tx_in));
+ sgs[0] = sg_out;
+ sgs[1] = sg_in;
+
+ putidx = virtio_can_alloc_tx_idx(priv);
+
+ if (unlikely(putidx < 0)) {
+ netif_stop_queue(dev);
+ kfree(can_tx_msg);
+ netdev_warn(dev, "TX: Stop queue, no putidx available\n");
necessarily because of no putidx available. Maybe better to print the
error message (with %pe to show the mnemotechnic).
here an int.
Do:
$ git grep -A1 "%pe"
if you need examples.
Now that you say it, it rings a bell.VIRTIO_CAN_F_RTR_FRAMES is a feature flag. RTR frames may or may not be
Why do we need both VIRTIO_CAN_F_RTR_FRAMES VIRTIO_CAN_FLAGS_RTR?
Is it to manage devices not able to sent remote frames? If so, we may
also need to add a CAN_CTRLMODE_RTR in linux/can/netlink.h?
supported. AUTOSAR CAN drivers do not know anything about RTR frames.
So indeed, we will probably need a new flag in can/netlink.h to report
to the userland whether a device is capable or not to manage remote
frames.
if someone wants to build a virtio CAN device on top of an AUTOSAR CANACK.
driver with the additional requirement not to change the existing
AUTOSAR CAN driver RTR frames cannot be supported and the feature flag
won't be offered by the virtio device.
VIRTIO_CAN_FLAGS_RTR is a bit to indicate a frame type in a CAN message.
Used internally in an Linux SocketCAN interface.
On a side note, did you have a look at:
https://ddec1-0-en-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2felixir.bootlin.com%2flinux%2flatest%2fsource%2finclude%2fuapi%2flinux%2fcan%2fnetlink.h%23L95&umid=0b3549ac-d010-4d96-a348-2702485d82af&auth=53c7c7de28b92dfd96e93d9dd61a23e634d2fbec-75dedb6bf65ef4342bf7c18b89f4f30ed7dc9dc6
?
It lists the different hardware capabilities which may or may not be
present at the hardware level. This list can be used as an input to
decide how to extend the feature bit list.
Sorry, but I do not buy this argument. Do you really now AUTOSARLooked into the AUTOSAR_SWS_StandardTypes.pdf Std_ReturnType:+Silly question, but what is the rationale of not using the error code
+/* CAN Result Types */
+#define VIRTIO_CAN_RESULT_OK 0
+#define VIRTIO_CAN_RESULT_NOT_OK 1
from errno.h?
E_OK = 0
E_NOT_OK = 1
other are "Available for user specific errors" like CAN_BUSY.
Linux is only one operating system. An important one but there are
others. AUTOSAR people may ask you "What is errno.h?" (and also "What is
malloc?").
developpers who do not know about malloc()?
Our internal client is interested in a Virtio AUTOSAR CANIs it AUTOSAR Classic or AUTOSAR Adaptive?
driver. So there were reasons to look first into AUTOSAR.
AUTOSAR Adaptive is POSIX (to some extends):
[SWS_OSI_01001] POSIX PSE51 Interface: [The OSI shall provide OS
functionality with POSIX PSE51 interface, according to the
1003.13-2003 specification.]
Ref: AUTOSAR AP R22-11 - Specification of Operating System Interface
https://ddec1-0-en-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fwww.autosar.org%2ffileadmin%2fstandards%2fR22%2d11%2fAP%2fAUTOSAR%5fSWS%5fOperatingSystemInterface.pdf&umid=0b3549ac-d010-4d96-a348-2702485d82af&auth=53c7c7de28b92dfd96e93d9dd61a23e634d2fbec-1b9dde25c1a8497018be33058ca535bcfe2c272a
There is also a CAN_BUSY for the AUTOSAR Can_Write() to be returned butThat's my point. ISO C is so predominant that those error codes are
this is not needed at this interface as a virtio AUTOSAR CAN driver was
busy when there are no sufficient messages available in the virtqueue,
so for this condition we need no defined error code to be used in a
virtio message.
Virtio block defines VIRTIO_BLK_S_OK 0, VIRTIO_BLK_S_IOERR 1,
VIRTIO_BLK_S_UNSUPP 2.
I do see that some other virtio devices do the same:I cannot speak for virtio. errno.h is ANSI C and POSIX but virtio does
https://ddec1-0-en-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2felixir.bootlin.com%2flinux%2fv4.6%2fsource%2finclude%2fuapi%2flinux%2fvirtio%5fnet.h%23L140&umid=0b3549ac-d010-4d96-a348-2702485d82af&auth=53c7c7de28b92dfd96e93d9dd61a23e634d2fbec-698619745d87a25323604ab5a614cc946b24e642
But I am genuinely curious to understand why virtio do not use more
standard error codes.
not only address those environments. It is a more general specification.
available nearly everywhere. And this being just some #define, it can
easily be integrated to the few system which do not have this header.
If there is a requirement to make virtio header self contained, then I
would understand why POSIX error code can not be used. But as I said,
I am genously curious to understand the reason behind this choice.
For the virtio RPMB device the result codes in the virtio specificationYes, I did ask here:
come for example directly from an JEDEC specification for eMMC. Which
has some connection to a JEDEC UFS specification, same result codes
there. Makes a lot of sense to use those result codes in this context.
As virtio is more general, I have for this also my doubts whether it
really was a good idea to take over the CAN RX and CAN TX message
definitions 1:1 from Linux (if this is possible). Someone proposed but
I've my doubts.
https://ddec1-0-en-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2flore.kernel.org%2flinux%2dcan%2fCAMZ6RqLALOYFWQJ4C4HTaRw7y%2dwaUbqOX0WzrWVNiQG51QexHw%40mail.gmail.com%2f&umid=0b3549ac-d010-4d96-a348-2702485d82af&auth=53c7c7de28b92dfd96e93d9dd61a23e634d2fbec-6453b89fa56fa0a97905d808b20a7df3eb16f85a
I am still waiting for your answer.
I do understand that Linux is not the only OS. However, it is the only
one with a complehensive set of open source CAN dirvers. Reusing the
Linux structures would allow to reuse bigger chunks of code,
decreasing the amount of effort needed implement drivers in the virtio
host.
That said, the POSIX error code and reusing the Linux CAN structures
are two different topics.
No, The DLC is coded on four bits and ranges from 0 to 15 for bothClassical CAN cannot have a DLC > 8. CAN FD has a length up to 64 bytes.+/* CAN flags to determine type of CAN Id */Can we use this field to report the classical CAN DLC greater than 8?
+#define VIRTIO_CAN_FLAGS_EXTENDED 0x8000
+#define VIRTIO_CAN_FLAGS_FD 0x4000
+#define VIRTIO_CAN_FLAGS_RTR 0x2000
+
+struct virtio_can_config {
+#define VIRTIO_CAN_S_CTRL_BUSOFF (1u << 0) /* Controller BusOff */
+ /* CAN controller status */
+ __le16 status;
+};
+
+/* TX queue message types */
+struct virtio_can_tx_out {
+#define VIRTIO_CAN_TX 0x0001
+ __le16 msg_type;
+ __le16 length; /* 0..8 CC, 0..64 CAN-FD, 0..2048 CAN-XL, 12 bits */
+ __le32 reserved; /* May be needed in part for CAN XL priority */
+ __le32 flags;
+ __le32 can_id;
+ __u8 sdu[64];
+};
+
+struct virtio_can_tx_in {
+ __u8 result;
+};
+
+/* RX queue message types */
+struct virtio_can_rx {
+#define VIRTIO_CAN_RX 0x0101
+ __le16 msg_type;
+ __le16 length; /* 0..8 CC, 0..64 CAN-FD, 0..2048 CAN-XL, 12 bits */
+ __le32 reserved; /* May be needed in part for CAN XL priority */
If also needed by CAN XL, the field can be turned into a union.
Classical CAN and CAN-FD.
Please refer to:
commit ea7800565a12 ("can: add optional DLC element to Classical CAN
frame structure")
Link:https://ddec1-0-en-ctp.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fgit.kernel.org%2ftorvalds%2fc%2fea7800565a12&umid=0b3549ac-d010-4d96-a348-2702485d82af&auth=53c7c7de28b92dfd96e93d9dd61a23e634d2fbec-83a945dba88675fd8f98628601040c6860123b6d
For more details, please refor to section 8.4.2.4 "DLC field" of ISO
11898-1:2015.
I do believe that AUTOSAR do not allow Classical CAN frames with a DLC
greater than 8, but the virtio implementation should support the ISO
definitions.
RegardsCAN XL into it.ACK.
But for CAN XL we need anyway a more critical look from CAN XL experts
on the list. Here in the house there is already only fewer experience
with CAN FD in comparison with classic CAN but none at all with CAN XL.
Too new. If something is done in a stupid way we can define in the
future completely new messages as we have the msg_type. But if no
mistake is made now we can avoid this and enhancing things will be more
simple later. The RX and TX messages are really critical. Some bugs in
the software can be fixed easily. But if we define here something not
future proof this can only be addressed later in the spec with some more
effort.
Yours sincerely,+ __le32 flags;
+ __le32 can_id;
+ __u8 sdu[64];
+};
+
+/* Control queue message types */
+struct virtio_can_control_out {
+#define VIRTIO_CAN_SET_CTRL_MODE_START 0x0201
+#define VIRTIO_CAN_SET_CTRL_MODE_STOP 0x0202
+ __le16 msg_type;
+};
+
+struct virtio_can_control_in {
+ __u8 result;
+};
+
+#endif /* #ifndef _LINUX_VIRTIO_VIRTIO_CAN_H */
Vincent Mailhol