]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Slow down TX path if needed.
authorJiri Vanek <vanekjir@fel.cvut.cz>
Sat, 5 May 2012 10:35:31 +0000 (12:35 +0200)
committerJiri Vanek <vanekjir@fel.cvut.cz>
Sat, 5 May 2012 10:35:31 +0000 (12:35 +0200)
kernel/2.6/drivers/net/can/usb/ctu_usbcan.c

index fcb64cad69bd2bb59b21ba65b20ce0c26a5a86ad..2b2fcbc0a540e6b69acdb9d033f1e6018f494b72 100644 (file)
@@ -79,7 +79,7 @@ struct ctu_usbcan_usb {
 
        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 */
@@ -88,8 +88,6 @@ struct ctu_usbcan_usb {
        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 */
@@ -98,7 +96,6 @@ struct ctu_usbcan_usb {
 
        spinlock_t              list_lock;                      /* list lock */
        struct task_struct *comthread;                  /* usb communication kernel thread  */
-       wait_queue_head_t queue;
 
        volatile long flags;
 
@@ -144,14 +141,14 @@ static int get_bittiming_constants(struct ctu_usbcan_usb *dev)
        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);
 
@@ -240,7 +237,7 @@ static void ctu_usbcan_tx_callback(struct urb *urb){
 
        /* success */
 
-       printk("TX callback: URB successfully transmitted\n");
+       //printk("TX callback: URB successfully transmitted\n");
 
        stats->tx_packets++;
        stats->tx_bytes += m->dlc;
@@ -270,7 +267,7 @@ static void ctu_usbcan_rx_callback(struct urb *urb)
 
        /* 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);
@@ -287,12 +284,14 @@ static netdev_tx_t ctu_usbcan_start_xmit(struct sk_buff *skb, struct net_device
        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)
@@ -320,16 +319,24 @@ static netdev_tx_t ctu_usbcan_start_xmit(struct sk_buff *skb, struct net_device
 
        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:
 
@@ -377,6 +384,7 @@ static void usbcan_kthread_free_urbs(struct ctu_usbcan_usb *dev)
                kfree(m);
        }
 
+
 }
 
 void usbcan_kthread_write_handler(struct ctu_usbcan_usb *dev, struct usbcan_message *m)
@@ -384,6 +392,9 @@ void usbcan_kthread_write_handler(struct ctu_usbcan_usb *dev, struct usbcan_mess
 
        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)
@@ -396,7 +407,7 @@ void usbcan_kthread_read_handler(struct ctu_usbcan_usb *dev, struct usbcan_messa
        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
@@ -404,8 +415,6 @@ void usbcan_kthread_read_handler(struct ctu_usbcan_usb *dev, struct usbcan_messa
        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");
@@ -413,7 +422,7 @@ void usbcan_kthread_read_handler(struct ctu_usbcan_usb *dev, struct usbcan_messa
        }
 
        
-       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;
@@ -522,8 +531,8 @@ int usbcan_kthread(void *data)
        /* 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");
@@ -562,6 +571,7 @@ int usbcan_kthread(void *data)
        }
 
 
+
        /* an endless loop in which we are doing our work */
        for(;;)
        {
@@ -621,6 +631,9 @@ static int ctu_usbcan_open(struct net_device *netdev)
        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");
 
@@ -633,6 +646,8 @@ static int ctu_usbcan_close(struct net_device *netdev)
        struct ctu_usbcan_usb *dev = netdev_priv(netdev);
        kthread_stop(dev->comthread);
 
+       netif_stop_queue(netdev);
+
        close_candev(netdev);
        
        return 0;
@@ -657,14 +672,13 @@ static int ctu_usbcan_probe(struct usb_interface *intf,
 
        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)
@@ -684,6 +698,7 @@ static int ctu_usbcan_probe(struct usb_interface *intf,
        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;
@@ -717,7 +732,7 @@ static int ctu_usbcan_probe(struct usb_interface *intf,
        }
 
        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;