lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1f7aa964766c4f65b836f7e1d716a1e3@realtek.com>
Date:   Mon, 28 Nov 2022 02:00:54 +0000
From:   Ping-Ke Shih <pkshih@...ltek.com>
To:     Sascha Hauer <s.hauer@...gutronix.de>,
        "linux-wireless@...r.kernel.org" <linux-wireless@...r.kernel.org>
CC:     Neo Jou <neojou@...il.com>, Hans Ulli Kroll <linux@...i-kroll.de>,
        Yan-Hsuan Chuang <tony0620emma@...il.com>,
        Kalle Valo <kvalo@...nel.org>,
        "netdev@...r.kernel.org" <netdev@...r.kernel.org>,
        "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
        "Martin Blumenstingl" <martin.blumenstingl@...glemail.com>,
        "kernel@...gutronix.de" <kernel@...gutronix.de>,
        Johannes Berg <johannes@...solutions.net>,
        Alexander Hochbaum <alex@...udo.com>,
        Da Xue <da@...re.computer>,
        "Bernie Huang" <phhuang@...ltek.com>,
        Viktor Petrenko <g0000ga@...il.com>,
        neo_jou <neo_jou@...ltek.com>
Subject: RE: [PATCH v3 07/11] rtw88: Add common USB chip support



> -----Original Message-----
> From: Sascha Hauer <s.hauer@...gutronix.de>
> Sent: Tuesday, November 22, 2022 10:52 PM
> To: linux-wireless@...r.kernel.org
> Cc: Neo Jou <neojou@...il.com>; Hans Ulli Kroll <linux@...i-kroll.de>; Ping-Ke Shih <pkshih@...ltek.com>;
> Yan-Hsuan Chuang <tony0620emma@...il.com>; Kalle Valo <kvalo@...nel.org>; netdev@...r.kernel.org;
> linux-kernel@...r.kernel.org; Martin Blumenstingl <martin.blumenstingl@...glemail.com>;
> kernel@...gutronix.de; Johannes Berg <johannes@...solutions.net>; Alexander Hochbaum <alex@...udo.com>;
> Da Xue <da@...re.computer>; Bernie Huang <phhuang@...ltek.com>; Viktor Petrenko <g0000ga@...il.com>;
> Sascha Hauer <s.hauer@...gutronix.de>; neo_jou <neo_jou@...ltek.com>
> Subject: [PATCH v3 07/11] rtw88: Add common USB chip support
> 
> Add the common bits and pieces to add USB support to the RTW88 driver.
> This is based on https://github.com/ulli-kroll/rtw88-usb.git which
> itself is first written by Neo Jou.
> 
> Signed-off-by: neo_jou <neo_jou@...ltek.com>
> Signed-off-by: Hans Ulli Kroll <linux@...i-kroll.de>
> Signed-off-by: Sascha Hauer <s.hauer@...gutronix.de>
> ---
> 
> Notes:
>     Changes since v2:
>     - Fix buffer length for aggregated tx packets
>     - Increase maximum transmit buffer size to 20KiB as found in downstream drivers
>     - Change register write functions to synchronous accesses instead of just firing
>       a URB without waiting for its completion
>     - requeue rx URBs directly in completion handler rather than having a workqueue
>       for it.
> 
>     Changes since v1:
>     - Make checkpatch.pl clean
>     - Drop WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL flag
>     - Use 'ret' as variable name for return values
>     - Sort variable declarations in reverse Xmas tree order
>     - Change potentially endless loop to a limited loop
>     - Change locking to be more obviously correct
>     - drop unnecessary check for !rtwdev
>     - make sure the refill workqueue is not restarted again after we have
>       cancelled it
> 
>  drivers/net/wireless/realtek/rtw88/Kconfig  |   3 +
>  drivers/net/wireless/realtek/rtw88/Makefile |   2 +
>  drivers/net/wireless/realtek/rtw88/mac.c    |   3 +
>  drivers/net/wireless/realtek/rtw88/main.c   |   4 +
>  drivers/net/wireless/realtek/rtw88/main.h   |   4 +
>  drivers/net/wireless/realtek/rtw88/reg.h    |   1 +
>  drivers/net/wireless/realtek/rtw88/tx.h     |  31 +
>  drivers/net/wireless/realtek/rtw88/usb.c    | 918 ++++++++++++++++++++
>  drivers/net/wireless/realtek/rtw88/usb.h    | 107 +++
>  9 files changed, 1073 insertions(+)
>  create mode 100644 drivers/net/wireless/realtek/rtw88/usb.c
>  create mode 100644 drivers/net/wireless/realtek/rtw88/usb.h
> 
> diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
> index e3d7cb6c12902..1624c5db69bac 100644
> --- a/drivers/net/wireless/realtek/rtw88/Kconfig
> +++ b/drivers/net/wireless/realtek/rtw88/Kconfig
> @@ -16,6 +16,9 @@ config RTW88_CORE
>  config RTW88_PCI
>  	tristate
> 
> +config RTW88_USB
> +	tristate
> +
>  config RTW88_8822B
>  	tristate
> 
> diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
> index 834c66ec0af9e..9e095f8181483 100644
> --- a/drivers/net/wireless/realtek/rtw88/Makefile
> +++ b/drivers/net/wireless/realtek/rtw88/Makefile
> @@ -45,4 +45,6 @@ obj-$(CONFIG_RTW88_8821CE)	+= rtw88_8821ce.o
>  rtw88_8821ce-objs		:= rtw8821ce.o
> 
>  obj-$(CONFIG_RTW88_PCI)		+= rtw88_pci.o
> +obj-$(CONFIG_RTW88_USB)		+= rtw88_usb.o
>  rtw88_pci-objs			:= pci.o
> +rtw88_usb-objs			:= usb.o

nit: I prefer not interleaving with PCI.


[...]

> diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
> new file mode 100644
> index 0000000000000..4a12934d20712
> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw88/usb.c

[...]

> +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 ret;
> +	static int count;
> +
> +	spin_lock_irqsave(&rtwusb->usb_lock, flags);
> +
> +	rtwusb->usb_data_index++;
> +	rtwusb->usb_data_index &= (RTW_USB_MAX_RXTX_COUNT - 1);
> +
> +	spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
> +
> +	data = &rtwusb->usb_data[rtwusb->usb_data_index];

Don't you need to hold &rtwusb->usb_lock to access rtwusb->usb_data_index?
rtw_usb_write() has similar code.

> +
> +	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);
> +
> +	return le32_to_cpu(*data);
> +}
> +

[...]

> +
> +static void rtw_usb_write_port_tx_complete(struct urb *urb)
> +{
> +	struct rtw_usb_txcb *txcb = urb->context;
> +	struct rtw_dev *rtwdev = txcb->rtwdev;
> +	struct ieee80211_hw *hw = rtwdev->hw;
> +
> +	while (true) {

Is it possible to have a hard limit to prevent unexpected infinite loop?

> +		struct sk_buff *skb = skb_dequeue(&txcb->tx_ack_queue);
> +		struct ieee80211_tx_info *info;
> +		struct rtw_usb_tx_data *tx_data;
> +
> +		if (!skb)
> +			break;
> +
> +		info = IEEE80211_SKB_CB(skb);
> +		tx_data = rtw_usb_get_tx_data(skb);
> +
> +		/* enqueue to wait for tx report */
> +		if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
> +			rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn);
> +			continue;
> +		}
> +
> +		/* always ACK for others, then they won't be marked as drop */
> +		ieee80211_tx_info_clear_status(info);
> +		if (info->flags & IEEE80211_TX_CTL_NO_ACK)
> +			info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
> +		else
> +			info->flags |= IEEE80211_TX_STAT_ACK;
> +
> +		ieee80211_tx_status_irqsafe(hw, skb);
> +	}
> +
> +	kfree(txcb);
> +}
> +

[...]

> +
> +static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list)
> +{
> +	struct rtw_dev *rtwdev = rtwusb->rtwdev;
> +	struct rtw_usb_txcb *txcb;
> +	struct sk_buff *skb_head;
> +	struct sk_buff *skb_iter;
> +	u8 *data_ptr;
> +	int agg_num = 0;
> +	unsigned int align_next = 0;
> +
> +	if (skb_queue_empty(list))
> +		return false;
> +
> +	txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC);
> +	if (!txcb)
> +		return false;
> +
> +	txcb->rtwdev = rtwdev;
> +	skb_queue_head_init(&txcb->tx_ack_queue);
> +
> +	skb_iter = skb_dequeue(list);
> +
> +	if (skb_queue_empty(list)) {
> +		skb_head = skb_iter;
> +		goto queue;
> +	}
> +
> +	skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ);
> +	if (!skb_head) {
> +		skb_head = skb_iter;
> +		goto queue;
> +	}
> +
> +	data_ptr = skb_head->data;
> +
> +	while (skb_iter) {
> +		unsigned long flags;
> +
> +		memcpy(data_ptr, skb_iter->data, skb_iter->len);
> +		skb_put(skb_head, skb_iter->len + align_next);

skb_put(skb_head, align_next);
skb_put_data(skb_head, skb_iter->data, skb_iter->len);

Then, don't need to maintain 'data_ptr'.

> +
> +		align_next = ALIGN(skb_iter->len, 8) - skb_iter->len;
> +		data_ptr += skb_iter->len + align_next;
> +
> +		agg_num++;
> +
> +		skb_queue_tail(&txcb->tx_ack_queue, skb_iter);
> +
> +		spin_lock_irqsave(&list->lock, flags);
> +
> +		skb_iter = skb_peek(list);
> +
> +		if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ)
> +			__skb_unlink(skb_iter, list);
> +		else
> +			skb_iter = NULL;
> +		spin_unlock_irqrestore(&list->lock, flags);
> +	}
> +
> +	if (agg_num > 1)
> +		rtw_usb_fill_tx_checksum(rtwusb, skb_head, agg_num);
> +
> +queue:
> +	skb_queue_tail(&txcb->tx_ack_queue, skb_head);
> +
> +	rtw_usb_write_port(rtwdev, GET_TX_DESC_QSEL(skb_head->data), skb_head,
> +			   rtw_usb_write_port_tx_complete, txcb);
> +
> +	return true;
> +}
> +

[...]

> +
> +static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb)
> +{
> +	struct rtw_dev *rtwdev = rtwusb->rtwdev;
> +	int error;
> +
> +	rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC);
> +	if (!rxcb->rx_skb)
> +		return;
> +
> +	usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev,
> +			  usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in),
> +			  rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ,
> +			  rtw_usb_read_port_complete, rxcb);
> +
> +	error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC);
> +	if (error) {
> +		kfree_skb(rxcb->rx_skb);
> +		if (error != -ENODEV)
> +			rtw_err(rtwdev, "Err sending rx data urb %d\n",
> +				error);

nit: straighten rtw_err()

> +	}
> +}
> +

[...]

> diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h
> new file mode 100644
> index 0000000000000..e26f8afb09f29
> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw88/usb.h

[...]

> +
> +static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)
> +{
> +	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> +
> +	BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) >
> +		sizeof(info->status.status_driver_data));

coding style: 

align the open parenthesis 

	BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) >
		     sizeof(info->status.status_driver_data));

> +
> +	return (struct rtw_usb_tx_data *)info->status.status_driver_data;
> +}
> +
> +int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id);
> +void rtw_usb_disconnect(struct usb_interface *intf);
> +
> +#endif
> --
> 2.30.2

Powered by blists - more mailing lists