Merge commit 'v0.11.1' into stable-0.11

* commit 'v0.11.1':
  Update version and changelog for 0.11.1 release
  fix I2C slave addressing
  Revert "vga: do not resize the screen on hw_invalidate"
  slirp: fix use-after-free
  Fix sparc.ld
  ELF codedump build failures
  kvm: Move KVM mp_state accessors to i386-specific code
  this patch fixes a typo where armv4l was incorrectly spelled arm4l,
  net: disable draining tap queue in one go
  pcnet: Restart poll timer on pcnet_start
  Sparc32: Fix lance
  mac99: fix segmentation fault on startup
  usb-linux.c: fix buffer overflow
  ARM host: fix generated blocks linking
  qemu serial: lost tx irqs (affecting FreeBSD's new uart(4) driver)
  exec-all.h: increase MAX_OP_PER_INSTR to 96 from 64

Conflicts:
	net.c

Signed-off-by: Avi Kivity <avi@redhat.com>
diff --git a/Changelog b/Changelog
index 857cbb2..2d594cd 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,20 @@
+Version 0.11.1
+  - fix I2C slave addressing (Juha Riihimäki)
+  - Revert "vga: do not resize the screen on hw_invalidate" (Aurelien Jarno)
+  - slirp: fix use-after-free (Mark McLoughlin)
+  - Fix sparc.ld (Blue Swirl)
+  - ELF codedump build failures (Laurent Desnogues)
+  - kvm: Move KVM mp_state accessors to i386-specific code (Hollis Blanchard)
+  - fix configure script with armv4l cpu (Laurent Desnogues)
+  - net: disable draining tap queue in one go (Mark McLoughlin)
+  - pcnet: Restart poll timer on pcnet_start (Jan Kiszka)
+  - Sparc32: Fix lance (Blue Swirl)
+  - mac99: fix segmentation fault on startup (Aurelien Jarno)
+  - usb-linux.c: fix buffer overflow (Jim Paris)
+  - ARM host: fix generated blocks linking (Laurent Desnogues)
+  - qemu serial: lost tx irqs (affecting FreeBSD's new uart(4) driver (Juergen Lock)
+  - exec-all.h: increase MAX_OP_PER_INSTR to 96 from 64 (Aurelien Jarno)
+
 version 0.11.0
   - fix rtc polling mode (Bernhard Kauer)
   - qcow2: order concurrent aio requests (Kevin Wolf)
diff --git a/VERSION b/VERSION
index d9df1bb..af88ba8 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.11.0
+0.11.1
diff --git a/configure b/configure
index 02afe65..35ce2e1 100755
--- a/configure
+++ b/configure
@@ -1638,7 +1638,7 @@
   i386|x86_64|alpha|cris|hppa|ia64|m68k|microbaze|mips|mips64|ppc|ppc64|s390|sparc|sparc64)
     ARCH=$cpu
   ;;
-  armv4b|arm4l)
+  armv4b|armv4l)
     ARCH=arm
   ;;
   *)
diff --git a/exec-all.h b/exec-all.h
index 31ab7ad..6439e3c 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -34,7 +34,7 @@
 typedef struct TranslationBlock TranslationBlock;
 
 /* XXX: make safe guess about sizes */
-#define MAX_OP_PER_INSTR 64
+#define MAX_OP_PER_INSTR 96
 /* A Call op needs up to 6 + 2N parameters (N = number of arguments).  */
 #define MAX_OPC_PARAM 10
 #define OPC_BUF_SIZE 512
@@ -211,7 +211,9 @@
 #endif
 
     /* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */
-    *(uint32_t *)jmp_addr |= ((addr - (jmp_addr + 8)) >> 2) & 0xffffff;
+    *(uint32_t *)jmp_addr =
+        (*(uint32_t *)jmp_addr & ~0xffffff)
+        | (((addr - (jmp_addr + 8)) >> 2) & 0xffffff);
 
 #if QEMU_GNUC_PREREQ(4, 1)
     __clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
diff --git a/hw/i2c.c b/hw/i2c.c
index 42a5d7a..16e5112 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -81,9 +81,11 @@
     i2c_slave *slave = NULL;
 
     LIST_FOREACH(qdev, &bus->qbus.children, sibling) {
-        slave = I2C_SLAVE_FROM_QDEV(qdev);
-        if (slave->address == address)
+        i2c_slave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
+        if (candidate->address == address) {
+            slave = candidate;
             break;
+        }
     }
 
     if (!slave)
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 22ab6be..008b71a 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -936,6 +936,7 @@
 
     s->csr[0] &= ~0x0004;       /* clear STOP bit */
     s->csr[0] |= 0x0002;
+    pcnet_poll_timer(s);
 }
 
 static void pcnet_stop(PCNetState *s)
diff --git a/hw/serial.c b/hw/serial.c
index d70504b..498f4a0 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -195,12 +195,10 @@
          * this is not in the specification but is observed on existing
          * hardware.  */
         tmp_iir = UART_IIR_CTI;
-    } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR)) {
-        if (!(s->fcr & UART_FCR_FE)) {
-           tmp_iir = UART_IIR_RDI;
-        } else if (s->recv_fifo.count >= s->recv_fifo.itl) {
-           tmp_iir = UART_IIR_RDI;
-        }
+    } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR) &&
+               (!(s->fcr & UART_FCR_FE) ||
+                s->recv_fifo.count >= s->recv_fifo.itl)) {
+        tmp_iir = UART_IIR_RDI;
     } else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {
         tmp_iir = UART_IIR_THRI;
     } else if ((s->ier & UART_IER_MSI) && (s->msr & UART_MSR_ANY_DELTA)) {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index c810b35..f390595 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -374,6 +374,7 @@
 
     dev = qdev_create(NULL, "lance");
     dev->nd = nd;
+    qdev_prop_set_ptr(dev, "dma", dma_opaque);
     qdev_init(dev);
     s = sysbus_from_qdev(dev);
     sysbus_mmio_map(s, 0, leaddr);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 0ad0cd3..ca8d9a5 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -234,7 +234,7 @@
     cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);
 
     d = pci_register_device(s->bus, "Uni-north AGP", sizeof(PCIDevice),
-                            11 << 3, NULL, NULL);
+                            12 << 3, NULL, NULL);
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_AGP);
     d->config[0x08] = 0x00; // revision
diff --git a/hw/vga.c b/hw/vga.c
index ec7a7c3..31bf369 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1844,8 +1844,7 @@
     if (ds_get_bits_per_pixel(s->ds) == 0) {
         /* nothing to do */
     } else {
-        full_update = s->full_update;
-        s->full_update = 0;
+        full_update = 0;
         if (!(s->ar_index & 0x20)) {
             graphic_mode = GMODE_BLANK;
         } else {
@@ -1878,7 +1877,8 @@
 {
     VGAState *s = (VGAState *)opaque;
 
-    s->full_update = 1;
+    s->last_width = -1;
+    s->last_height = -1;
 }
 
 void vga_reset(void *opaque)
diff --git a/hw/vga_int.h b/hw/vga_int.h
index be174f3..1aaf5c5 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -158,7 +158,6 @@
     uint32_t last_width, last_height; /* in chars or pixels */
     uint32_t last_scr_width, last_scr_height; /* in pixels */
     uint32_t last_depth; /* in bits */
-    uint8_t full_update;
     uint8_t cursor_start, cursor_end;
     uint32_t cursor_offset;
     unsigned int (*rgb_to_pixel)(unsigned int r,
diff --git a/kvm-all.c b/kvm-all.c
index b4b5a35..5d9d0b6 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -194,26 +194,6 @@
     return ret;
 }
 
-int kvm_put_mp_state(CPUState *env)
-{
-    struct kvm_mp_state mp_state = { .mp_state = env->mp_state };
-
-    return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, &mp_state);
-}
-
-int kvm_get_mp_state(CPUState *env)
-{
-    struct kvm_mp_state mp_state;
-    int ret;
-
-    ret = kvm_vcpu_ioctl(env, KVM_GET_MP_STATE, &mp_state);
-    if (ret < 0) {
-        return ret;
-    }
-    env->mp_state = mp_state.mp_state;
-    return 0;
-}
-
 /*
  * dirty pages logging control
  */
diff --git a/kvm.h b/kvm.h
index 0191752..c4f21ec 100644
--- a/kvm.h
+++ b/kvm.h
@@ -74,9 +74,6 @@
 
 int kvm_vcpu_ioctl(CPUState *env, int type, ...);
 
-int kvm_get_mp_state(CPUState *env);
-int kvm_put_mp_state(CPUState *env);
-
 /* Arch specific hooks */
 
 int kvm_arch_post_run(CPUState *env, struct kvm_run *run);
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 3a8268b..dbadc51 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -134,13 +134,13 @@
     regs->rip = infop->entry;
 }
 
-typedef target_ulong    elf_greg_t;
+typedef target_ulong    target_elf_greg_t;
 typedef uint32_t        target_uid_t;
 typedef uint32_t        target_gid_t;
 typedef int32_t         target_pid_t;
 
 #define ELF_NREG    27
-typedef elf_greg_t  elf_gregset_t[ELF_NREG];
+typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
 
 /*
  * Note that ELF_NREG should be 29 as there should be place for
@@ -149,7 +149,7 @@
  *
  * See linux kernel: arch/x86/include/asm/elf.h
  */
-static void elf_core_copy_regs(elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 {
     (*regs)[0] = env->regs[15];
     (*regs)[1] = env->regs[14];
@@ -211,13 +211,13 @@
     regs->edx = 0;
 }
 
-typedef target_ulong    elf_greg_t;
+typedef target_ulong    target_elf_greg_t;
 typedef uint16_t        target_uid_t;
 typedef uint16_t        target_gid_t;
 typedef int32_t         target_pid_t;
 
 #define ELF_NREG    17
-typedef elf_greg_t  elf_gregset_t[ELF_NREG];
+typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
 
 /*
  * Note that ELF_NREG should be 19 as there should be place for
@@ -226,7 +226,7 @@
  *
  * See linux kernel: arch/x86/include/asm/elf.h
  */
-static void elf_core_copy_regs(elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 {
     (*regs)[0] = env->regs[R_EBX];
     (*regs)[1] = env->regs[R_ECX];
@@ -286,15 +286,15 @@
     regs->ARM_r10 = infop->start_data;
 }
 
-typedef uint32_t elf_greg_t;
+typedef uint32_t target_elf_greg_t;
 typedef uint16_t target_uid_t;
 typedef uint16_t target_gid_t;
 typedef int32_t  target_pid_t;
 
 #define ELF_NREG    18
-typedef elf_greg_t  elf_gregset_t[ELF_NREG];
+typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
 
-static void elf_core_copy_regs(elf_gregset_t *regs, const CPUState *env)
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 {
     (*regs)[0] = env->regs[0];
     (*regs)[1] = env->regs[1];
@@ -1725,7 +1725,7 @@
 
 /*
  * Definitions to generate Intel SVR4-like core files.
- * These mostly have the same names as the SVR4 types with "elf_"
+ * These mostly have the same names as the SVR4 types with "target_elf_"
  * tacked on the front to prevent clashes with linux definitions,
  * and the typedef forms have been avoided.  This is mostly like
  * the SVR4 structure, but more Linuxy, with things that Linux does
@@ -1745,9 +1745,9 @@
  * Next you define type of register set used for dumping.  ELF specification
  * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
  *
- * typedef <target_regtype> elf_greg_t;
+ * typedef <target_regtype> target_elf_greg_t;
  * #define ELF_NREG <number of registers>
- * typedef elf_greg_t elf_gregset_t[ELF_NREG];
+ * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
  *
  * Then define following types to match target types.  Actual types can
  * be found from linux kernel (arch/<ARCH>/include/asm/posix_types.h):
@@ -1759,7 +1759,8 @@
  * Last step is to implement target specific function that copies registers
  * from given cpu into just specified register set.  Prototype is:
  *
- * static void elf_core_copy_regs(elf_gregset_t *regs, const CPUState *env);
+ * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
+ *                                const CPUState *env);
  *
  * Parameters:
  *     regs - copy register values into here (allocated and zeroed by caller)
@@ -1779,14 +1780,14 @@
     size_t     notesz;
 };
 
-struct elf_siginfo {
+struct target_elf_siginfo {
     int  si_signo; /* signal number */
     int  si_code;  /* extra code */
     int  si_errno; /* errno */
 };
 
-struct elf_prstatus {
-    struct elf_siginfo pr_info;      /* Info associated with signal */
+struct target_elf_prstatus {
+    struct target_elf_siginfo pr_info;      /* Info associated with signal */
     short              pr_cursig;    /* Current signal */
     target_ulong       pr_sigpend;   /* XXX */
     target_ulong       pr_sighold;   /* XXX */
@@ -1798,13 +1799,13 @@
     struct target_timeval pr_stime;  /* XXX System time */
     struct target_timeval pr_cutime; /* XXX Cumulative user time */
     struct target_timeval pr_cstime; /* XXX Cumulative system time */
-    elf_gregset_t      pr_reg;       /* GP registers */
+    target_elf_gregset_t      pr_reg;       /* GP registers */
     int                pr_fpvalid;   /* XXX */
 };
 
 #define ELF_PRARGSZ     (80) /* Number of chars for args */
 
-struct elf_prpsinfo {
+struct target_elf_prpsinfo {
     char         pr_state;       /* numeric process state */
     char         pr_sname;       /* char for pr_state */
     char         pr_zomb;        /* zombie */
@@ -1821,7 +1822,7 @@
 /* Here is the structure in which status of each thread is captured. */
 struct elf_thread_status {
     TAILQ_ENTRY(elf_thread_status)  ets_link;
-    struct elf_prstatus prstatus;   /* NT_PRSTATUS */
+    struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */
 #if 0
     elf_fpregset_t fpu;             /* NT_PRFPREG */
     struct task_struct *thread;
@@ -1833,8 +1834,8 @@
 
 struct elf_note_info {
     struct memelfnote   *notes;
-    struct elf_prstatus *prstatus;  /* NT_PRSTATUS */
-    struct elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
+    struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */
+    struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
 
     TAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
 #if 0
@@ -1876,8 +1877,8 @@
 static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
 static void fill_note(struct memelfnote *, const char *, int,
     unsigned int, void *);
-static void fill_prstatus(struct elf_prstatus *, const TaskState *, int);
-static int fill_psinfo(struct elf_prpsinfo *, const TaskState *);
+static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
+static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
 static void fill_auxv_note(struct memelfnote *, const TaskState *);
 static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
 static size_t note_size(const struct memelfnote *);
@@ -1891,10 +1892,10 @@
 static int write_note_info(struct elf_note_info *, int);
 
 #ifdef BSWAP_NEEDED
-static void bswap_prstatus(struct elf_prstatus *);
-static void bswap_psinfo(struct elf_prpsinfo *);
+static void bswap_prstatus(struct target_elf_prstatus *);
+static void bswap_psinfo(struct target_elf_prpsinfo *);
 
-static void bswap_prstatus(struct elf_prstatus *prstatus)
+static void bswap_prstatus(struct target_elf_prstatus *prstatus)
 {
     prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
     prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
@@ -1911,7 +1912,7 @@
     prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
 }
 
-static void bswap_psinfo(struct elf_prpsinfo *psinfo)
+static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
 {
     psinfo->pr_flag = tswapl(psinfo->pr_flag);
     psinfo->pr_uid = tswap16(psinfo->pr_uid);
@@ -2105,7 +2106,7 @@
     return (note->notesz);
 }
 
-static void fill_prstatus(struct elf_prstatus *prstatus,
+static void fill_prstatus(struct target_elf_prstatus *prstatus,
     const TaskState *ts, int signr)
 {
     (void) memset(prstatus, 0, sizeof (*prstatus));
@@ -2120,7 +2121,7 @@
 #endif
 }
 
-static int fill_psinfo(struct elf_prpsinfo *psinfo, const TaskState *ts)
+static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
 {
     char *filename, *base_filename;
     unsigned int i, len;
diff --git a/net.c b/net.c
index a1c1111..effd9a2 100644
--- a/net.c
+++ b/net.c
@@ -1453,27 +1453,24 @@
 {
     TAPState *s = opaque;
     int size;
+    uint8_t *buf = s->buf;
 
-    do {
-        uint8_t *buf = s->buf;
-
-        size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
-        if (size <= 0) {
-            break;
-        }
+    size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
+    if (size <= 0) {
+        return;
+    }
 
 #ifdef IFF_VNET_HDR
-        if (s->has_vnet_hdr && !s->using_vnet_hdr) {
-            buf += sizeof(struct virtio_net_hdr);
-            size -= sizeof(struct virtio_net_hdr);
-        }
+    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
+        buf += sizeof(struct virtio_net_hdr);
+        size -= sizeof(struct virtio_net_hdr);
+    }
 #endif
 
-        size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed);
-        if (size == 0) {
-            tap_read_poll(s, 0);
-        }
-    } while (size > 0);
+    size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed);
+    if (size == 0) {
+        tap_read_poll(s, 0);
+    }
 }
 
 #ifdef TUNSETSNDBUF
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index 7652fea..87508ba 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -95,8 +95,8 @@
 	 * Either free() it or put it on the free list
 	 */
 	if (m->m_flags & M_DOFREE) {
-		free(m);
 		m->slirp->mbuf_alloced--;
+		free(m);
 	} else if ((m->m_flags & M_FREELIST) == 0) {
 		insque(m,&m->slirp->m_freelist);
 		m->m_flags = M_FREELIST; /* Clobber other flags */
diff --git a/sparc.ld b/sparc.ld
index 26ab415..9d23636 100644
--- a/sparc.ld
+++ b/sparc.ld
@@ -66,6 +66,26 @@
   .data1   : { *(.data1) }
   .tdata    : { *(.tdata) }
   .tbss    : { *(.tbss) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+     PROVIDE_HIDDEN (__init_array_start = .);
+     KEEP (*(SORT(.init_array.*)))
+     KEEP (*(.init_array))
+     PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(.fini_array))
+    KEEP (*(SORT(.fini_array.*)))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
   .ctors         :
   {
     *(.ctors)
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index cfa5b80..6037b20 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -665,6 +665,26 @@
     return 0;
 }
 
+static int kvm_put_mp_state(CPUState *env)
+{
+    struct kvm_mp_state mp_state = { .mp_state = env->mp_state };
+
+    return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, &mp_state);
+}
+
+static int kvm_get_mp_state(CPUState *env)
+{
+    struct kvm_mp_state mp_state;
+    int ret;
+
+    ret = kvm_vcpu_ioctl(env, KVM_GET_MP_STATE, &mp_state);
+    if (ret < 0) {
+        return ret;
+    }
+    env->mp_state = mp_state.mp_state;
+    return 0;
+}
+
 int kvm_arch_put_registers(CPUState *env)
 {
     int ret;
diff --git a/usb-linux.c b/usb-linux.c
index 043f6b6..eb1c5f0 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -115,7 +115,7 @@
     uint16_t offset;
     uint8_t  state;
     struct   usb_ctrlrequest req;
-    uint8_t  buffer[1024];
+    uint8_t  buffer[2048];
 };
 
 typedef struct USBHostDevice {
@@ -552,6 +552,7 @@
     struct usbdevfs_urb *urb;
     AsyncURB *aurb;
     int ret, value, index;
+    int buffer_len;
 
     /* 
      * Process certain standard device requests.
@@ -580,6 +581,13 @@
 
     /* The rest are asynchronous */
 
+    buffer_len = 8 + s->ctrl.len;
+    if (buffer_len > sizeof(s->ctrl.buffer)) {
+	    fprintf(stderr, "husb: ctrl buffer too small (%u > %lu)\n",
+		    buffer_len, sizeof(s->ctrl.buffer));
+	    return USB_RET_STALL;
+    }
+
     aurb = async_alloc();
     aurb->hdev   = s;
     aurb->packet = p;
@@ -596,7 +604,7 @@
     urb->endpoint = p->devep;
 
     urb->buffer        = &s->ctrl.req;
-    urb->buffer_length = 8 + s->ctrl.len;
+    urb->buffer_length = buffer_len;
 
     urb->usercontext = s;