int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, unsigned int count) { int r; struct usb_device *udev; struct usb_req_write_regs *req = NULL; int i, req_len, actual_req_len; if (count == 0) return 0; if (count > USB_MAX_IOWRITE16_COUNT) { dev_dbg_f(zd_usb_dev(usb), "error: count %u exceeds possible max %u\n", count, USB_MAX_IOWRITE16_COUNT); return -EINVAL; } if (in_atomic()) { dev_dbg_f(zd_usb_dev(usb), "error: io in atomic context not supported\n"); return -EWOULDBLOCK; } req_len = sizeof(struct usb_req_write_regs) + count * sizeof(struct reg_data); req = kmalloc(req_len, GFP_KERNEL); if (!req) return -ENOMEM; req->id = cpu_to_le16(USB_REQ_WRITE_REGS); for (i = 0; i < count; i++) { struct reg_data *rw = &req->reg_writes[i]; rw->addr = cpu_to_le16((u16)ioreqs[i].addr); rw->value = cpu_to_le16(ioreqs[i].value); } udev = zd_usb_to_usbdev(usb); r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), req, req_len, &actual_req_len, 1000 /* ms */); if (r) { dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg(). Error number %d\n", r); goto error; } if (req_len != actual_req_len) { dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()" " req_len %d != actual_req_len %d\n", req_len, actual_req_len); r = -EIO; goto error; } /* FALL-THROUGH with r == 0 */ error: kfree(req); return r; }
void zd_usb_disable_int(struct zd_usb *usb) { unsigned long flags; struct usb_device *udev = zd_usb_to_usbdev(usb); struct zd_usb_interrupt *intr = &usb->intr; struct urb *urb; void *buffer; dma_addr_t buffer_dma; spin_lock_irqsave(&intr->lock, flags); urb = intr->urb; if (!urb) { spin_unlock_irqrestore(&intr->lock, flags); return; } intr->urb = NULL; buffer = intr->buffer; buffer_dma = intr->buffer_dma; intr->buffer = NULL; spin_unlock_irqrestore(&intr->lock, flags); usb_kill_urb(urb); dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb); usb_free_urb(urb); if (buffer) usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER, buffer, buffer_dma); }
static void disconnect(struct usb_interface *intf) { struct net_device *netdev = zd_intf_to_netdev(intf); struct zd_mac *mac = zd_netdev_mac(netdev); struct zd_usb *usb = &mac->chip.usb; /* Either something really bad happened, or we're just dealing with * a DEVICE_INSTALLER. */ if (netdev == NULL) return; dev_dbg_f(zd_usb_dev(usb), "\n"); zd_netdev_disconnect(netdev); /* Just in case something has gone wrong! */ zd_usb_disable_rx(usb); zd_usb_disable_int(usb); /* If the disconnect has been caused by a removal of the * driver module, the reset allows reloading of the driver. If the * reset will not be executed here, the upload of the firmware in the * probe function caused by the reloading of the driver will fail. */ usb_reset_device(interface_to_usbdev(intf)); zd_netdev_free(netdev); dev_dbg(&intf->dev, "disconnected\n"); }
static int get_results(struct zd_usb *usb, u16 *values, struct usb_req_read_regs *req, unsigned int count) { int r; int i; struct zd_usb_interrupt *intr = &usb->intr; struct read_regs_int *rr = &intr->read_regs; struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; spin_lock_irq(&intr->lock); r = -EIO; /* The created block size seems to be larger than expected. * However results appear to be correct. */ if (rr->length < usb_int_regs_length(count)) { dev_dbg_f(zd_usb_dev(usb), "error: actual length %d less than expected %d\n", rr->length, usb_int_regs_length(count)); goto error_unlock; } if (rr->length > sizeof(rr->buffer)) { dev_dbg_f(zd_usb_dev(usb), "error: actual length %d exceeds buffer size %zu\n", rr->length, sizeof(rr->buffer)); goto error_unlock; } for (i = 0; i < count; i++) { struct reg_data *rd = ®s->regs[i]; if (rd->addr != req->addr[i]) { dev_dbg_f(zd_usb_dev(usb), "rd[%d] addr %#06hx expected %#06hx\n", i, le16_to_cpu(rd->addr), le16_to_cpu(req->addr[i])); goto error_unlock; } values[i] = le16_to_cpu(rd->value); } r = 0; error_unlock: spin_unlock_irq(&intr->lock); return r; }
static int __zd_usb_enable_rx(struct zd_usb *usb) { int i, r; struct zd_usb_rx *rx = &usb->rx; struct urb **urbs; dev_dbg_f(zd_usb_dev(usb), "\n"); r = -ENOMEM; urbs = kcalloc(RX_URBS_COUNT, sizeof(struct urb *), GFP_KERNEL); if (!urbs) goto error; for (i = 0; i < RX_URBS_COUNT; i++) { urbs[i] = alloc_rx_urb(usb); if (!urbs[i]) goto error; } ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&rx->lock); if (rx->urbs) { spin_unlock_irq(&rx->lock); r = 0; goto error; } rx->urbs = urbs; rx->urbs_count = RX_URBS_COUNT; spin_unlock_irq(&rx->lock); for (i = 0; i < RX_URBS_COUNT; i++) { r = usb_submit_urb(urbs[i], GFP_KERNEL); if (r) goto error_submit; } return 0; error_submit: for (i = 0; i < RX_URBS_COUNT; i++) { usb_kill_urb(urbs[i]); } spin_lock_irq(&rx->lock); rx->urbs = NULL; rx->urbs_count = 0; spin_unlock_irq(&rx->lock); error: if (urbs) { for (i = 0; i < RX_URBS_COUNT; i++) free_rx_urb(urbs[i]); } return r; }
void zd_usb_disable_int(struct zd_usb *usb) { unsigned long flags; struct zd_usb_interrupt *intr = &usb->intr; struct urb *urb; spin_lock_irqsave(&intr->lock, flags); urb = intr->urb; if (!urb) { spin_unlock_irqrestore(&intr->lock, flags); return; } intr->urb = NULL; spin_unlock_irqrestore(&intr->lock, flags); usb_kill_urb(urb); dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb); usb_free_urb(urb); }
/** * zd_usb_tx: initiates transfer of a frame of the device * * @usb: the zd1211rw-private USB structure * @skb: a &struct sk_buff pointer * * This function tranmits a frame to the device. It doesn't wait for * completion. The frame must contain the control set and have all the * control set information available. * * The function returns 0 if the transfer has been successfully initiated. */ int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb) { int r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct usb_device *udev = zd_usb_to_usbdev(usb); struct urb *urb; struct zd_usb_tx *tx = &usb->tx; if (!atomic_read(&tx->enabled)) { r = -ENOENT; goto out; } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { r = -ENOMEM; goto out; } usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), skb->data, skb->len, tx_urb_complete, skb); info->rate_driver_data[1] = (void *)jiffies; skb_queue_tail(&tx->submitted_skbs, skb); usb_anchor_urb(urb, &tx->submitted); r = usb_submit_urb(urb, GFP_ATOMIC); if (r) { dev_dbg_f(zd_usb_dev(usb), "error submit urb %p %d\n", urb, r); usb_unanchor_urb(urb); skb_unlink(skb, &tx->submitted_skbs); goto error; } tx_inc_submitted_urbs(usb); return 0; error: usb_free_urb(urb); out: return r; }
int zd_usb_enable_int(struct zd_usb *usb) { int r; struct usb_device *udev = zd_usb_to_usbdev(usb); struct zd_usb_interrupt *intr = &usb->intr; struct urb *urb; dev_dbg_f(zd_usb_dev(usb), "\n"); urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { r = -ENOMEM; goto out; } ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&intr->lock); if (intr->urb) { spin_unlock_irq(&intr->lock); r = 0; goto error_free_urb; } intr->urb = urb; spin_unlock_irq(&intr->lock); r = -ENOMEM; intr->buffer = usb_alloc_coherent(udev, USB_MAX_EP_INT_BUFFER, GFP_KERNEL, &intr->buffer_dma); if (!intr->buffer) { dev_dbg_f(zd_usb_dev(usb), "couldn't allocate transfer_buffer\n"); goto error_set_urb_null; } usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), intr->buffer, USB_MAX_EP_INT_BUFFER, int_urb_complete, usb, intr->interval); urb->transfer_dma = intr->buffer_dma; urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); r = usb_submit_urb(urb, GFP_KERNEL); if (r) { dev_dbg_f(zd_usb_dev(usb), "Couldn't submit urb. Error number %d\n", r); goto error; } return 0; error: usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER, intr->buffer, intr->buffer_dma); error_set_urb_null: spin_lock_irq(&intr->lock); intr->urb = NULL; spin_unlock_irq(&intr->lock); error_free_urb: usb_free_urb(urb); out: return r; }
int zd_usb_enable_int(struct zd_usb *usb) { int r; struct usb_device *udev; struct zd_usb_interrupt *intr = &usb->intr; void *transfer_buffer = NULL; struct urb *urb; dev_dbg_f(zd_usb_dev(usb), "\n"); urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { r = -ENOMEM; goto out; } ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&intr->lock); if (intr->urb) { spin_unlock_irq(&intr->lock); r = 0; goto error_free_urb; } intr->urb = urb; spin_unlock_irq(&intr->lock); /* TODO: make it a DMA buffer */ r = -ENOMEM; transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_KERNEL); if (!transfer_buffer) { dev_dbg_f(zd_usb_dev(usb), "couldn't allocate transfer_buffer\n"); goto error_set_urb_null; } udev = zd_usb_to_usbdev(usb); usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), transfer_buffer, USB_MAX_EP_INT_BUFFER, int_urb_complete, usb, intr->interval); dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); r = usb_submit_urb(urb, GFP_KERNEL); if (r) { dev_dbg_f(zd_usb_dev(usb), "Couldn't submit urb. Error number %d\n", r); goto error; } return 0; error: kfree(transfer_buffer); error_set_urb_null: spin_lock_irq(&intr->lock); intr->urb = NULL; spin_unlock_irq(&intr->lock); error_free_urb: usb_free_urb(urb); out: return r; }
int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) { int r; struct usb_device *udev; struct usb_req_rfwrite *req = NULL; int i, req_len, actual_req_len; u16 bit_value_template; if (in_atomic()) { dev_dbg_f(zd_usb_dev(usb), "error: io in atomic context not supported\n"); return -EWOULDBLOCK; } if (bits < USB_MIN_RFWRITE_BIT_COUNT) { dev_dbg_f(zd_usb_dev(usb), "error: bits %d are smaller than" " USB_MIN_RFWRITE_BIT_COUNT %d\n", bits, USB_MIN_RFWRITE_BIT_COUNT); return -EINVAL; } if (bits > USB_MAX_RFWRITE_BIT_COUNT) { dev_dbg_f(zd_usb_dev(usb), "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n", bits, USB_MAX_RFWRITE_BIT_COUNT); return -EINVAL; } #ifdef DEBUG if (value & (~0UL << bits)) { dev_dbg_f(zd_usb_dev(usb), "error: value %#09x has bits >= %d set\n", value, bits); return -EINVAL; } #endif /* DEBUG */ dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits); r = zd_usb_ioread16(usb, &bit_value_template, CR203); if (r) { dev_dbg_f(zd_usb_dev(usb), "error %d: Couldn't read CR203\n", r); goto out; } bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16); req = kmalloc(req_len, GFP_KERNEL); if (!req) return -ENOMEM; req->id = cpu_to_le16(USB_REQ_WRITE_RF); /* 1: 3683a, but not used in ZYDAS driver */ req->value = cpu_to_le16(2); req->bits = cpu_to_le16(bits); for (i = 0; i < bits; i++) { u16 bv = bit_value_template; if (value & (1 << (bits-1-i))) bv |= RF_DATA; req->bit_values[i] = cpu_to_le16(bv); } udev = zd_usb_to_usbdev(usb); r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), req, req_len, &actual_req_len, 1000 /* ms */); if (r) { dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg(). Error number %d\n", r); goto out; } if (req_len != actual_req_len) { dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()" " req_len %d != actual_req_len %d\n", req_len, actual_req_len); r = -EIO; goto out; } /* FALL-THROUGH with r == 0 */ out: kfree(req); return r; }
int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, const zd_addr_t *addresses, unsigned int count) { int r; int i, req_len, actual_req_len; struct usb_device *udev; struct usb_req_read_regs *req = NULL; unsigned long timeout; if (count < 1) { dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n"); return -EINVAL; } if (count > USB_MAX_IOREAD16_COUNT) { dev_dbg_f(zd_usb_dev(usb), "error: count %u exceeds possible max %u\n", count, USB_MAX_IOREAD16_COUNT); return -EINVAL; } if (in_atomic()) { dev_dbg_f(zd_usb_dev(usb), "error: io in atomic context not supported\n"); return -EWOULDBLOCK; } if (!usb_int_enabled(usb)) { dev_dbg_f(zd_usb_dev(usb), "error: usb interrupt not enabled\n"); return -EWOULDBLOCK; } req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16); req = kmalloc(req_len, GFP_KERNEL); if (!req) return -ENOMEM; req->id = cpu_to_le16(USB_REQ_READ_REGS); for (i = 0; i < count; i++) req->addr[i] = cpu_to_le16((u16)addresses[i]); udev = zd_usb_to_usbdev(usb); prepare_read_regs_int(usb); r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), req, req_len, &actual_req_len, 1000 /* ms */); if (r) { dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg(). Error number %d\n", r); goto error; } if (req_len != actual_req_len) { dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n" " req_len %d != actual_req_len %d\n", req_len, actual_req_len); r = -EIO; goto error; } timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion, msecs_to_jiffies(1000)); if (!timeout) { disable_read_regs_int(usb); dev_dbg_f(zd_usb_dev(usb), "read timed out\n"); r = -ETIMEDOUT; goto error; } r = get_results(usb, values, req, count); error: kfree(req); return r; }