Commit e6499e49 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Linus Torvalds

IrDA updates 1/4:

	o [FEATURE] Update various comments to current state
	o [CORRECT] Handle properly failure of URB with new speed
	o [CORRECT] Don't test for (self != NULL) after using it (doh !)
	o [FEATURE] Other minor cleanups
parent 4d0b85ea
...@@ -30,23 +30,24 @@ ...@@ -30,23 +30,24 @@
* IMPORTANT NOTE * IMPORTANT NOTE
* -------------- * --------------
* *
* As of kernel 2.4.10, this is the state of compliance and testing of * As of kernel 2.5.20, this is the state of compliance and testing of
* this driver (irda-usb) with regards to the USB low level drivers... * this driver (irda-usb) with regards to the USB low level drivers...
* *
* This driver has been tested SUCCESSFULLY with the following drivers : * This driver has been tested SUCCESSFULLY with the following drivers :
* o usb-uhci (For Intel/Via USB controllers) * o usb-uhci-hcd (For Intel/Via USB controllers)
* o usb-ohci (For other USB controllers) * o uhci-hcd (Alternate/JE driver for Intel/Via USB controllers)
* *
* This driver has NOT been tested with the following drivers : * This driver has NOT been tested with the following drivers :
* o usb-ehci (USB 2.0 controllers) * o ehci-hcd (USB 2.0 controllers)
* *
* This driver WON'T WORK with the following drivers : * This driver DOESN'T SEEM TO WORK with the following drivers :
* o uhci (Alternate/JE driver for Intel/Via USB controllers) * o ohci-hcd (For other USB controllers)
* Amongst the reasons : * The first outgoing URB never calls its completion/failure callback.
* o uhci doesn't implement USB_ZERO_PACKET *
* o uhci non-compliant use of urb->timeout * Note that all HCD drivers do USB_ZERO_PACKET and timeout properly,
* The final fix for USB_ZERO_PACKET in uhci is likely to be in 2.4.19 and * so we don't have to worry about that anymore.
* 2.5.8. With this fix, the driver will work properly. More on that later. * One common problem is the failure to set the address on the dongle,
* but this happens before the driver gets loaded...
* *
* Jean II * Jean II
*/ */
...@@ -167,7 +168,8 @@ static void irda_usb_build_header(struct irda_usb_cb *self, ...@@ -167,7 +168,8 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
IRDA_DEBUG(2, __FUNCTION__ "(), changing speed to %d\n", self->new_speed); IRDA_DEBUG(2, __FUNCTION__ "(), changing speed to %d\n", self->new_speed);
self->speed = self->new_speed; self->speed = self->new_speed;
self->new_speed = -1; /* We will do ` self->new_speed = -1; ' in the completion
* handler just in case the current URB fail - Jean II */
switch (self->speed) { switch (self->speed) {
case 2400: case 2400:
...@@ -208,7 +210,8 @@ static void irda_usb_build_header(struct irda_usb_cb *self, ...@@ -208,7 +210,8 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
if (self->new_xbofs != -1) { if (self->new_xbofs != -1) {
IRDA_DEBUG(2, __FUNCTION__ "(), changing xbofs to %d\n", self->new_xbofs); IRDA_DEBUG(2, __FUNCTION__ "(), changing xbofs to %d\n", self->new_xbofs);
self->xbofs = self->new_xbofs; self->xbofs = self->new_xbofs;
self->new_xbofs = -1; /* We will do ` self->new_xbofs = -1; ' in the completion
* handler just in case the current URB fail - Jean II */
switch (self->xbofs) { switch (self->xbofs) {
case 48: case 48:
...@@ -286,7 +289,8 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) ...@@ -286,7 +289,8 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/* /*
* Note : this function will be called with both speed_urb and empty_urb... * Speed URB callback
* Now, we can only get called for the speed URB.
*/ */
static void speed_bulk_callback(struct urb *urb) static void speed_bulk_callback(struct urb *urb)
{ {
...@@ -295,10 +299,9 @@ static void speed_bulk_callback(struct urb *urb) ...@@ -295,10 +299,9 @@ static void speed_bulk_callback(struct urb *urb)
IRDA_DEBUG(2, __FUNCTION__ "()\n"); IRDA_DEBUG(2, __FUNCTION__ "()\n");
/* We should always have a context */ /* We should always have a context */
if (self == NULL) { ASSERT(self != NULL, return;);
WARNING(__FUNCTION__ "(), Bug : self == NULL\n"); /* We should always be called for the speed URB */
return; ASSERT(urb == self->speed_urb, return;);
}
/* Check for timeout and other USB nasties */ /* Check for timeout and other USB nasties */
if (urb->status != 0) { if (urb->status != 0) {
...@@ -314,12 +317,14 @@ static void speed_bulk_callback(struct urb *urb) ...@@ -314,12 +317,14 @@ static void speed_bulk_callback(struct urb *urb)
} }
/* urb is now available */ /* urb is now available */
urb->status = 0; //urb->status = 0; -> tested above
/* New speed and xbof is now commited in hardware */
self->new_speed = -1;
self->new_xbofs = -1;
/* If it was the speed URB, allow the stack to send more packets */ /* Allow the stack to send more packets */
if(urb == self->speed_urb) {
netif_wake_queue(self->netdev); netif_wake_queue(self->netdev);
}
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
...@@ -334,6 +339,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -334,6 +339,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
s32 speed; s32 speed;
s16 xbofs; s16 xbofs;
int res, mtt; int res, mtt;
int err = 1; /* Failed */
IRDA_DEBUG(4, __FUNCTION__ "() on %s\n", netdev->name);
netif_stop_queue(netdev); netif_stop_queue(netdev);
...@@ -343,10 +351,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -343,10 +351,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Check if the device is still there. /* Check if the device is still there.
* We need to check self->present under the spinlock because * We need to check self->present under the spinlock because
* of irda_usb_disconnect() is synchronous - Jean II */ * of irda_usb_disconnect() is synchronous - Jean II */
if ((!self) || (!self->present)) { if (!self->present) {
IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n"); IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n");
spin_unlock_irqrestore(&self->lock, flags); goto drop;
return 1; /* Failed */
} }
/* Check if we need to change the number of xbofs */ /* Check if we need to change the number of xbofs */
...@@ -373,6 +380,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -373,6 +380,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
irda_usb_change_speed_xbofs(self); irda_usb_change_speed_xbofs(self);
netdev->trans_start = jiffies; netdev->trans_start = jiffies;
/* Will netif_wake_queue() in callback */ /* Will netif_wake_queue() in callback */
err = 0; /* No error */
goto drop; goto drop;
} }
} }
...@@ -479,7 +487,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -479,7 +487,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Drop silently the skb and exit */ /* Drop silently the skb and exit */
dev_kfree_skb(skb); dev_kfree_skb(skb);
spin_unlock_irqrestore(&self->lock, flags); spin_unlock_irqrestore(&self->lock, flags);
return 0; return err; /* Usually 1 */
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
...@@ -495,10 +503,9 @@ static void write_bulk_callback(struct urb *urb) ...@@ -495,10 +503,9 @@ static void write_bulk_callback(struct urb *urb)
IRDA_DEBUG(2, __FUNCTION__ "()\n"); IRDA_DEBUG(2, __FUNCTION__ "()\n");
/* We should always have a context */ /* We should always have a context */
if (self == NULL) { ASSERT(self != NULL, return;);
WARNING(__FUNCTION__ "(), Bug : self == NULL\n"); /* We should always be called for the speed URB */
return; ASSERT(urb == self->tx_urb, return;);
}
/* Free up the skb */ /* Free up the skb */
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -531,10 +538,21 @@ static void write_bulk_callback(struct urb *urb) ...@@ -531,10 +538,21 @@ static void write_bulk_callback(struct urb *urb)
return; return;
} }
/* If we need to change the speed or xbofs, do it now */ /* If changes to speed or xbofs is pending... */
if ((self->new_speed != -1) || (self->new_xbofs != -1)) { if ((self->new_speed != -1) || (self->new_xbofs != -1)) {
if ((self->new_speed != self->speed) ||
(self->new_xbofs != self->xbofs)) {
/* We haven't changed speed yet (because of
* IUC_SPEED_BUG), so do it now - Jean II */
IRDA_DEBUG(1, __FUNCTION__ "(), Changing speed now...\n"); IRDA_DEBUG(1, __FUNCTION__ "(), Changing speed now...\n");
irda_usb_change_speed_xbofs(self); irda_usb_change_speed_xbofs(self);
} else {
/* New speed and xbof is now commited in hardware */
self->new_speed = -1;
self->new_xbofs = -1;
/* Done, waiting for next packet */
netif_wake_queue(self->netdev);
}
} else { } else {
/* Otherwise, allow the stack to send more packets */ /* Otherwise, allow the stack to send more packets */
netif_wake_queue(self->netdev); netif_wake_queue(self->netdev);
...@@ -559,11 +577,13 @@ static void irda_usb_net_timeout(struct net_device *netdev) ...@@ -559,11 +577,13 @@ static void irda_usb_net_timeout(struct net_device *netdev)
int done = 0; /* If we have made any progress */ int done = 0; /* If we have made any progress */
IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n"); IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n");
ASSERT(self != NULL, return;);
/* Protect us from USB callbacks, net Tx and else. */ /* Protect us from USB callbacks, net Tx and else. */
spin_lock_irqsave(&self->lock, flags); spin_lock_irqsave(&self->lock, flags);
if ((!self) || (!self->present)) { /* self->present *MUST* be read under spinlock */
if (!self->present) {
WARNING(__FUNCTION__ "(), device not present!\n"); WARNING(__FUNCTION__ "(), device not present!\n");
netif_stop_queue(netdev); netif_stop_queue(netdev);
spin_unlock_irqrestore(&self->lock, flags); spin_unlock_irqrestore(&self->lock, flags);
...@@ -678,35 +698,7 @@ static void irda_usb_net_timeout(struct net_device *netdev) ...@@ -678,35 +698,7 @@ static void irda_usb_net_timeout(struct net_device *netdev)
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/* /*
* Submit a Rx URB to the USB layer to handle reception of a frame * Submit a Rx URB to the USB layer to handle reception of a frame
* * Mostly called by the completion callback of the previous URB.
* Important note :
* The function process_urb() in usb-uhci.c contains the following code :
* > urb->complete ((struct urb *) urb);
* > // Re-submit the URB if ring-linked
* > if (is_ring && (urb->status != -ENOENT) && !contains_killed) {
* > urb->dev=usb_dev;
* > uhci_submit_urb (urb);
* > }
* The way I see it is that if we submit more than one Rx URB at a
* time, the Rx URB can be automatically re-submitted after the
* completion handler is called.
*
* My take is that it's a questionable feature, and quite difficult
* to control and to make work effectively.
* The outcome (re-submited or not) depend on various complex
* test ('is_ring' and 'contains_killed'), and the completion handler
* don't have this information, so basically the driver has no way
* to know if URB are resubmitted or not. Yuck !
* If everything is perfect, it's cool, but the problem is when
* an URB is killed (timeout, call to unlink_urb(), ...), things get
* messy...
* The other problem is that this scheme deal only with the URB
* and ignore everything about the associated buffer. So, it would
* resubmit URB even if the buffer is still in use or non-existent.
* On the other hand, submitting ourself in the completion callback
* is quite trivial and work well (this function).
* Moreover, this scheme doesn't allow to have an idle URB, which is
* necessary to overcome some URB failures.
* *
* Jean II * Jean II
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment