Skip to content
/ linux Public

Commit 7003794

Browse files
Ji-Ze Hong (Peter Hong)gregkh
authored andcommitted
USB: serial: f81232: fix incomplete serial port generation
commit cd644b8 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 58b91c5 commit 7003794

File tree

1 file changed

+47
-30
lines changed

1 file changed

+47
-30
lines changed

drivers/usb/serial/f81232.c

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ MODULE_DEVICE_TABLE(usb, combined_id_table);
7070
#define F81232_REGISTER_REQUEST 0xa0
7171
#define F81232_GET_REGISTER 0xc0
7272
#define F81232_SET_REGISTER 0x40
73-
#define F81534A_ACCESS_REG_RETRY 2
7473

7574
#define SERIAL_BASE_ADDRESS 0x0120
7675
#define RECEIVE_BUFFER_REGISTER (0x00 + SERIAL_BASE_ADDRESS)
@@ -824,36 +823,31 @@ static void f81232_lsr_worker(struct work_struct *work)
824823
static int f81534a_ctrl_set_register(struct usb_interface *intf, u16 reg,
825824
u16 size, void *val)
826825
{
827-
struct usb_device *dev = interface_to_usbdev(intf);
828-
int retry = F81534A_ACCESS_REG_RETRY;
829-
int status;
830-
831-
while (retry--) {
832-
status = usb_control_msg_send(dev,
833-
0,
834-
F81232_REGISTER_REQUEST,
835-
F81232_SET_REGISTER,
836-
reg,
837-
0,
838-
val,
839-
size,
840-
USB_CTRL_SET_TIMEOUT,
841-
GFP_KERNEL);
842-
if (status) {
843-
status = usb_translate_errors(status);
844-
if (status == -EIO)
845-
continue;
846-
}
847-
848-
break;
849-
}
850-
851-
if (status) {
852-
dev_err(&intf->dev, "failed to set register 0x%x: %d\n",
853-
reg, status);
854-
}
826+
return usb_control_msg_send(interface_to_usbdev(intf),
827+
0,
828+
F81232_REGISTER_REQUEST,
829+
F81232_SET_REGISTER,
830+
reg,
831+
0,
832+
val,
833+
size,
834+
USB_CTRL_SET_TIMEOUT,
835+
GFP_KERNEL);
836+
}
855837

856-
return status;
838+
static int f81534a_ctrl_get_register(struct usb_interface *intf, u16 reg,
839+
u16 size, void *val)
840+
{
841+
return usb_control_msg_recv(interface_to_usbdev(intf),
842+
0,
843+
F81232_REGISTER_REQUEST,
844+
F81232_GET_REGISTER,
845+
reg,
846+
0,
847+
val,
848+
size,
849+
USB_CTRL_GET_TIMEOUT,
850+
GFP_KERNEL);
857851
}
858852

859853
static int f81534a_ctrl_enable_all_ports(struct usb_interface *intf, bool en)
@@ -869,6 +863,29 @@ static int f81534a_ctrl_enable_all_ports(struct usb_interface *intf, bool en)
869863
* bit 0~11 : Serial port enable bit.
870864
*/
871865
if (en) {
866+
/*
867+
* The Fintek F81532A/534A/535/536 family relies on the
868+
* F81534A_CTRL_CMD_ENABLE_PORT (116h) register during
869+
* initialization to both determine serial port status and
870+
* control port creation.
871+
*
872+
* If the driver experiences fast load/unload cycles, the
873+
* device state may becomes unstable, resulting in the
874+
* incomplete generation of serial ports.
875+
*
876+
* Performing a dummy read operation on the register prior
877+
* to the initial write command resolves the issue.
878+
*
879+
* This clears the device's stale internal state. Subsequent
880+
* write operations will correctly generate all serial ports.
881+
*/
882+
status = f81534a_ctrl_get_register(intf,
883+
F81534A_CTRL_CMD_ENABLE_PORT,
884+
sizeof(enable),
885+
enable);
886+
if (status)
887+
return status;
888+
872889
enable[0] = 0xff;
873890
enable[1] = 0x8f;
874891
}

0 commit comments

Comments
 (0)