2017-01-30 1 views
1

우리는 커널 3.2 버전을 실행하는 사용자 지정 보드를 사용하고 있지만 MMC 계층의 견고성을 테스트 할 때 몇 가지 문제가 있습니다.카드와의 통신이 끊어지면 MMC 큐가 새로운 요청을 가져 오지 못하도록 막습니다.

먼저 MMC 슬롯에는 카드 감지 핀이 없습니다. 문제의 문제는 다음과 같이 구성됩니다.

  1. 모듈 (omap_hsmmc)을로드하십시오. 카드는 전원이 켜질 때 감지되고 이며 적절하게 마운트됩니다.
  2. SD 카드의 내용을 읽으십시오 (예 : cat foo.txt)
  3. 파일을 읽는 동안 카드를 제거하십시오.
  4. 많은 실패한 시도 후에 시스템이 중단됩니다.

는 지금, 나는 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 등을 호출했습니다. 이것들과 함께, 내가 성취 할 수 있었던 것은 스레드를 "무해한"상태로 유지하는 것이 었습니다. 스레드는 여전히 존재했지만 자원을 소비하지 않았습니다. 그러나 호출을 트리거 한 사용자 공간 프로그램이 리턴되지 않고 중단 불가능 상태로 잠 깁니다.

내 질문 :

  1. 새로운 요청을에서 상위 계층을 중지하여이 문제를 해결하는 가장 좋은 방법은 무엇입니까? 또는 스레드 자체가 '종료'되어야합니까?
  2. 광산과 같은 경우에는 카드 감지 핀이 없으므로 카드를 제거하면 안된다고 가정해야합니까?

업데이트 : 당신이 카드 삽입/제거를 감지하는 폴링을 사용하여 드라이버를 알 수 있다는 것을 발견했습니다.드라이버 초기화시 mmc의 .capsMMC_CAP_NEEDS_POLL 플래그를 추가하여 수행 할 수 있습니다 (최신 커널에서는 DT에 broken-cd 속성을 사용할 수 있음). 그러나이 수정 후에도 문제가 계속 발생합니다.

+0

사용하는 보드는 무엇입니까? 더 구체적으로, SoC는 무엇입니까? 또한 정확히 어떤 커널을 사용합니까 (소스에 대한 링크)? –

+0

@Sam Protsenko, AM335x가있는 맞춤형 보드를 사용합니다. 커널 버전은 [Texas Instruments의 3.2 버전] (https://git.ti.com/ti-linux-kernel/ti-linux-kernel/trees/v3.2)입니다. –

+0

@andriy,이 질문을 작성한 이후로, 폴링을 통해 카드를 감지해야한다는 것을 커널에 알릴 수 있다는 것을 알았습니다. 이것은 mmc의'.caps'에'MMC_CAP_NEEDS_POLL'을 수행 할 수 있습니다. 이렇게하면 커널이 카드가 제거되었음을 감지하지만 삭제 된 문제는 계속됩니다. 의견을 보내 주셔서 감사합니다. =] –

답변

1

솔루션을 알아 냈습니다!

내가 의심하는 바에 따르면, 카드 요청이 차단 된 후에도 요청이 계속 발행되었습니다. 이 오류는 커밋에서 수정되었습니다 a8ad82cc1b22d04916d9cdb1dc75052e80ac803cTexas' kernel repository에서 :

commit a8ad82cc1b22d04916d9cdb1dc75052e80ac803c 
Author: Sujit Reddy Thumma <[email protected]> 
Date: Thu Dec 8 14:05:50 2011 +0530 

    mmc: card: Kill block requests if card is removed 

    Kill block requests when the host realizes that the card is 
    removed from the slot and is sure that subsequent requests 
    are bound to fail. Do this silently so that the block 
    layer doesn't output unnecessary error messages. 

    Signed-off-by: Sujit Reddy Thumma <[email protected]> 
    Acked-by: Adrian Hunter <[email protected]> 
    Signed-off-by: Chris Ball <[email protected]> 

의 키 커밋 return BLKPREP_KILL 특정을 추가, 오류 처리에 약간의 '단위'를 추가 약간의 개조하면 되겠 게다가, mmc_prep_request()에 추가 된 것입니다 카드가 제거 된 경우의 코드.

+1

FYI, 그 패치는 k3.3, [here] (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=a8ad82cc1b22d04916d9cdb1dc75052e80ac803c)에서 업스트림되었습니다. –

관련 문제