drivers/net/wireless/purelifi/plfxlc/usb.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/purelifi/plfxlc/usb.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/purelifi/plfxlc/usb.c
Extension
.c
Size
20659 bytes
Lines
876
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

if (tx->submitted_urbs++ < PURELIFI_URB_RETRY_MAX) {
			dev_dbg(plfxlc_urb_dev(urb), "urb %p resubmit %d", urb,
				tx->submitted_urbs++);
			goto resubmit;
		} else {
			dev_dbg(plfxlc_urb_dev(urb), "urb %p  max resubmits reached", urb);
			tx->submitted_urbs = 0;
			return;
		}
	}

	buffer = urb->transfer_buffer;
	length = le32_to_cpu(*(__le32 *)(buffer + sizeof(struct rx_status)))
		 + sizeof(u32);

	if (urb->actual_length != (PLF_MSG_STATUS_OFFSET + 1)) {
		if (usb->initialized && usb->link_up)
			handle_rx_packet(usb, buffer, length);
		goto resubmit;
	}

	status = buffer[PLF_MSG_STATUS_OFFSET];

	switch (status) {
	case STATION_FIFO_ALMOST_FULL_NOT_MESSAGE:
		dev_dbg(&usb->intf->dev,
			"FIFO full not packet receipt\n");
		tx->mac_fifo_full = 1;
		for (sidx = 0; sidx < MAX_STA_NUM; sidx++)
			tx->station[sidx].flag |= STATION_FIFO_FULL_FLAG;
		break;
	case STATION_FIFO_ALMOST_FULL_MESSAGE:
		dev_dbg(&usb->intf->dev, "FIFO full packet receipt\n");

		for (sidx = 0; sidx < MAX_STA_NUM; sidx++)
			tx->station[sidx].flag &= STATION_ACTIVE_FLAG;

		plfxlc_send_packet_from_data_queue(usb);
		break;
	case STATION_CONNECT_MESSAGE:
		usb->link_up = 1;
		dev_dbg(&usb->intf->dev, "ST_CONNECT_MSG packet receipt\n");
		break;
	case STATION_DISCONNECT_MESSAGE:
		usb->link_up = 0;
		dev_dbg(&usb->intf->dev, "ST_DISCONN_MSG packet receipt\n");
		break;
	default:
		dev_dbg(&usb->intf->dev, "Unknown packet receipt\n");
		break;
	}

resubmit:
	r = usb_submit_urb(urb, GFP_ATOMIC);
	if (r)
		dev_dbg(plfxlc_urb_dev(urb), "urb %p resubmit fail (%d)\n", urb, r);
}

static struct urb *alloc_rx_urb(struct plfxlc_usb *usb)
{
	struct usb_device *udev = plfxlc_usb_to_usbdev(usb);
	struct urb *urb;
	void *buffer;

	urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!urb)
		return NULL;

	buffer = usb_alloc_coherent(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
				    &urb->transfer_dma);
	if (!buffer) {
		usb_free_urb(urb);
		return NULL;
	}

	usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN),
			  buffer, USB_MAX_RX_SIZE,
			  rx_urb_complete, usb);
	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	return urb;
}

static void free_rx_urb(struct urb *urb)
{
	if (!urb)
		return;
	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
			  urb->transfer_buffer, urb->transfer_dma);
	usb_free_urb(urb);

Annotation

Implementation Notes