drivers/net/wireless/ath/ath10k/usb.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/ath/ath10k/usb.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath10k/usb.c
Extension
.c
Size
27972 bytes
Lines
1127
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (urb->status) {
		case -ECONNRESET:
		case -ENOENT:
		case -ESHUTDOWN:
			/* no need to spew these errors when device
			 * removed or urb killed due to driver shutdown
			 */
			status = -ECANCELED;
			break;
		default:
			ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
				   "usb recv pipe %d ep 0x%2.2x failed: %d\n",
				   pipe->logical_pipe_num,
				   pipe->ep_address, urb->status);
			break;
		}
		goto cleanup_recv_urb;
	}

	if (urb->actual_length == 0)
		goto cleanup_recv_urb;

	skb = urb_context->skb;

	/* we are going to pass it up */
	urb_context->skb = NULL;
	skb_put(skb, urb->actual_length);

	/* note: queue implements a lock */
	skb_queue_tail(&pipe->io_comp_queue, skb);
	schedule_work(&pipe->io_complete_work);

cleanup_recv_urb:
	ath10k_usb_cleanup_recv_urb(urb_context);

	if (status == 0 &&
	    pipe->urb_cnt >= pipe->urb_cnt_thresh) {
		/* our free urbs are piling up, post more transfers */
		ath10k_usb_post_recv_transfers(ar, pipe);
	}
}

static void ath10k_usb_transmit_complete(struct urb *urb)
{
	struct ath10k_urb_context *urb_context = urb->context;
	struct ath10k_usb_pipe *pipe = urb_context->pipe;
	struct ath10k *ar = pipe->ar_usb->ar;
	struct sk_buff *skb;

	if (urb->status != 0) {
		ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
			   "pipe: %d, failed:%d\n",
			   pipe->logical_pipe_num, urb->status);
	}

	skb = urb_context->skb;
	urb_context->skb = NULL;
	ath10k_usb_free_urb_to_pipe(urb_context->pipe, urb_context);

	/* note: queue implements a lock */
	skb_queue_tail(&pipe->io_comp_queue, skb);
	schedule_work(&pipe->io_complete_work);
}

/* pipe operations */
static void ath10k_usb_post_recv_transfers(struct ath10k *ar,
					   struct ath10k_usb_pipe *recv_pipe)
{
	struct ath10k_urb_context *urb_context;
	struct urb *urb;
	int usb_status;

	for (;;) {
		urb_context = ath10k_usb_alloc_urb_from_pipe(recv_pipe);
		if (!urb_context)
			break;

		urb_context->skb = dev_alloc_skb(ATH10K_USB_RX_BUFFER_SIZE);
		if (!urb_context->skb)
			goto err;

		urb = usb_alloc_urb(0, GFP_ATOMIC);
		if (!urb)
			goto err;

		usb_fill_bulk_urb(urb,
				  recv_pipe->ar_usb->udev,
				  recv_pipe->usb_pipe_handle,
				  urb_context->skb->data,
				  ATH10K_USB_RX_BUFFER_SIZE,

Annotation

Implementation Notes