struct can_priv can; /* must be the first member */
- struct can_bittiming_const cbc;
+ struct can_bittiming_const btc;
u32 can_clock;
struct usb_device *udev; /* the usb device for this device */
u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
- struct mutex io_mutex; /* synchronize I/O with disconnect */
-
struct list_head rx_pend_list; /* URBs waiting for data receive */
struct list_head rx_ready_list; /* URBs with valid received data */
struct list_head tx_idle_list; /* URBs prepared to hold Tx messages */
spinlock_t list_lock; /* list lock */
struct task_struct *comthread; /* usb communication kernel thread */
- wait_queue_head_t queue;
volatile long flags;
ptr = (u32*) usbbuf;
dev->can_clock = le32_to_cpu(*(ptr++));
- dev->cbc.tseg1_min = le32_to_cpu(*(ptr++));
- dev->cbc.tseg1_max = le32_to_cpu(*(ptr++));
- dev->cbc.tseg2_min = le32_to_cpu(*(ptr++));
- dev->cbc.tseg2_max = le32_to_cpu(*(ptr++));
- dev->cbc.sjw_max = le32_to_cpu(*(ptr++));
- dev->cbc.brp_min = le32_to_cpu(*(ptr++));
- dev->cbc.brp_max = le32_to_cpu(*(ptr++));
- dev->cbc.brp_inc = le32_to_cpu(*(ptr));
+ dev->btc.tseg1_min = le32_to_cpu(*(ptr++));
+ dev->btc.tseg1_max = le32_to_cpu(*(ptr++));
+ dev->btc.tseg2_min = le32_to_cpu(*(ptr++));
+ dev->btc.tseg2_max = le32_to_cpu(*(ptr++));
+ dev->btc.sjw_max = le32_to_cpu(*(ptr++));
+ dev->btc.brp_min = le32_to_cpu(*(ptr++));
+ dev->btc.brp_max = le32_to_cpu(*(ptr++));
+ dev->btc.brp_inc = le32_to_cpu(*(ptr));
set_bit(USBCAN_BITTIMING_CONST_SET,&dev->flags);
/* success */
- printk("TX callback: URB successfully transmitted\n");
+ //printk("TX callback: URB successfully transmitted\n");
stats->tx_packets++;
stats->tx_bytes += m->dlc;
/* success */
- printk("RX callback: URB successfully received\n");
+ //printk("RX callback: URB successfully received\n");
set_bit(USBCAN_DATA_OK,&m->dev->flags);
usbcan_usb_message_move_list(m->dev, m, &m->dev->rx_ready_list);
u8 *ptr;
u16 flags = 0;
- if(list_empty(&dev->tx_idle_list))
+
+ if(list_empty(&dev->tx_idle_list)){
goto exit;
+ }
m = list_first_entry(&dev->tx_idle_list, typeof(*m), list_node);
- /* naplneni */
+ /* fill */
len = cf->can_dlc;
if(len > CAN_MSG_LENGTH)
usbcan_usb_message_move_list(dev, m, &dev->tx_pend_list);
+ /* put on stack - local echo */
can_put_echo_skb(skb, netdev, m->echo_index);
- /* odeslani */
+ /* send*/
retval = usb_submit_urb(m->u, GFP_ATOMIC);
if (retval){
err("Error submitting URB: %d", retval);
+ can_free_echo_skb(netdev, m->echo_index);
usbcan_usb_message_move_list(dev, m, &dev->tx_idle_list);
+ dev_kfree_skb(skb);
goto exit;
}
+ /* slow down tx path if needed */
+ if(list_empty(&dev->tx_idle_list))
+ netif_stop_queue(netdev);
+
+
exit:
kfree(m);
}
+
}
void usbcan_kthread_write_handler(struct ctu_usbcan_usb *dev, struct usbcan_message *m)
usbcan_usb_message_move_list(dev, m, &dev->tx_idle_list);
+ if (netif_queue_stopped(m->dev->netdev))
+ netif_wake_queue(m->dev->netdev);
+
}
void usbcan_kthread_read_handler(struct ctu_usbcan_usb *dev, struct usbcan_message *m)
u16 flags = 0;
struct net_device_stats *stats = &m->dev->netdev->stats;
-/*
+
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
skb = alloc_can_skb(m->dev->netdev, &cf);
#else
skb->protocol = htons(ETH_P_CAN);
cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
#endif
-*/
- skb = alloc_can_skb(m->dev->netdev, &cf);
if (skb == NULL){
err("RX: error alloc skb\n");
}
- printk("RX: URB successfully received\n");
+ //printk("RX: URB successfully received\n");
len=*(u8 *)(m->msg+1);
if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
/* Prepare transmit urbs */
for (i=0;i<USBCAN_TOT_TX_URBS;i++){
- u = usb_alloc_urb(0, GFP_ATOMIC);
- m = kzalloc(sizeof(struct usbcan_message), GFP_ATOMIC);
+ u = usb_alloc_urb(0, GFP_KERNEL);
+ m = kzalloc(sizeof(struct usbcan_message), GFP_KERNEL);
if (!u){
err("Error allocating usb transmit urb");
}
+
/* an endless loop in which we are doing our work */
for(;;)
{
if (err)
return err;
+ if (netif_queue_stopped(netdev))
+ netif_wake_queue(netdev);
+
/* start kernel thread */
dev->comthread = kthread_run(usbcan_kthread, (void *)dev, "usbcan_1");
struct ctu_usbcan_usb *dev = netdev_priv(netdev);
kthread_stop(dev->comthread);
+ netif_stop_queue(netdev);
+
close_candev(netdev);
return 0;
printk(KERN_INFO "CTU USBCAN device now attached\n");
-/*
+
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
netdev = alloc_candev(sizeof(struct ctu_usbcan_usb), USBCAN_TOT_TX_URBS);
#else
netdev = alloc_candev(sizeof(struct ctu_usbcan_usb));
#endif
-*/
- netdev = alloc_candev(sizeof(struct ctu_usbcan_usb), USBCAN_TOT_TX_URBS);
+
if (!netdev) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,33)
netdev->netdev_ops = &ctu_usbcan_netdev_ops;
netdev->flags |= IFF_ECHO;
+
/* set up the endpoint information */
/* use only the first bulk-in and bulk-out endpoints */
iface_desc = intf->cur_altsetting;
}
dev->can.clock.freq = dev->can_clock;
- dev->can.bittiming_const = &dev->cbc;
+ dev->can.bittiming_const = &dev->btc;
dev->can.do_set_bittiming = ctu_usbcan_set_bittiming;
dev->can.do_set_mode = ctu_usbcan_set_mode;