이더넷 PHY (Physical Layer)
이더넷 PHY는 MAC이 만든 프레임을 실제 전기·광 신호로 바꾸고, 반대로 선로에서 들어온 신호를 디지털 비트스트림으로 복원하는 계층입니다. 이 문서는 PHY의 역할과 계층 경계, MDIO 레지스터 접근, Clause 22/45와 MMD, phylib/phylink 수명주기, 분리형 PCS와 phylink_pcs, SerDes/SFP, EEE·downshift·EDPD·FEC 같은 기능 튜닝, Device Tree와 보드 bring-up, 신호 무결성, 링크 장애 디버깅 절차를 커널 드라이버와 하드웨어 설계 관점에서 최대한 상세히 정리합니다.
핵심 요약
- PHY — MAC과 실제 매체 사이에서 부호화, 클럭 복구, 신호 송수신, 링크 감지를 담당하는 계층입니다.
- MDIO — MAC이나 SoC가 PHY 레지스터를 읽고 쓰는 관리 버스입니다. Clause 22와 Clause 45 두 주소 모델이 있습니다.
- phylib — 커널의 공통 PHY 프레임워크로,
phy_device와phy_driver를 통해 링크 상태 머신을 운영합니다. - phylink — MAC, PHY, PCS, SFP, fixed-link를 하나의 정책 계층으로 묶어 주는 상위 프레임워크입니다.
- phy-mode — RGMII, SGMII, 1000BASE-X 같은 MAC-PHY 인터페이스 모드를 뜻하며, 이 설정이 틀리면 링크는 올라와도 CRC 오류와 속도 강등이 생길 수 있습니다.
단계별 이해
- PHY가 어디까지 담당하는지 구분하기
MAC은 프레임을 만들고, PHY는 그 프레임을 선로에 맞는 신호로 바꿉니다. PCS/PMA/PMD 경계를 먼저 잡아야 로그와 보드 문제를 분리할 수 있습니다. - MDIO로 상태를 읽는 법 익히기
링크 업 여부, PHY ID, 광고 능력, RGMII 지연 같은 핵심 정보는 대부분 MDIO 레지스터에서 확인합니다. PHY 디버깅의 기본은 레지스터 관찰입니다. - 커널 수명주기 이해하기
probe에서 attach하고, open에서phy_start()혹은phylink_start()를 호출하며, 링크 변화 시 MAC 재설정 콜백이 들어오는 흐름을 따라가야 합니다. - 보드와 링크 장애를 함께 점검하기
phy-mode, reset GPIO, 클럭, 전원, 케이블, 상대편 광고 능력을 같이 봐야 합니다. PHY 문제는 드라이버 버그와 보드 타이밍 문제가 자주 섞여 나타납니다.
개요
이더넷 PHY의 핵심 임무는 세 가지입니다. 첫째, MAC이 제공한 병렬 또는 직렬 디지털 데이터를 선로 규격에 맞는 전기·광 신호로 변환합니다. 둘째, 상대편 장치와 링크 속도, 듀플렉스, pause, FEC 같은 능력을 협상합니다. 셋째, 온도·전압·신호 품질 변화에 따라 CDR(Clock and Data Recovery), equalization, amplitude 설정을 조정해 실제 배선 위에서 동작하도록 만듭니다.
즉 PHY는 단순한 "포트"가 아니라, 아날로그 회로와 디지털 상태 머신이 결합된 독립 장치입니다. 링크가 안 올라오거나 CRC가 증가할 때는 소프트웨어만 볼 일이 아니라, PHY 내부 지연 보상, reference clock, magnetics, 케이블 품질, 상대편 포트의 협상 정책까지 같이 봐야 합니다.
Link detected: yes가 찍힌다고 PHY 문제가 끝난 것이 아닙니다.
링크 업 이후에도 CRC 증가, carrier error, EEE 복귀 지연, 잘못된 speed/duplex 합의, RGMII skew 오류가 남을 수 있으므로 "업 여부"와 "링크 품질"을 반드시 분리해서 봐야 합니다.
MAC과 PHY의 경계
문제를 빨리 좁히려면 "어디까지가 MAC이고 어디부터 PHY인가"를 먼저 구분해야 합니다. MAC은 프레임 헤더, 주소 필터, pause 처리, DMA와 큐를 담당하고, PHY는 부호화/직렬화/클럭 복구/매체 송수신을 맡습니다. 1G 이하 임베디드 보드에서는 MAC과 외부 PHY가 RGMII로 연결되는 경우가 많고, 서버 NIC에서는 MAC/PCS가 SoC나 NIC 내부에 있고 외부 모듈은 PMD 역할만 하는 경우도 흔합니다.
| 구성 요소 | 주요 책임 | 대표 증상 | 점검 포인트 |
|---|---|---|---|
| MAC | 프레임 조립, 주소 필터, DMA, pause, 통계 | queue hang, TX timeout, 잘못된 offload | net_device, DMA 링, IRQ, NAPI |
| MAC-PHY 인터페이스 | RGMII/SGMII 등 디지털 링크 | 속도 강등, CRC, 불안정한 링크 | phy-mode, skew, clock, in-band status |
| PHY PCS/PMA | 부호화, AN, 직렬화, CDR | 링크 미협상, symbol error | MDIO 레지스터, 광고 능력, 벤더 확장 레지스터 |
| PMD/매체 | 전기·광 신호, magnetics, 커넥터 | 거리 민감, 케이블 교체 시 개선 | 케이블, 모듈, 커넥터, 온도, 전원 품질 |
- MDIO는 제어면입니다. 데이터 패킷은 RGMII/SGMII 같은 MAC-PHY 인터페이스를 지나고, 설정과 상태 조회만 MDIO를 통합니다.
- PCS와 PMA는 종종 MAC 안에도 존재합니다. 특히 10G 이상 SerDes 기반 장비에서는 PHY가 외부 칩이 아니라 모듈이나 PMD 수준으로 축소될 수 있습니다.
- 링크 품질 문제는 경계에 걸쳐 나타납니다. 잘못된
phy-mode는 MAC 로그로 보이고, 원인은 PHY 내부 지연 혹은 PCB 스큐일 수 있습니다.
PHY 내부 하위 계층
이더넷 PHY를 깊게 이해하려면 PHY를 단일 칩으로 보지 말고 PCS, PMA, PMD, MDI로 나눠 생각해야 합니다. 1000BASE-T 같은 구리 PHY는 PCS에서 부호화와 auto-negotiation control word 처리를 하고, PMA/PMD에서 echo cancellation, NEXT/FEXT 제거, adaptive equalization, timing recovery 같은 DSP 처리를 수행합니다. 반면 광 링크는 PMD가 레이저 드라이버, CDR, 광 수신기와 더 강하게 결합됩니다.
즉 "링크가 안 붙는다"는 하나의 증상도 PCS 문제인지, PMA의 CDR lock 실패인지, PMD의 광 세기 부족인지, MDI 쪽 배선 문제인지에 따라 전혀 다른 디버깅 절차가 필요합니다. 초기에 이 구분을 해 두면 드라이버와 보드 설계 문제를 훨씬 빠르게 분리할 수 있습니다.
| 하위 계층 | 주요 역할 | 구리 PHY 구현 예 | 광/SerDes 구현 예 | 문제 징후 |
|---|---|---|---|---|
| PCS | 부호화, 스크램블링, AN control word 처리 | 1000BASE-T 4D-PAM5 심볼 처리 준비 | 8B/10B, 64B/66B, block lock | 협상 실패, block lock 불가 |
| PMA | 직렬화, 클럭 복구, lane 정렬 | ADC/DAC와 DSP 사이 timing recovery | SerDes, CDR, lane deskew | 링크 flap, symbol error |
| PMD | 실제 매체 송수신 | magnetics, hybrid, echo cancellation | laser/TIA, 광 세기, DAC/AOC | 거리 민감, 온도 민감, CRC 증가 |
| MDI | 커넥터와 매체 접점 | RJ45, 트위스트 페어 | LC 커넥터, backplane, DAC | 케이블 교체 시 증상 변화 |
MDIO와 표준 레지스터
MDIO는 PHY를 설정하고 상태를 읽는 가장 기본적인 관리 경로입니다. 10/100/1000 PHY에서는 Clause 22가, 고속 PHY와 복잡한 서브블록을 가진 장치에서는 Clause 45가 많이 쓰입니다. Clause 22는 5비트 PHY 주소와 5비트 레지스터 번호만 다루지만, Clause 45는 MMD(devad) 개념을 도입해 PMA/PCS/AN 등 기능 블록별 레지스터 공간을 분리합니다.
| 모드 | 주소 구조 | 적용 범위 | 특징 |
|---|---|---|---|
| Clause 22 | PHY 주소 5비트 + 레지스터 5비트 | 주로 1G 이하 PHY | 구조가 단순하고 기본 상태 조회에 적합 |
| Clause 45 | PHY 주소 + MMD(devad) + 16비트 레지스터 | 10G 이상, 복합 PHY | PMA/PCS/AN/FEC를 블록별로 분리해 접근 |
| 레지스터 | Clause 22 주소 | 의미 | 실무 활용 |
|---|---|---|---|
| BMCR | 0x00 | reset, speed select, duplex, autoneg enable | 강제 속도/듀플렉스 설정 여부 확인 |
| BMSR | 0x01 | link, autoneg capable, autoneg complete | 링크 업과 협상 완료 여부 점검 |
| PHYID1 | 0x02 | 벤더 OUI 상위 비트 | PHY 모델 식별 |
| PHYID2 | 0x03 | OUI 하위 비트 + 모델/리비전 | 드라이버 매칭 검증 |
| ANAR / ANLPAR | 0x04 / 0x05 | 광고 능력 / 상대편 응답 | 속도, pause, duplex 불일치 원인 파악 |
# 네트워크 인터페이스가 어떤 PHY에 연결되었는지 확인
readlink -f /sys/class/net/eth0/phydev
# MDIO 버스에 보이는 PHY 목록과 ID 확인
grep . /sys/bus/mdio_bus/devices/*/phy_id
# 기본 링크 정보와 광고 능력 확인
ethtool eth0
# 드라이버가 찍는 PHY 로그 확인
dmesg | grep -i -E "phy|mdio|link"
ethtool 출력과 함께 비교하는 습관이 필요합니다.
Clause 45와 MMD 주소 공간
Clause 45의 핵심은 PHY를 하나의 납작한 레지스터 맵으로 보지 않고, 기능 블록별 MMD(Manageable Device)로 나누는 데 있습니다. 10G 이상 PHY나 복합 SerDes는 PMA/PMD, PCS, Auto-Negotiation, vendor-specific 블록이 분리되어 있어야 디버깅과 기능 확장이 가능합니다. 리눅스 커널도 이를 mdiobus_c45_read() 같은 API와 MDIO_MMD_* 매크로로 반영합니다.
| devad | MMD 이름 | 대표 내용 | 실무 활용 |
|---|---|---|---|
| 1 | PMA/PMD | signal detect, PMD control, optical/copper 특성 | 광 세기, lane signal, 전기 특성 확인 |
| 2 | WIS | WAN 인터페이스 하위 계층 | 특수 WAN PHY에서 사용 |
| 3 | PCS | block lock, fault, PCS status | SerDes lock, alignment, fault 분리 |
| 4 | PHY XS | PHY 확장 SerDes 계층 | 고속 lane 상태 확인 |
| 5 | DTE XS | DTE 쪽 확장 SerDes | 호스트 측 lane 진단 |
| 6 | TC | transmission convergence | 특정 고속 PHY 구현에서 사용 |
| 7 | Auto-Negotiation | AN control/status, next page | 고속 AN 실패 원인 분석 |
| 30/31 | Vendor 1/2 | 벤더 확장 기능 | RGMII delay, downshift, 온도 센서, patch RAM |
/* 개념 예시: Clause 45 MMD 직접 읽기 */
struct mii_bus *bus = phydev->mdio.bus;
int phy_addr = phydev->mdio.addr;
/* PCS status 1 */
int pcs_stat = mdiobus_c45_read(bus, phy_addr, MDIO_MMD_PCS, 0x0001);
/* AN status 1 */
int an_stat = mdiobus_c45_read(bus, phy_addr, MDIO_MMD_AN, 0x0001);
/* 벤더 확장 레지스터 */
int vend = mdiobus_c45_read(bus, phy_addr, MDIO_MMD_VEND1, 0x8050);
MDIO 버스 토폴로지와 다중 PHY
실제 보드에서는 PHY가 하나만 있는 경우보다, 하나의 MDIO 버스에 여러 PHY와 스위치 내부 포트 PHY, retimer, 별도 PCS, SFP 관리 장치가 함께 매달리는 경우가 더 많습니다. MDIO는 I2C처럼 주소 기반 공유 버스이므로, 주소 충돌과 버스 길이, pull-up, reset 순서를 동시에 관리해야 합니다. 보드 bring-up에서 PHY 하나는 보이고 나머지는 안 보인다면 드라이버보다 먼저 버스 토폴로지를 확인해야 합니다.
특히 스위치 칩은 외부 포트의 copper PHY와 별개로 내부 포트용 PHY 또는 PCS를 또 가지고 있을 수 있습니다. 이 경우 운영체제는 "인터페이스 하나당 PHY 하나"라고 단순화해서 볼 수 없고, MDIO 버스 아래에 여러 개의 mdio_device와 phy_device가 계층적으로 배치됩니다. 주소가 겹치거나 reset 순서가 꼬이면 전혀 다른 장치에 레지스터를 쓰는 사고가 발생할 수 있습니다.
| 토폴로지 | 구성 예 | 장점 | 흔한 문제 |
|---|---|---|---|
| 단일 버스 + 단일 PHY | SoC MAC ↔ 외부 RJ45 PHY | 가장 단순, bring-up 쉬움 | 주소 실수, reset 타이밍 |
| 단일 버스 + 다중 PHY | 듀얼 포트 보드, 4포트 PHY | 배선 단순화 | 주소 충돌, 전원 순서, 버스 부하 |
| 버스 뒤에 스위치/DSA | CPU MAC ↔ 스위치 ↔ 포트 PHY들 | 포트 확장 용이 | 내부 MDIO 주소 맵 이해 필요 |
| MDIO mux/게이트 | 백플레인 슬롯별 PHY 선택 | 주소 재사용 가능 | mux 선택 상태와 reset 순서 꼬임 |
| MAC PCS + 외부 PHY 혼합 | host PCS는 MAC 내부, copper PHY는 외부 | SerDes와 copper 분리 가능 | PCS와 PHY 상태를 따로 해석해야 함 |
/* 개념 예시: 하나의 MDIO 버스에 다중 PHY가 매달린 경우 */
&mdio0 {
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@1 {
reg = <1>;
};
phy1: ethernet-phy@2 {
reg = <2>;
};
switch0: ethernet-switch@10 {
reg = <0x10>;
};
};
- 주소는 0..31 범위만 있으므로, 슬롯 구조에서는 물리적으로 같은 주소를 재사용하고 mux로 분리하는 설계가 흔합니다.
- 0xffff / 0x0000 읽힘이 한 포트에서만 발생하면 전체 드라이버보다 해당 포트의 reset, pull-up, mux 선택 상태를 먼저 의심하세요.
- DSA 스위치가 개입되면 CPU 포트용 PCS, 사용자 포트용 PHY, 내부 MDIO 주소 맵을 각각 분리해서 이해해야 합니다.
PHY 탐지와 링크 수명주기
커널 관점에서 PHY 수명주기는 "발견, attach, 광고 설정, 상태 머신 시작, 링크 변화 통지, stop"의 반복입니다. probe 단계에서는 PHY 노드를 찾고 드라이버를 매칭합니다. 인터페이스가 올라갈 때는 phy_start() 또는 phylink_start()가 상태 머신을 돌리고, 링크가 변하면 드라이버는 speed, duplex, pause, interface mode를 MAC에 다시 적용해야 합니다.
- 발견 —
phy-handle또는 firmware node를 통해 PHY를 찾고 ID를 읽어 드라이버를 매칭합니다. - attach —
of_phy_connect()또는 phylink 연결 함수로 MAC과 PHY를 연결합니다. - 정책 설정 — 지원 속도, EEE, pause, advertisement, in-band status 정책을 설정합니다.
- 상태 머신 시작 — 인터페이스 up 시 PHY state machine이 주기적으로 링크를 확인합니다.
- 링크 변화 통지 —
adjust_link혹은mac_link_up()경로에서 MAC 레지스터가 재설정됩니다. - 정지 — 인터페이스 down 시 queue 정지 후 PHY polling 또는 IRQ를 멈춥니다.
/* 개념 예시: phylib attach와 링크 수명주기 */
static void my_adjust_link(struct net_device *ndev)
{
struct phy_device *phydev = ndev->phydev;
if (!phydev->link) {
my_mac_link_down(ndev);
return;
}
my_mac_link_up(ndev, phydev->speed, phydev->duplex);
}
static int my_probe(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct device_node *phy_np;
struct phy_device *phydev;
phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
if (!phy_np)
return -ENODEV;
phydev = of_phy_connect(ndev, phy_np, &my_adjust_link, 0,
PHY_INTERFACE_MODE_RGMII_ID);
of_node_put(phy_np);
if (!phydev)
return -ENODEV;
phy_set_max_speed(phydev, SPEED_1000);
phy_attached_info(phydev);
return 0;
}
static int my_open(struct net_device *ndev)
{
phy_start(ndev->phydev);
netif_start_queue(ndev);
return 0;
}
static int my_stop(struct net_device *ndev)
{
netif_stop_queue(ndev);
phy_stop(ndev->phydev);
return 0;
}
리눅스 커널 객체 모델
리눅스에서 PHY 관련 코드를 읽을 때는 mii_bus, mdio_device, phy_device, phy_driver, phylink, net_device가 어떤 관계인지 먼저 잡아야 합니다. mii_bus는 실제 MDIO 컨트롤러이고, phy_device는 그 버스 위에 매달린 PHY 인스턴스, phy_driver는 특정 PHY ID에 매칭되는 동작 구현, phylink는 MAC과 PHY 사이 정책 오케스트레이터입니다.
| 객체 | 대표 소유자 | 핵심 역할 | 어디서 자주 보나 |
|---|---|---|---|
mii_bus | MAC/SoC 드라이버 | MDIO read/write/reset 제공 | MDIO 컨트롤러 probe |
mdio_device | MDIO 코어 | 버스 위 디바이스 공통 래퍼 | PHY 이외 MDIO 장치 |
phy_device | phylib | 링크 상태, 광고 능력, 인터페이스 모드 보유 | phydev->link, speed, duplex |
phy_driver | 벤더 PHY 드라이버 | config_init, config_aneg, read_status 구현 | drivers/net/phy/ |
phylink | MAC 드라이버 | MAC/PHY/PCS/SFP 정책 통합 | SFP, fixed-link, in-band status |
net_device | MAC 드라이버 | 유저스페이스와 커널 네트워크 스택 진입점 | eth0 링크 관리 |
/* 개념 예시: PHY 관련 커널 객체의 대표 필드 */
struct mii_bus {
char id[MII_BUS_ID_SIZE];
int (*read)(...);
int (*write)(...);
int (*reset)(...);
struct device *parent;
};
struct phy_device {
struct mdio_device mdio;
phy_interface_t interface;
int link;
int speed;
int duplex;
int pause;
int asym_pause;
int irq;
linkmode_t supported;
linkmode_t advertising;
linkmode_t lp_advertising;
};
struct phy_driver {
u32 phy_id;
u32 phy_id_mask;
const char *name;
int (*config_init)(...);
int (*config_aneg)(...);
int (*read_status)(...);
irqreturn_t (*handle_interrupt)(...);
};
PHY 드라이버 콜백을 어디까지 구현해야 하나
많은 PHY는 genphy_config_aneg(), genphy_read_status() 같은 공통 헬퍼만으로도 동작합니다. 하지만 RGMII 지연, downshift, EEE, LED, strap override, 온도 센서, FEC 정책처럼 벤더 확장 기능이 필요한 경우에는 전용 콜백 구현이 필요합니다.
| 콜백 | 언제 필요한가 | 대표 작업 |
|---|---|---|
config_init | probe 직후 초기 설정 | strap 보정, 지연 모드, 기본 LED 정책 |
config_aneg | 광고 능력 커스터마이즈 | EEE/FEC/downshift/속도 제한 |
read_status | 링크 상태 해석이 벤더별로 다름 | speed/duplex/pause, master/slave 반영 |
handle_interrupt | IRQ 기반 PHY | 링크 변화 인터럽트 처리 |
suspend/resume | 저전력 운용 필요 | WoL, EEE, analog power gating |
/* 개념 예시: 벤더 페이지 전환 레지스터 접근 패턴 */
static int myphy_set_rgmii_delay(struct phy_device *phydev)
{
int oldpage, ret;
oldpage = phy_select_page(phydev, 0xd08);
if (oldpage < 0)
return oldpage;
ret = phy_modify(phydev, 0x11, 0x0300, 0x0200);
return phy_restore_page(phydev, oldpage, ret);
}
Auto-Negotiation
Auto-Negotiation은 "링크 업" 자체보다 "어떤 모드로 링크를 올릴지"를 결정하는 규칙입니다. 구리 PHY에서는 FLP(Fast Link Pulse) 기반 Clause 28이 기본이고, SerDes 기반 인터페이스에서는 Clause 37이나 Clause 73의 in-band status가 많이 쓰입니다. 현대 장비는 속도뿐 아니라 pause, FEC, EEE, master/slave 역할까지 협상에 포함할 수 있습니다.
| 규격 | 주요 대상 | 교환 방식 | 실무 포인트 |
|---|---|---|---|
| Clause 28 | 10/100BASE-T | FLP burst | 기본 페이지로 speed/duplex/pause 광고 |
| Clause 37 | 1000BASE-X, SGMII | 8B/10B in-band | SerDes 링크와 MAC 상태 동기화 |
| Clause 73 | 백플레인, 10G 이상 | base page + next page | FEC, lane 특성, 고속 backplane와 결합 |
autoneg off로 고정하면 상대편이 평행 감지(parallel detect)로 링크를 올리면서 duplex를 잘못 해석할 수 있습니다.
이런 경우 링크는 올라오지만 late collision, carrier error, 심한 처리량 저하가 발생합니다. 양쪽 정책을 반드시 짝으로 맞추세요.
# 현재 링크 협상 결과
ethtool eth0
# 자동 협상 끄고 강제 설정
ethtool -s eth0 speed 1000 duplex full autoneg off
# EEE 상태 확인
ethtool --show-eee eth0
# 링크 업/다운 이벤트 실시간 감시
ip monitor link
협상 디버깅에서 중요한 것은 "로컬이 무엇을 광고했고 상대편이 무엇을 응답했는가"입니다. 단순히 속도 결과만 보면 중간 원인을 놓칩니다. 예를 들어 2.5G 포트가 1G로만 붙는다면 케이블 품질 문제일 수도 있지만, 상대편의 advertisement mask가 1G까지만 켜져 있는 정책 문제일 수도 있습니다.
MAC-PHY 인터페이스 모드
phy-mode는 매체 종류가 아니라 MAC과 PHY 사이의 디지털 인터페이스 계약을 뜻합니다. 이 값이 틀리면 링크가 아예 안 올라오거나, 올라와도 CRC와 symbol error가 폭증합니다. 특히 RGMII 계열은 지연 보상 위치를 명확히 해야 하고, SGMII/1000BASE-X/2500BASE-X는 in-band status 처리 여부까지 맞아야 합니다.
| 모드 | 형태 | 주요 속도 | 핵심 주의점 |
|---|---|---|---|
| MII / RMII | 병렬 | 10/100M | 저속 임베디드, 핀 수와 기준 클럭 확인 |
| GMII / RGMII | 병렬 | 1G | RGMII는 2ns 지연을 한 곳에서만 추가 |
| SGMII / QSGMII | 직렬 SerDes | 1G, 4x1G | in-band status와 PCS 설정 동기화 |
| 1000BASE-X / 2500BASE-X | 직렬 SerDes | 1G, 2.5G | 광 모듈, switch port, PCS 모드 일치 필요 |
| USXGMII | 직렬 SerDes | 10/5/2.5/1G | 멀티기가비트 통합, MAC과 PHY 모두 지원 필요 |
rgmii는 내부 지연 없음, rgmii-id는 TX/RX 둘 다 PHY가 지연, rgmii-txid와 rgmii-rxid는 한 방향만 PHY가 지연한다는 뜻입니다.
PCB 지연을 이미 넣은 설계에서 rgmii-id를 추가로 쓰면 이중 지연이 발생합니다.
SerDes, PCS, SFP 모듈
구리 RJ45 PHY만 생각하면 PHY를 외부 칩 하나로 이해하기 쉽지만, 실제 장비에서는 host PCS, SerDes lane, SFP cage, 모듈 내부 PHY 또는 광 PMD가 나뉘어 있을 수 있습니다. 특히 1000BASE-X와 SGMII는 비슷한 1.25Gbaud 직렬 링크처럼 보여도 control word 의미와 in-band status 해석이 달라, 모드를 잘못 맞추면 링크 LED는 켜져도 실제 프레임 송수신이 안 될 수 있습니다.
| 모드 | 주요 대상 | baud / lane | 협상/상태 전달 | 주의점 |
|---|---|---|---|---|
| SGMII | MAC ↔ 외부 PHY | 1.25Gbaud, 1 lane | in-band status, speed code | 속도 표시는 control word에 실림 |
| 1000BASE-X | 광 모듈, 스위치 업링크 | 1.25Gbaud, 1 lane | Clause 37 AN | SGMII와 전기적 속도는 비슷해도 의미가 다름 |
| 2500BASE-X | 2.5G SerDes | 3.125Gbaud, 1 lane | 장치별 운용 차이 존재 | 양단 PCS 설정 일치 필요 |
| QSGMII | 4포트 집적 PHY | 5Gbaud, 1 lane | 4개 포트 상태 다중화 | 포트 분리 해석 필요 |
| USXGMII | 멀티기가비트 | 10.3125Gbaud, 1 lane | 10/5/2.5/1G 다중화 | MAC/PHY 둘 다 지원해야 의미 있음 |
- 광 모듈은 주로 PMD 성격이 강하고, host 쪽 PCS와 SerDes 설정이 맞아야 링크가 정상입니다.
- RJ45 copper SFP는 안에 별도 copper PHY가 들어 있어 발열, 전력, latency 특성이 일반 광 모듈과 다릅니다.
- LOS/TX_FAULT/MOD_ABS는 MDIO가 아니라 모듈 sideband 신호인 경우가 많습니다. PHY 레지스터만 봐서는 원인을 못 찾을 수 있습니다.
SFP sideband 신호를 같이 봐야 하는 이유
광 모듈 문제는 MDIO만으로 보이지 않는 경우가 많습니다. 모듈이 스스로 올리는 LOS, TX_FAULT, MOD_ABS, TX_DISABLE 같은 sideband는 host PCS와 phylink 정책에 직접 영향을 줍니다. 즉 광량과 DOM은 정상인데도 sideband 한 줄이 반대로 연결되어 전체 링크가 막힐 수 있습니다.
| 신호 | 의미 | 보통 누가 해석하나 | 문제 시 증상 |
|---|---|---|---|
MOD_ABS | 모듈 삽입 여부 | SFP 코어 / phylink | 모듈이 꽂혀도 미삽입으로 보임 |
LOS | 수신 광 신호 손실 | host 드라이버 / 모듈 상태기 | 광량은 있는데 링크 down 반복 |
TX_FAULT | 송신 레이저 fault | host 드라이버 | 송신만 불가, fault latched |
TX_DISABLE | 송신 레이저 비활성화 | host 제어 | 모듈은 인식되지만 원격 링크 없음 |
RATE_SELECT | 속도/이퀄라이저 선택 | host와 모듈 조합 | 특정 속도에서만 불안정 |
phylib과 phylink
phylib은 "PHY 칩을 커널이 공통 방식으로 다루기 위한 프레임워크"이고, phylink는 "MAC, PHY, PCS, fixed-link, SFP를 하나의 정책으로 묶는 상위 계층"입니다. 외부 PHY 하나를 단순히 연결하는 임베디드 보드라면 phylib만으로 충분할 수 있지만, SFP 모듈 핫플러그나 in-band status, 고속 SerDes가 얽히면 phylink가 사실상 표준 선택입니다.
| 항목 | phylib | phylink |
|---|---|---|
| 주요 대상 | 외부 PHY 직접 연결 | MAC + PHY + PCS + SFP 조합 |
| 핵심 구조체 | phy_device, phy_driver | phylink, phylink_config, phylink_mac_ops |
| 장점 | 단순하고 익숙함 | fixed-link, SFP, in-band status 통합 |
| 주의점 | 복합 토폴로지 대응이 약함 | MAC 콜백 계약을 정확히 구현해야 함 |
/* 개념 예시: PHY 드라이버가 구현하는 핵심 콜백 */
static int myphy_config_init(struct phy_device *phydev);
static int myphy_config_aneg(struct phy_device *phydev);
static int myphy_read_status(struct phy_device *phydev);
static struct phy_driver myphy_driver = {
.phy_id = 0x001cc916,
.phy_id_mask = 0xfffffff0,
.name = "Example PHY",
.config_init = myphy_config_init,
.config_aneg = myphy_config_aneg,
.read_status = myphy_read_status,
};
/* 개념 예시: phylink 초기화와 firmware 기반 PHY 연결 */
static const struct phylink_mac_ops my_phylink_ops = {
.mac_config = my_mac_config,
.mac_link_up = my_mac_link_up,
.mac_link_down = my_mac_link_down,
};
static int my_phylink_init(struct my_priv *priv)
{
struct phylink_config *cfg = &priv->phylink_config;
struct fwnode_handle *fwnode = dev_fwnode(priv->dev);
phy_interface_t iface = priv->phy_mode;
priv->phylink = phylink_create(cfg, fwnode, iface, &my_phylink_ops);
if (IS_ERR(priv->phylink))
return PTR_ERR(priv->phylink);
if (is_of_node(fwnode))
return phylink_of_phy_connect(priv->phylink, to_of_node(fwnode), 0);
return phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
}
phylink를 도입하면 링크 업/다운 알림, SFP 모듈 감지, PCS 선택, fixed-link 해석을 한 계층에서 정리할 수 있습니다. 반대로 mac_config(), mac_link_up(), mac_link_down() 구현이 느슨하면 링크는 오르는데 실제 MAC 레지스터가 이전 속도를 유지하는 문제가 생길 수 있습니다.
분리형 PCS와 In-Band Status
고속 SerDes 기반 설계에서는 PHY가 모든 계층을 혼자 담당하지 않습니다. host MAC 안에 별도 PCS가 있고, 외부에는 PMA/PMD 성격이 강한 장치만 있거나, 반대로 외부 PHY는 있지만 링크 상태 결정은 host PCS가 수행하는 경우가 있습니다. 이때 커널은 단순한 phy_device만으로는 부족하고, phylink_pcs를 통해 "MAC 옆의 PCS"를 별도 객체로 다뤄야 합니다.
실무적으로는 SGMII, 1000BASE-X, 2500BASE-X, 10GBASE-R에서 이 구분이 중요합니다. 외부 copper PHY가 속도 협상을 끝냈더라도, host PCS가 그 결과를 in-band status로 받아 MAC 속도를 다시 맞추지 않으면 실제 데이터 경로가 잘못된 속도로 남을 수 있습니다.
| 구성 | 누가 상태를 결정하나 | phylink 역할 | 실수하기 쉬운 점 |
|---|---|---|---|
| RGMII + 외부 PHY | 외부 PHY | PHY 결과를 MAC에 전달 | phy-mode와 지연 설정 불일치 |
| SGMII + 외부 PHY + host PCS | 외부 PHY와 host PCS 둘 다 | PCS와 PHY 결과 동기화 | in-band status 미적용 |
| 1000BASE-X + SFP | host PCS와 모듈 상태 | 모듈 삽입, LOS, Clause 37 AN 조정 | SGMII와 의미 혼동 |
| fixed-link + host PCS | firmware 고정값 | MAC 설정만 적용 | 고정 링크인데도 AN 기대 |
| backplane + Clause 73 | host PCS/AN 블록 | FEC와 lane 정책 조정 | FEC 강제/자동 혼선 |
/* 개념 예시: 분리형 PCS를 phylink에 등록 */
static void my_pcs_get_state(struct phylink_pcs *pcs,
struct phylink_link_state *state)
{
/* host PCS의 block lock, speed code, duplex 상태 해석 */
}
static const struct phylink_pcs_ops my_pcs_ops = {
.pcs_get_state = my_pcs_get_state,
.pcs_config = my_pcs_config,
.pcs_an_restart = my_pcs_restart_an,
.pcs_link_up = my_pcs_link_up,
};
static int my_mac_select_pcs(struct phylink_config *config,
phy_interface_t interface)
{
return interface == PHY_INTERFACE_MODE_SGMII ? 0 : 0;
}
/* SFP/SerDes 경로에서 host PCS가 in-band status를 읽는 예시 */
ð0 {
phy-mode = "sgmii";
managed = "in-band-status";
sfp = <&sfp0>;
status = "okay";
};
fixed-link, managed = "in-band-status", 외부 PHY attach는 같은 포트에서 역할이 다릅니다.
고정 링크인데도 in-band status를 기대하거나, host PCS가 속도를 결정하는데 외부 PHY 결과만 믿으면 MAC 속도가 이전 값에 남아 실제 송수신이 어긋날 수 있습니다.
PHY 기능과 튜닝 포인트
PHY는 단순히 링크를 올리는 장치가 아니라, 운영 중 성능과 안정성을 좌우하는 여러 정책을 가집니다. 저전력 중심이면 EEE가 중요하고, 긴 케이블과 구형 배선이면 downshift와 cable diagnostics가 유용하며, 고속 광링크에서는 FEC 선택이 BER과 latency를 좌우합니다. 튜닝은 "항상 켠다/끈다"가 아니라 증상과 환경에 따라 선택해야 합니다.
| 기능 | 무엇을 하나 | 언제 점검하나 | 대표 명령 | 주의점 |
|---|---|---|---|---|
| EEE | 유휴 시 LPI로 전력 절감 | idle 후 첫 패킷 지연, link flap | ethtool --show-eee eth0 | 저지연 환경에서 불리할 수 있음 |
| Downshift | 고속 협상 실패 시 낮은 속도로 폴백 | 2.5G/5G가 자주 1G로 떨어짐 | ethtool --set-phy-tunable eth0 downshift on count 3 | 배선 문제를 가릴 수 있음 |
| Master/Slave | 1000BASE-T 기준 클럭 소스 결정 | 특정 스위치와 협상 불안정 | ethtool eth0 | 한쪽만 강제하면 오히려 문제 |
| Cable Test | TDR 기반 배선 진단 | 구리선 품질 의심 | ethtool --cable-test eth0 | PHY 지원 필요 |
| FEC | 고속 링크 비트 오류 정정 | 25G+/광 링크 BER 높음 | ethtool --show-fec eth0 | 약간의 지연 증가 가능 |
| Loopback | MAC/PHY 내부 경로 단독 검사 | 상대편 없이 자체 진단 | 벤더 레지스터 또는 self-test | 트래픽 경로 일부만 검증 |
# EEE 상태 조회와 비활성화
ethtool --show-eee eth0
ethtool --set-eee eth0 eee off
# Downshift 정책 설정 (지원 PHY만)
ethtool --set-phy-tunable eth0 downshift on count 3
# 케이블 테스트 (지원 PHY만)
ethtool --cable-test eth0
# FEC 상태 조회
ethtool --show-fec eth0
Master/Slave, downshift, EDPD를 함께 읽기
1000BASE-T 이상 구리 PHY에서는 링크 양단이 기준 클럭 제공자를 정해야 합니다. 이것이 master/slave 결정입니다. 동시에 배선 품질이 좋지 않으면 고속 협상에 반복 실패하고, 그 결과 downshift가 작동해 낮은 속도로만 링크가 붙습니다. 여기서 EDPD(Energy Detect Power Down)가 섞이면 idle 상태에서 PHY가 더 깊게 잠들었다가 복귀하면서 협상이 늦어지는 증상이 나타날 수 있습니다.
| 항목 | 좋은 경우 | 나쁜 경우 | 주로 보이는 증상 |
|---|---|---|---|
| Master/Slave | 자동 결정 또는 양단 일관 설정 | 한쪽만 강제 | 간헐적 협상 실패, 재협상 반복 |
| Downshift | 불량 배선에서 폴백 안전장치 | 원인 숨김 | 2.5G 장비가 계속 1G로만 링크 업 |
| EDPD | 유휴 전력 절감 | 상대편과 복귀 정책 불일치 | idle 후 첫 링크 업 지연 |
| EEE | 지속 유휴 구간에서 전력 절감 | 낮은 지연 요구와 충돌 | burst 트래픽에서 변동 지연 |
# PHY 튜너블 조회
ethtool --show-phy-tunable eth0
# 에너지 감지 파워다운 설정 (지원 PHY만)
ethtool --set-phy-tunable eth0 energy-detect-power-down on
Loopback과 자가 진단을 계층별로 분리하기
루프백은 "상대편 없이 내 경로만 검증"하는 가장 빠른 방법이지만, 어느 계층에서 되돌리는지에 따라 검증 범위가 달라집니다. MAC loopback은 MAC과 DMA까지만 확인하고, PCS loopback은 host PCS와 SerDes 일부까지, PHY loopback은 PMA/PMD까지 포함할 수 있습니다. 반대로 외부 케이블과 원격 포트는 빠지므로, 루프백이 통과했다고 실제 배선 문제가 사라지는 것은 아닙니다.
- MAC loopback
DMA, descriptor, netdev 경로를 빠르게 검증합니다. - PCS loopback
SerDes encoding과 block lock 경로를 좁혀 봅니다. - PHY 내부 loopback
외부 케이블 없이 PHY 내부 DSP 경로를 확인합니다. - 원격 loopback
상대편 장비가 지원할 때 전체 선로까지 포함한 검증이 가능합니다.
PHY 하드웨어 타임스탬프와 시간 민감 네트워크
일부 PHY는 MAC보다 더 선로 가까운 위치에서 송수신 타임스탬프를 찍을 수 있습니다. 이런 PHY는 PTP(IEEE 1588)나 TSN 환경에서 유리할 수 있는데, 패킷이 실제 wire를 통과한 시점에 더 가까운 시각을 얻을 수 있기 때문입니다. 다만 시스템 전체에서는 MAC 쪽 PHC와 PHY 쪽 타임스탬프 경로를 혼동하지 않아야 하며, 사용자 공간에서는 결국 SO_TIMESTAMPING과 ethtool -T로 노출된 능력으로 보게 됩니다.
| 위치 | 장점 | 주의점 | 대표 점검 |
|---|---|---|---|
| MAC 타임스탬프 | 드라이버 통합이 단순 | 선로 기준과 약간 거리 있음 | ethtool -T eth0 |
| PHY 타임스탬프 | wire-side 기준에 더 가까움 | PHY와 MAC의 clock domain 정렬 필요 | driver timestamp capability |
| 소프트웨어 타임스탬프 | 지원 폭 넓음 | 지연/지터 큼 | SO_TIMESTAMPING fallback |
# 인터페이스의 HW timestamping / PHC 지원 확인
ethtool -T eth0
PHY 인터럽트, 폴링, 전원 관리
PHY 상태 머신은 크게 폴링과 인터럽트 두 방식으로 링크 변화를 감시합니다. 폴링은 단순하고 안정적이지만 변화 감지가 느리고, 인터럽트는 빠르지만 마스크/ack 처리와 공유 IRQ 문제를 정확히 구현해야 합니다. 모바일·임베디드 장치에서는 여기에 suspend/resume, Wake-on-LAN, EEE, EDPD가 더해져 "전원이 꺼져 있을 때 PHY를 어디까지 살릴 것인가"가 추가 과제가 됩니다.
| 주제 | 핵심 API/개념 | 장점 | 위험 요소 |
|---|---|---|---|
| 폴링 | phy_start(), 상태 머신 주기 점검 | 구현 단순, IRQ 불필요 | 감지 지연, 불필요한 MDIO 트래픽 |
| 인터럽트 | handle_interrupt, phy_trigger_machine() | 링크 변화 즉시 반응 | ack 누락, IRQ storm, 공유 선 문제 |
| suspend/resume | suspend, resume | 전력 절감 | refclk/strap 재초기화 누락 |
| Wake-on-LAN | magic packet, PHY 유지 전원 | 저전력 대기에서 원격 기동 | analog rail 완전 차단 시 실패 |
| EDPD/EEE | LPI, energy detect | 유휴 전력 절감 | 복귀 지연, flap 오인 |
/* 개념 예시: IRQ 기반 PHY 링크 감지 */
static irqreturn_t myphy_handle_interrupt(struct phy_device *phydev)
{
int irq_stat;
irq_stat = phy_read(phydev, 0x13);
if (irq_stat < 0)
return IRQ_NONE;
/* 벤더 IRQ status를 읽어 clear 한 뒤 상태 머신 재실행 */
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
static int myphy_suspend(struct phy_device *phydev)
{
/* WoL, EEE, EDPD 정책에 따라 analog block 일부만 유지 */
return genphy_suspend(phydev);
}
static int myphy_resume(struct phy_device *phydev)
{
int ret = genphy_resume(phydev);
if (ret)
return ret;
/* resume 뒤 strap override와 delay bit를 다시 써야 하는 PHY도 있다 */
return myphy_set_rgmii_delay(phydev);
}
- IRQ가 있다고 항상 좋은 것은 아닙니다. 링크 변화가 잦은 환경에서는 잘못된 인터럽트 마스크가 오히려 CPU를 더 흔듭니다.
- resume 뒤 재설정이 필요한 PHY가 있습니다. strap 결과를 runtime에서 override한 경우 특히 resume에서 다시 써야 합니다.
- WoL을 켜려면 PHY analog rail과 magic packet 검출 경로를 살려야 하므로, 단순 regulator off와 충돌할 수 있습니다.
Device Tree와 보드 설계 포인트
보드 bring-up에서는 커널 코드보다 Device Tree와 하드웨어 배선이 더 자주 문제를 일으킵니다. PHY 주소가 틀리거나, reset GPIO hold 시간이 부족하거나, 25MHz reference clock이 안정되기 전에 MDIO 접근이 시작되면 드라이버는 정상이어도 PHY를 못 찾습니다. 특히 RGMII는 내부 지연과 PCB trace delay를 어느 한 곳에서만 넣어야 합니다.
/* 보드 .dts 예시: 외부 RGMII PHY 연결 */
&emac {
pinctrl-names = "default";
pinctrl-0 = <&ext_rgmii_pins>;
phy-mode = "rgmii-id";
phy-handle = <&ext_rgmii_phy>;
phy-supply = <®_gmac_3v3>;
status = "okay";
};
&mdio {
ext_rgmii_phy: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>;
reset-assert-us = <15000>;
reset-deassert-us = <40000>;
};
};
strap pin과 reset 시퀀싱을 따로 점검하기
많은 PHY는 reset 해제 순간 strap pin을 샘플링해 주소, RGMII delay 기본값, LED 모드, SGMII/Fiber 선택 같은 초기 동작을 결정합니다. 이때 LED 핀과 strap 핀이 겸용인 설계가 흔해서, pull-up/pull-down 세기와 reset 폭이 기대와 조금만 어긋나도 PHY는 전혀 다른 모드로 부팅할 수 있습니다. 소프트웨어가 나중에 override할 수 있어도, 부팅 초기에 이미 잘못된 주소와 모드로 올라오면 MDIO 탐지부터 실패할 수 있습니다.
| strap 항목 | 잘못 샘플링되면 | 흔한 단서 | 대응 |
|---|---|---|---|
| PHY 주소 | 다른 주소로 부팅 | 기대 주소에서 0xffff | pull 저항과 reset 타이밍 재검토 |
| RGMII delay 기본값 | 내부 지연 on/off 반전 | 1G CRC 폭증 | strap 상태와 runtime override 둘 다 확인 |
| fiber / copper 선택 | 잘못된 매체 모드 | 링크 LED 동작이 이상함 | strap 조합과 보드 옵션 확인 |
| LED 모드 | LED 핀 동작 혼선 | 링크는 되는데 LED만 오작동 | strap 겸용 핀 배치 재검토 |
| 항목 | 왜 중요한가 | 실패 시 증상 |
|---|---|---|
phy-handle / PHY 주소 | 올바른 PHY 노드와 연결 | probe 실패, 잘못된 PHY 드라이버 매칭 |
phy-mode | MAC-PHY 인터페이스 계약 일치 | 링크 불안정, CRC, 속도 강등 |
| reset 타이밍 | strap pin, clock 안정화 보장 | PHY ID가 0xffff로 읽힘 |
| 전원 / regulator | 아날로그 블록 안정성 확보 | 온도 민감, 링크 flapping |
| reference clock | PMA/CDR 기준 클럭 | autoneg 실패, symbol error |
보드 Bring-up 체크리스트
외부 PHY가 달린 보드를 처음 올릴 때는 "드라이버가 로드됐는가"보다 "PHY가 물리적으로 살아 있는가"부터 확인해야 합니다. bring-up 초반에는 MDIO 읽기가 성공하는지만으로도 절반은 해결된 상태입니다. 이후에는 reset 타이밍, strap pin, 지연 보상, 상대편 링크 정책, 실제 트래픽 품질 순서로 범위를 좁히는 것이 좋습니다.
| 단계 | 무엇을 확인하나 | 성공 기준 | 실패 시 다음 행동 |
|---|---|---|---|
| 1. 전원 | PHY rail, analog rail, module power | 전압 안정, brown-out 없음 | regulator 순서와 power-good 재검토 |
| 2. 기준 클럭 | 25MHz/50MHz/refclk 존재 | 오실로스코프에서 안정적 파형 | clock source, pinmux 확인 |
| 3. reset/strap | reset 폭, strap 샘플링 타이밍 | 예상 PHY 주소와 모드로 부팅 | reset-assert/deassert 시간 조정 |
| 4. MDIO 스캔 | PHY ID 읽기, 버스 접근 | 정상 OUI/모델 읽힘 | PHY 주소, MDIO pull-up, bus mux 확인 |
| 5. 링크 정책 | phy-mode, advertisement, fixed-link | 예상 속도와 duplex 협상 | 양단 설정 비교 |
| 6. 트래픽 | CRC, drops, EEE/LPI | 오류 카운터 안정 | RGMII 지연, 케이블, EEE 검토 |
| 7. 스트레스 | 열, idle/wake, 장시간 안정성 | link flap 없음 | 전원 margin, 온도, 모듈 교체 테스트 |
외부 PHY가 없는 경우: fixed-link
스위치 CPU 포트나 백플레인처럼 외부 PHY가 없이 PCS/SerDes만 존재하는 경우에는 phy-handle 대신 fixed-link를 사용하기도 합니다. 이 경우 MDIO로 읽을 PHY가 없으므로, 링크 정책과 상태 전달을 MAC/phylink 계층에서 처리해야 합니다.
/* 외부 PHY 없이 고정 링크를 선언하는 예시 */
ð0 {
phy-mode = "sgmii";
fixed-link {
speed = <1000>;
full-duplex;
pause;
};
};
신호 무결성과 보드 레이아웃
PHY 문서가 소프트웨어 쪽으로만 흘러가기 쉽지만, 실제로는 보드 레이아웃이 링크 품질을 절반 이상 좌우합니다. 특히 RGMII 병렬 버스는 각 신호의 도착 시간 차이가 중요하고, SerDes는 임피던스와 return path, via stub, refclk 품질이 더 중요합니다. 같은 드라이버가 어떤 보드에서는 완벽하고 다른 보드에서는 CRC를 뿜는 이유가 여기에 있습니다.
중요한 점은 "숫자 하나"를 외우는 것이 아니라, PHY 데이터시트와 PCB stack-up, 커넥터 배치, 전원 분리 전략을 함께 보는 것입니다. RGMII는 지연 위치가 핵심이고, SGMII/USXGMII는 차동쌍 품질과 refclk 지터, 광 모듈 경로는 cage 접지와 전력 예산이 중요합니다.
| 항목 | 왜 중요한가 | 나빠질 때 보이는 현상 | 실무 점검 포인트 |
|---|---|---|---|
| RGMII 길이 매칭 | 125MHz DDR 타이밍 여유 확보 | 1G에서만 CRC, 100M은 정상 | 지연을 PCB와 PHY 중 한 곳만 부여 |
| refclk 품질 | PMA/CDR 기준 안정성 | 협상 불안정, symbol error | 클럭 소스, 전원 노이즈, jitter budget |
| SerDes 차동쌍 | 임피던스와 손실 관리 | block lock 불안정, BER 증가 | 차동 간격, via 수, return path 연속성 |
| magnetics 배치 | 구리 포트 절연과 잡음 억제 | 거리 민감, ESD 이후 링크 저하 | RJ45 근접 배치, center tap 전원/접지 검토 |
| 전원 decoupling | 아날로그 프런트엔드 안정화 | 온도 의존 링크 flap | analog/digital rail 분리와 근접 캐패시터 |
| SFP cage 접지 | EMI와 모듈 안정성 | 모듈별 편차, hot-plug 불안정 | cage 접지, 전력 예산, sideband pull-up |
대표 장애 패턴과 원인 분리
PHY 문제는 반복적으로 비슷한 모양으로 나타납니다. 아래 패턴을 외워 두면 "드라이버 버그인지, 보드 타이밍인지, 상대편 정책인지"를 빨리 구분할 수 있습니다.
패턴 1: 100M은 되는데 1G에서만 CRC가 폭증
가장 흔한 원인은 RGMII 지연 위치 오류입니다. 100M에서는 타이밍 margin이 커서 버티지만, 1G에서는 125MHz DDR 경계가 매우 빡빡해져 CRC와 carrier error가 늘어납니다. 이 경우 케이블을 바꿔도 개선이 거의 없고, phy-mode를 바꾸거나 PHY 내부 delay bit를 조정하면 즉시 달라집니다.
패턴 2: 수 분 간격으로 링크가 내려갔다 올라온다
EEE, 전원 품질, 열, 상대편 스위치 호환성 중 하나일 가능성이 큽니다. idle 상태에서만 재현되면 EEE를 먼저 끄고, 부하를 걸면 사라지면 전원 rail 또는 module thermal 문제일 가능성이 있습니다. dmesg에 일정 간격으로 link down/up이 반복되면 소프트웨어보다는 물리 계층이나 협상 정책 쪽을 더 의심하는 편이 맞습니다.
패턴 3: PHY ID가 0xffff 또는 0x0000으로 읽힌다
이 경우는 대부분 MDIO 자체가 실패하거나 PHY가 reset에서 아직 나오지 않았다는 뜻입니다. 잘못된 PHY 주소, MDC/MDIO pull-up 불량, reset deassert 지연 부족, refclk 부재를 우선 확인하세요. 드라이버를 아무리 바꿔도 PHY ID가 안 읽히면 소프트웨어 문제일 확률은 낮습니다.
패턴 4: SGMII와 1000BASE-X를 바꾸면 링크 LED만 반응하고 데이터는 안 흐른다
전기적 속도만 같다고 프로토콜 의미까지 같은 것은 아닙니다. SGMII는 speed code와 duplex 상태를 control word에 담고, 1000BASE-X는 Clause 37 의미를 따릅니다. 양단의 PCS 의미 체계가 다르면 block lock은 되더라도 유효 프레임 처리가 안 될 수 있습니다.
패턴 5: RJ45 SFP 모듈만 유난히 뜨겁고 링크 품질이 나쁘다
RJ45 SFP는 작은 폼팩터 안에 copper PHY와 magnetics 상당 부분을 넣기 때문에 열 여유가 매우 작습니다. 일부 스위치나 NIC는 전력 예산 때문에 copper SFP를 제한하기도 합니다. 광 모듈에서는 멀쩡한 포트가 copper SFP만 꽂으면 불안정해진다면 모듈 발열과 host cage 전원 budget을 의심하세요.
패턴 6: 부팅 직후는 정상인데 suspend/resume 뒤 링크가 나빠진다
resume 경로에서 PHY strap override, RGMII delay bit, host PCS mode, 모듈 sideband 초기화가 다시 적용되지 않는 경우가 많습니다. 특히 부팅 때만 실행한 config_init에 핵심 설정을 몰아 넣으면, resume 뒤에는 기본 strap 값으로 돌아가 CRC나 속도 강등이 다시 나타날 수 있습니다.
패턴 7: 같은 보드인데 슬롯이나 포트 하나만 간헐적으로 안 보인다
이 경우는 PHY 드라이버보다 MDIO mux, shared reset, 주소 재사용 구조를 먼저 봐야 합니다. 특정 슬롯에서만 PHY ID가 0xffff로 튄다면 해당 슬롯의 mux 선택선, pull-up, hot-plug reset 타이밍이 가장 유력합니다. 동일한 드라이버가 다른 슬롯에서는 멀쩡하다는 사실이 중요한 단서입니다.
패턴 8: fixed-link로는 되는데 in-band status로 바꾸면 링크가 흐트러진다
보통은 host PCS가 speed code와 duplex 상태를 제대로 읽지 못하거나, 반대로 양단이 AN 의미를 서로 다르게 해석하고 있다는 뜻입니다. fixed-link는 문제가 가려진 상태일 수 있으므로, 실제 목표 토폴로지가 in-band status라면 PCS와 SerDes 설정을 끝까지 맞춰야 합니다.
패턴 9: 광량은 정상인데 LOS가 계속 올라와 링크가 안 오른다
SFP 계열에서는 PHY 레지스터보다 cage sideband가 더 중요할 때가 있습니다. LOS, TX_FAULT, MOD_ABS pull-up 전압이 맞지 않거나 극성이 뒤집히면 광 모듈 자체는 정상이어도 host는 계속 fault 상태로 판단합니다. 이 경우 ethtool -m으로 DOM이 정상인데 링크만 안 오른다는 모순된 모습이 나옵니다.
트러블슈팅
PHY 장애는 "링크가 안 오른다", "링크는 오르는데 품질이 나쁘다", "부팅 직후만 실패한다" 세 부류로 나누면 정리가 쉽습니다. 첫 번째는 Device Tree, reset, PHY 주소, 케이블, 상대편 광고 능력부터 확인합니다. 두 번째는 phy-mode, RGMII 지연, EEE, FEC, 온도, 모듈 품질로 좁힙니다. 세 번째는 부팅 순서와 전원 안정화, strap pin, clock ready 타이밍 문제일 가능성이 큽니다.
| 증상 | 가능한 원인 | 즉시 확인할 것 | 다음 조치 |
|---|---|---|---|
| PHY를 전혀 찾지 못함 | 잘못된 PHY 주소, reset 타이밍 부족, 전원 미인가 | dmesg, /sys/bus/mdio_bus/devices | PHY 주소와 reset GPIO, regulator 순서 점검 |
| 링크 업 안 됨 | 상대편 포트 정책, 케이블, advertisement 불일치 | ethtool eth0 | 양쪽 autoneg 정책과 케이블 등급 확인 |
| 링크 업 후 CRC 증가 | RGMII skew, 신호 품질, magnetics 문제 | ethtool -S eth0 | phy-mode와 보드 지연 위치 재검토 |
| 2.5G/5G가 1G로만 붙음 | 케이블 품질, 상대편 광고 제한 | supported/advertised link modes | Cat5e/Cat6 등급과 상대편 설정 확인 |
| 온도 올라가면 링크 flapping | 전원 품질, 모듈 열화, 아날로그 margin 부족 | 온도 로그, 모듈 DOM | 전원 rail, 방열, PHY 벤더 권장값 적용 |
# 1. 기본 링크 요약
ethtool eth0
# 2. NIC/드라이버 통계에서 물리 계층 오류 확인
ethtool -S eth0 | grep -E "crc|align|carrier|symbol|an|eee"
# 3. 현재 netdev가 어떤 PHY에 연결되어 있는지 추적
readlink -f /sys/class/net/eth0/phydev
# 4. 커널 로그에서 MDIO / PHY 이벤트 추적
dmesg | grep -i -E "phy|mdio|link|eee"
# 5. Device Tree의 phy-mode 확인
grep -R . /sys/firmware/devicetree/base | grep phy-mode
# 6. PHY 튜너블과 EDPD/downshift 확인
ethtool --show-phy-tunable eth0
# 7. 지원 시 케이블 TDR 진단
ethtool --cable-test-tdr eth0
# 8. SFP DOM / 광량 확인
ethtool -m eth0
커널 디버그 훅 활용
PHY 문제를 깊게 보려면 ethtool 출력만으로는 부족할 때가 있습니다. 이때는 동적 디버그, 드라이버별 register dump, 모듈 DOM, 장시간 링크 이벤트 로그를 조합해 "협상 실패인지, 품질 문제인지, 전원 복귀 문제인지"를 분리합니다. 특히 phylib는 공통 상태 머신을 쓰므로, 공통 로그와 벤더 드라이버 로그를 같이 보는 것이 좋습니다.
# 동적 디버그가 켜진 커널에서 PHY 공통 로그 활성화
echo 'file drivers/net/phy/* +p' > /sys/kernel/debug/dynamic_debug/control
# 특정 MAC 드라이버 로그도 함께 활성화
echo 'file drivers/net/ethernet/*/* +p' > /sys/kernel/debug/dynamic_debug/control
# 드라이버가 지원하면 MAC/PHY 레지스터 덤프
ethtool -d eth0
# 인터페이스 링크 이벤트 감시
ip monitor link
| 도구 | 무엇을 보기 좋나 | 언제 쓰나 |
|---|---|---|
ethtool | 링크 정책, 통계, EEE, FEC, 케이블 테스트 | 가장 먼저 |
dmesg | probe, reset, link flap, SFP 이벤트 | 부팅 직후 실패 |
| dynamic debug | phylib 상태 머신과 벤더 드라이버 상세 로그 | 간헐 재현, resume 이슈 |
ethtool -m | 광 모듈 DOM, 온도, RX/TX power | 광 링크 품질 문제 |
ethtool -d | 드라이버 제공 레지스터 덤프 | 벤더 드라이버 비교 |
실전 점검 순서
- PHY가 존재하는지
/sys/bus/mdio_bus/devices와 PHY ID부터 봅니다. - 링크 정책이 맞는지
ethtool eth0에서 speed, duplex, advertisement, pause를 확인합니다. - 오류가 물리 계층인지
ethtool -S에서 CRC, align, symbol, carrier 카운터를 봅니다. - 보드 타이밍 문제인지
phy-mode, RGMII delay, reset timing, clock 안정성을 점검합니다. - 상대편 의존 문제인지
스위치 포트, 모듈, 케이블, 강제 속도 설정을 바꿔 증상이 이동하는지 확인합니다.
참고자료
- 이더넷 (Ethernet)
- Network Device 드라이버 (net_device)
- ethtool 심화
- Device Tree
- DSA Tagging
- Linux kernel networking PHY documentation
- 이더넷 (Ethernet) — PHY가 전체 이더넷 설계 안에서 어디에 위치하는지 다시 연결
- Network Device 드라이버 — MAC 쪽 링크 콜백과 큐 제어 계약 이해
- ethtool 심화 — 운영 환경에서 링크 정책과 통계를 읽는 방법