Merge "Usb: Signal irq_hpd to drm stack" into udc-d1-dev

This commit is contained in:
Badhri Jagan Sridharan 2023-05-25 19:46:52 +00:00 committed by Android (Google) Code Review
commit 378b155ab6
3 changed files with 58 additions and 22 deletions

View file

@ -17,6 +17,7 @@
#define LOG_TAG "android.hardware.usb.aidl-service" #define LOG_TAG "android.hardware.usb.aidl-service"
#include <android-base/logging.h> #include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h> #include <android-base/properties.h>
#include <android-base/strings.h> #include <android-base/strings.h>
#include <assert.h> #include <assert.h>
@ -86,6 +87,7 @@ constexpr char kThermalZoneForTempReadSecondary2[] = "qi_therm";
constexpr char kPogoUsbActive[] = "/sys/devices/platform/google,pogo/pogo_usb_active"; constexpr char kPogoUsbActive[] = "/sys/devices/platform/google,pogo/pogo_usb_active";
constexpr char kPogoEnableUsb[] = "/sys/devices/platform/google,pogo/enable_usb"; constexpr char kPogoEnableUsb[] = "/sys/devices/platform/google,pogo/enable_usb";
constexpr char kPowerSupplyUsbType[] = "/sys/class/power_supply/usb/usb_type"; constexpr char kPowerSupplyUsbType[] = "/sys/class/power_supply/usb/usb_type";
constexpr char kIrqHpdCounPath[] = "-0025/irq_hpd_count";
constexpr int kSamplingIntervalSec = 5; constexpr int kSamplingIntervalSec = 5;
void queryVersionHelper(android::hardware::usb::Usb *usb, void queryVersionHelper(android::hardware::usb::Usb *usb,
std::vector<PortStatus> *currentPortStatus); std::vector<PortStatus> *currentPortStatus);
@ -468,9 +470,9 @@ Usb::Usb()
ALOGE("pthread_condattr_destroy failed: %s", strerror(errno)); ALOGE("pthread_condattr_destroy failed: %s", strerror(errno));
abort(); abort();
} }
mDisplayPortShutdown = eventfd(0, EFD_NONBLOCK); mDisplayPortEventPipe = eventfd(0, EFD_NONBLOCK);
if (mDisplayPortShutdown == -1) { if (mDisplayPortEventPipe == -1) {
ALOGE("mDisplayPortShutdown eventfd failed: %s", strerror(errno)); ALOGE("mDisplayPortEventPipe eventfd failed: %s", strerror(errno));
abort(); abort();
} }
} }
@ -970,9 +972,16 @@ static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
} }
pthread_mutex_unlock(&payload->usb->mRoleSwitchLock); pthread_mutex_unlock(&payload->usb->mRoleSwitchLock);
} }
if (!!strncmp(cp, "DEVTYPE=typec_alternate_mode", strlen("DEVTYPE=typec_alternate_mode"))) { if (!strncmp(cp, "DRIVER=max77759tcpc", strlen("DRIVER=max77759tcpc"))
break; && payload->usb->mDisplayPortPollRunning) {
uint64_t flag = DISPLAYPORT_IRQ_HPD_COUNT_CHECK;
ALOGI("usbdp: DISPLAYPORT_IRQ_HPD_COUNT_CHECK sent");
write(payload->usb->mDisplayPortEventPipe, &flag, sizeof(flag));
} }
/*if (!!strncmp(cp, "DEVTYPE=typec_alternate_mode", strlen("DEVTYPE=typec_alternate_mode"))) {
break;
}*/
} else if (!strncmp(cp, kOverheatStatsDev, strlen(kOverheatStatsDev))) { } else if (!strncmp(cp, kOverheatStatsDev, strlen(kOverheatStatsDev))) {
ALOGV("Overheat Cooling device suez update"); ALOGV("Overheat Cooling device suez update");
report_overheat_event(payload->usb); report_overheat_event(payload->usb);
@ -1171,6 +1180,21 @@ Status Usb::writeDisplayPortAttribute(string attribute, string usb_path) {
return Status::SUCCESS; return Status::SUCCESS;
} }
} }
} else if (!strncmp(attribute.c_str(), "irq_hpd_count", strlen("irq_hpd_count"))) {
uint32_t temp;
if (!::android::base::ParseUint(Trim(attrUsb), &temp)) {
ALOGE("usbdp: failed parsing irq_hpd_count:%s", attrUsb.c_str());
return Status::SUCCESS;
}
// Used to cache the values read from tcpci's irq_hpd_count.
// Update drm driver when cached value is not the same as the read value.
ALOGI("usbdp: mIrqHpdCountCache:%u irq_hpd_count:%u", mIrqHpdCountCache, temp);
if (mIrqHpdCountCache == temp) {
return Status::SUCCESS;
} else {
mIrqHpdCountCache = temp;
}
attrDrmPath = string(kDisplayPortDrmPath) + "irq_hpd";
} else if (!strncmp(attribute.c_str(), "pin_assignment", strlen("pin_assignment"))) { } else if (!strncmp(attribute.c_str(), "pin_assignment", strlen("pin_assignment"))) {
size_t pos = attrUsb.find("["); size_t pos = attrUsb.find("[");
if (pos != string::npos) { if (pos != string::npos) {
@ -1217,26 +1241,32 @@ void *displayPortPollWork(void *param) {
int epoll_fd; int epoll_fd;
struct epoll_event ev_hpd, ev_pin, ev_orientation, ev_eventfd, ev_link; struct epoll_event ev_hpd, ev_pin, ev_orientation, ev_eventfd, ev_link;
int nevents = 0; int nevents = 0;
int numRetries = 0;
int hpd_fd, pin_fd, orientation_fd, link_fd; int hpd_fd, pin_fd, orientation_fd, link_fd;
int file_flags = O_RDONLY; int file_flags = O_RDONLY;
int epoll_flags; int epoll_flags;
bool orientationSet = false; bool orientationSet = false;
bool pinSet = false; bool pinSet = false;
string displayPortUsbPath; string displayPortUsbPath, irqHpdCountPath, hpdPath, pinAssignmentPath, orientationPath;
string hpdPath, pinAssignmentPath, orientationPath, linkPath; string tcpcI2cBus, linkPath;
::aidl::android::hardware::usb::Usb *usb = (::aidl::android::hardware::usb::Usb *)param; ::aidl::android::hardware::usb::Usb *usb = (::aidl::android::hardware::usb::Usb *)param;
if (usb->getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::ERROR) { if (usb->getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::ERROR) {
ALOGE("usbdp: could not locate usb displayport directory"); ALOGE("usbdp: could not locate usb displayport directory");
goto usb_path_error; goto usb_path_error;
} }
usb->mDisplayPortPollRunning = true;
ALOGI("usbdp: displayport usb path located at %s", displayPortUsbPath.c_str()); ALOGI("usbdp: displayport usb path located at %s", displayPortUsbPath.c_str());
hpdPath = displayPortUsbPath + "hpd"; hpdPath = displayPortUsbPath + "hpd";
pinAssignmentPath = displayPortUsbPath + "pin_assignment"; pinAssignmentPath = displayPortUsbPath + "pin_assignment";
orientationPath = "/sys/class/typec/port0/orientation"; orientationPath = "/sys/class/typec/port0/orientation";
linkPath = string(kDisplayPortDrmPath) + "link_status"; linkPath = string(kDisplayPortDrmPath) + "link_status";
getI2cBusHelper(&tcpcI2cBus);
irqHpdCountPath = kI2CPath + tcpcI2cBus + "/" + tcpcI2cBus + kIrqHpdCounPath;
ALOGI("udbdp: irqHpdCountPath:%s", irqHpdCountPath.c_str());
epoll_fd = epoll_create(64); epoll_fd = epoll_create(64);
if (epoll_fd == -1) { if (epoll_fd == -1) {
ALOGE("usbdp: epoll_create failed; errno=%d", errno); ALOGE("usbdp: epoll_create failed; errno=%d", errno);
@ -1267,7 +1297,7 @@ void *displayPortPollWork(void *param) {
ev_hpd.data.fd = hpd_fd; ev_hpd.data.fd = hpd_fd;
ev_pin.data.fd = pin_fd; ev_pin.data.fd = pin_fd;
ev_orientation.data.fd = orientation_fd; ev_orientation.data.fd = orientation_fd;
ev_eventfd.data.fd = usb->mDisplayPortShutdown; ev_eventfd.data.fd = usb->mDisplayPortEventPipe;
ev_link.data.fd = link_fd; ev_link.data.fd = link_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, hpd_fd, &ev_hpd) == -1) { if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, hpd_fd, &ev_hpd) == -1) {
@ -1286,7 +1316,7 @@ void *displayPortPollWork(void *param) {
ALOGE("usbdp: epoll_ctl failed to add link status; errno=%d", errno); ALOGE("usbdp: epoll_ctl failed to add link status; errno=%d", errno);
goto error; goto error;
} }
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortShutdown, &ev_eventfd) == -1) { if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortEventPipe, &ev_eventfd) == -1) {
ALOGE("usbdp: epoll_ctl failed to add orientation; errno=%d", errno); ALOGE("usbdp: epoll_ctl failed to add orientation; errno=%d", errno);
goto error; goto error;
} }
@ -1314,15 +1344,9 @@ void *displayPortPollWork(void *param) {
} else if (events[n].data.fd == orientation_fd) { } else if (events[n].data.fd == orientation_fd) {
usb->writeDisplayPortAttribute("orientation", orientationPath); usb->writeDisplayPortAttribute("orientation", orientationPath);
orientationSet = true; orientationSet = true;
} else if (events[n].data.fd == link_fd) { } else if (events[n].data.fd == usb->mDisplayPortEventPipe) {
if (usb->determineDisplayPortRetry(linkPath, hpdPath) && numRetries < 3) {
ALOGW("usbdp: Link Training Failed, rewriting hpd to trigger retry.");
usb->writeDisplayPortAttributeOverride("hpd", "1");
numRetries++;
}
} else if (events[n].data.fd == usb->mDisplayPortShutdown) {
uint64_t flag = 0; uint64_t flag = 0;
if (!read(usb->mDisplayPortShutdown, &flag, sizeof(flag))) { if (!read(usb->mDisplayPortEventPipe, &flag, sizeof(flag))) {
if (errno == EAGAIN) if (errno == EAGAIN)
continue; continue;
ALOGI("usbdp: Shutdown eventfd read error"); ALOGI("usbdp: Shutdown eventfd read error");
@ -1332,6 +1356,9 @@ void *displayPortPollWork(void *param) {
ALOGI("usbdp: Shutdown eventfd triggered"); ALOGI("usbdp: Shutdown eventfd triggered");
destroyDisplayPortThread = true; destroyDisplayPortThread = true;
break; break;
} else if (flag == DISPLAYPORT_IRQ_HPD_COUNT_CHECK) {
ALOGI("usbdp: IRQ_HPD event through DISPLAYPORT_IRQ_HPD_COUNT_CHECK");
usb->writeDisplayPortAttribute("irq_hpd_count", irqHpdCountPath);
} }
} }
} }
@ -1346,10 +1373,11 @@ orientation_fd_error:
pin_fd_error: pin_fd_error:
close(hpd_fd); close(hpd_fd);
hpd_fd_error: hpd_fd_error:
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortShutdown, &ev_eventfd); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortEventPipe, &ev_eventfd);
close(epoll_fd); close(epoll_fd);
epoll_fd_error: epoll_fd_error:
usb_path_error: usb_path_error:
usb->mDisplayPortPollRunning = false;
ALOGI("usbdp: Exiting worker thread"); ALOGI("usbdp: Exiting worker thread");
return NULL; return NULL;
} }
@ -1357,7 +1385,7 @@ usb_path_error:
void Usb::setupDisplayPortPoll() { void Usb::setupDisplayPortPoll() {
uint64_t flag = DISPLAYPORT_SHUTDOWN_CLEAR; uint64_t flag = DISPLAYPORT_SHUTDOWN_CLEAR;
write(mDisplayPortShutdown, &flag, sizeof(flag)); write(mDisplayPortEventPipe, &flag, sizeof(flag));
destroyDisplayPortThread = false; destroyDisplayPortThread = false;
/* /*
@ -1394,7 +1422,7 @@ void Usb::shutdownDisplayPortPoll() {
} }
// Shutdown thread, make sure to rewrite hpd because file no longer exists. // Shutdown thread, make sure to rewrite hpd because file no longer exists.
write(mDisplayPortShutdown, &flag, sizeof(flag)); write(mDisplayPortEventPipe, &flag, sizeof(flag));
if (pthread_create(&mDisplayPortShutdownHelper, NULL, shutdownDisplayPortPollWork, this)) { if (pthread_create(&mDisplayPortShutdownHelper, NULL, shutdownDisplayPortPollWork, this)) {
ALOGE("pthread creation failed %d", errno); ALOGE("pthread creation failed %d", errno);
} }

View file

@ -59,6 +59,7 @@ constexpr char kGadgetName[] = "11210000.dwc3";
#define DISPLAYPORT_SHUTDOWN_CLEAR 0 #define DISPLAYPORT_SHUTDOWN_CLEAR 0
#define DISPLAYPORT_SHUTDOWN_SET 1 #define DISPLAYPORT_SHUTDOWN_SET 1
#define DISPLAYPORT_IRQ_HPD_COUNT_CHECK 3
struct Usb : public BnUsb { struct Usb : public BnUsb {
Usb(); Usb();
@ -103,12 +104,17 @@ struct Usb : public BnUsb {
float mPluggedTemperatureCelsius; float mPluggedTemperatureCelsius;
// Usb Data status // Usb Data status
bool mUsbDataEnabled; bool mUsbDataEnabled;
// True when mDisplayPortPoll pthread is running
volatile bool mDisplayPortPollRunning;
// Used to cache the values read from tcpci's irq_hpd_count.
// Update drm driver when cached value is not the same as the read value.
uint32_t mIrqHpdCountCache;
// Protects writeDisplayPortToExynos(), setupDisplayPortPoll(), and // Protects writeDisplayPortToExynos(), setupDisplayPortPoll(), and
// shutdownDisplayPortPoll() // shutdownDisplayPortPoll()
pthread_mutex_t mDisplayPortLock; pthread_mutex_t mDisplayPortLock;
// eventfd to signal DisplayPort thread // eventfd to signal DisplayPort thread
int mDisplayPortShutdown; int mDisplayPortEventPipe;
private: private:
pthread_t mPoll; pthread_t mPoll;
pthread_t mDisplayPortPoll; pthread_t mDisplayPortPoll;

View file

@ -69,6 +69,7 @@ on post-fs
chown root system /sys/devices/platform/10cb0000.hsi2c/i2c-8/8-0025/usb_limit_source_enable chown root system /sys/devices/platform/10cb0000.hsi2c/i2c-8/8-0025/usb_limit_source_enable
chown root system /sys/devices/platform/10cb0000.hsi2c/i2c-9/9-0025/usb_limit_source_enable chown root system /sys/devices/platform/10cb0000.hsi2c/i2c-9/9-0025/usb_limit_source_enable
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/irq_hpd
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status
@ -143,6 +144,7 @@ on post-fs
chmod 664 /sys/devices/platform/10cb0000.hsi2c/i2c-8/8-0025/usb_limit_source_enable chmod 664 /sys/devices/platform/10cb0000.hsi2c/i2c-8/8-0025/usb_limit_source_enable
chmod 664 /sys/devices/platform/10cb0000.hsi2c/i2c-9/9-0025/usb_limit_source_enable chmod 664 /sys/devices/platform/10cb0000.hsi2c/i2c-9/9-0025/usb_limit_source_enable
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/irq_hpd
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status