우리는 커널 3.2 버전을 실행하는 사용자 지정 보드를 사용하고 있지만 MMC 계층의 견고성을 테스트 할 때 몇 가지 문제가 있습니다.카드와의 통신이 끊어지면 MMC 큐가 새로운 요청을 가져 오지 못하도록 막습니다.
먼저 MMC 슬롯에는 카드 감지 핀이 없습니다. 문제의 문제는 다음과 같이 구성됩니다.
- 모듈 (omap_hsmmc)을로드하십시오. 카드는 전원이 켜질 때 감지되고 이며 적절하게 마운트됩니다.
- SD 카드의 내용을 읽으십시오 (예 :
cat foo.txt
) - 파일을 읽는 동안 카드를 제거하십시오.
- 많은 실패한 시도 후에 시스템이 중단됩니다.
는 지금, 나는 drivers/mmc/card/queue.c
에서 다음 코드 섹션에 문제를 추적했습니다
static int mmc_queue_thread(void *d)
{
struct mmc_queue *mq = d;
struct request_queue *q = mq->queue;
current->flags |= PF_MEMALLOC;
down(&mq->thread_sem);
do {
struct request *req = NULL;
struct mmc_queue_req *tmp;
spin_lock_irq(q->queue_lock);
set_current_state(TASK_INTERRUPTIBLE);
req = blk_fetch_request(q);
mq->mqrq_cur->req = req;
spin_unlock_irq(q->queue_lock);
if (req || mq->mqrq_prev->req) {
set_current_state(TASK_RUNNING);
mq->issue_fn(mq, req);
} else {
if (kthread_should_stop()) {
set_current_state(TASK_RUNNING);
break;
}
up(&mq->thread_sem);
schedule();
down(&mq->thread_sem);
}
/* Current request becomes previous request and vice versa. */
mq->mqrq_prev->brq.mrq.data = NULL;
mq->mqrq_prev->req = NULL;
tmp = mq->mqrq_prev;
mq->mqrq_prev = mq->mqrq_cur;
mq->mqrq_cur = tmp;
} while (1);
up(&mq->thread_sem);
return 0;
}
이 코드를 조사, 나는 그것이 mq->issue_fn(mq, req)
전화 내부에 달려 있음을 발견했습니다. 이 함수는 전달 된 요청을 채우기 위해 적절한 명령을 준비하고 실행하며 카드와 통신 할 수 없을 때 발생하는 오류를 인식합니다. 오류는 (제 의견으로는) 어색한 방식으로 처리되며 mmc_queue_thread
에 '버블 업'되지 않습니다. 그러나 가장 최근의 커널 릴리즈 (4.9)의 버전과 내 버전의 코드를 비교해 보았습니다. 각 오류 케이스를 더 잘 구분할 수 있다는 점을 제외하고는 이러한 오류 처리에 차이점을 보지 못했습니다 (처리 방법은 매우 유사합니다).
위의 계층이 MMC 카드에서 읽는 새 요청을 중지 할 수 없기 때문에 문제가 발생한 것으로 판단됩니다. 나는 무엇을 시도했다
:
- 재 작성 내가
ret = mq->issue_fn(mq, req)
을 할 수 있도록 오류가 위로 통과되도록 코드입니다. - 특정 오류를 식별 할 수 있기 때문에 다른 방법으로 스레드를 취소하려고 시도했습니다. 을 호출하고
mmc_queue_suspend
,__blk_end_request
등을 호출했습니다. 이것들과 함께, 내가 성취 할 수 있었던 것은 스레드를 "무해한"상태로 유지하는 것이 었습니다. 스레드는 여전히 존재했지만 자원을 소비하지 않았습니다. 그러나 호출을 트리거 한 사용자 공간 프로그램이 리턴되지 않고 중단 불가능 상태로 잠 깁니다.
내 질문 :
- 새로운 요청을에서 상위 계층을 중지하여이 문제를 해결하는 가장 좋은 방법은 무엇입니까? 또는 스레드 자체가 '종료'되어야합니까?
- 광산과 같은 경우에는 카드 감지 핀이 없으므로 카드를 제거하면 안된다고 가정해야합니까?
업데이트 : 당신이 카드 삽입/제거를 감지하는 폴링을 사용하여 드라이버를 알 수 있다는 것을 발견했습니다.드라이버 초기화시 mmc의 .caps
에 MMC_CAP_NEEDS_POLL
플래그를 추가하여 수행 할 수 있습니다 (최신 커널에서는 DT에 broken-cd
속성을 사용할 수 있음). 그러나이 수정 후에도 문제가 계속 발생합니다.
사용하는 보드는 무엇입니까? 더 구체적으로, SoC는 무엇입니까? 또한 정확히 어떤 커널을 사용합니까 (소스에 대한 링크)? –
@Sam Protsenko, AM335x가있는 맞춤형 보드를 사용합니다. 커널 버전은 [Texas Instruments의 3.2 버전] (https://git.ti.com/ti-linux-kernel/ti-linux-kernel/trees/v3.2)입니다. –
@andriy,이 질문을 작성한 이후로, 폴링을 통해 카드를 감지해야한다는 것을 커널에 알릴 수 있다는 것을 알았습니다. 이것은 mmc의'.caps'에'MMC_CAP_NEEDS_POLL'을 수행 할 수 있습니다. 이렇게하면 커널이 카드가 제거되었음을 감지하지만 삭제 된 문제는 계속됩니다. 의견을 보내 주셔서 감사합니다. =] –