drivers/net/wireless/realtek/rtw88/usb.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/realtek/rtw88/usb.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/realtek/rtw88/usb.c
Extension
.c
Size
34294 bytes
Lines
1393
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

struct rtw_usb_txcb {
	struct rtw_dev *rtwdev;
	struct sk_buff_head tx_ack_queue;
};

static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
				     struct sk_buff *skb, int agg_num)
{
	struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
	struct rtw_dev *rtwdev = rtwusb->rtwdev;
	struct rtw_tx_pkt_info pkt_info;

	le32p_replace_bits(&tx_desc->w7, agg_num, RTW_TX_DESC_W7_DMA_TXAGG_NUM);
	pkt_info.pkt_offset = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_PKT_OFFSET);
	rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
}

static void rtw_usb_reg_sec(struct rtw_dev *rtwdev, u32 addr, __le32 *data)
{
	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
	struct usb_device *udev = rtwusb->udev;
	bool reg_on_section = false;
	u16 t_reg = 0x4e0;
	u8 t_len = 1;
	int status;

	/* There are three sections:
	 * 1. on (0x00~0xFF; 0x1000~0x10FF): this section is always powered on
	 * 2. off (< 0xFE00, excluding "on" section): this section could be
	 *    powered off
	 * 3. local (>= 0xFE00): usb specific registers section
	 */
	if (addr <= 0xff || (addr >= 0x1000 && addr <= 0x10ff))
		reg_on_section = true;

	if (!reg_on_section)
		return;

	status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
				 RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
				 t_reg, 0, data, t_len, 500);

	if (status != t_len && status != -ENODEV)
		rtw_err(rtwdev, "%s: reg 0x%x, usb write %u fail, status: %d\n",
			__func__, t_reg, t_len, status);
}

static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
{
	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
	struct usb_device *udev = rtwusb->udev;
	__le32 *data;
	unsigned long flags;
	int idx, ret;
	static int count;

	spin_lock_irqsave(&rtwusb->usb_lock, flags);

	idx = rtwusb->usb_data_index;
	rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1);

	spin_unlock_irqrestore(&rtwusb->usb_lock, flags);

	data = &rtwusb->usb_data[idx];

	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
			      RTW_USB_CMD_REQ, RTW_USB_CMD_READ, addr,
			      RTW_USB_VENQT_CMD_IDX, data, len, 1000);
	if (ret < 0 && ret != -ENODEV && count++ < 4)
		rtw_err(rtwdev, "read register 0x%x failed with %d\n",
			addr, ret);

	if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C ||
	    rtwdev->chip->id == RTW_CHIP_TYPE_8822B ||
	    rtwdev->chip->id == RTW_CHIP_TYPE_8821C)
		rtw_usb_reg_sec(rtwdev, addr, data);

	return le32_to_cpu(*data);
}

static u8 rtw_usb_read8(struct rtw_dev *rtwdev, u32 addr)
{
	return (u8)rtw_usb_read(rtwdev, addr, 1);
}

static u16 rtw_usb_read16(struct rtw_dev *rtwdev, u32 addr)
{
	return (u16)rtw_usb_read(rtwdev, addr, 2);
}

Annotation

Implementation Notes