kernel/net/phy.rs
1// SPDX-License-Identifier: GPL-2.0
2
3// Copyright (C) 2023 FUJITA Tomonori <fujita.tomonori@gmail.com>
4
5//! Network PHY device.
6//!
7//! C headers: [`include/linux/phy.h`](srctree/include/linux/phy.h).
8
9use crate::{device_id::RawDeviceId, error::*, prelude::*, types::Opaque};
10use core::{marker::PhantomData, ptr::addr_of_mut};
11use safety_macro::safety;
12pub mod reg;
13
14/// PHY state machine states.
15///
16/// Corresponds to the kernel's [`enum phy_state`].
17///
18/// Some of PHY drivers access to the state of PHY's software state machine.
19///
20/// [`enum phy_state`]: srctree/include/linux/phy.h
21#[derive(PartialEq, Eq)]
22pub enum DeviceState {
23 /// PHY device and driver are not ready for anything.
24 Down,
25 /// PHY is ready to send and receive packets.
26 Ready,
27 /// PHY is up, but no polling or interrupts are done.
28 Halted,
29 /// PHY is up, but is in an error state.
30 Error,
31 /// PHY and attached device are ready to do work.
32 Up,
33 /// PHY is currently running.
34 Running,
35 /// PHY is up, but not currently plugged in.
36 NoLink,
37 /// PHY is performing a cable test.
38 CableTest,
39}
40
41/// A mode of Ethernet communication.
42///
43/// PHY drivers get duplex information from hardware and update the current state.
44pub enum DuplexMode {
45 /// PHY is in full-duplex mode.
46 Full,
47 /// PHY is in half-duplex mode.
48 Half,
49 /// PHY is in unknown duplex mode.
50 Unknown,
51}
52
53/// An instance of a PHY device.
54///
55/// Wraps the kernel's [`struct phy_device`].
56///
57/// A [`Device`] instance is created when a callback in [`Driver`] is executed. A PHY driver
58/// executes [`Driver`]'s methods during the callback.
59///
60/// # Invariants
61///
62/// - Referencing a `phy_device` using this struct asserts that you are in
63/// a context where all methods defined on this struct are safe to call.
64/// - This struct always has a valid `self.0.mdio.dev`.
65///
66/// [`struct phy_device`]: srctree/include/linux/phy.h
67// During the calls to most functions in [`Driver`], the C side (`PHYLIB`) holds a lock that is
68// unique for every instance of [`Device`]. `PHYLIB` uses a different serialization technique for
69// [`Driver::resume`] and [`Driver::suspend`]: `PHYLIB` updates `phy_device`'s state with
70// the lock held, thus guaranteeing that [`Driver::resume`] has exclusive access to the instance.
71// [`Driver::resume`] and [`Driver::suspend`] also are called where only one thread can access
72// to the instance.
73#[repr(transparent)]
74pub struct Device(Opaque<bindings::phy_device>);
75
76impl Device {
77 /// Creates a new [`Device`] instance from a raw pointer.
78 ///
79 /// # Safety
80 ///
81 /// For the duration of `'a`,
82 /// - the pointer must point at a valid `phy_device`, and the caller
83 /// must be in a context where all methods defined on this struct
84 /// are safe to call.
85 /// - `(*ptr).mdio.dev` must be a valid.
86 #[safety{Typed(ptr, phy_device), ValidInstance("(*ptr).mdio.dev")}]
87 unsafe fn from_raw<'a>(ptr: *mut bindings::phy_device) -> &'a mut Self {
88 // CAST: `Self` is a `repr(transparent)` wrapper around `bindings::phy_device`.
89 let ptr = ptr.cast::<Self>();
90 // SAFETY: by the function requirements the pointer is valid and we have unique access for
91 // the duration of `'a`.
92 unsafe { &mut *ptr }
93 }
94
95 /// Gets the id of the PHY.
96 pub fn phy_id(&self) -> u32 {
97 let phydev = self.0.get();
98 // SAFETY: The struct invariant ensures that we may access
99 // this field without additional synchronization.
100 unsafe { (*phydev).phy_id }
101 }
102
103 /// Gets the state of PHY state machine states.
104 pub fn state(&self) -> DeviceState {
105 let phydev = self.0.get();
106 // SAFETY: The struct invariant ensures that we may access
107 // this field without additional synchronization.
108 let state = unsafe { (*phydev).state };
109 // TODO: this conversion code will be replaced with automatically generated code by bindgen
110 // when it becomes possible.
111 match state {
112 bindings::phy_state_PHY_DOWN => DeviceState::Down,
113 bindings::phy_state_PHY_READY => DeviceState::Ready,
114 bindings::phy_state_PHY_HALTED => DeviceState::Halted,
115 bindings::phy_state_PHY_ERROR => DeviceState::Error,
116 bindings::phy_state_PHY_UP => DeviceState::Up,
117 bindings::phy_state_PHY_RUNNING => DeviceState::Running,
118 bindings::phy_state_PHY_NOLINK => DeviceState::NoLink,
119 bindings::phy_state_PHY_CABLETEST => DeviceState::CableTest,
120 _ => DeviceState::Error,
121 }
122 }
123
124 /// Gets the current link state.
125 ///
126 /// It returns true if the link is up.
127 pub fn is_link_up(&self) -> bool {
128 const LINK_IS_UP: u64 = 1;
129 // TODO: the code to access to the bit field will be replaced with automatically
130 // generated code by bindgen when it becomes possible.
131 // SAFETY: The struct invariant ensures that we may access
132 // this field without additional synchronization.
133 let bit_field = unsafe { &(*self.0.get())._bitfield_1 };
134 bit_field.get(14, 1) == LINK_IS_UP
135 }
136
137 /// Gets the current auto-negotiation configuration.
138 ///
139 /// It returns true if auto-negotiation is enabled.
140 pub fn is_autoneg_enabled(&self) -> bool {
141 // TODO: the code to access to the bit field will be replaced with automatically
142 // generated code by bindgen when it becomes possible.
143 // SAFETY: The struct invariant ensures that we may access
144 // this field without additional synchronization.
145 let bit_field = unsafe { &(*self.0.get())._bitfield_1 };
146 bit_field.get(13, 1) == u64::from(bindings::AUTONEG_ENABLE)
147 }
148
149 /// Gets the current auto-negotiation state.
150 ///
151 /// It returns true if auto-negotiation is completed.
152 pub fn is_autoneg_completed(&self) -> bool {
153 const AUTONEG_COMPLETED: u64 = 1;
154 // TODO: the code to access to the bit field will be replaced with automatically
155 // generated code by bindgen when it becomes possible.
156 // SAFETY: The struct invariant ensures that we may access
157 // this field without additional synchronization.
158 let bit_field = unsafe { &(*self.0.get())._bitfield_1 };
159 bit_field.get(15, 1) == AUTONEG_COMPLETED
160 }
161
162 /// Sets the speed of the PHY.
163 pub fn set_speed(&mut self, speed: u32) {
164 let phydev = self.0.get();
165 // SAFETY: The struct invariant ensures that we may access
166 // this field without additional synchronization.
167 unsafe { (*phydev).speed = speed as c_int };
168 }
169
170 /// Sets duplex mode.
171 pub fn set_duplex(&mut self, mode: DuplexMode) {
172 let phydev = self.0.get();
173 let v = match mode {
174 DuplexMode::Full => bindings::DUPLEX_FULL,
175 DuplexMode::Half => bindings::DUPLEX_HALF,
176 DuplexMode::Unknown => bindings::DUPLEX_UNKNOWN,
177 };
178 // SAFETY: The struct invariant ensures that we may access
179 // this field without additional synchronization.
180 unsafe { (*phydev).duplex = v as c_int };
181 }
182
183 /// Reads a PHY register.
184 // This function reads a hardware register and updates the stats so takes `&mut self`.
185 pub fn read<R: reg::Register>(&mut self, reg: R) -> Result<u16> {
186 reg.read(self)
187 }
188
189 /// Writes a PHY register.
190 pub fn write<R: reg::Register>(&mut self, reg: R, val: u16) -> Result {
191 reg.write(self, val)
192 }
193
194 /// Reads a paged register.
195 pub fn read_paged(&mut self, page: u16, regnum: u16) -> Result<u16> {
196 let phydev = self.0.get();
197 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
198 // So it's just an FFI call.
199 let ret = unsafe { bindings::phy_read_paged(phydev, page.into(), regnum.into()) };
200
201 to_result(ret).map(|()| ret as u16)
202 }
203
204 /// Resolves the advertisements into PHY settings.
205 pub fn resolve_aneg_linkmode(&mut self) {
206 let phydev = self.0.get();
207 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
208 // So it's just an FFI call.
209 unsafe { bindings::phy_resolve_aneg_linkmode(phydev) };
210 }
211
212 /// Executes software reset the PHY via `BMCR_RESET` bit.
213 pub fn genphy_soft_reset(&mut self) -> Result {
214 let phydev = self.0.get();
215 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
216 // So it's just an FFI call.
217 to_result(unsafe { bindings::genphy_soft_reset(phydev) })
218 }
219
220 /// Initializes the PHY.
221 pub fn init_hw(&mut self) -> Result {
222 let phydev = self.0.get();
223 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
224 // So it's just an FFI call.
225 to_result(unsafe { bindings::phy_init_hw(phydev) })
226 }
227
228 /// Starts auto-negotiation.
229 pub fn start_aneg(&mut self) -> Result {
230 let phydev = self.0.get();
231 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
232 // So it's just an FFI call.
233 to_result(unsafe { bindings::_phy_start_aneg(phydev) })
234 }
235
236 /// Resumes the PHY via `BMCR_PDOWN` bit.
237 pub fn genphy_resume(&mut self) -> Result {
238 let phydev = self.0.get();
239 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
240 // So it's just an FFI call.
241 to_result(unsafe { bindings::genphy_resume(phydev) })
242 }
243
244 /// Suspends the PHY via `BMCR_PDOWN` bit.
245 pub fn genphy_suspend(&mut self) -> Result {
246 let phydev = self.0.get();
247 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
248 // So it's just an FFI call.
249 to_result(unsafe { bindings::genphy_suspend(phydev) })
250 }
251
252 /// Checks the link status and updates current link state.
253 pub fn genphy_read_status<R: reg::Register>(&mut self) -> Result<u16> {
254 R::read_status(self)
255 }
256
257 /// Updates the link status.
258 pub fn genphy_update_link(&mut self) -> Result {
259 let phydev = self.0.get();
260 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
261 // So it's just an FFI call.
262 to_result(unsafe { bindings::genphy_update_link(phydev) })
263 }
264
265 /// Reads link partner ability.
266 pub fn genphy_read_lpa(&mut self) -> Result {
267 let phydev = self.0.get();
268 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
269 // So it's just an FFI call.
270 to_result(unsafe { bindings::genphy_read_lpa(phydev) })
271 }
272
273 /// Reads PHY abilities.
274 pub fn genphy_read_abilities(&mut self) -> Result {
275 let phydev = self.0.get();
276 // SAFETY: `phydev` is pointing to a valid object by the type invariant of `Self`.
277 // So it's just an FFI call.
278 to_result(unsafe { bindings::genphy_read_abilities(phydev) })
279 }
280}
281
282impl AsRef<kernel::device::Device> for Device {
283 fn as_ref(&self) -> &kernel::device::Device {
284 let phydev = self.0.get();
285 // SAFETY: The struct invariant ensures that `mdio.dev` is valid.
286 unsafe { kernel::device::Device::from_raw(addr_of_mut!((*phydev).mdio.dev)) }
287 }
288}
289
290/// Defines certain other features this PHY supports (like interrupts).
291///
292/// These flag values are used in [`Driver::FLAGS`].
293pub mod flags {
294 /// PHY is internal.
295 pub const IS_INTERNAL: u32 = bindings::PHY_IS_INTERNAL;
296 /// PHY needs to be reset after the refclk is enabled.
297 pub const RST_AFTER_CLK_EN: u32 = bindings::PHY_RST_AFTER_CLK_EN;
298 /// Polling is used to detect PHY status changes.
299 pub const POLL_CABLE_TEST: u32 = bindings::PHY_POLL_CABLE_TEST;
300 /// Don't suspend.
301 pub const ALWAYS_CALL_SUSPEND: u32 = bindings::PHY_ALWAYS_CALL_SUSPEND;
302}
303
304/// An adapter for the registration of a PHY driver.
305struct Adapter<T: Driver> {
306 _p: PhantomData<T>,
307}
308
309impl<T: Driver> Adapter<T> {
310 /// # Safety
311 ///
312 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
313 #[safety{OriginateFrom(phydev, soft_reset)}]
314 unsafe extern "C" fn soft_reset_callback(phydev: *mut bindings::phy_device) -> c_int {
315 from_result(|| {
316 // SAFETY: This callback is called only in contexts
317 // where we hold `phy_device->lock`, so the accessors on
318 // `Device` are okay to call.
319 let dev = unsafe { Device::from_raw(phydev) };
320 T::soft_reset(dev)?;
321 Ok(0)
322 })
323 }
324
325 /// # Safety
326 ///
327 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
328 #[safety{OriginateFrom(phydev, probe)}]
329 unsafe extern "C" fn probe_callback(phydev: *mut bindings::phy_device) -> c_int {
330 from_result(|| {
331 // SAFETY: This callback is called only in contexts
332 // where we can exclusively access `phy_device` because
333 // it's not published yet, so the accessors on `Device` are okay
334 // to call.
335 let dev = unsafe { Device::from_raw(phydev) };
336 T::probe(dev)?;
337 Ok(0)
338 })
339 }
340
341 /// # Safety
342 ///
343 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
344 #[safety{OriginateFrom(phydev, get_features)}]
345 unsafe extern "C" fn get_features_callback(phydev: *mut bindings::phy_device) -> c_int {
346 from_result(|| {
347 // SAFETY: This callback is called only in contexts
348 // where we hold `phy_device->lock`, so the accessors on
349 // `Device` are okay to call.
350 let dev = unsafe { Device::from_raw(phydev) };
351 T::get_features(dev)?;
352 Ok(0)
353 })
354 }
355
356 /// # Safety
357 ///
358 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
359 #[safety{OriginateFrom(phydev, suspend)}]
360 unsafe extern "C" fn suspend_callback(phydev: *mut bindings::phy_device) -> c_int {
361 from_result(|| {
362 // SAFETY: The C core code ensures that the accessors on
363 // `Device` are okay to call even though `phy_device->lock`
364 // might not be held.
365 let dev = unsafe { Device::from_raw(phydev) };
366 T::suspend(dev)?;
367 Ok(0)
368 })
369 }
370
371 /// # Safety
372 ///
373 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
374 #[safety{OriginateFrom(phydev, resume)}]
375 unsafe extern "C" fn resume_callback(phydev: *mut bindings::phy_device) -> c_int {
376 from_result(|| {
377 // SAFETY: The C core code ensures that the accessors on
378 // `Device` are okay to call even though `phy_device->lock`
379 // might not be held.
380 let dev = unsafe { Device::from_raw(phydev) };
381 T::resume(dev)?;
382 Ok(0)
383 })
384 }
385
386 /// # Safety
387 ///
388 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
389 #[safety{OriginateFrom(phydev, config_aneg)}]
390 unsafe extern "C" fn config_aneg_callback(phydev: *mut bindings::phy_device) -> c_int {
391 from_result(|| {
392 // SAFETY: This callback is called only in contexts
393 // where we hold `phy_device->lock`, so the accessors on
394 // `Device` are okay to call.
395 let dev = unsafe { Device::from_raw(phydev) };
396 T::config_aneg(dev)?;
397 Ok(0)
398 })
399 }
400
401 /// # Safety
402 ///
403 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
404 #[safety{OriginateFrom(phydev, read_status)}]
405 unsafe extern "C" fn read_status_callback(phydev: *mut bindings::phy_device) -> c_int {
406 from_result(|| {
407 // SAFETY: This callback is called only in contexts
408 // where we hold `phy_device->lock`, so the accessors on
409 // `Device` are okay to call.
410 let dev = unsafe { Device::from_raw(phydev) };
411 T::read_status(dev)?;
412 Ok(0)
413 })
414 }
415
416 /// # Safety
417 ///
418 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
419 #[safety{OriginateFrom(phydev, match_phy_device)}]
420 unsafe extern "C" fn match_phy_device_callback(
421 phydev: *mut bindings::phy_device,
422 _phydrv: *const bindings::phy_driver,
423 ) -> c_int {
424 // SAFETY: This callback is called only in contexts
425 // where we hold `phy_device->lock`, so the accessors on
426 // `Device` are okay to call.
427 let dev = unsafe { Device::from_raw(phydev) };
428 T::match_phy_device(dev).into()
429 }
430
431 /// # Safety
432 ///
433 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
434 #[safety{OriginateFrom(phydev, read_mmd)}]
435 unsafe extern "C" fn read_mmd_callback(
436 phydev: *mut bindings::phy_device,
437 devnum: i32,
438 regnum: u16,
439 ) -> i32 {
440 from_result(|| {
441 // SAFETY: This callback is called only in contexts
442 // where we hold `phy_device->lock`, so the accessors on
443 // `Device` are okay to call.
444 let dev = unsafe { Device::from_raw(phydev) };
445 // CAST: the C side verifies devnum < 32.
446 let ret = T::read_mmd(dev, devnum as u8, regnum)?;
447 Ok(ret.into())
448 })
449 }
450
451 /// # Safety
452 ///
453 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
454 #[safety{OriginateFrom(phydev, write_mmd)}]
455 unsafe extern "C" fn write_mmd_callback(
456 phydev: *mut bindings::phy_device,
457 devnum: i32,
458 regnum: u16,
459 val: u16,
460 ) -> i32 {
461 from_result(|| {
462 // SAFETY: This callback is called only in contexts
463 // where we hold `phy_device->lock`, so the accessors on
464 // `Device` are okay to call.
465 let dev = unsafe { Device::from_raw(phydev) };
466 T::write_mmd(dev, devnum as u8, regnum, val)?;
467 Ok(0)
468 })
469 }
470
471 /// # Safety
472 ///
473 /// `phydev` must be passed by the corresponding callback in `phy_driver`.
474 #[safety{OriginateFrom(phydev, link_change_notify)}]
475 unsafe extern "C" fn link_change_notify_callback(phydev: *mut bindings::phy_device) {
476 // SAFETY: This callback is called only in contexts
477 // where we hold `phy_device->lock`, so the accessors on
478 // `Device` are okay to call.
479 let dev = unsafe { Device::from_raw(phydev) };
480 T::link_change_notify(dev);
481 }
482}
483
484/// Driver structure for a particular PHY type.
485///
486/// Wraps the kernel's [`struct phy_driver`].
487/// This is used to register a driver for a particular PHY type with the kernel.
488///
489/// # Invariants
490///
491/// `self.0` is always in a valid state.
492///
493/// [`struct phy_driver`]: srctree/include/linux/phy.h
494#[repr(transparent)]
495pub struct DriverVTable(Opaque<bindings::phy_driver>);
496
497// SAFETY: `DriverVTable` doesn't expose any &self method to access internal data, so it's safe to
498// share `&DriverVTable` across execution context boundaries.
499unsafe impl Sync for DriverVTable {}
500
501/// Creates a [`DriverVTable`] instance from [`Driver`].
502///
503/// This is used by [`module_phy_driver`] macro to create a static array of `phy_driver`.
504///
505/// [`module_phy_driver`]: crate::module_phy_driver
506pub const fn create_phy_driver<T: Driver>() -> DriverVTable {
507 // INVARIANT: All the fields of `struct phy_driver` are initialized properly.
508 DriverVTable(Opaque::new(bindings::phy_driver {
509 name: crate::str::as_char_ptr_in_const_context(T::NAME).cast_mut(),
510 flags: T::FLAGS,
511 phy_id: T::PHY_DEVICE_ID.id(),
512 phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(),
513 soft_reset: if T::HAS_SOFT_RESET {
514 Some(Adapter::<T>::soft_reset_callback)
515 } else {
516 None
517 },
518 probe: if T::HAS_PROBE {
519 Some(Adapter::<T>::probe_callback)
520 } else {
521 None
522 },
523 get_features: if T::HAS_GET_FEATURES {
524 Some(Adapter::<T>::get_features_callback)
525 } else {
526 None
527 },
528 match_phy_device: if T::HAS_MATCH_PHY_DEVICE {
529 Some(Adapter::<T>::match_phy_device_callback)
530 } else {
531 None
532 },
533 suspend: if T::HAS_SUSPEND {
534 Some(Adapter::<T>::suspend_callback)
535 } else {
536 None
537 },
538 resume: if T::HAS_RESUME {
539 Some(Adapter::<T>::resume_callback)
540 } else {
541 None
542 },
543 config_aneg: if T::HAS_CONFIG_ANEG {
544 Some(Adapter::<T>::config_aneg_callback)
545 } else {
546 None
547 },
548 read_status: if T::HAS_READ_STATUS {
549 Some(Adapter::<T>::read_status_callback)
550 } else {
551 None
552 },
553 read_mmd: if T::HAS_READ_MMD {
554 Some(Adapter::<T>::read_mmd_callback)
555 } else {
556 None
557 },
558 write_mmd: if T::HAS_WRITE_MMD {
559 Some(Adapter::<T>::write_mmd_callback)
560 } else {
561 None
562 },
563 link_change_notify: if T::HAS_LINK_CHANGE_NOTIFY {
564 Some(Adapter::<T>::link_change_notify_callback)
565 } else {
566 None
567 },
568 // SAFETY: The rest is zeroed out to initialize `struct phy_driver`,
569 // sets `Option<&F>` to be `None`.
570 ..unsafe { core::mem::MaybeUninit::<bindings::phy_driver>::zeroed().assume_init() }
571 }))
572}
573
574/// Driver implementation for a particular PHY type.
575///
576/// This trait is used to create a [`DriverVTable`].
577#[vtable]
578pub trait Driver {
579 /// Defines certain other features this PHY supports.
580 /// It is a combination of the flags in the [`flags`] module.
581 const FLAGS: u32 = 0;
582
583 /// The friendly name of this PHY type.
584 const NAME: &'static CStr;
585
586 /// This driver only works for PHYs with IDs which match this field.
587 /// The default id and mask are zero.
588 const PHY_DEVICE_ID: DeviceId = DeviceId::new_with_custom_mask(0, 0);
589
590 /// Issues a PHY software reset.
591 fn soft_reset(_dev: &mut Device) -> Result {
592 build_error!(VTABLE_DEFAULT_ERROR)
593 }
594
595 /// Sets up device-specific structures during discovery.
596 fn probe(_dev: &mut Device) -> Result {
597 build_error!(VTABLE_DEFAULT_ERROR)
598 }
599
600 /// Probes the hardware to determine what abilities it has.
601 fn get_features(_dev: &mut Device) -> Result {
602 build_error!(VTABLE_DEFAULT_ERROR)
603 }
604
605 /// Returns true if this is a suitable driver for the given phydev.
606 /// If not implemented, matching is based on [`Driver::PHY_DEVICE_ID`].
607 fn match_phy_device(_dev: &Device) -> bool {
608 false
609 }
610
611 /// Configures the advertisement and resets auto-negotiation
612 /// if auto-negotiation is enabled.
613 fn config_aneg(_dev: &mut Device) -> Result {
614 build_error!(VTABLE_DEFAULT_ERROR)
615 }
616
617 /// Determines the negotiated speed and duplex.
618 fn read_status(_dev: &mut Device) -> Result<u16> {
619 build_error!(VTABLE_DEFAULT_ERROR)
620 }
621
622 /// Suspends the hardware, saving state if needed.
623 fn suspend(_dev: &mut Device) -> Result {
624 build_error!(VTABLE_DEFAULT_ERROR)
625 }
626
627 /// Resumes the hardware, restoring state if needed.
628 fn resume(_dev: &mut Device) -> Result {
629 build_error!(VTABLE_DEFAULT_ERROR)
630 }
631
632 /// Overrides the default MMD read function for reading a MMD register.
633 fn read_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16) -> Result<u16> {
634 build_error!(VTABLE_DEFAULT_ERROR)
635 }
636
637 /// Overrides the default MMD write function for writing a MMD register.
638 fn write_mmd(_dev: &mut Device, _devnum: u8, _regnum: u16, _val: u16) -> Result {
639 build_error!(VTABLE_DEFAULT_ERROR)
640 }
641
642 /// Callback for notification of link change.
643 fn link_change_notify(_dev: &mut Device) {}
644}
645
646/// Registration structure for PHY drivers.
647///
648/// Registers [`DriverVTable`] instances with the kernel. They will be unregistered when dropped.
649///
650/// # Invariants
651///
652/// The `drivers` slice are currently registered to the kernel via `phy_drivers_register`.
653pub struct Registration {
654 drivers: Pin<&'static mut [DriverVTable]>,
655}
656
657// SAFETY: The only action allowed in a `Registration` instance is dropping it, which is safe to do
658// from any thread because `phy_drivers_unregister` can be called from any thread context.
659unsafe impl Send for Registration {}
660
661impl Registration {
662 /// Registers a PHY driver.
663 pub fn register(
664 module: &'static crate::ThisModule,
665 drivers: Pin<&'static mut [DriverVTable]>,
666 ) -> Result<Self> {
667 if drivers.is_empty() {
668 return Err(code::EINVAL);
669 }
670 // SAFETY: The type invariants of [`DriverVTable`] ensure that all elements of
671 // the `drivers` slice are initialized properly. `drivers` will not be moved.
672 // So it's just an FFI call.
673 to_result(unsafe {
674 bindings::phy_drivers_register(drivers[0].0.get(), drivers.len().try_into()?, module.0)
675 })?;
676 // INVARIANT: The `drivers` slice is successfully registered to the kernel via `phy_drivers_register`.
677 Ok(Registration { drivers })
678 }
679}
680
681impl Drop for Registration {
682 fn drop(&mut self) {
683 // SAFETY: The type invariants guarantee that `self.drivers` is valid.
684 // So it's just an FFI call.
685 unsafe {
686 bindings::phy_drivers_unregister(self.drivers[0].0.get(), self.drivers.len() as i32)
687 };
688 }
689}
690
691/// An identifier for PHY devices on an MDIO/MII bus.
692///
693/// Represents the kernel's `struct mdio_device_id`. This is used to find an appropriate
694/// PHY driver.
695#[repr(transparent)]
696#[derive(Clone, Copy)]
697pub struct DeviceId(bindings::mdio_device_id);
698
699impl DeviceId {
700 /// Creates a new instance with the exact match mask.
701 pub const fn new_with_exact_mask(id: u32) -> Self {
702 Self(bindings::mdio_device_id {
703 phy_id: id,
704 phy_id_mask: DeviceMask::Exact.as_int(),
705 })
706 }
707
708 /// Creates a new instance with the model match mask.
709 pub const fn new_with_model_mask(id: u32) -> Self {
710 Self(bindings::mdio_device_id {
711 phy_id: id,
712 phy_id_mask: DeviceMask::Model.as_int(),
713 })
714 }
715
716 /// Creates a new instance with the vendor match mask.
717 pub const fn new_with_vendor_mask(id: u32) -> Self {
718 Self(bindings::mdio_device_id {
719 phy_id: id,
720 phy_id_mask: DeviceMask::Vendor.as_int(),
721 })
722 }
723
724 /// Creates a new instance with a custom match mask.
725 pub const fn new_with_custom_mask(id: u32, mask: u32) -> Self {
726 Self(bindings::mdio_device_id {
727 phy_id: id,
728 phy_id_mask: DeviceMask::Custom(mask).as_int(),
729 })
730 }
731
732 /// Creates a new instance from [`Driver`].
733 pub const fn new_with_driver<T: Driver>() -> Self {
734 T::PHY_DEVICE_ID
735 }
736
737 /// Get the MDIO device's PHY ID.
738 pub const fn id(&self) -> u32 {
739 self.0.phy_id
740 }
741
742 /// Get the MDIO device's match mask.
743 pub const fn mask_as_int(&self) -> u32 {
744 self.0.phy_id_mask
745 }
746
747 // macro use only
748 #[doc(hidden)]
749 pub const fn mdio_device_id(&self) -> bindings::mdio_device_id {
750 self.0
751 }
752}
753
754// SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct mdio_device_id`
755// and does not add additional invariants, so it's safe to transmute to `RawType`.
756unsafe impl RawDeviceId for DeviceId {
757 type RawType = bindings::mdio_device_id;
758}
759
760enum DeviceMask {
761 Exact,
762 Model,
763 Vendor,
764 Custom(u32),
765}
766
767impl DeviceMask {
768 const MASK_EXACT: u32 = !0;
769 const MASK_MODEL: u32 = !0 << 4;
770 const MASK_VENDOR: u32 = !0 << 10;
771
772 const fn as_int(&self) -> u32 {
773 match self {
774 DeviceMask::Exact => Self::MASK_EXACT,
775 DeviceMask::Model => Self::MASK_MODEL,
776 DeviceMask::Vendor => Self::MASK_VENDOR,
777 DeviceMask::Custom(mask) => *mask,
778 }
779 }
780}
781
782/// Declares a kernel module for PHYs drivers.
783///
784/// This creates a static array of kernel's `struct phy_driver` and registers it.
785/// This also corresponds to the kernel's `MODULE_DEVICE_TABLE` macro, which embeds the information
786/// for module loading into the module binary file. Every driver needs an entry in `device_table`.
787///
788/// # Examples
789///
790/// ```
791/// # mod module_phy_driver_sample {
792/// use kernel::c_str;
793/// use kernel::net::phy::{self, DeviceId};
794/// use kernel::prelude::*;
795///
796/// kernel::module_phy_driver! {
797/// drivers: [PhySample],
798/// device_table: [
799/// DeviceId::new_with_driver::<PhySample>()
800/// ],
801/// name: "rust_sample_phy",
802/// authors: ["Rust for Linux Contributors"],
803/// description: "Rust sample PHYs driver",
804/// license: "GPL",
805/// }
806///
807/// struct PhySample;
808///
809/// #[vtable]
810/// impl phy::Driver for PhySample {
811/// const NAME: &'static CStr = c_str!("PhySample");
812/// const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x00000001);
813/// }
814/// # }
815/// ```
816///
817/// This expands to the following code:
818///
819/// ```ignore
820/// use kernel::c_str;
821/// use kernel::net::phy::{self, DeviceId};
822/// use kernel::prelude::*;
823///
824/// struct Module {
825/// _reg: ::kernel::net::phy::Registration,
826/// }
827///
828/// module! {
829/// type: Module,
830/// name: "rust_sample_phy",
831/// authors: ["Rust for Linux Contributors"],
832/// description: "Rust sample PHYs driver",
833/// license: "GPL",
834/// }
835///
836/// struct PhySample;
837///
838/// #[vtable]
839/// impl phy::Driver for PhySample {
840/// const NAME: &'static CStr = c_str!("PhySample");
841/// const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x00000001);
842/// }
843///
844/// const _: () = {
845/// static mut DRIVERS: [::kernel::net::phy::DriverVTable; 1] =
846/// [::kernel::net::phy::create_phy_driver::<PhySample>()];
847///
848/// impl ::kernel::Module for Module {
849/// fn init(module: &'static ::kernel::ThisModule) -> Result<Self> {
850/// let drivers = unsafe { &mut DRIVERS };
851/// let mut reg = ::kernel::net::phy::Registration::register(
852/// module,
853/// ::core::pin::Pin::static_mut(drivers),
854/// )?;
855/// Ok(Module { _reg: reg })
856/// }
857/// }
858/// };
859///
860/// const N: usize = 1;
861///
862/// const TABLE: ::kernel::device_id::IdArray<::kernel::net::phy::DeviceId, (), N> =
863/// ::kernel::device_id::IdArray::new_without_index([
864/// ::kernel::net::phy::DeviceId(
865/// ::kernel::bindings::mdio_device_id {
866/// phy_id: 0x00000001,
867/// phy_id_mask: 0xffffffff,
868/// }),
869/// ]);
870///
871/// ::kernel::module_device_table!("mdio", phydev, TABLE);
872/// ```
873#[macro_export]
874macro_rules! module_phy_driver {
875 (@replace_expr $_t:tt $sub:expr) => {$sub};
876
877 (@count_devices $($x:expr),*) => {
878 0usize $(+ $crate::module_phy_driver!(@replace_expr $x 1usize))*
879 };
880
881 (@device_table [$($dev:expr),+]) => {
882 const N: usize = $crate::module_phy_driver!(@count_devices $($dev),+);
883
884 const TABLE: $crate::device_id::IdArray<$crate::net::phy::DeviceId, (), N> =
885 $crate::device_id::IdArray::new_without_index([ $(($dev,())),+, ]);
886
887 $crate::module_device_table!("mdio", phydev, TABLE);
888 };
889
890 (drivers: [$($driver:ident),+ $(,)?], device_table: [$($dev:expr),+ $(,)?], $($f:tt)*) => {
891 struct Module {
892 _reg: $crate::net::phy::Registration,
893 }
894
895 $crate::prelude::module! {
896 type: Module,
897 $($f)*
898 }
899
900 const _: () = {
901 static mut DRIVERS: [$crate::net::phy::DriverVTable;
902 $crate::module_phy_driver!(@count_devices $($driver),+)] =
903 [$($crate::net::phy::create_phy_driver::<$driver>()),+];
904
905 impl $crate::Module for Module {
906 fn init(module: &'static $crate::ThisModule) -> Result<Self> {
907 // SAFETY: The anonymous constant guarantees that nobody else can access
908 // the `DRIVERS` static. The array is used only in the C side.
909 let drivers = unsafe { &mut DRIVERS };
910 let mut reg = $crate::net::phy::Registration::register(
911 module,
912 ::core::pin::Pin::static_mut(drivers),
913 )?;
914 Ok(Module { _reg: reg })
915 }
916 }
917 };
918
919 $crate::module_phy_driver!(@device_table [$($dev),+]);
920 }
921}