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