Implement the "error" event in usbmon.
Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
/*
*/
-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;
}
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.
*/
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,
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);
};