Francisco Jerez
2009-Jun-10 15:35 UTC
[Nouveau] [PATCH] Use nanosleep instead of usleep when waiting the hardware.
usleep() was being used without checking its return value. When the server receives SIGALRM or SIGIO the waits are shortened and random modesetting failures happen: Use nanosleep and loop around it until the requested time has elapsed. --- src/nouveau_hw.c | 2 +- src/nouveau_local.h | 6 ++++++ src/nv_bios.c | 2 +- src/nv_crtc.c | 2 +- src/nv_include.h | 1 + src/nv_output.c | 10 +++++----- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/nouveau_hw.c b/src/nouveau_hw.c index 7d210d7..c2cad37 100644 --- a/src/nouveau_hw.c +++ b/src/nouveau_hw.c @@ -208,7 +208,7 @@ static void setPLL_single(ScrnInfoPtr pScrn, uint32_t reg, if (chip_version < 0x17 && chip_version != 0x11) /* wait a bit on older chips */ - usleep(64000); + nouveau_usleep(64000); NVReadRAMDAC(pNv, 0, reg); /* then write the other half as well */ diff --git a/src/nouveau_local.h b/src/nouveau_local.h index d44e2dc..3a8bdf7 100644 --- a/src/nouveau_local.h +++ b/src/nouveau_local.h @@ -43,4 +43,10 @@ #define NOUVEAU_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) +static inline void nouveau_usleep(unsigned long usec){ + struct timespec t = { usec/1000000, (usec % 1000000)*1000 }; + + while (nanosleep(&t, &t) && errno == EINTR) {} +} + #endif diff --git a/src/nv_bios.c b/src/nv_bios.c index 182456a..b7490c1 100644 --- a/src/nv_bios.c +++ b/src/nv_bios.c @@ -41,7 +41,7 @@ #define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip, fmt, ##arg) #define LOG_OLD_VALUE(x) //x -#define BIOS_USLEEP(n) usleep(n) +#define BIOS_USLEEP(n) nouveau_usleep(n) #define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) #define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) diff --git a/src/nv_crtc.c b/src/nv_crtc.c index b8524fb..1ffb267 100644 --- a/src/nv_crtc.c +++ b/src/nv_crtc.c @@ -212,7 +212,7 @@ nv_crtc_dpms(xf86CrtcPtr crtc, int mode) seq1 |= (NVReadVgaSeq(pNv, nv_crtc->head, NV_VIO_SR_CLOCK_INDEX) & ~0x20); NVWriteVgaSeq(pNv, nv_crtc->head, NV_VIO_SR_CLOCK_INDEX, seq1); crtc17 |= (NVReadVgaCrtc(pNv, nv_crtc->head, NV_CIO_CR_MODE_INDEX) & ~0x80); - usleep(10000); + nouveau_usleep(10000); NVWriteVgaCrtc(pNv, nv_crtc->head, NV_CIO_CR_MODE_INDEX, crtc17); NVVgaSeqReset(pNv, nv_crtc->head, false); diff --git a/src/nv_include.h b/src/nv_include.h index 0409c89..46f809b 100644 --- a/src/nv_include.h +++ b/src/nv_include.h @@ -12,6 +12,7 @@ #include <errno.h> #include <unistd.h> #include <stdlib.h> +#include <time.h> /* All drivers should typically include these */ #include "xf86.h" diff --git a/src/nv_output.c b/src/nv_output.c index 0979bb9..d18bcd2 100644 --- a/src/nv_output.c +++ b/src/nv_output.c @@ -162,7 +162,7 @@ static bool nv_legacy_load_detect(ScrnInfoPtr pScrn) NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF); - usleep(10000); + nouveau_usleep(10000); saved_pi = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX); NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX, @@ -258,7 +258,7 @@ nv_nv17_load_detect(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder) nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); } - usleep(4000); + nouveau_usleep(4000); saved_routput = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset); head = (saved_routput & 0x100) >> 8; @@ -269,7 +269,7 @@ nv_nv17_load_detect(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder) /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset, (saved_routput & 0xfffffece) | head << 8); - usleep(1000); + nouveau_usleep(1000); temp = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset); NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset, temp | 1); @@ -279,7 +279,7 @@ nv_nv17_load_detect(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder) temp = NVReadRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL); NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL, temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED); - usleep(1000); + nouveau_usleep(1000); present = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI; @@ -871,7 +871,7 @@ nv_output_prepare(xf86OutputPtr output) */ NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL, FP_TG_CONTROL_OFF); - usleep(50000); + nouveau_usleep(50000); } /* don't inadvertently turn it on when state written later */ crtcstate[head].fp_control = FP_TG_CONTROL_OFF; -- 1.6.0.6