반응형

Model: Raspberry Pi 2 Model B V1.1

USB WLAN: TP-LINK TL-WN722N (Atheros ath9k_htc)


라즈베리파이를 무선 메쉬 네트워크의 메쉬 라우터로 만드는 과정에서, USB 무선랜카드 2개를 꽂으면 하나가 매우 자주 연결이 끊어지는 현상이 발생했고, 자세히 확인해 보니 아예 device driver가 죽었다가 다시 살아나기를 반복하고 있었다. 그 현상은 아래와 같이 demsg 화면에서 확인할 수 있다. 그림 속 빨간 색 글씨와 같은 에러가 대략 10여 초를 주기로 계속 발생한다. 즉, 겉으로 보면 USB 무선랜카드의 전원 LED가 10초를 주기로 꺼졌다가 켜지기를 반복한다. 당연히 네트워킹은 안 된다.


(2개 이상의 ath9k_htc 계열 USB 무선랜카드를 연결했을 때 자주 보게 되는 에러 메시지. 

저런 식으로 인터페이스 이름이 지속적으로 커져서 phy30이 넘은 적도 있었다... -_-)


5V/2A의 저전력에 의지하는 라즈베리파이 입장에서 USB 무선랜카드 2개를 동시에 쓰면 1개만 쓸 때에 비해서 아무래도 전력이 부족할 가능성이 높다. 게다가 알고 보니 내가 실험에 사용하는 TL-WN722N 모델이 USB 포트를 통한 전력 공급에 문제가 있는 것 같았다. 한 마디로 설상가상이다. ㅜㅜ 

어디선가 영어로 된 페이지에서 알려진 이슈로 위와 같은 현상이 언급되어 있었던 기억이 난다. 지금으로써는 비교할 만한 다른 ath9k_htc 계열 무선랜카드가 없어서 이것이 결함인지 아닌지 알 길이 없다. (그래도 어느정도 결함 수준으로 봐야 할 정도다.)


더 큰 문제는, 안그래도 전력을 많이 쓰는 녀석이 몸집마저 커서 Raspberry Pi 2 Model B에서는 두 개를 동시에 USB 포트에 직접 꽂을 수도 없다는 사실이다. 이것은 사실 라즈베리파이 2 모델의 디자인으로 인해서 생기는 문제이기도 한데, USB 포트 4개가 한 곳에 몰려 있기 때문에 연결되는 USB 객체가 조금이라도 크기가 커지면 연속으로 (심지어 대각선으로도) 꽂을 수가 없다.


그래서 아래 사진과 같이 하나는 USB 포트에 직접 꽂고, 다른 하나는 USB 확장 케이블을 통해서 연결해야만 했다.



그리고 예상대로, USB 확장 케이블(대략 1~1.5m 쯤 되는 듯)을 통해서 연결된 무선랜카드에서만 위의 dmesg 화면과 같이 디바이스 라이버가 재시작하는 문제가 지속적으로 봘생했다. 어쩌다 한 번씩 멀쩡하게 작동하는 듯 했지만, 하루가 지나고 보면 어김없이 하나는 꺼져 있었다.


결국, 매번 재부팅시키고 아슬아슬하게 살아 있기를 바라기만 해서는 정상적인 실험이 불가능하다고 판단하고, 가장 무식하지만 가장 확실한(...) 물리적인 해결책을 사용했다. 그 무식한 방법은 그냥 뚱뚱한 껍데기를 뜯어내는 것 -_-;;

나사가 하나도 없기 때문에 가장자리에서부터 힘으로 열려고 노력하면 생각 외로 잘 뜯어진다(...).  


그 결과...



이제 동시에 무선랜카드 2개를 USB 포트에 직접 꽂을 수 있게 되었고, 신기하게도 디바이스 드라이버가 재시작하는 현상이 말끔히 사라졌다.


...다음부터는 Atheros 계열 무선랜카드를 살 때, 알려진 문제점이 없는지 좀더 검색해 보고 사는 것이 좋겠다. ㅜㅜ



반응형
블로그 이미지

Bryan_

,
반응형

Model: Raspberry Pi 2 Model B

OS: Raspbian Jessie (2015.09.24)

WLAN: TP-LINK TL-WN722N (Atheros ath9k_htc)


라즈베리파이에 USB 무선랜카드를 연결하고, 이 무선랜카드를 더 자세히 제어해야 할 필요가 생겼다. 이를 위해 무선 네트워크 디바이스 드라이버 관련 오픈소스 패키지(Backports)에서 직접 소스코드를 수정하고 빌드하기로 하였다.


*주의사항: 이 방법은 서버나 PC에서 라즈베리파이 전용 device driver를 크로스 컴파일(cross-compile)하는 방법에 비하면 결코 좋은 방법은 아니다. 원래 정석은 강력한 PC에서 소스코드를 라즈베리파이에 맞게 ARM 계열 아키텍처로 설정하고 기타 조건을 지정한 다음 디바이스 드라이버 파일들(.ko 파일들)만 라즈베리파이에 복사해서 재시작하는 방법이다. backports를 크로스 컴파일하는 방법이 잘 정리된 글을 아직 찾지 못해서 임시방편으로 이렇게 하게 되었다.



1. 사전 준비


1-1. 필요한 패키지 사전 설치


$ sudo apt-get install dkms

$ sudo apt-get install libncurses5-dev


1-2. Raspbian용 linux headers 다운로드/설치


NOTE: (2016년 1월 18일에 확인) sudo apt-get install linux-headers-rpi 명령으로는 최신 커널 버전의 헤더를 받을 수가 없다. 따라서  인터넷에서 직접 커널 헤더 설치파일을 받아서 설치하였다.


우선 현재 라즈베리파이에 설치된 Raspbian이 쓰는 커널 버전부터 확인한다.

$ uname -a

Linux raspberrypi 4.1.7-v7+ #817 SMP PREEMPT Sat Sep 19 15:32:00 BST 2015 armv7l GNU/Linux


Linux raspberrypi 뒤에 적힌 버전 숫자와 일치하는 linux headers deb파일을 아래 페이지에 가서 다운로드 받는다.

https://www.niksula.hut.fi/~mhiienka/Rpi/linux-headers-rpi/


다운로드 받은 리눅스 헤더 설치:

$ sudo dpkg -i [다운로드 받은 헤더 설치파일].deb





2. Backports 소스코드 빌드 및 설치 환경 구축


2-1. Backports 소스코드 다운로드


https://www.kernel.org/pub/linux/kernel/projects/backports/stable/



2-2. Backports 소스코드 빌드를 위한 설정


특정 무선랜 인터페이스 소스코드를 사용하기 위해 프리셋 설정에서부터 시작하는 것이 안전하다. 어떤 프리셋이 있는지 아래 명령으로 확인한다. 참고로 make가 정상적으로 작동하기 위해서는 KLIB argument에서 헤더를 정확히 지정해 주어야 한다.

$ make KLIB=/lib/modules/4.1.7-v7+/ defconfig-help


필자의 경우 TP-LINK TL-WN722N (Atheros ath9k_htc) 무선랜카드를 쓰고 있기 때문에 ath9k 프리셋을 설정하였다.

$ make KLIB=/lib/modules/4.1.7-v7+/ defconfig-ath9k


이렇게 설정파일(.config)이 만들어진 상태에서 세부 설정을 추가하고 싶으면 아래 명령을 입력한다.

$ make KLIB=/lib/modules/4.1.7-v7+/ menuconfig



(backports 패키지의 make menuconfig 예시)



Wireless LAN > Atheros WIreless Cards > Atheros ath9k_htc debugging 항목 선택

 - 이렇게 하면 ath9k_htc의 debugfs 파일들이 /sys/kernel/debug/ieee80211/phyX/ 폴더 하위에 표시된다. (phyX = phy0, phy1, ... )


(Atheros ath9k 계열의 디버깅 설정)



2-3. Backport 소스코드 빌드 및 설치


설정이 끝나면 빌드를 한다.

$ sudo make KLIB=/lib/modules/4.1.7-v7+/


NOTE: 원래 sudo 없이 빌드가 되어야 하는데, 이상하게 리눅스 헤더를 deb 파일에서 dpkg로 설치하고 나면, 해당 버전의 헤더는 루트 권한 없이는 make가 진행되지 않는 문제가 있다. 이것을 해결하려면 /lib/modules/4.1.7-v7+/ 하위 파일들의 실행 권한을 루트가 아닌 사용자에게도 허용해야 하는데, 일단은 복잡하게 변경하지 않고 sudo make로 빌드하였다. 

(이렇게 진행해도 문제가 없었다.)


참고로 라즈베리파이에서 직접 컴파일하기 때문에 시간이 오래 걸린다. 이미 앞서 언급했지만, 크로스 컴파일에 비하면 좋은 방법이 아니다. 단지 아직 확실하게 크로스 컴파일하는 방법을 몰라서 일단 되는 방법부터 시도한 것이다.


빌드가 끝나면 운영체제에 디바이스 드라이버(device driver)를 설치한다.

$ sudo make KLIB=/lib/modules/4.1.7-v7+/ install





3. 재시작 및 테스트


설치가 끝나면 재부팅해서 작동 여부를 확인한다. 쉘에서 dmesg를 쳐서 오류 메세지가 뜨는 것은 없는지 확인해볼 것.


라즈베리파이는 전력이 약하기도 하고, 내가 테스트에 사용한 TL-WN722N이 하필이면 고질적으로 USB 포트에 따라 작동을 잘 하거나 전혀 작동하지 못하는 문제가 있기 때문에 dmesg에서 문제없이 디바이스 드라이버가 로드되었는지 점검하는 것이 필요하다. 아래는 2개의 USB 무선랜카드 중 1개가 제대로 작동하지 못해서 dmesg에서 오류가 발생한 예시이다.



위와 같은 오류가 발생할 때, 현재로써는 완전한 해결책을 찾지 못했다. 그저 USB 무선랜카드를 USB 포트에서 완전히 뺐다가 다시 꽂거나, 라즈베리파이 전원을 통째로 뺐다가 꽂으면 약 50% 확률로 정상 작동하였다.



반응형
블로그 이미지

Bryan_

,
반응형


연구 목적으로 compat-wireless 패키지에 들어 있는 Qualcomm Atheros 칩셋 중 하나인 ath9k의 소스코드를 고치고 있는데,아무리 봐도 내가 원하는 기능을 해당 코드에서 달성할 수 없는 것 같다. 디바이스 드라이버(device driver) 레벨보다 더 하위 레벨로 내려가야 할 것 같아서 찾아보니, 내가 갖고 있는 USB 랜카드(TP-LINK TL-WN722N)는 htc_9271.fw 라는 이름의 펌웨어를 쓴다는 것을 알게 되었다.


해당 펌웨어의 소스코드가 있는지 찾아 보니, 반갑게도 Qualcomm Atheros에서 htc 9271 펌웨어 소스코드를 오픈소스로 git에 올려 놓았다.


아래와 같은 순서대로 하면 ath9k 펌웨어 개발 환경을 얻을 수 있다. (주의사항: ath9k 디바이스 드라이버와는 다르다. 디바이스 드라이버는 compat-wireless 소스코드를 받아서 빌드해야 한다.)



1. Git에서 소스코드 다운받기 (https://github.com/qca/open-ath9k-htc-firmware)

 $ git clone https://github.com/qca/open-ath9k-htc-firmware



2. make 명령으로 toolchain 다운받고 설치하기

 $ cd ./open-ath9k-htc-firmware

 $ make toolchain

(한참 걸린다. 약 30분~1시간)



3. Firmware 빌드하기 

(참고로 cmake가 필요하다. 없으면 sudo apt-get install cmake 로 설치하자.)

 $ make -C target_firmware

(그리 오래 걸리지 않는다.)



4. open-ath9k-htc-firmware/target_firmware 디렉토리에 .fw 파일이 생성되어 있으면 빌드 성공.

htc_9271.fw 파일을 /lib/firmware/ 에 복사한 뒤에, 기존에 설치된 ath9k_htc 커널 모듈을 지우고 재설치한다.

$ sudo cp htc_9271.fw /lib/firmware/

$ sudo rmmod ath9k_htc

$ sudo modprobe ath9k_htc





반응형
블로그 이미지

Bryan_

,
반응형

OS: Ubuntu 계열 (11.04 32bit, 12.04 64bit 에서 테스트)

무선랜카드: IPTIME N150UA (Ralink RT2870/RT3070 칩셋)



<문제의  배경>

  • Ubuntu 시스템에서 실험을 목적으로 무선랜(Wi-Fi) 디바이스 드라이버(device driver) 코드를 수정하고 재설치하기 위해 compat-wireless-3.6.8-1 의 소스코드를 수정하였다.
  • 개발의 대상이 되는 디바이스 드라이버는 Atheros 계열의 ath9k와 ath9k-htc였고, 이에 따라 compat-wireless 소스코드에서 컴파일 대상을 ath9k로 한정지었다.
    ( $ ./scripts/driver-select ath9k )
  • 저렇게 설정하고 나서 compat-wireless를 컴파일하면($ sudo make install), 원래 Ubuntu에 들어 있던 네트워크 관련 커널모듈을 전부 교체해 버리게 된다. 즉, mac80211, cfg80211과 같이 리눅스에서 무선랜 제어에 사용하는 공통 커널 모듈까지 교체된다는 얘기.
  • 문제는 컴파일 대상 디바이스가 ath9k로 한정되는 바람에 Atheros ath9k 칩셋이 아닌 다른 USB 무선랜카드 (e.g. Ralink 계열, Broadcom 계열 등)는 인식을 못하는 경우가 생긴다.



<문제 상황>

ath9k 디바이스 드라이버를 개발하기 전에 쓰던 USB 무선랜카드는 IPTIME N150UA였다. compat-wireless 개발환경을 사용하고 나서 해당 무선랜카드를 PC에 꽂으니 커널 출력 메세지(dmesg 또는 /var/log/kern.log)에서 아래와 같이 수많은 기능들을 이해할 수 없다는 에러를 뿌린다.

$ dmesg

[338283.992800] usb 1-1.1: new high-speed USB device number 11 using ehci_hcd

[338284.102160] usb 1-1.1: New USB device found, idVendor=148f, idProduct=3070

[338284.102165] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3

[338284.102168] usb 1-1.1: Product: 802.11 n WLAN

[338284.102171] usb 1-1.1: Manufacturer: Ralink

[338284.102173] usb 1-1.1: SerialNumber: 1.0

[338284.122269] Compat-wireless backport release: compat-wireless-v3.6.8-1

[338284.122273] Backport based on linux-stable.git v3.6.8

[338284.122274] compat.git: linux-stable.git

[338284.124318] cfg80211: Calling CRDA to update world regulatory domain

[338284.129011] rt2x00lib: disagrees about version of symbol ieee80211_register_hw

[338284.129016] rt2x00lib: Unknown symbol ieee80211_register_hw (err -22)

[338284.129022] rt2x00lib: disagrees about version of symbol ieee80211_get_hdrlen_from_skb

[338284.129024] rt2x00lib: Unknown symbol ieee80211_get_hdrlen_from_skb (err -22)

[338284.129031] rt2x00lib: disagrees about version of symbol ieee80211_wake_queue

[338284.129033] rt2x00lib: Unknown symbol ieee80211_wake_queue (err -22)

[338284.129039] rt2x00lib: disagrees about version of symbol ieee80211_get_buffered_bc

[338284.129041] rt2x00lib: Unknown symbol ieee80211_get_buffered_bc (err -22)

[338284.129048] rt2x00lib: disagrees about version of symbol wiphy_rfkill_set_hw_state

[338284.129050] rt2x00lib: Unknown symbol wiphy_rfkill_set_hw_state (err -22)

[338284.129060] rt2x00lib: disagrees about version of symbol ieee80211_queue_delayed_work

[338284.129061] rt2x00lib: Unknown symbol ieee80211_queue_delayed_work (err -22)

[338284.129065] rt2x00lib: disagrees about version of symbol wiphy_rfkill_stop_polling

[338284.129066] rt2x00lib: Unknown symbol wiphy_rfkill_stop_polling (err -22)

[338284.129069] rt2x00lib: disagrees about version of symbol ieee80211_ctstoself_get

[338284.129071] rt2x00lib: Unknown symbol ieee80211_ctstoself_get (err -22)

[338284.129081] rt2x00lib: disagrees about version of symbol ieee80211_rx

[338284.129083] rt2x00lib: Unknown symbol ieee80211_rx (err -22)

[338284.129088] rt2x00lib: disagrees about version of symbol ieee80211_iterate_active_interfaces

[338284.129090] rt2x00lib: Unknown symbol ieee80211_iterate_active_interfaces (err -22)

[338284.129093] rt2x00lib: disagrees about version of symbol ieee80211_free_txskb

[338284.129095] rt2x00lib: Unknown symbol ieee80211_free_txskb (err -22)

[338284.129102] rt2x00lib: disagrees about version of symbol ieee80211_tx_status

[338284.129104] rt2x00lib: Unknown symbol ieee80211_tx_status (err -22)

[338284.129107] rt2x00lib: disagrees about version of symbol ieee80211_stop_queue

[338284.129109] rt2x00lib: Unknown symbol ieee80211_stop_queue (err -22)

[338284.129112] rt2x00lib: disagrees about version of symbol ieee80211_stop_queues

[338284.129114] rt2x00lib: Unknown symbol ieee80211_stop_queues (err -22)

[338284.129119] rt2x00lib: disagrees about version of symbol wiphy_rfkill_start_polling

[338284.129121] rt2x00lib: Unknown symbol wiphy_rfkill_start_polling (err -22)

[338284.129124] rt2x00lib: disagrees about version of symbol ieee80211_iterate_active_interfaces_atomic

[338284.129126] rt2x00lib: Unknown symbol ieee80211_iterate_active_interfaces_atomic (err -22)

[338284.129134] rt2x00lib: disagrees about version of symbol ieee80211_channel_to_frequency

[338284.129136] rt2x00lib: Unknown symbol ieee80211_channel_to_frequency (err -22)

[338284.129139] rt2x00lib: disagrees about version of symbol ieee80211_unregister_hw

[338284.129140] rt2x00lib: Unknown symbol ieee80211_unregister_hw (err -22)

[338284.129146] rt2x00lib: disagrees about version of symbol ieee80211_beacon_get_tim

[338284.129148] rt2x00lib: Unknown symbol ieee80211_beacon_get_tim (err -22)

[338284.129150] rt2x00lib: disagrees about version of symbol ieee80211_rts_get

[338284.129152] rt2x00lib: Unknown symbol ieee80211_rts_get (err -22)

[338284.129159] rt2x00lib: disagrees about version of symbol ieee80211_queue_work

[338284.129161] rt2x00lib: Unknown symbol ieee80211_queue_work (err -22)

[338284.130166] cfg80211: World regulatory domain updated:

[338284.130170] cfg80211:   (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)

[338284.130173] cfg80211:   (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)

[338284.130175] cfg80211:   (2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)

[338284.130177] cfg80211:   (2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)

[338284.130179] cfg80211:   (5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)

[338284.130180] cfg80211:   (5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)

$


USB 연결에는 이상이 없는지 확인해 보니 USB 장치 수준에서는 제대로 인식을 하고 있다.

$ lsusb

Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub

Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

Bus 001 Device 012: ID 148f:3070 Ralink Technology, Corp. RT2870/RT3070 Wireless Adapter

$




<해결 방법>

원인이 명확하게 Compat-wireless 개발환경이기 때문에 해결 방법은 간단하다.

Ralink 계열도 이해할 수 있도록 ath9k 뿐만 아니라 다른 모든 칩셋의 소스코드를 다 컴파일하면 된다. 그러면 다른 칩셋 계열의 기능을 이해할 수 있는 mac80211, cfg80211 커널 모듈이 새로 생성되고, 이들이 자동으로 시스템의 /lib/modules/ 에 복사된다.


  (먼저 compat-wireless 개발환경의 최상위 디렉토리로 이동한다.)

$ ./scripts/driver-select restore    <-- 소스코드 전체를 컴파일하도록 기본 설정으로 되돌림

$ sudo make install

  (모든 칩셋을 다 컴파일하기 때문에 성능이 안좋은 PC에서는 꽤 긴 시간이 걸린다.)


$ sudo make wlunload      <-- 기존에 로드된 무선네트워크 관련 모듈을 unload 시킨다.


위와 같이 하고 나서 USB 디바이스 드라이버에 해당하는 모듈을 sudo modprobe를 이용해서 load한다. (예: $ sudo modprobe rt2800usb) 콘솔 화면에서 무슨 모듈이 unload되었는지 확인하고 그것들을 다시 load하면 되는데, 무엇을 load해야 할 지 잘 모르는 경우가 있을 수도 있다. 

그럴 때는 USB 무선랜카드를 뽑았다가 다시 PC에 꽂으면 된다또는 깔끔하게 재부팅하는 것도 좋은 방법이다.





반응형
블로그 이미지

Bryan_

,