2011년 11월 13일 일요일

vibrator device driver code로 인한 watchdog reset

vibrator device driver에서 사용자의 입력을 받으면 진동을 울려주게 된다.

진동을 울린 후에 30ms 후에 진동을 멈춰야 한다.

Android Vibrator Service에서 vibrator를 on/off하게 된다.

그런데, Qualcomm chip 기반의 Andorid model을 개발하면서 하단 Touch(메뉴/Home/취소가 있는 부분) 영역을 손가락으로 문지르면(Touch device로 되어 있기 때문에 문지르는것이 가능하다), 몇초(약 4초)뒤에 Reset을 치게 되었다. 

느낌상 Watchdog Reset으로 보였지만 정확한 분석이 필요했다.

Reset이 되고 난 뒤에 RAM Dump를 수행하고 Trace32 simulator에 올려서 확인해 보니 Watchdog Reset이 맞았다.

vibrator device code에서 user space에서 호출되는 api를 확인해 보니 아래와 같이 되어 있었다.

function vibrator_on_off (on_or_off)

spin_lock_irqrestore;

printk "vibrator - start";

if ( on )

cancel_work_sync "vibrator_on" work queue;

queue_work vibrator_on;

else

queue_work vibrator_off;

printk "vibrator -off";

spin_unlock_irqrestore;

end function

vibrator를 on 시키면 이전에 vibrator_on work queue를 cancel_work_sync 함수로 이전에 실행된 vibrator_on work queue를 cancel 시키고, 다시 work queue에 등록시켜주고 있었다. 그리고, vibrator를 off 시킬 때는 무조건 vibrator work queue를 등록하도록 되어 있었다.

그래서, 아래와 같은 단계로 debugging을 진행했다.

1. printk 문을 제외한 모든 코드를 삭제 해 보았다. 

- 여전히 Watchdog Reset이 발생했다.

- printk 안을 뒤져보니 spin_lock_irqrestore 함수를 호출되고 있었다.

- printk을 호출하면 잠깐씩 irq가 disable되고 있다.

- log 에서 vibrator_on_off 함수의 호출이 많이 호출되고 있다. (그럴수밖에 마구마구 문질러대니...)

2. vibrator_on_off 함수의 빈번한 호출과 vibrator_on / vibrator_off work queue의 빈번한 호출로 인해서 Watchdog bark interrupt handler가 동작하지 못한다는 결론을 내렸다.

3. vibraotr_on 함수 및 vibrator device driver를 수정하기로 했다.

- 불필요한 printk문을 모두 삭제했다.

- vibrator_on / vibrator_off work queue를 delayed work queue로 만들었다.

- vibrator_on_off 함수의 spin_lock_irqrestore 함수대신 spin_lock을 사용하였다.

- vibrator_on_off 함수내에서 vibrator_on / vibrator_off delayed work queue를 work queue에서 추가하기 전에 모두 cancel_delayed_work_sync 를 호출하여 실행되고 있지 않은 모든 delayed work queue를 취소시켰다.

- 대략 아래와 같이 수정하였다.

function vibrator_on_off (on_or_off)

cancel_delayed_work_sync "vibrator_on" work queue;

cancel_delayed_work_sync "vibrator_off" work queue;

spin_lock_irq;

if ( on )

queue_delayed_work vibrator_on, msecs_to_jiffies(10);

else

queue_delayed_work vibrator_off, msecs_to_jiffies(10);

spin_unlock;

end function

4. kernel을 다시 빌드 후 Test를 진행했다. 마구마구 문질렀다. 

- 정상동작을 확인했다.

- 안 죽는다!

 

이전에 nVidia Chip을 사용하던 경우에는 Watchdog을 사용하지 않았기 때문에 device driver code로 인한 Watchdog Reset을 경험한 적이 없었다.

vibrator device driver가 touch key pad의 특성으로 인해서 과도한 호출이 일어남으로써 발생하는 것이었지만, device driver 구현시 고려를 해 봐야하는 것이 아닐까하는 생각이 든다.

이제 퇴근해야지!

댓글 1개:

  1. 저 핸드폰에서 watchdog reset 이라고 뜨는데
    해결하는 방법좀 알려주세요..
    그냥 잘되다가 갑자기 뜨고 그러네요..

    답글삭제