Re: [PATCH v3] can: usb: IXXAT USB-to-CAN adapters drivers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Wolfgang,

thank you very much for your review.
Before I send another patch I want to discuss some of the issues:

> You changed error handling to "if (ret < 0)" for *all* functions. Please
> use "ret < 0" only, if a positive return code means success, otherwise
> "if (err)".

So we should use "if (ret < 0)" if the returncode on success can be 
greater than zero and "if (err)" if only zero means success?

> > +int ixxat_usb_send_cmd(struct usb_device *dev,
> > +		       struct ixxat_usb_dal_req *dal_req)
> > +{
> > +	int ret = 0;
> > +	int i;
> > +	u16 size;
> > +	u16 value;
> > +	u8 request;
> > +	u8 requesttype;
> > +	u8 *buf;
> > +
> > +	request = 0xff;
> > +	requesttype = USB_TYPE_VENDOR | USB_DIR_OUT;
> > +	value = le16_to_cpu(dal_req->req_port);
> > +	size = le32_to_cpu(dal_req->req_size);
> 
> Please initialize the values in the declararion above.
> 
> > +	size += sizeof(struct ixxat_usb_dal_res);
> 
> le32_to_cpu?

dal_req->req_size is __le32 and needs to be converted to __u32.
sizeof() already returns an integer in cpu format.

> > +
> > +	buf = kmalloc(size, GFP_KERNEL);
> > +	if (!buf)
> > +		return -ENOMEM;
> > +
> > +	memcpy(buf, (u8 *)dal_req, size);
> 
> Cast needed?
> 
> I'm trying to understand what you are doing here. You assume that behind
> "dal_req" is "struct ixxat_usb_dal_res". That's not really transparent!

The IXXAT device command always starts with a "struct ixxat_usb_dal_req".
Then there may or may not follow some special command data which has the 
size stored in dal_req->req_size.
After the special command data there has to be a
"struct ixxat_usb_dal_res" indeed. The firmware needs to know the expected 
response size which is stored in this response structure.

Should we use a command structure like this?

struct ixxat_usb_cmd {
	struct ixxat_usb_req req;
	union {
		struct ixxat_usb_caps_req caps_req;
		struct ixxat_usb_init_cl1_req init_cl1_req;
		struct ixxat_usb_init_cl2_req init_cl2_req;
		struct ixxat_usb_start_req start_req;
		struct ixxat_usb_stop_req stop_req;
		struct ixxat_usb_power_req power_req;
		struct ixxat_usb_info_req info_req;
	};
	struct ixxat_usb_res res;
	union {
		struct ixxat_usb_caps_res caps_res;
		struct ixxat_usb_init_cl1_res init_cl1_res;
		struct ixxat_usb_init_cl2_res init_cl2_res;
		struct ixxat_usb_start_res start_res;
		struct ixxat_usb_stop_res stop_res;
		struct ixxat_usb_power_res power_res;
		struct ixxat_usb_info_res info_res;
	};
};

But then we still need this:

int ixxat_usb_send_cmd(struct usb_device *dev,
		       struct ixxat_usb_cmd *cmd)
{
	...
	u16 size = le32_to_cpu(cmd->req.size) + sizeof(cmd->res)
	...
}

> > +static int ixxat_usb_handle_canmsg(struct ixxat_usb_device *dev,
> > +				   struct ixxat_can_msg *rx)
> > +{
> > +	struct net_device *netdev = dev->netdev;
> > +	struct canfd_frame *can_frame;
> > +	struct sk_buff *skb;
> > +	const u32 flags = le32_to_cpu(rx->flags);
> > +	const u8 dlc = IXXAT_USB_DECODE_DLC(flags);
> > +
> > +	if (flags & IXXAT_USB_FDMSG_FLAGS_EDL)
> > +		skb = alloc_canfd_skb(netdev, &can_frame);
> > +	else
> > +		skb = alloc_can_skb(netdev, (struct can_frame **)&can_frame);
> 
> Argh, we should avoid such ugly casts! But I find it in other drivers as
> well :(.

We could use a union like this:

union can_canfd_frame {
	struct can_frame *cf;
	struct canfd_frame *cfd;
};

static int ixxat_usb_handle_canmsg(struct ixxat_usb_device *dev,
				   struct ixxat_can_msg *rx)
{
	struct net_device *netdev = dev->netdev;
	union can_canfd_frame ccfu;
	struct sk_buff *skb;
	...

	if (flags & IXXAT_USB_FDMSG_FLAGS_EDL)
		skb = alloc_canfd_skb(netdev, &ccfu.cfd);
	else
		skb = alloc_can_skb(netdev, &ccfu.cf);

	...
}

Do you have any better suggestions to avoid the casts?

> > +static int ixxat_usb_handle_status(struct ixxat_usb_device *dev,
> > +				   struct ixxat_can_msg *rx)
> > +{
> > +	struct net_device *netdev = dev->netdev;
> > +	struct can_frame *can_frame;
> > +	struct sk_buff *skb;
> > +
> > +	u32 raw_status = le32_to_cpu(*(u32 *)(rx->data));
> > +	enum can_state new_state = CAN_STATE_ERROR_ACTIVE;
> > +
> > +	skb = alloc_can_err_skb(netdev, &can_frame);
> > +	if (!skb)
> > +		return -ENOMEM;
> > +
> > +	if (raw_status == IXXAT_USB_CAN_STATUS_OK) {
> > +		dev->can.state = CAN_STATE_ERROR_ACTIVE;
> > +		can_frame->can_id |= CAN_ERR_CRTL;
> > +		can_frame->data[1] |= CAN_ERR_CRTL_ACTIVE;
> > +	} else if (raw_status & IXXAT_USB_CAN_STATUS_BUSOFF) {
> > +		can_frame->can_id |= CAN_ERR_BUSOFF;
> > +		dev->can.can_stats.bus_off++;
> > +		new_state = CAN_STATE_BUS_OFF;
> > +		can_bus_off(netdev);
> 
> Does the device recover automatically from bus-off?

No, it doesn't. Is this a problem here?


Kind regards,

Florian
--
To unsubscribe from this list: send the line "unsubscribe linux-can" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux