Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: chipidea: add CI_HDRC_HAS_SHORT_PKT_LIMIT flag

Currently, the imx deivice controller has below limitations:

1. can't generate short packet interrupt if IOC not set in dTD. So if one
request span more than one dTDs and only the last dTD set IOC, the usb
request will pending there if no more data comes.
2. the controller can't accurately deliver data to differtent usb requests
in some cases due to short packet. For example: one usb request span 3
dTDs, then if the controller received a short packet the next packet
will go to 2nd dTD of current request rather than the first dTD of next
request.
3. can't build a bus packet use multiple dTDs. For example: controller
needs to send one packet of 512 bytes use dTD1 (200 bytes) + dTD2
(312 bytes), actually the host side will see 200 bytes short packet.

Based on these limits, add CI_HDRC_HAS_SHORT_PKT_LIMIT flag and use it on
imx platforms.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Acked-by: Peter Chen <peter.chen@kernel.org>
Link: https://lore.kernel.org/r/20240923081203.2851768-1-xu.yang_2@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Xu Yang and committed by
Greg Kroah-Hartman
ec841b8d 669e995f

+5
+1
drivers/usb/chipidea/ci.h
··· 260 260 bool b_sess_valid_event; 261 261 bool imx28_write_fix; 262 262 bool has_portsc_pec_bug; 263 + bool has_short_pkt_limit; 263 264 bool supports_runtime_pm; 264 265 bool in_lpm; 265 266 bool wakeup_int;
+1
drivers/usb/chipidea/ci_hdrc_imx.c
··· 342 342 struct ci_hdrc_platform_data pdata = { 343 343 .name = dev_name(&pdev->dev), 344 344 .capoffset = DEF_CAPOFFSET, 345 + .flags = CI_HDRC_HAS_SHORT_PKT_LIMIT, 345 346 .notify_event = ci_hdrc_imx_notify_event, 346 347 }; 347 348 int ret;
+2
drivers/usb/chipidea/core.c
··· 1076 1076 CI_HDRC_SUPPORTS_RUNTIME_PM); 1077 1077 ci->has_portsc_pec_bug = !!(ci->platdata->flags & 1078 1078 CI_HDRC_HAS_PORTSC_PEC_MISSED); 1079 + ci->has_short_pkt_limit = !!(ci->platdata->flags & 1080 + CI_HDRC_HAS_SHORT_PKT_LIMIT); 1079 1081 platform_set_drvdata(pdev, ci); 1080 1082 1081 1083 ret = hw_device_init(ci, base);
+1
include/linux/usb/chipidea.h
··· 65 65 #define CI_HDRC_PHY_VBUS_CONTROL BIT(16) 66 66 #define CI_HDRC_HAS_PORTSC_PEC_MISSED BIT(17) 67 67 #define CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS BIT(18) 68 + #define CI_HDRC_HAS_SHORT_PKT_LIMIT BIT(19) 68 69 enum usb_dr_mode dr_mode; 69 70 #define CI_HDRC_CONTROLLER_RESET_EVENT 0 70 71 #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1