summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/score/include/sys/timepps.h18
-rw-r--r--cpukit/score/src/kern_tc.c13
2 files changed, 25 insertions, 6 deletions
diff --git a/cpukit/score/include/sys/timepps.h b/cpukit/score/include/sys/timepps.h
index 85bb6813cf..419e781be3 100644
--- a/cpukit/score/include/sys/timepps.h
+++ b/cpukit/score/include/sys/timepps.h
@@ -135,6 +135,13 @@ struct pps_kcbind_args {
struct mtx;
+#define KCMODE_EDGEMASK 0x03
+#define KCMODE_ABIFLAG 0x80000000 /* Internal use: abi-aware driver. */
+
+#define PPS_ABI_VERSION 1
+
+#define PPSFLAG_MTX_SPIN 0x01 /* Driver mtx is MTX_SPIN type. */
+
struct pps_state {
/* Capture information. */
struct timehands *capth;
@@ -142,9 +149,6 @@ struct pps_state {
unsigned capgen;
unsigned capcount;
- /* pointer to mutex protecting this state, if any */
- struct mtx *mtx;
-
/* State information. */
pps_params_t ppsparam;
pps_info_t ppsinfo;
@@ -153,11 +157,19 @@ struct pps_state {
int ppscap;
struct timecounter *ppstc;
unsigned ppscount[3];
+ /*
+ * The following fields are valid if the driver calls pps_init_abi().
+ */
+ uint16_t driver_abi; /* Driver sets before pps_init_abi(). */
+ uint16_t kernel_abi; /* Kernel sets during pps_init_abi(). */
+ struct mtx *driver_mtx; /* Optional, valid if non-NULL. */
+ uint32_t flags;
};
void pps_capture(struct pps_state *pps);
void pps_event(struct pps_state *pps, int event);
void pps_init(struct pps_state *pps);
+void pps_init_abi(struct pps_state *pps);
int pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps);
void hardpps(struct timespec *tsp, long nsec);
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index 0b27c8b68f..242983b464 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -1713,10 +1713,17 @@ pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps)
cseq = pps->ppsinfo.clear_sequence;
while (aseq == pps->ppsinfo.assert_sequence &&
cseq == pps->ppsinfo.clear_sequence) {
- if (pps->mtx != NULL)
- err = msleep(pps, pps->mtx, PCATCH, "ppsfch", timo);
- else
+ if (abi_aware(pps, 1) && pps->driver_mtx != NULL) {
+ if (pps->flags & PPSFLAG_MTX_SPIN) {
+ err = msleep_spin(pps, pps->driver_mtx,
+ "ppsfch", timo);
+ } else {
+ err = msleep(pps, pps->driver_mtx, PCATCH,
+ "ppsfch", timo);
+ }
+ } else {
err = tsleep(pps, PCATCH, "ppsfch", timo);
+ }
if (err == EWOULDBLOCK && fapi->timeout.tv_sec == -1) {
continue;
} else if (err != 0) {