updated patch with throttling

Roman Kagan rkagan at mail.ru
Fri Mar 25 09:38:06 EST 2005


On Fri, Mar 25, 2005 at 04:39:00PM +0300, Roman Kagan wrote:
> Then I would add a limit counter.  If we get this number of consecutive
> usb errors (either on submission or on completion) then we just barf and
> tell the user to wipe it out.  I guess it shouldn't influence overall
> design too much.

How about this? (This is an incremental patch, I'll send a complete one
against current CVS in another mail).

Roman.


diff -u usbatm.h usbatm.h
--- usbatm.h	25 Mar 2005 11:02:17 -0000
+++ usbatm.h	25 Mar 2005 14:34:12 -0000
@@ -161,6 +161,8 @@
 	struct sk_buff_head sndqueue;
 
 	struct sk_buff *current_skb;			/* being emptied */
+
+	atomic_t num_allowed_errors;
 };
 
 #endif	/* _USBATM_H_ */
diff -u usbatm.c usbatm.c
--- usbatm.c	25 Mar 2005 11:02:18 -0000
+++ usbatm.c	25 Mar 2005 14:34:12 -0000
@@ -108,6 +108,7 @@
 #define UDSL_NUM_CELLS(x)		(((x) + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD)
 
 #define THROTTLE_MSECS			5	/* delay to recover processing after urb submission fails */
+#define USBATM_MAX_ERRORS		1024	/* number of consecutive usb errors to tolerate */
 
 /* receive */
 
@@ -223,6 +224,23 @@
 	return init;
 }
 
+/* error limit */
+static void usbatm_check_usb_errcode(struct usbatm_data* instance, int errcode)
+{
+	if (likely(!errcode)) {
+		/* reset allowed errors counter */
+		atomic_set(&instance->num_allowed_errors, USBATM_MAX_ERRORS);
+		return;
+	}
+
+	if (atomic_dec_and_test(&instance->num_allowed_errors)) {
+		dev_err(&instance->usb_intf->dev,
+			"too many consecutive usb errors, aborting.\n");
+		tasklet_disable(&instance->rx_tasklet);
+		tasklet_disable(&instance->tx_tasklet);
+	}
+}
+
 /* buffer management */
 static inline struct usbatm_transceiver *usbatm_pop_transceiver(struct list_head *trx_list,
 								spinlock_t *lock)
@@ -265,6 +283,9 @@
 	if (ret)
 		dbg("usbatm_submit: trx 0x%p (#%d) urb 0x%p submission failed (%d)!",
 		    trx, trx - instance->transceivers, trx->urb, ret);
+
+	usbatm_check_usb_errcode(instance, ret);
+
 	return ret;
 }
 
@@ -278,6 +299,8 @@
 
 	rx->filled_cells = urb->status ? 0 : urb->actual_length / (ATM_CELL_SIZE + instance->rx_padding);
 
+	usbatm_check_usb_errcode(instance, urb->status);
+
 	vdbg("usbatm_rx_complete: urb 0x%p, status %d, actual_length %d, filled_cells %u, rx 0x%p",
 	     urb, urb->status, urb->actual_length, rx->filled_cells, rx);
 
@@ -297,6 +320,8 @@
 	struct usbatm_data *instance = tx->instance;
 	unsigned long flags;
 
+	usbatm_check_usb_errcode(instance, urb->status);
+
 	vdbg("usbatm_tx_complete: urb 0x%p, status %d, tx 0x%p",
 	     urb, urb->status, tx);
 
@@ -1150,6 +1175,8 @@
 	instance->tx_delay.data = (unsigned long) &instance->tx_tasklet;
 	init_timer(&instance->tx_delay);
 
+	atomic_set(&instance->num_allowed_errors, USBATM_MAX_ERRORS);
+
 	skb_queue_head_init(&instance->sndqueue);
 
 	instance->transceivers = kmalloc(sizeof(*instance->transceivers) * (num_rcv_urbs + num_snd_urbs),



More information about the Usbatm mailing list