Bitterblue Smith <rtl8821cerfe2@xxxxxxxxx> wrote: > Add some extra configuration for USB devices. Currently only RTL8822BU > version (cut) D needs this. The new code makes use of the existing > usb3_param_8822b array from rtw8822b.c. > > A user reported that TP-Link Archer T3U in USB 3 mode was randomly > disconnecting from USB: > > [ 26.036502] usb 2-2: new SuperSpeed USB device number 3 using xhci_hcd > ... > [ 27.576491] usb 2-2: USB disconnect, device number 3 > [ 28.621528] usb 2-2: new SuperSpeed USB device number 4 using xhci_hcd > ... > [ 45.984521] usb 2-2: USB disconnect, device number 4 > ... > [ 46.845585] usb 2-2: new SuperSpeed USB device number 5 using xhci_hcd > ... > [ 94.400380] usb 2-2: USB disconnect, device number 5 > ... > [ 95.590421] usb 2-2: new SuperSpeed USB device number 6 using xhci_hcd > > This patch fixes that. > > Link: https://github.com/lwfinger/rtw88/issues/262. As Kalle mentioned, please remove the dot in the end. By the way, I can modify commit message during committing if needed. > Signed-off-by: Bitterblue Smith <rtl8821cerfe2@xxxxxxxxx> > --- > drivers/net/wireless/realtek/rtw88/usb.c | 70 ++++++++++++++++++++++++ > 1 file changed, 70 insertions(+) > > diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c > index b405f8317021..b5ef7e31df19 100644 > --- a/drivers/net/wireless/realtek/rtw88/usb.c > +++ b/drivers/net/wireless/realtek/rtw88/usb.c > @@ -1127,6 +1127,73 @@ static int rtw_usb_switch_mode(struct rtw_dev *rtwdev) > return rtw_usb_switch_mode_new(rtwdev); > } > > +#define USB_REG_PAGE 0xf4 > +#define USB_PHY_PAGE0 0x9b > +#define USB_PHY_PAGE1 0xbb > + > +static void rtw_usb_phy_write(struct rtw_dev *rtwdev, u16 addr, u16 data, > + enum usb_device_speed speed) > +{ > + if (speed == USB_SPEED_SUPER) { > + rtw_write8(rtwdev, 0xff0d, (u8)data); > + rtw_write8(rtwdev, 0xff0e, (u8)(data >> 8)); > + rtw_write8(rtwdev, 0xff0c, addr | BIT(7)); The casting of u8 is not unnecessary. The register names (non-official naming): #define U3_PHY_DAT_L 0xff0d #define U3_PHY_DAT_H 0xff0e #define U3_PHY_ADR 0xff0c #define U3_PHY_ADR_WR BIT(7) #define U3_PHY_ADR_RD BIT(6) #define U3_PHY_ADR_MASK GENMASK(5, 0) > + } else if (speed == USB_SPEED_HIGH) { > + rtw_write8(rtwdev, 0xfe41, (u8)data); > + rtw_write8(rtwdev, 0xfe40, addr); > + rtw_write8(rtwdev, 0xfe42, 0x81); The register names (non-official naming): #define U2_PHY_DAT 0xfe41 #define U2_PHY_ADR 0xfe40 #define U2_PHY_CMD 0xfe42 #define U2_PHY_CMD_TRG 0x81 > + } > +} > + > +static void rtw_usb_page_switch(struct rtw_dev *rtwdev, > + enum usb_device_speed speed, u8 page) > +{ > + if (speed == USB_SPEED_SUPER) > + return; > + > + rtw_usb_phy_write(rtwdev, USB_REG_PAGE, page, speed); > +} > + > +static void rtw_usb_phy_cfg(struct rtw_dev *rtwdev, > + enum usb_device_speed speed) > +{ > + const struct rtw_intf_phy_para *para = NULL; > + u16 cut, offset; > + > + if (!rtwdev->chip->intf_table) > + return; > + > + if (speed == USB_SPEED_SUPER) > + para = rtwdev->chip->intf_table->usb3_para; > + else if (speed == USB_SPEED_HIGH) > + para = rtwdev->chip->intf_table->usb2_para; > + > + if (!para) > + return; > + > + cut = BIT(0) << rtwdev->hal.cut_version; cut = BIT(rtwdev->hal.cut_version); > + > + for ( ; para->offset != 0xffff; para++) { > + if (!(para->cut_mask & cut)) > + continue; > + > + offset = para->offset; > + > + if (para->ip_sel == RTW_IP_SEL_MAC) { > + rtw_write8(rtwdev, offset, para->value); > + } else { > + if (offset > 0x100) > + rtw_usb_page_switch(rtwdev, speed, USB_PHY_PAGE1); > + else > + rtw_usb_page_switch(rtwdev, speed, USB_PHY_PAGE0); > + > + offset &= 0xff; > + > + rtw_usb_phy_write(rtwdev, offset, para->value, speed); The argument type of offset can be 'u8', so you don't worry about type casting. > + } > + } > +} > + > int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) > { > struct rtw_dev *rtwdev; > @@ -1182,6 +1249,9 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) > goto err_destroy_rxwq; > } > > + rtw_usb_phy_cfg(rtwdev, USB_SPEED_HIGH); > + rtw_usb_phy_cfg(rtwdev, USB_SPEED_SUPER); > + > ret = rtw_usb_switch_mode(rtwdev); > if (ret) { > /* Not a fail, but we do need to skip rtw_register_hw. */ > -- > 2.47.1