USB: serial: f81232: fix incomplete serial port generation

The Fintek F81532A/534A/535/536 family relies on the
F81534A_CTRL_CMD_ENABLE_PORT (116h) register during initialization to
both determine serial port status and control port creation. If the
driver experiences fast load/unload cycles, the device state may becomes
unstable, resulting in the incomplete generation of serial ports.

Performing a dummy read operation on the register prior to the initial
write command resolves the issue. This clears the device's stale internal
state. Subsequent write operations will correctly generate all serial
ports.

This patch also removes the retry loop in f81534a_ctrl_set_register()
because the stale state has been fixed.

Tested on: HygonDM1SLT(Hygon C86 3250 8-core Processor)

Signed-off-by: Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>
Signed-off-by: Johan Hovold <johan@kernel.org>

authored by Ji-Ze Hong (Peter Hong) and committed by Johan Hovold cd644b80 c0afe95e

+47 -30
+47 -30
drivers/usb/serial/f81232.c
··· 70 #define F81232_REGISTER_REQUEST 0xa0 71 #define F81232_GET_REGISTER 0xc0 72 #define F81232_SET_REGISTER 0x40 73 - #define F81534A_ACCESS_REG_RETRY 2 74 75 #define SERIAL_BASE_ADDRESS 0x0120 76 #define RECEIVE_BUFFER_REGISTER (0x00 + SERIAL_BASE_ADDRESS) ··· 823 static int f81534a_ctrl_set_register(struct usb_interface *intf, u16 reg, 824 u16 size, void *val) 825 { 826 - struct usb_device *dev = interface_to_usbdev(intf); 827 - int retry = F81534A_ACCESS_REG_RETRY; 828 - int status; 829 830 - while (retry--) { 831 - status = usb_control_msg_send(dev, 832 - 0, 833 - F81232_REGISTER_REQUEST, 834 - F81232_SET_REGISTER, 835 - reg, 836 - 0, 837 - val, 838 - size, 839 - USB_CTRL_SET_TIMEOUT, 840 - GFP_KERNEL); 841 - if (status) { 842 - status = usb_translate_errors(status); 843 - if (status == -EIO) 844 - continue; 845 - } 846 - 847 - break; 848 - } 849 - 850 - if (status) { 851 - dev_err(&intf->dev, "failed to set register 0x%x: %d\n", 852 - reg, status); 853 - } 854 - 855 - return status; 856 } 857 858 static int f81534a_ctrl_enable_all_ports(struct usb_interface *intf, bool en) ··· 863 * bit 0~11 : Serial port enable bit. 864 */ 865 if (en) { 866 enable[0] = 0xff; 867 enable[1] = 0x8f; 868 }
··· 70 #define F81232_REGISTER_REQUEST 0xa0 71 #define F81232_GET_REGISTER 0xc0 72 #define F81232_SET_REGISTER 0x40 73 74 #define SERIAL_BASE_ADDRESS 0x0120 75 #define RECEIVE_BUFFER_REGISTER (0x00 + SERIAL_BASE_ADDRESS) ··· 824 static int f81534a_ctrl_set_register(struct usb_interface *intf, u16 reg, 825 u16 size, void *val) 826 { 827 + return usb_control_msg_send(interface_to_usbdev(intf), 828 + 0, 829 + F81232_REGISTER_REQUEST, 830 + F81232_SET_REGISTER, 831 + reg, 832 + 0, 833 + val, 834 + size, 835 + USB_CTRL_SET_TIMEOUT, 836 + GFP_KERNEL); 837 + } 838 839 + static int f81534a_ctrl_get_register(struct usb_interface *intf, u16 reg, 840 + u16 size, void *val) 841 + { 842 + return usb_control_msg_recv(interface_to_usbdev(intf), 843 + 0, 844 + F81232_REGISTER_REQUEST, 845 + F81232_GET_REGISTER, 846 + reg, 847 + 0, 848 + val, 849 + size, 850 + USB_CTRL_GET_TIMEOUT, 851 + GFP_KERNEL); 852 } 853 854 static int f81534a_ctrl_enable_all_ports(struct usb_interface *intf, bool en) ··· 869 * bit 0~11 : Serial port enable bit. 870 */ 871 if (en) { 872 + /* 873 + * The Fintek F81532A/534A/535/536 family relies on the 874 + * F81534A_CTRL_CMD_ENABLE_PORT (116h) register during 875 + * initialization to both determine serial port status and 876 + * control port creation. 877 + * 878 + * If the driver experiences fast load/unload cycles, the 879 + * device state may becomes unstable, resulting in the 880 + * incomplete generation of serial ports. 881 + * 882 + * Performing a dummy read operation on the register prior 883 + * to the initial write command resolves the issue. 884 + * 885 + * This clears the device's stale internal state. Subsequent 886 + * write operations will correctly generate all serial ports. 887 + */ 888 + status = f81534a_ctrl_get_register(intf, 889 + F81534A_CTRL_CMD_ENABLE_PORT, 890 + sizeof(enable), 891 + enable); 892 + if (status) 893 + return status; 894 + 895 enable[0] = 0xff; 896 enable[1] = 0x8f; 897 }