changing URB allocation API

Oliver Neukum <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
Hi,

I tried switching our allocation APIs to:

struct urb *usb_alloc_urb(struct usb_host_endpoint *ep, size_t alloc_length, gfp_t mem_flags);
struct urb *usb_alloc_iso_urb(struct usb_host_endpoint *ep, unsigned int iso_packets, gfp_t mem_flags);

Unfortunately during initialisation ep->ep_dev turns out to be NULL.
Should I change the allocator or the initialisation?

	Regards
		Oliver

------------[ cut here ]------------
Jul  6 14:17:48 valisk kernel: kernel BUG at drivers/usb/core/urb.c:63!
Jul  6 14:17:48 valisk kernel: invalid opcode: 0000 [1] SMP
Jul  6 14:17:48 valisk kernel: CPU 0
Jul  6 14:17:48 valisk kernel: Modules linked in: ohci_hcd usbcore af_packet cpufreq_conservative cpufreq_ondemand cpufreq_userspace cpufreq_powersave powernow_k8 freq_table snd_pcm_o
ss snd_mixer_oss snd_seq snd_seq_device bay dock button battery ac dm_mod atiixp pcmcia generic snd_atiixp firewire_ohci bcm43xx firewire_core crc_itu_t snd_ac97_codec nsc_ircc ohci13
94 ac97_bus ieee1394 firmware_class ide_core irda tifm_7xx1 snd_pcm ieee80211softmac crc_ccitt tifm_core snd_timer yenta_socket rsrc_nonstatic ieee80211 tg3 rtc_cmos rtc_core rtc_lib
snd pcmcia_core ieee80211_crypt k8temp hwmon soundcore snd_page_alloc i2c_piix4 i2c_core shpchp pci_hotplug joydev parport_pc lp parport edd fan thermal processor
Jul  6 14:17:48 valisk kernel: Pid: 3557, comm: insmod Not tainted 2.6.22-rc7-nomem-default #14
Jul  6 14:17:48 valisk kernel: RIP: 0010:[<ffffffff883a761f>]  [<ffffffff883a761f>] :usbcore:usb_alloc_urb+0x16/0x9f
Jul  6 14:17:48 valisk kernel: RSP: 0018:ffff81002da51bc8  EFLAGS: 00010246
Jul  6 14:17:48 valisk kernel: RAX: 0000000000000000 RBX: ffff8100381d8bc0 RCX: 0000000000000080
Jul  6 14:17:48 valisk kernel: RDX: 0000000000000010 RSI: 0000000000000012 RDI: ffff81002da35048
Jul  6 14:17:48 valisk kernel: RBP: 0000000000000012 R08: 0000000000000100 R09: ffff81002da35048
Jul  6 14:17:48 valisk kernel: R10: ffff81003e0690c0 R11: ffffffff8043a340 R12: 00000000fffffff4
Jul  6 14:17:48 valisk kernel: R13: 0000000000000000 R14: 0000000000000012 R15: 0000000000000080
Jul  6 14:17:48 valisk kernel: FS:  00002b37467ea6f0(0000) GS:ffffffff80571000(0000) knlGS:0000000000000000
Jul  6 14:17:48 valisk kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
Jul  6 14:17:48 valisk kernel: CR2: 00002b2aca5670a8 CR3: 000000002d5ef000 CR4: 00000000000006e0
Jul  6 14:17:48 valisk kernel: Process insmod (pid: 3557, threadinfo ffff81002da50000, task ffff810037c54100)
Jul  6 14:17:48 valisk kernel: Stack:  ffff8100381d8bc0 ffffffff883a7dcf 0000000000000008 8000018000000006
Jul  6 14:17:48 valisk kernel:  ffff81002da35000 000000000018a416 ffff810037c542e8 ffff8100381d8be0
Jul  6 14:17:48 valisk kernel:  0000000000000000 00000000ffffff01 0000000000000012 ffff81002da35000
Jul  6 14:17:48 valisk kernel: Call Trace:
Jul  6 14:17:48 valisk kernel:  [<ffffffff883a7dcf>] :usbcore:usb_control_msg+0x8b/0x101
Jul  6 14:17:48 valisk kernel:  [<ffffffff883a8736>] :usbcore:usb_get_descriptor+0x72/0xa1
Jul  6 14:17:48 valisk kernel:  [<ffffffff883a8d39>] :usbcore:usb_get_device_descriptor+0x4e/0x78
Jul  6 14:17:48 valisk kernel:  [<ffffffff883a680c>] :usbcore:usb_add_hcd+0x41c/0x53d
Jul  6 14:17:48 valisk kernel:  [<ffffffff883b0044>] :usbcore:usb_hcd_pci_probe+0x1e6/0x28e
Jul  6 14:17:48 valisk kernel:  [<ffffffff8032230d>] pci_device_probe+0xe2/0x14e
Jul  6 14:17:48 valisk kernel:  [<ffffffff8037e546>] driver_probe_device+0xf7/0x174
Jul  6 14:17:48 valisk kernel:  [<ffffffff8037e6d9>] __driver_attach+0x6f/0xae
Jul  6 14:17:48 valisk kernel:  [<ffffffff8037e66a>] __driver_attach+0x0/0xae
Jul  6 14:17:48 valisk kernel:  [<ffffffff8037e66a>] __driver_attach+0x0/0xae
Jul  6 14:17:48 valisk kernel:  [<ffffffff8037d962>] bus_for_each_dev+0x43/0x6e
Jul  6 14:17:48 valisk kernel:  [<ffffffff8037dc88>] bus_add_driver+0x7b/0x19d
Jul  6 14:17:48 valisk kernel:  [<ffffffff803224eb>] __pci_register_driver+0x58/0x8a
Jul  6 14:17:48 valisk kernel:  [<ffffffff8024d854>] sys_init_module+0x1630/0x1793
Jul  6 14:17:48 valisk kernel:  [<ffffffff8025cf9b>] audit_syscall_entry+0x141/0x174
Jul  6 14:17:48 valisk kernel:  [<ffffffff80209cec>] tracesys+0xdc/0xe1
Jul  6 14:17:48 valisk kernel:
Jul  6 14:17:48 valisk kernel:
Jul  6 14:17:48 valisk kernel: Code: 0f 0b eb fe 48 8b 40 08 48 85 c0 75 04 0f 0b eb fe 48 8b 78
Jul  6 14:17:48 valisk kernel: RIP  [<ffffffff883a761f>] :usbcore:usb_alloc_urb+0x16/0x9f
Jul  6 14:17:48 valisk kernel:  RSP <ffff81002da51bc8>

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
iso_demo (text/x-diff, 9.6 KB)
diff -urp vanilla/drivers/usb/class/cdc-acm.c isotree/drivers/usb/class/cdc-acm.c
--- vanilla/drivers/usb/class/cdc-acm.c	2007-07-04 14:14:45.000000000 +0200
+++ isotree/drivers/usb/class/cdc-acm.c	2007-07-05 13:23:20.000000000 +0200
@@ -989,7 +989,7 @@ skip_normal_probe:
 		goto alloc_fail4;
 	}
 
-	acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
+	acm->ctrlurb = usb_alloc_urb(usb_dev->ep_in[epctrl->bEndpointAddress], ctrlsize, GFP_KERNEL);
 	if (!acm->ctrlurb) {
 		dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)");
 		goto alloc_fail5;
@@ -997,7 +997,7 @@ skip_normal_probe:
 	for (i = 0; i < num_rx_buf; i++) {
 		struct acm_ru *rcv = &(acm->ru[i]);
 
-		if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
+		if (!(rcv->urb = usb_alloc_urb(usb_dev->ep_in[epread->bEndpointAddress], readsize, GFP_KERNEL))) {
 			dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)");
 			goto alloc_fail7;
 		}
@@ -1013,7 +1013,7 @@ skip_normal_probe:
 			goto alloc_fail7;
 		}
 	}
-	acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
+	acm->writeurb = usb_alloc_urb(usb_dev->ep_out[epwrite->bEndpointAddress], acm->writesize, GFP_KERNEL);
 	if (!acm->writeurb) {
 		dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)");
 		goto alloc_fail7;
diff -urp vanilla/drivers/usb/core/devio.c isotree/drivers/usb/core/devio.c
--- vanilla/drivers/usb/core/devio.c	2007-07-04 16:37:09.000000000 +0200
+++ isotree/drivers/usb/core/devio.c	2007-07-05 14:23:23.000000000 +0200
@@ -207,14 +207,28 @@ err:
  * async list handling
  */
 
-static struct async *alloc_async(unsigned int numisoframes)
+static struct async *alloc_async_iso(struct usb_host_endpoint *ep, unsigned int numisoframes)
 {
         unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
         struct async *as = kzalloc(assize, GFP_KERNEL);
 
         if (!as)
                 return NULL;
-	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
+	as->urb = usb_alloc_iso_urb(ep, numisoframes, GFP_KERNEL);
+	if (!as->urb) {
+		kfree(as);
+		return NULL;
+	}
+        return as;
+}
+
+static struct async *alloc_async(struct usb_host_endpoint *ep, size_t size)
+{
+        struct async *as = kzalloc(sizeof(struct async), GFP_KERNEL);
+
+        if (!as)
+                return NULL;
+	as->urb = usb_alloc_urb(ep, size, GFP_KERNEL);
 	if (!as->urb) {
 		kfree(as);
 		return NULL;
@@ -1027,10 +1041,18 @@ static int proc_do_submiturb(struct dev_
 	default:
 		return -EINVAL;
 	}
-	if (!(as = alloc_async(uurb->number_of_packets))) {
-		kfree(isopkt);
-		kfree(dr);
-		return -ENOMEM;
+	if (uurb->type == USBDEVFS_URB_TYPE_ISO) {
+		if (!(as = alloc_async_iso(ep, uurb->number_of_packets))) {
+			kfree(isopkt);
+			kfree(dr);
+			return -ENOMEM;
+		}
+	} else {
+		if (!(as = alloc_async(ep,uurb->buffer_length ))) {
+			kfree(isopkt);
+			kfree(dr);
+			return -ENOMEM;
+		}
 	}
 	if (!(as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL))) {
 		kfree(isopkt);
diff -urp vanilla/drivers/usb/core/endpoint.c isotree/drivers/usb/core/endpoint.c
--- vanilla/drivers/usb/core/endpoint.c	2007-07-04 14:09:34.000000000 +0200
+++ isotree/drivers/usb/core/endpoint.c	2007-07-05 13:56:00.000000000 +0200
@@ -19,23 +19,6 @@
 static int usb_endpoint_major;
 static DEFINE_IDR(endpoint_idr);
 
-struct ep_device {
-	struct usb_endpoint_descriptor *desc;
-	struct usb_device *udev;
-	struct device dev;
-	int minor;
-};
-#define to_ep_device(_dev) \
-	container_of(_dev, struct ep_device, dev)
-
-struct ep_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct usb_device *,
-			struct usb_endpoint_descriptor *, char *);
-};
-#define to_ep_attribute(_attr) \
-	container_of(_attr, struct ep_attribute, attr)
-
 #define usb_ep_attr(field, format_string)			\
 static ssize_t show_ep_##field(struct device *dev,		\
 			       struct device_attribute *attr,	\
diff -urp vanilla/drivers/usb/core/hcd.h isotree/drivers/usb/core/hcd.h
--- vanilla/drivers/usb/core/hcd.h	2007-07-04 14:14:45.000000000 +0200
+++ isotree/drivers/usb/core/hcd.h	2007-07-04 18:27:32.000000000 +0200
@@ -187,6 +187,12 @@ struct hc_driver {
 					struct urb *urb,
 					gfp_t mem_flags);
 	int	(*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
+	struct urb * (*alloc_urb) (struct usb_hcd *hcd,
+					struct usb_host_endpoint *,
+					size_t alloc_length,
+					unsigned int num_iso_packets,
+					gfp_t mem_flags);
+	void	(*free_urb) (struct usb_hcd *hcd, struct urb *urb);
 
 	/* hw synch, freeing endpoint resources that urb_dequeue can't */
 	void 	(*endpoint_disable)(struct usb_hcd *hcd,
diff -urp vanilla/drivers/usb/core/hub.c isotree/drivers/usb/core/hub.c
--- vanilla/drivers/usb/core/hub.c	2007-07-04 14:14:45.000000000 +0200
+++ isotree/drivers/usb/core/hub.c	2007-07-05 13:48:11.000000000 +0200
@@ -818,7 +818,7 @@ static int hub_configure(struct usb_hub 
 	if (maxp > sizeof(*hub->buffer))
 		maxp = sizeof(*hub->buffer);
 
-	hub->urb = usb_alloc_urb(0, GFP_KERNEL);
+	hub->urb = usb_alloc_urb(hdev->ep_in[endpoint->bEndpointAddress], maxp, GFP_KERNEL);
 	if (!hub->urb) {
 		message = "couldn't allocate interrupt urb";
 		ret = -ENOMEM;
diff -urp vanilla/drivers/usb/core/message.c isotree/drivers/usb/core/message.c
--- vanilla/drivers/usb/core/message.c	2007-07-04 14:14:45.000000000 +0200
+++ isotree/drivers/usb/core/message.c	2007-07-05 14:05:31.000000000 +0200
@@ -77,7 +77,7 @@ static int usb_internal_control_msg(stru
 	int retv;
 	int length;
 
-	urb = usb_alloc_urb(0, GFP_NOIO);
+	urb = usb_alloc_urb(usb_dev->ep_out[usb_pipeendpoint(pipe)], len, GFP_NOIO);
 	if (!urb)
 		return -ENOMEM;
   
@@ -215,7 +215,7 @@ int usb_bulk_msg(struct usb_device *usb_
 	if (!ep || len < 0)
 		return -EINVAL;
 
-	urb = usb_alloc_urb(0, GFP_KERNEL);
+	urb = usb_alloc_urb(ep, len, GFP_KERNEL);
 	if (!urb)
 		return -ENOMEM;
 
@@ -391,7 +391,9 @@ int usb_sg_init (
 	for (i = 0; i < io->entries; i++) {
 		unsigned		len;
 
-		io->urbs [i] = usb_alloc_urb (0, mem_flags);
+		io->urbs [i] = usb_alloc_urb(
+			(usb_pipein (pipe) ? dev->ep_in : dev->ep_out)[usb_pipeendpoint(pipe)],
+			0, mem_flags);
 		if (!io->urbs [i]) {
 			io->entries = i;
 			goto nomem;
diff -urp vanilla/drivers/usb/core/urb.c isotree/drivers/usb/core/urb.c
--- vanilla/drivers/usb/core/urb.c	2007-07-04 16:37:09.000000000 +0200
+++ isotree/drivers/usb/core/urb.c	2007-07-06 14:05:36.000000000 +0200
@@ -11,8 +11,10 @@
 static void urb_destroy(struct kref *kref)
 {
 	struct urb *urb = to_urb(kref);
+	struct usb_hcd	*hcd = bus_to_hcd(urb->dev->bus);
+
 	kfree(urb->iso_packets);
-	kfree(urb);
+	(hcd->driver->free_urb)(hcd, urb);
 }
 
 /**
@@ -54,24 +56,49 @@ void usb_init_urb(struct urb *urb)
  *
  * The driver must call usb_free_urb() when it is finished with the urb.
  */
-struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
+struct urb *usb_alloc_urb(struct usb_host_endpoint *ep, size_t alloc_length, gfp_t mem_flags)
 {
 	struct urb *urb;
-	struct usb_iso_packet_descriptor *frames = NULL;
-
-	if (iso_packets) {
-		frames = kmalloc(iso_packets * sizeof(struct usb_iso_packet_descriptor), mem_flags);
-		if (!frames)
-			return NULL;
+BUG_ON(ep == NULL);
+BUG_ON(ep->ep_dev == NULL);
+BUG_ON(ep->ep_dev->udev == NULL);
+	struct usb_device *dev = ep->ep_dev->udev;
+	struct usb_hcd	*hcd = bus_to_hcd(dev->bus);
+BUG_ON(hcd == NULL);
+BUG_ON(hcd->driver == NULL);
+	if (!hcd->driver->alloc_urb) {
+		err("No allocation method");
+		return NULL;
 	}
+	urb = (hcd->driver->alloc_urb)(hcd, ep, alloc_length, 0, mem_flags);
+	if (!urb) {
+		err("usb_alloc_urb: failed to alloc URB");
+		return NULL;
+	}
+
+	usb_init_urb(urb);
+	return urb;
+}
+
+struct urb *usb_alloc_iso_urb(struct usb_host_endpoint *ep, unsigned int iso_packets, gfp_t mem_flags)
+{
+	struct urb *urb;
+	struct usb_iso_packet_descriptor *packets = NULL;
+	struct usb_device *dev = ep->ep_dev->udev;
+	struct usb_hcd	*hcd = bus_to_hcd(dev->bus);
+
+	packets = kmalloc(iso_packets * sizeof(struct usb_iso_packet_descriptor), mem_flags);
+	if (!packets)
+		return NULL;
 
-	urb = kmalloc(sizeof(struct urb), mem_flags);
+	urb = (hcd->driver->alloc_urb)(hcd, ep, 0, iso_packets, mem_flags);
 	if (!urb) {
-		err("alloc_urb: kmalloc failed");
-		kfree(frames);
+		err("usb_alloc_iso_urb: failed to alloc URB");
+		kfree(packets);
 		return NULL;
 	}
-	urb->iso_packets = frames;
+	usb_init_urb(urb);
+	urb->iso_packets = packets;
 
 	return urb;
 }
@@ -488,6 +515,7 @@ void usb_kill_urb(struct urb *urb)
 
 EXPORT_SYMBOL(usb_init_urb);
 EXPORT_SYMBOL(usb_alloc_urb);
+EXPORT_SYMBOL(usb_alloc_iso_urb);
 EXPORT_SYMBOL(usb_free_urb);
 EXPORT_SYMBOL(usb_get_urb);
 EXPORT_SYMBOL(usb_submit_urb);
diff -urp vanilla/drivers/usb/host/ohci-mem.c isotree/drivers/usb/host/ohci-mem.c
--- vanilla/drivers/usb/host/ohci-mem.c	2007-02-04 19:44:54.000000000 +0100
+++ isotree/drivers/usb/host/ohci-mem.c	2007-07-05 15:03:04.000000000 +0200
@@ -136,3 +136,16 @@ ed_free (struct ohci_hcd *hc, struct ed 
 	dma_pool_free (hc->ed_cache, ed, ed->dma);
 }
 
+static void ohci_free_urb(struct usb_hcd *hcd, struct urb *urb)
+{
+	kfree(urb);
+}
+
+static struct urb *ohci_alloc_urb(struct usb_hcd *hcd,
+					struct usb_host_endpoint *ep,
+					size_t alloc_length,
+					unsigned int num_iso_packets,
+					gfp_t mem_flags)
+{
+	return kmalloc(sizeof(struct urb), mem_flags);
+}
diff -urp vanilla/drivers/usb/host/ohci-pci.c isotree/drivers/usb/host/ohci-pci.c
--- vanilla/drivers/usb/host/ohci-pci.c	2007-07-04 14:14:45.000000000 +0200
+++ isotree/drivers/usb/host/ohci-pci.c	2007-07-05 14:59:59.000000000 +0200
@@ -282,6 +282,9 @@ static const struct hc_driver ohci_pci_h
 	.urb_dequeue =		ohci_urb_dequeue,
 	.endpoint_disable =	ohci_endpoint_disable,
 
+	.alloc_urb =		ohci_alloc_urb,
+	.free_urb =		ohci_free_urb,
+
 	/*
 	 * scheduling support
 	 */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.