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
| ||
|
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