Page MenuHomeFreeBSD

D55035.diff
No OneTemporary

D55035.diff

diff --git a/sys/compat/linuxkpi/common/include/linux/usb.h b/sys/compat/linuxkpi/common/include/linux/usb.h
--- a/sys/compat/linuxkpi/common/include/linux/usb.h
+++ b/sys/compat/linuxkpi/common/include/linux/usb.h
@@ -120,6 +120,8 @@
/* USB Request Block (URB). */
struct urb;
+struct usb_anchor;
+
typedef void (usb_complete_t)(struct urb *);
/*
@@ -145,6 +147,10 @@
struct usb_device *dev; /* (in) pointer to associated device */
struct usb_host_endpoint *endpoint; /* (in) pipe pointer */
struct kref kref;
+
+ struct list_head anchor_list;
+ struct usb_anchor *anchor;
+
uint8_t *setup_packet; /* (in) setup packet (control only) */
uint8_t *bsd_data_ptr;
void *transfer_buffer; /* (in) associated data buffer */
@@ -236,6 +242,41 @@
linuxkpi_usb_free_urb(urb);
}
+/* Anchor. */
+struct usb_anchor {
+ struct list_head urb_list;
+ spinlock_t lock;
+};
+
+void linuxkpi_init_usb_anchor(struct usb_anchor *);
+void linuxkpi_usb_anchor_urb(struct urb *, struct usb_anchor *);
+void linuxkpi_usb_unanchor_urb(struct urb *);
+void linuxkpi_usb_kill_anchored_urbs(struct usb_anchor *);
+
+static inline void
+init_usb_anchor(struct usb_anchor *ua)
+{
+ linuxkpi_init_usb_anchor(ua);
+}
+
+static inline void
+usb_anchor_urb(struct urb *urb, struct usb_anchor *ua)
+{
+ linuxkpi_usb_anchor_urb(urb, ua);
+}
+
+static inline void
+usb_unanchor_urb(struct urb *urb)
+{
+ linuxkpi_usb_unanchor_urb(urb);
+}
+
+static inline void
+usb_kill_anchored_urbs(struct usb_anchor *ua)
+{
+ linuxkpi_usb_kill_anchored_urbs(ua);
+}
+
/* ---------------------------------------------------------------------------- */
/* Driver related. */
diff --git a/sys/compat/linuxkpi/common/src/linuxkpi_usb.c b/sys/compat/linuxkpi/common/src/linuxkpi_usb.c
--- a/sys/compat/linuxkpi/common/src/linuxkpi_usb.c
+++ b/sys/compat/linuxkpi/common/src/linuxkpi_usb.c
@@ -156,6 +156,8 @@
urb = usbd_xfer_get_priv(xfer);
usbd_xfer_set_priv(xfer, NULL);
+ usb_unanchor_urb(urb);
+
/* Prevent complete() macro expansion, *sigh*. */
if (urb->complete != NULL)
(urb->complete)(urb);
@@ -1004,6 +1006,72 @@
urb->context = arg;
}
+/* Anchor. */
+void
+linuxkpi_init_usb_anchor(struct usb_anchor *ua)
+{
+ memset(ua, 0, sizeof(*ua));
+ spin_lock_init(&ua->lock);
+ INIT_LIST_HEAD(&ua->urb_list);
+}
+
+void
+linuxkpi_usb_anchor_urb(struct urb *urb, struct usb_anchor *ua)
+{
+ unsigned long flags;
+
+ /* Make sure the urb stays valid while on the anchor list. */
+ usb_get_urb(urb);
+
+ spin_lock_irqsave(&ua->lock, flags);
+ list_add_tail(&urb->anchor_list, &ua->urb_list);
+ urb->anchor = ua;
+ spin_unlock_irqrestore(&ua->lock, flags);
+}
+
+void
+linuxkpi_usb_unanchor_urb(struct urb *urb)
+{
+ unsigned long flags;
+ struct usb_anchor *ua;
+
+ if (urb == NULL)
+ return;
+
+ ua = urb->anchor;
+ if (ua == NULL)
+ return;
+
+ spin_lock_irqsave(&ua->lock, flags);
+ /* Re-check under lock. */
+ if (urb->anchor == NULL)
+ goto out;
+
+ urb->anchor = NULL;
+ list_del(&urb->anchor_list);
+ usb_put_urb(urb);
+out:
+ spin_unlock_irqrestore(&ua->lock, flags);
+}
+
+void
+linuxkpi_usb_kill_anchored_urbs(struct usb_anchor *ua)
+{
+ struct urb *urb;
+
+ spin_lock_irq(&ua->lock);
+ while (!list_empty(&ua->urb_list)) {
+ urb = list_entry(ua->urb_list.prev, struct urb, anchor_list);
+ usb_get_urb(urb);
+ /* We need to drop the lock. */
+ spin_unlock_irq(&ua->lock);
+ usb_kill_urb(urb);
+ usb_put_urb(urb);
+ spin_lock_irq(&ua->lock);
+ }
+ spin_unlock_irq(&ua->lock);
+}
+
/*
* usb_control_msg()
*

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 2, 4:43 AM (7 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40060385
Default Alt Text
D55035.diff (3 KB)

Event Timeline