From 12e72feab5d9a23107f245b0f241a2484cbb5a4e Mon Sep 17 00:00:00 2001
From: Pete Zaitcev <zaitcev@redhat.com>
Date: Fri, 9 Jun 2006 22:03:32 -0700
Subject: [PATCH] [PATCH] USB: implement error event in usbmon

Implement the "error" event in usbmon.

Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/usb/mon/mon_main.c | 20 ++++++++++++++++----
 drivers/usb/mon/mon_text.c | 27 +++++++++++++++++++++++++++
 drivers/usb/mon/usb_mon.h  |  1 +
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 86db92b4915b55..275a66f8305878 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -114,20 +114,32 @@ out_unlocked:
 
 /*
  */
-static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int err)
+static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
 {
 	struct mon_bus *mbus;
+	unsigned long flags;
+	struct list_head *pos;
+	struct mon_reader *r;
 
 	mbus = ubus->mon_bus;
 	if (mbus == NULL)
 		goto out_unlocked;
 
-	/*
-	 * XXX Capture the error code and the 'E' event.
-	 */
+	spin_lock_irqsave(&mbus->lock, flags);
+	if (mbus->nreaders == 0)
+		goto out_locked;
 
+	mbus->cnt_events++;
+	list_for_each (pos, &mbus->r_list) {
+		r = list_entry(pos, struct mon_reader, r_link);
+		r->rnf_error(r->r_data, urb, error);
+	}
+
+	spin_unlock_irqrestore(&mbus->lock, flags);
 	return;
 
+out_locked:
+	spin_unlock_irqrestore(&mbus->lock, flags);
 out_unlocked:
 	return;
 }
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 9f9236bf62d241..e02c1a30c4cd4d 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -182,6 +182,32 @@ static void mon_text_complete(void *data, struct urb *urb)
 	mon_text_event(rp, urb, 'C');
 }
 
+static void mon_text_error(void *data, struct urb *urb, int error)
+{
+	struct mon_reader_text *rp = data;
+	struct mon_event_text *ep;
+
+	if (rp->nevents >= EVENT_MAX ||
+	    (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
+		rp->r.m_bus->cnt_text_lost++;
+		return;
+	}
+
+	ep->type = 'E';
+	ep->pipe = urb->pipe;
+	ep->id = (unsigned long) urb;
+	ep->tstamp = 0;
+	ep->length = 0;
+	ep->status = error;
+
+	ep->setup_flag = '-';
+	ep->data_flag = 'E';
+
+	rp->nevents++;
+	list_add_tail(&ep->e_link, &rp->e_list);
+	wake_up(&rp->wait);
+}
+
 /*
  * Fetch next event from the circular buffer.
  */
@@ -235,6 +261,7 @@ static int mon_text_open(struct inode *inode, struct file *file)
 	rp->r.m_bus = mbus;
 	rp->r.r_data = rp;
 	rp->r.rnf_submit = mon_text_submit;
+	rp->r.rnf_error = mon_text_error;
 	rp->r.rnf_complete = mon_text_complete;
 
 	snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum,
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index 92702835b1e5b8..33678c24ebeed5 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -40,6 +40,7 @@ struct mon_reader {
 	void *r_data;		/* Use container_of instead? */
 
 	void (*rnf_submit)(void *data, struct urb *urb);
+	void (*rnf_error)(void *data, struct urb *urb, int error);
 	void (*rnf_complete)(void *data, struct urb *urb);
 };
 
-- 
GitLab