Skip to content

Commit 2107413

Browse files
pdp7RobertCNelson
authored andcommitted
tieqep: fix unhandled fault on eQEP register access
Call pm_runtime_get_sync() at the beginning of any functions that will read or write to the memory mapped eQEP registers. This is to ensure that the eQEP peripheral is running and its clock is enabled. Before this patch, an attempt to read the position file via sysfs would results in a segmentation fault. The kernel log would be contain this error: [ 2591.653471] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa304180 [ 2591.915165] [<bf005310>] (eqep_get_position [tieqep]) from [<c08930d0>] (dev_attr_show+0x2c/0x58) More details: https://gist.github.com/pdp7/fe07082d23f2bfbc362c733a7b0aea72 BeagleBoard mailing list thread: https://groups.google.com/d/msg/beagleboard/_TdTH7oPEXE/MNvU-mY6DgAJ
1 parent e31a085 commit 2107413

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

drivers/misc/tieqep.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,13 @@ static ssize_t eqep_get_enabled(struct device *dev, struct device_attribute *att
241241
{
242242
/* Get the instance structure */
243243
struct eqep_chip *eqep = dev_get_drvdata(dev);
244+
u16 enabled = 0;
245+
246+
/* Increment the device usage count and run pm_runtime_resume() */
247+
pm_runtime_get_sync(dev);
244248

245249
/* Read the qep control register and mask all but the enabled bit */
246-
u16 enabled = readw(eqep->mmio_base + QEPCTL) & PHEN;
250+
enabled = readw(eqep->mmio_base + QEPCTL) & PHEN;
247251

248252
/* Return the target in string format */
249253
return sprintf(buf, "%u\n", (enabled) ? 1 : 0);
@@ -262,6 +266,8 @@ static ssize_t eqep_set_enabled(struct device *dev, struct device_attribute *att
262266
if ((rc = kstrtou8(buf, 0, &enabled)))
263267
return rc;
264268

269+
/* Increment the device usage count and run pm_runtime_resume() */
270+
pm_runtime_get_sync(dev);
265271
/* Get the existing state of QEPCTL */
266272
val = readw(eqep->mmio_base + QEPCTL);
267273

@@ -286,6 +292,8 @@ static ssize_t eqep_get_position(struct device *dev, struct device_attribute *at
286292
struct eqep_chip *eqep = dev_get_drvdata(dev);
287293

288294
s32 position = 0;
295+
/* Increment the device usage count and run pm_runtime_resume() */
296+
pm_runtime_get_sync(dev);
289297

290298
if (eqep->op_mode == TIEQEP_MODE_ABSOLUTE) {
291299
position = readl(eqep->mmio_base + QPOSCNT);
@@ -308,6 +316,8 @@ static ssize_t eqep_set_position(struct device *dev, struct device_attribute *at
308316
if ((rc = kstrtos32(buf, 0, &position)))
309317
return rc;
310318

319+
/* Increment the device usage count and run pm_runtime_resume() */
320+
pm_runtime_get_sync(dev);
311321
/*
312322
* If we are in absolute mode, set the position of the encoder,
313323
* discard relative mode because thats pointless
@@ -327,6 +337,8 @@ static ssize_t eqep_get_timer_period(struct device *dev, struct device_attribute
327337
struct eqep_chip *eqep = dev_get_drvdata(dev);
328338
u64 period;
329339

340+
/* Increment the device usage count and run pm_runtime_resume() */
341+
pm_runtime_get_sync(dev);
330342
/* Convert from counts per interrupt back into period_ns */
331343
period = readl(eqep->mmio_base + QUPRD);
332344
period = period * NSEC_PER_SEC;
@@ -348,6 +360,8 @@ static ssize_t eqep_set_timer_period(struct device *dev, struct device_attribute
348360
if ((rc = kstrtou64(buf, 0, &period)))
349361
return rc;
350362

363+
/* Increment the device usage count and run pm_runtime_resume() */
364+
pm_runtime_get_sync(dev);
351365
/* Disable the unit timer before modifying its period register */
352366
tmp = readw(eqep->mmio_base + QEPCTL);
353367
tmp &= ~(UTE | QCLM);
@@ -395,6 +409,8 @@ static ssize_t eqep_set_mode(struct device *dev, struct device_attribute *attr,
395409

396410
dev_dbg(dev, "eqep_set_mode:%d\n", tmp_mode);
397411

412+
/* Increment the device usage count and run pm_runtime_resume() */
413+
pm_runtime_get_sync(dev);
398414
val = readw(eqep->mmio_base + QEPCTL);
399415

400416
if (tmp_mode == TIEQEP_MODE_ABSOLUTE) {

0 commit comments

Comments
 (0)