Ejemplo n.º 1
0
static void mon_text_error(void *data, struct urb *urb, int error)
{
	struct mon_reader_text *rp = data;
	struct mon_event_text *ep;

	if (rp->nevents >= EVENT_MAX ||
	    (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) {
		rp->r.m_bus->cnt_text_lost++;
		return;
	}

	ep->type = 'E';
	ep->id = (unsigned long) urb;
	ep->busnum = urb->dev->bus->busnum;
	ep->devnum = urb->dev->devnum;
	ep->epnum = usb_endpoint_num(&urb->ep->desc);
	ep->xfertype = usb_endpoint_type(&urb->ep->desc);
	ep->is_in = usb_urb_dir_in(urb);
	ep->tstamp = mon_get_timestamp();
	ep->length = 0;
	ep->status = error;

	ep->setup_flag = '-';
	ep->data_flag = 'E';

	rp->nevents++;
	list_add_tail(&ep->e_link, &rp->e_list);
	wake_up(&rp->wait);
}
Ejemplo n.º 2
0
static int sunxi_hcd_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
{
	enum dma_data_direction dir;
	struct temp_buffer *temp;

	if (urb->num_sgs)
		return 0;
	if (urb->sg)
		return 0;
	if (urb->transfer_buffer_length == 0)
		return 0;
	if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
		return 0;

	/* sunxi hardware requires transfer buffers to be DMA aligned */
	if (!((uintptr_t)urb->transfer_buffer & (SUNXI_USB_DMA_ALIGN - 1)))
		return 0;

	/* Allocate a buffer with enough padding for alignment */
	temp = alloc_temp_buffer(urb->transfer_buffer_length, mem_flags);
	if (!temp)
		return -ENOMEM;

	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;

	temp->old_buffer = urb->transfer_buffer;
	if (dir == DMA_TO_DEVICE)
		memcpy(temp->data, urb->transfer_buffer,
		       urb->transfer_buffer_length);
	urb->transfer_buffer = temp->data;

	urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;

	return 0;
}
Ejemplo n.º 3
0
static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd,
	struct urb *urb, gfp_t mem_flags)
{
	int ret;

	ret = alloc_align_buffer(urb, mem_flags);
	if (ret)
		return ret;

	ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);

	/* Control packets over dma */
	if (urb->setup_dma)
		dma_sync_single_for_device(hcd->self.controller,
			urb->setup_dma, sizeof(struct usb_ctrlrequest),
			DMA_TO_DEVICE);

	/* urb buffers over dma */
	if (urb->transfer_dma) {
		enum dma_data_direction dir;
		dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;

		dma_sync_single_for_device(hcd->self.controller,
			urb->transfer_dma, urb->transfer_buffer_length, dir);
	}

	if (ret)
		free_align_buffer(urb);

	return ret;
}
Ejemplo n.º 4
0
static int alloc_align_buffer(struct urb *urb, gfp_t mem_flags)
{
	struct dma_align_buffer *temp, *kmalloc_ptr;
	size_t kmalloc_size;

	if (urb->num_sgs || urb->sg ||
		urb->transfer_buffer_length == 0 ||
		!((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1)))
		return 0;

	/* Allocate a buffer with enough padding for alignment */
	kmalloc_size = urb->transfer_buffer_length +
		sizeof(struct dma_align_buffer) + TEGRA_USB_DMA_ALIGN - 1;
	kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);

	if (!kmalloc_ptr)
		return -ENOMEM;

	/* Position our struct dma_align_buffer such that data is aligned */
	temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1;
	temp->kmalloc_ptr = kmalloc_ptr;
	temp->old_xfer_buffer = urb->transfer_buffer;
	/* OUT transaction, DMA to Device */
	if (!usb_urb_dir_in(urb))
		memcpy(temp->data, urb->transfer_buffer,
				urb->transfer_buffer_length);

	urb->transfer_buffer = temp->data;
	urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;

	return 0;
}
void mtk_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb){
	enum dma_data_direction dir;

	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
	hcd_free_coherent(urb->dev->bus,
			&urb->transfer_dma,
			&urb->transfer_buffer,
			urb->transfer_buffer_length,
			dir);
}
Ejemplo n.º 6
0
static char *
get_hex_data(char *dbuf, struct urb *urb, int event, int status, size_t max_len)
{
	char *ubuf = urb->transfer_buffer;
	size_t len =
		event ? urb->actual_length : urb->transfer_buffer_length;

	if (status == -EINPROGRESS)
		status = 0;

	/*Only dump ep in completions and epout submissions*/
	if (len && !status && ((usb_urb_dir_in(urb) && event) ||
		(usb_urb_dir_in(urb) && !event))) {
		if (len >= max_len)
			len = max_len;
		hex_dump_to_buffer(ubuf, len, 32, 4, dbuf, HEX_DUMP_LEN, 0);
	} else {
		dbuf = "";
	}

	return dbuf;
}
Ejemplo n.º 7
0
static int check_log_mask(struct dbg_data *d, int ep_addr, struct urb *urb)
{
	int dir, num;

	dir = usb_urb_dir_in(urb) ? USB_DIR_IN : USB_DIR_OUT;
	num = ep_addr & ~USB_DIR_IN;
	num = 1 << num;

	if ((dir == USB_DIR_IN) && (num & d->inep_log_mask))
		return 1;
	if ((dir == USB_DIR_OUT) && (num & d->outep_log_mask))
		return 1;

	return 0;
}
Ejemplo n.º 8
0
static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd,
	struct urb *urb)
{
	usb_hcd_unmap_urb_for_dma(hcd, urb);
	free_align_buffer(urb);

	if (urb->transfer_dma) {
		enum dma_data_direction dir;
		dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
		if (dir == DMA_FROM_DEVICE)
			dma_sync_single_for_cpu(hcd->self.controller,
				urb->transfer_dma, urb->transfer_buffer_length,
									   DMA_FROM_DEVICE);
	}
}
Ejemplo n.º 9
0
static void free_align_buffer(struct urb *urb)
{
	struct dma_align_buffer *temp = container_of(urb->transfer_buffer,
						struct dma_align_buffer, data);

	if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
		return;

	/* In transaction, DMA from Device */
	if (usb_urb_dir_in(urb))
		memcpy(temp->old_xfer_buffer, temp->data,
					urb->transfer_buffer_length);

	urb->transfer_buffer = temp->old_xfer_buffer;
	urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
	kfree(temp->kmalloc_ptr);
}
Ejemplo n.º 10
0
int mtk_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags){
	enum dma_data_direction dir;
	int ret = 0;
	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
	/* Map the URB's buffers for DMA access.
	 * Lower level HCD code should use *_dma exclusively,
	 * unless it uses pio or talks to another transport,
	 * or uses the provided scatter gather list for bulk.
	 */
	ret = hcd_alloc_coherent(
					urb->dev->bus, mem_flags,
					&urb->transfer_dma,
					&urb->transfer_buffer,
					urb->transfer_buffer_length,
					dir);

	if (ret == 0)
		urb->transfer_flags |= URB_MAP_LOCAL;
	return ret;
}
static void free_align_buffer(struct urb *urb, struct usb_hcd *hcd)
{
	struct dma_align_buffer *temp = container_of(urb->transfer_buffer,
						struct dma_align_buffer, data);
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);

	if (tegra->unaligned_dma_buf_supported)
		return;

	if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
		return;

	/* In transaction, DMA from Device */
	if (usb_urb_dir_in(urb))
		memcpy(temp->old_xfer_buffer, temp->data,
					urb->transfer_buffer_length);

	urb->transfer_buffer = temp->old_xfer_buffer;
	urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
	kfree(temp->kmalloc_ptr);
}
Ejemplo n.º 12
0
static void sunxi_hcd_free_temp_buffer(struct urb *urb)
{
	enum dma_data_direction dir;
	struct temp_buffer *temp;

	if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
		return;

	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;

	temp = container_of(urb->transfer_buffer, struct temp_buffer, data);

	if (dir == DMA_FROM_DEVICE)
		memcpy(temp->old_buffer, temp->data,
		       urb->transfer_buffer_length);

	urb->transfer_buffer = temp->old_buffer;
	kfree(temp->kmalloc_ptr);

	urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
}
Ejemplo n.º 13
0
static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
    char ev_type, int status)
{
	struct mon_event_text *ep;
	unsigned int stamp;
	struct usb_iso_packet_descriptor *fp;
	struct mon_iso_desc *dp;
	int i, ndesc;

	stamp = mon_get_timestamp();

	if (rp->nevents >= EVENT_MAX ||
	    (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) {
		rp->r.m_bus->cnt_text_lost++;
		return;
	}

	ep->type = ev_type;
	ep->id = (unsigned long) urb;
	ep->busnum = urb->dev->bus->busnum;
	ep->devnum = urb->dev->devnum;
	ep->epnum = usb_endpoint_num(&urb->ep->desc);
	ep->xfertype = usb_endpoint_type(&urb->ep->desc);
	ep->is_in = usb_urb_dir_in(urb);
	ep->tstamp = stamp;
	ep->length = (ev_type == 'S') ?
	    urb->transfer_buffer_length : urb->actual_length;
	/* Collecting status makes debugging sense for submits, too */
	ep->status = status;

	if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
		ep->interval = urb->interval;
	} else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) {
		ep->interval = urb->interval;
		ep->start_frame = urb->start_frame;
		ep->error_count = urb->error_count;
	}
	ep->numdesc = urb->number_of_packets;
	if (ep->xfertype == USB_ENDPOINT_XFER_ISOC &&
			urb->number_of_packets > 0) {
		if ((ndesc = urb->number_of_packets) > ISODESC_MAX)
			ndesc = ISODESC_MAX;
		fp = urb->iso_frame_desc;
		dp = ep->isodesc;
		for (i = 0; i < ndesc; i++) {
			dp->status = fp->status;
			dp->offset = fp->offset;
			dp->length = (ev_type == 'S') ?
			    fp->length : fp->actual_length;
			fp++;
			dp++;
		}
		/* Wasteful, but simple to understand: ISO 'C' is sparse. */
		if (ev_type == 'C')
			ep->length = urb->transfer_buffer_length;
	}

	ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
	ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
			rp->r.m_bus);

	rp->nevents++;
	list_add_tail(&ep->e_link, &rp->e_list);
	wake_up(&rp->wait);
}
Ejemplo n.º 14
0
void __maybe_unused
xhci_dbg_log_event(struct dbg_data *d, struct urb *urb, char *event,
		unsigned extra)
{
	unsigned long flags;
	int ep_addr;
	char tbuf[TIME_BUF_LEN];
	char dbuf[HEX_DUMP_LEN];

	if (!d->log_events)
		return;

	if (!urb) {
		write_lock_irqsave(&d->ctrl_lck, flags);
		scnprintf(d->ctrl_buf[d->ctrl_idx], DBG_MSG_LEN,
			"%s: %s : %d", get_timestamp(tbuf), event, extra);
		dbg_inc(&d->ctrl_idx);
		write_unlock_irqrestore(&d->ctrl_lck, flags);
		return;
	}

	ep_addr = urb->ep->desc.bEndpointAddress;
	if (!check_log_mask(d, ep_addr, urb))
		return;

	if ((ep_addr & 0x0f) == 0x0) {
		/*submit event*/
		if (!xhci_str_to_event(event)) {
			write_lock_irqsave(&d->ctrl_lck, flags);
			scnprintf(d->ctrl_buf[d->ctrl_idx],
				DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
				  "%02x %02x %04x %04x %04x  %u %d %s",
				  get_timestamp(tbuf), event, urb,
				  usb_urb_dir_in(urb) ? "in" : "out",
				  urb->setup_packet[0], urb->setup_packet[1],
				  (urb->setup_packet[3] << 8) |
				  urb->setup_packet[2],
				  (urb->setup_packet[5] << 8) |
				  urb->setup_packet[4],
				  (urb->setup_packet[7] << 8) |
				  urb->setup_packet[6],
				  urb->transfer_buffer_length, extra,
				  d->log_payload ? get_hex_data(dbuf, urb,
				  xhci_str_to_event(event), extra, 16) : "");

			dbg_inc(&d->ctrl_idx);
			write_unlock_irqrestore(&d->ctrl_lck, flags);
		} else {
			write_lock_irqsave(&d->ctrl_lck, flags);
			scnprintf(d->ctrl_buf[d->ctrl_idx],
				DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d %s",
				  get_timestamp(tbuf), event, urb,
				  usb_urb_dir_in(urb) ? "in" : "out",
				  urb->actual_length, extra,
				  d->log_payload ? get_hex_data(dbuf, urb,
				xhci_str_to_event(event), extra, 16) : "");

			dbg_inc(&d->ctrl_idx);
			write_unlock_irqrestore(&d->ctrl_lck, flags);
		}
	} else {
		write_lock_irqsave(&d->data_lck, flags);
		scnprintf(d->data_buf[d->data_idx], DBG_MSG_LEN,
			  "%s: [%s : %p]:ep%d[%s]  %u %d %s",
			  get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
			  usb_urb_dir_in(urb) ? "in" : "out",
			  xhci_str_to_event(event) ? urb->actual_length :
			  urb->transfer_buffer_length, extra,
			  d->log_payload ? get_hex_data(dbuf, urb,
				  xhci_str_to_event(event), extra, 32) : "");

		dbg_inc(&d->data_idx);
		write_unlock_irqrestore(&d->data_lck, flags);
	}
}