Hi, > +struct ks959_speedparams { > + __le32 baudrate; /* baud rate, little endian */ > + unsigned int data_bits : 2; /* data bits - 5 (5..8) */ > + unsigned int : 1; > + unsigned int stop_bits : 1; > + unsigned int parity_enable : 1; > + unsigned int parity_type : 1; > + unsigned int : 1; > + unsigned int reset : 1; > + __u8 reserved[3]; > +} __attribute__ ((packed));
The attribute is not needed. > +/* Send a control request to change speed of the dongle */ > +static int ks959_change_speed(struct ks959_cb * kingsun, unsigned speed) > +{ > + static unsigned int supported_speeds[] = {2400, 9600, 19200, 38400, > + 57600, 115200, 576000, 1152000, 4000000, 0}; > + int err; > + unsigned int i; > + > + if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL) > + return -ENOMEM; > + > + /* Check that requested speed is among the supported ones */ > + for (i = 0; supported_speeds[i] != 0 && supported_speeds[i] != speed; > i++); > + if (supported_speeds[i] == 0) return -EOPNOTSUPP; > + > + memset(&(kingsun->speedparams), 0, sizeof(struct ks959_speedparams)); > + kingsun->speedparams.baudrate = cpu_to_le32(speed); > + kingsun->speedparams.data_bits = 3; /* 8 data bits */ > + > + kingsun->speed_setuprequest->bRequestType = USB_DIR_OUT | > USB_TYPE_CLASS | USB_RECIP_INTERFACE; > + kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND; > + kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200); > + kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001); > + kingsun->speed_setuprequest->wLength = cpu_to_le16(8); > + usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev, > + usb_sndctrlpipe(kingsun->usbdev, 0), > + (unsigned char *)kingsun->speed_setuprequest, > + &(kingsun->speedparams), sizeof(struct > ks959_speedparams), > + ks959_speed_irq, kingsun); > + kingsun->speed_urb->status = 0; > + err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC); > + > + return err; > +} Are you sure the URB doesn't need to be waited for? > +close_irlap: > + irlap_close(kingsun->irlap); > +free_mem: > + if (kingsun->speed_urb) { > + usb_free_urb(kingsun->speed_urb); > + kingsun->speed_urb = NULL; > + } > + if (kingsun->tx_urb) { > + usb_free_urb(kingsun->tx_urb); > + kingsun->tx_urb = NULL; > + } > + if (kingsun->rx_urb) { > + usb_free_urb(kingsun->rx_urb); > + kingsun->rx_urb = NULL; > + } > + if (kingsun->rx_unwrap_buff.skb) { > + kfree_skb(kingsun->rx_unwrap_buff.skb); > + kingsun->rx_unwrap_buff.skb = NULL; > + kingsun->rx_unwrap_buff.head = NULL; > + } > + return err; > +} usb_free_urb() can take NULL. > +static int ks959_net_close(struct net_device *netdev) > +{ > + struct ks959_cb *kingsun = netdev_priv(netdev); > + > + /* Stop transmit processing */ > + netif_stop_queue(netdev); > + > + /* Mop up receive && transmit urb's */ > + usb_kill_urb(kingsun->speed_urb); > + usb_kill_urb(kingsun->tx_urb); > + usb_kill_urb(kingsun->rx_urb); Race condition. You must kill the tx_urb first, as it can submit the speed_urb Regards Oliver ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel